1 | /* This file is part of the KDE project |
2 | Copyright (C) 2009 Dag Andersen <danders@get2net.dk> |
3 | |
4 | This library is free software; you can redistribute it and/or |
5 | modify it under the terms of the GNU Library General Public |
6 | License as published by the Free Software Foundation; either |
7 | version 2 of the License, or (at your option) any later version. |
8 | |
9 | This library is distributed in the hope that it will be useful, |
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
12 | Library General Public License for more details. |
13 | |
14 | You should have received a copy of the GNU Library General Public License |
15 | along with this library; see the file COPYING.LIB. If not, write to |
16 | the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
17 | Boston, MA 02110-1301, USA. |
18 | */ |
19 | |
20 | #include "kptbuiltinschedulerplugin.h" |
21 | |
22 | #include "kptproject.h" |
23 | #include "kptschedule.h" |
24 | #include "kptxmlloaderobject.h" |
25 | |
26 | #include <QApplication> |
27 | #include <QDomDocument> |
28 | #include <QDomElement> |
29 | #include <QTimer> |
30 | #include <QMutexLocker> |
31 | |
32 | namespace KPlato |
33 | { |
34 | |
35 | BuiltinSchedulerPlugin::BuiltinSchedulerPlugin(QObject *parent) |
36 | : SchedulerPlugin(parent) |
37 | { |
38 | setName( i18nc( "Network = task dependency network" , "Network Scheduler" ) ); |
39 | setComment( i18nc( "@info:tooltip" , "Built-in network (PERT) based scheduler" ) ); |
40 | } |
41 | |
42 | BuiltinSchedulerPlugin::~BuiltinSchedulerPlugin() |
43 | { |
44 | } |
45 | |
46 | QString BuiltinSchedulerPlugin::description() const |
47 | { |
48 | return i18nc( "@info:whatsthis" , "<title>Network (PERT) Scheduler</title>" |
49 | "<para>The network scheduler generally schedules tasks according to their dependencies." |
50 | " When a task is scheduled it is scheduled in full, booking the allocated resources if available." |
51 | " If overbooking is not allowed, subsequent tasks that requests the same resource" |
52 | " will be scheduled later in time.</para>" |
53 | "<para>Tasks with time constraints will be scheduled first to minimize the problem" |
54 | " with resource conflicts</para>" |
55 | "<para><note>This scheduler does not handle resource conflicts well." |
56 | "<nl/>You can try a different scheduler if available." |
57 | " You may also change resource allocations or add dummy dependencies to avoid the conflicts.</note></para>" |
58 | ); |
59 | } |
60 | |
61 | void BuiltinSchedulerPlugin::calculate( Project &project, ScheduleManager *sm, bool nothread ) |
62 | { |
63 | KPlatoScheduler *job = new KPlatoScheduler( &project, sm ); |
64 | m_jobs << job; |
65 | connect(job, SIGNAL(jobStarted(SchedulerThread*)), SLOT(slotStarted(SchedulerThread*))); |
66 | connect(job, SIGNAL(jobFinished(SchedulerThread*)), SLOT(slotFinished(SchedulerThread*))); |
67 | |
68 | // connect(this, SIGNAL(sigCalculationStarted(Project*,ScheduleManager*)), &project, SIGNAL(sigCalculationStarted(Project*,ScheduleManager*))); |
69 | // connect(this, SIGNAL(sigCalculationFinished(Project*,ScheduleManager*)), &project, SIGNAL(sigCalculationFinished(Project*,ScheduleManager*))); |
70 | |
71 | sm->setScheduling( true ); |
72 | if ( nothread ) { |
73 | connect(job, SIGNAL(maxProgressChanged(int)), sm, SLOT(setMaxProgress(int))); |
74 | connect(job, SIGNAL(progressChanged(int)), sm, SLOT(setProgress(int))); |
75 | job->doRun(); |
76 | } else { |
77 | job->start(); |
78 | } |
79 | m_synctimer.start(); |
80 | } |
81 | |
82 | void BuiltinSchedulerPlugin::slotStarted( SchedulerThread *job ) |
83 | { |
84 | qDebug()<<"BuiltinSchedulerPlugin::slotStarted:" <<job->mainProject()<<job->mainManager(); |
85 | |
86 | emit sigCalculationStarted( job->mainProject(), job->mainManager() ); |
87 | } |
88 | |
89 | void BuiltinSchedulerPlugin::slotFinished( SchedulerThread *job ) |
90 | { |
91 | ScheduleManager *sm = job->mainManager(); |
92 | Project *mp = job->mainProject(); |
93 | qDebug()<<"BuiltinSchedulerPlugin::slotFinished:" <<mp<<sm<<job->isStopped(); |
94 | if ( job->isStopped() ) { |
95 | sm->setCalculationResult( ScheduleManager::CalculationCanceled ); |
96 | } else { |
97 | updateLog( job ); |
98 | Project *tp = static_cast<KPlatoScheduler*>( job )->project(); |
99 | ScheduleManager *tm = static_cast<KPlatoScheduler*>( job )->manager(); |
100 | updateProject( tp, tm, mp, sm ); |
101 | sm->setCalculationResult( ScheduleManager::CalculationDone ); |
102 | } |
103 | sm->setScheduling( false ); |
104 | |
105 | m_jobs.removeAt( m_jobs.indexOf( job ) ); |
106 | if ( m_jobs.isEmpty() ) { |
107 | m_synctimer.stop(); |
108 | } |
109 | emit sigCalculationFinished( mp, sm ); |
110 | |
111 | disconnect(this, SIGNAL(sigCalculationStarted(Project*,ScheduleManager*)), mp, SIGNAL(sigCalculationStarted(Project*,ScheduleManager*))); |
112 | disconnect(this, SIGNAL(sigCalculationFinished(Project*,ScheduleManager*)), mp, SIGNAL(sigCalculationFinished(Project*,ScheduleManager*))); |
113 | |
114 | job->deleteLater(); |
115 | qDebug()<<"BuiltinSchedulerPlugin::slotFinished: <<<" ; |
116 | } |
117 | |
118 | |
119 | //-------------------- |
120 | KPlatoScheduler::KPlatoScheduler( Project *project, ScheduleManager *sm, QObject *parent ) |
121 | : SchedulerThread( project, sm, parent) |
122 | { |
123 | qDebug()<<"KPlatoScheduler::KPlatoScheduler:" <<m_mainmanager<<m_mainmanager->name()<<m_mainmanagerId; |
124 | } |
125 | |
126 | KPlatoScheduler::~KPlatoScheduler() |
127 | { |
128 | qDebug()<<"KPlatoScheduler::~KPlatoScheduler:" <<QThread::currentThreadId(); |
129 | } |
130 | |
131 | KLocale *KPlatoScheduler::locale() const |
132 | { |
133 | return KGlobal::locale(); |
134 | } |
135 | |
136 | void KPlatoScheduler::stopScheduling() |
137 | { |
138 | m_stopScheduling = true; |
139 | if ( m_project ) { |
140 | m_project->stopcalculation = true; |
141 | } |
142 | } |
143 | |
144 | void KPlatoScheduler::run() |
145 | { |
146 | if ( m_haltScheduling ) { |
147 | deleteLater(); |
148 | return; |
149 | } |
150 | if ( m_stopScheduling ) { |
151 | return; |
152 | } |
153 | { // mutex --> |
154 | m_projectMutex.lock(); |
155 | m_managerMutex.lock(); |
156 | |
157 | m_project = new Project(); |
158 | loadProject( m_project, m_pdoc ); |
159 | m_project->setName( "Schedule: " + m_project->name() ); //Debug |
160 | |
161 | m_manager = m_project->scheduleManager( m_mainmanagerId ); |
162 | Q_ASSERT( m_manager ); |
163 | Q_ASSERT( m_manager->expected() ); |
164 | Q_ASSERT( m_manager != m_mainmanager ); |
165 | Q_ASSERT( m_manager->scheduleId() == m_mainmanager->scheduleId() ); |
166 | Q_ASSERT( m_manager->expected() != m_mainmanager->expected() ); |
167 | m_manager->setName( "Schedule: " + m_manager->name() ); //Debug |
168 | |
169 | m_managerMutex.unlock(); |
170 | m_projectMutex.unlock(); |
171 | } // <--- mutex |
172 | |
173 | connect(m_project, SIGNAL(maxProgress(int)), this, SLOT(setMaxProgress(int))); |
174 | connect(m_project, SIGNAL(sigProgress(int)), this, SLOT(setProgress(int))); |
175 | |
176 | bool x = connect(m_manager, SIGNAL(sigLogAdded(Schedule::Log)), this, SLOT(slotAddLog(Schedule::Log))); |
177 | Q_ASSERT( x ); Q_UNUSED( x ); |
178 | m_project->calculate( *m_manager ); |
179 | if ( m_haltScheduling ) { |
180 | deleteLater(); |
181 | } |
182 | } |
183 | |
184 | |
185 | } //namespace KPlato |
186 | |
187 | |