File indexing completed on 2024-04-28 16:24:34

0001 /* This file is part of the KDE project
0002   Copyright (C) 2009 Dag Andersen <danders@get2net.dk>
0003 
0004   This library is free software; you can redistribute it and/or
0005   modify it under the terms of the GNU Library General Public
0006   License as published by the Free Software Foundation; either
0007   version 2 of the License, or (at your option) any later version.
0008 
0009   This library is distributed in the hope that it will be useful,
0010   but WITHOUT ANY WARRANTY; without even the implied warranty of
0011   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0012   Library General Public License for more details.
0013 
0014   You should have received a copy of the GNU Library General Public License
0015   along with this library; see the file COPYING.LIB.  If not, write to
0016   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0017   Boston, MA 02110-1301, USA.
0018 */
0019 
0020 // clazy:excludeall=qstring-arg
0021 #include "kptbuiltinschedulerplugin.h"
0022 
0023 #include "kptproject.h"
0024 #include "kptschedule.h"
0025 #include "kptxmlloaderobject.h"
0026 
0027 #include <KLocalizedString>
0028 
0029 namespace KPlato
0030 {
0031 
0032 BuiltinSchedulerPlugin::BuiltinSchedulerPlugin(QObject *parent)
0033     : SchedulerPlugin(parent)
0034 {
0035     setName(i18nc("Network = task dependency network", "Network Scheduler"));
0036     setComment(xi18nc("@info:tooltip", "Built-in network (PERT) based scheduler"));
0037 }
0038  
0039 BuiltinSchedulerPlugin::~BuiltinSchedulerPlugin()
0040 {
0041 }
0042 
0043 QString BuiltinSchedulerPlugin::description() const
0044 {
0045     return xi18nc("@info:whatsthis", "<title>Network (PERT) Scheduler</title>"
0046                     "<para>The network scheduler generally schedules tasks according to their dependencies."
0047                     " When a task is scheduled it is scheduled in full, booking the allocated resources if available."
0048                     " If overbooking is not allowed, subsequent tasks that requests the same resource"
0049                     " will be scheduled later in time.</para>"
0050                     "<para>Tasks with time constraints will be scheduled first to minimize the problem"
0051                     " with resource conflicts</para>"
0052                     "<para><note>This scheduler does not handle resource conflicts well."
0053                     "<nl/>You can try a different scheduler if available."
0054                     " You may also change resource allocations or add dummy dependencies to avoid the conflicts.</note></para>"
0055                 );
0056 }
0057 
0058 void BuiltinSchedulerPlugin::calculate(Project &project, ScheduleManager *sm, bool nothread)
0059 {
0060     KPlatoScheduler *job = new KPlatoScheduler(&project, sm);
0061     m_jobs << job;
0062     connect(job, &SchedulerThread::jobStarted, this, &BuiltinSchedulerPlugin::slotStarted);
0063     connect(job, &SchedulerThread::jobFinished, this, &BuiltinSchedulerPlugin::slotFinished);
0064 
0065     connect(this, &BuiltinSchedulerPlugin::sigCalculationStarted, &project, &Project::sigCalculationStarted);
0066     connect(this, &BuiltinSchedulerPlugin::sigCalculationFinished, &project, &Project::sigCalculationFinished);
0067 
0068     sm->setScheduling(true);
0069     if (nothread) {
0070         connect(job, &SchedulerThread::maxProgressChanged, sm, &ScheduleManager::setMaxProgress);
0071         connect(job, &SchedulerThread::progressChanged, sm, &ScheduleManager::setProgress);
0072         job->doRun();
0073     } else {
0074         job->start();
0075     }
0076     m_synctimer.start();
0077 }
0078 
0079 void BuiltinSchedulerPlugin::slotStarted(SchedulerThread *job)
0080 {
0081     qDebug()<<"BuiltinSchedulerPlugin::slotStarted:"<<job->mainProject()<<job->mainManager();
0082     
0083     emit sigCalculationStarted(job->mainProject(), job->mainManager());
0084 }
0085 
0086 void BuiltinSchedulerPlugin::slotFinished(SchedulerThread *job)
0087 {
0088     ScheduleManager *sm = job->mainManager();
0089     Project *mp = job->mainProject();
0090     qDebug()<<"BuiltinSchedulerPlugin::slotFinished:"<<mp<<sm<<job->isStopped();
0091     if (job->isStopped()) {
0092         sm->setCalculationResult(ScheduleManager::CalculationCanceled);
0093     } else {
0094         updateLog(job);
0095         Project *tp = static_cast<KPlatoScheduler*>(job)->project();
0096         ScheduleManager *tm = static_cast<KPlatoScheduler*>(job)->manager();
0097         updateProject(tp, tm, mp, sm);
0098         sm->setCalculationResult(ScheduleManager::CalculationDone);
0099     }
0100     sm->setScheduling(false);
0101 
0102     m_jobs.removeAt(m_jobs.indexOf(job));
0103     if (m_jobs.isEmpty()) {
0104         m_synctimer.stop();
0105     }
0106     emit sigCalculationFinished(mp, sm);
0107 
0108     disconnect(this, &BuiltinSchedulerPlugin::sigCalculationStarted, mp, &Project::sigCalculationStarted);
0109     disconnect(this, &BuiltinSchedulerPlugin::sigCalculationFinished, mp, &Project::sigCalculationFinished);
0110 
0111     job->deleteLater();
0112     qDebug()<<"BuiltinSchedulerPlugin::slotFinished: <<<";
0113 }
0114 
0115 
0116 //--------------------
0117 KPlatoScheduler::KPlatoScheduler(Project *project, ScheduleManager *sm, QObject *parent)
0118     : SchedulerThread(project, sm, parent)
0119 {
0120     qDebug()<<"KPlatoScheduler::KPlatoScheduler:"<<m_mainmanager<<m_mainmanager->name()<<m_mainmanagerId;
0121 }
0122 
0123 KPlatoScheduler::~KPlatoScheduler()
0124 {
0125     qDebug()<<"KPlatoScheduler::~KPlatoScheduler:"<<QThread::currentThreadId();
0126 }
0127 
0128 void KPlatoScheduler::stopScheduling()
0129 {
0130     m_stopScheduling = true;
0131     if (m_project) {
0132         m_project->stopcalculation = true;
0133     }
0134 }
0135 
0136 void KPlatoScheduler::run()
0137 {
0138     if (m_haltScheduling) {
0139         deleteLater();
0140         return;
0141     }
0142     if (m_stopScheduling) {
0143         return;
0144     }
0145     { // mutex -->
0146         m_projectMutex.lock();
0147         m_managerMutex.lock();
0148 
0149         m_project = new Project();
0150         loadProject(m_project, m_pdoc);
0151         m_project->setName("Schedule: " + m_project->name()); //Debug
0152 
0153         m_manager = m_project->scheduleManager(m_mainmanagerId);
0154         Q_ASSERT(m_manager);
0155         Q_ASSERT(m_manager->expected());
0156         Q_ASSERT(m_manager != m_mainmanager);
0157         Q_ASSERT(m_manager->scheduleId() == m_mainmanager->scheduleId());
0158         Q_ASSERT(m_manager->expected() != m_mainmanager->expected());
0159         m_manager->setName("Schedule: " + m_manager->name()); //Debug
0160 
0161         m_managerMutex.unlock();
0162         m_projectMutex.unlock();
0163     } // <--- mutex
0164 
0165     connect(m_project, SIGNAL(maxProgress(int)), this, SLOT(setMaxProgress(int)));
0166     connect(m_project, SIGNAL(sigProgress(int)), this, SLOT(setProgress(int)));
0167 
0168     bool x = connect(m_manager, SIGNAL(sigLogAdded(KPlato::Schedule::Log)), this, SLOT(slotAddLog(KPlato::Schedule::Log)));
0169     Q_ASSERT(x); Q_UNUSED(x);
0170     m_project->calculate(*m_manager);
0171     if (m_haltScheduling) {
0172         deleteLater();
0173     }
0174 }
0175 
0176 
0177 } //namespace KPlato
0178