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
32namespace KPlato
33{
34
35BuiltinSchedulerPlugin::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
42BuiltinSchedulerPlugin::~BuiltinSchedulerPlugin()
43{
44}
45
46QString 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
61void 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
82void BuiltinSchedulerPlugin::slotStarted( SchedulerThread *job )
83{
84 qDebug()<<"BuiltinSchedulerPlugin::slotStarted:"<<job->mainProject()<<job->mainManager();
85
86 emit sigCalculationStarted( job->mainProject(), job->mainManager() );
87}
88
89void 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//--------------------
120KPlatoScheduler::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
126KPlatoScheduler::~KPlatoScheduler()
127{
128 qDebug()<<"KPlatoScheduler::~KPlatoScheduler:"<<QThread::currentThreadId();
129}
130
131KLocale *KPlatoScheduler::locale() const
132{
133 return KGlobal::locale();
134}
135
136void KPlatoScheduler::stopScheduling()
137{
138 m_stopScheduling = true;
139 if ( m_project ) {
140 m_project->stopcalculation = true;
141 }
142}
143
144void 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