1 /* This file is part of the KDE project
2 
3    Copyright (C) 2005 Dario Massarin <nekkar@libero.it>
4    Copyright (C) 2010 Matthias Fuchs <mat69@gmx.net>
5 
6    This program is free software; you can redistribute it and/or
7    modify it under the terms of the GNU General Public
8    License as published by the Free Software Foundation; either
9    version 2 of the License, or (at your option) any later version.
10 */
11 
12 #ifndef SCHEDULER_H
13 #define SCHEDULER_H
14 
15 #include <QObject>
16 #include <QMap>
17 #include <QTimerEvent>
18 
19 #include "core/job.h"
20 #include "core/jobqueue.h"
21 #include "kget_export.h"
22 
23 /**
24  * @brief Scheduler class: what handle all the jobs in kget.
25  *
26  * This class handles all the jobs in kget. See job.h for further details.
27  * When we want a job to be executed in kget, we have to add the queue
28  * that owns the job in the scheduler calling the addQueue(JobQueue *) function.
29  *
30  */
31 
32 class KGET_EXPORT Scheduler : public QObject
33 {
34     Q_OBJECT
35 
36     friend class SchedulerTest;
37 
38     public:
39 
40         enum FailureStatus {
41             None         = 0,
42             AboutToStall = 1,
43             Stall        = 2,
44             StallTimeout = 3,
45             Abort        = 4,
46             AbortTimeout = 5,
47             Error = 6
48         };
49 
50         class JobFailure {
51             public:
JobFailure()52             JobFailure()
53                 : status(None), time(-1), count(0)
54             {}
55 
isValid()56             bool isValid()                  {return ((status != None) && (time != -1));}
57 
58             FailureStatus status;
59             int time;
60             int count;
61 
62             bool operator==(JobFailure f) const {return ((status == f.status) && (time == f.time));}
63             bool operator!=(JobFailure f) const {return ((status != f.status) || (time != f.time));}
64         };
65 
66         Scheduler(QObject * parent = nullptr);
67         ~Scheduler() override;
68 
69         /**
70          * Starts globally the execution of the jobs
71          *
72          * @see stop()
73          */
74         void start();
75 
76         /**
77          * Stops globally the execution of the jobs
78          *
79          * @see start()
80          */
81         void stop();
82 
83         /**
84          * Can be used to suspend the scheduler before doing lenghty operations
85          * and activating it later again
86          *
87          * NOTE does not stop running jobs, just prevents changes to jobs
88          * HACK this is needed since the scheduler would constantly update the queue
89          * when stopping starting multiple transfers, this slows down that operation a lot
90          * and could result in transfers finishing before they are stopped etc.
91          */
92         void setIsSuspended(bool isSuspended);
93 
94         /**
95          * The JobQueues will be informed of changes in the network connection
96          * If there is no network connection then the Scheduler won't act on
97          * the timerEvent or updateQueue
98          */
99         void setHasNetworkConnection(bool hasConnection);
100 
101         /**
102          * Adds a queue to the scheduler.
103          *
104          * @param queue The queue that should be added
105          */
106         void addQueue(JobQueue * queue);
107 
108         /**
109          * Deletes a queue from the scheduler.
110          * If some jobs in the given queue are being executed, they are
111          * first stopped, then removed from the scheduler.
112          *
113          * @param queue The queue that should be removed
114          */
115         void delQueue(JobQueue * queue);
116 
117         /**
118          * @returns true if there is at least one Job in the Running state
119          */
120         bool hasRunningJobs() const;
121 
122         /**
123          * @returns the number of jobs that are currently in a Running state
124          */
125         int countRunningJobs() const;
126 
127         /**
128          * This function gets called by the KGet class whenever the settings
129          * have changed.
130          */
131         void settingsChanged();
132 
133         //JobQueue notifications
134         virtual void jobQueueChangedEvent(JobQueue * queue, JobQueue::Status status);
135         virtual void jobQueueMovedJobEvent(JobQueue * queue, Job * job);
136         virtual void jobQueueAddedJobEvent(JobQueue * queue, Job * job);
137         virtual void jobQueueAddedJobsEvent(JobQueue *queue, const QList<Job*> jobs);
138         virtual void jobQueueRemovedJobEvent(JobQueue * queue, Job * job);
139         virtual void jobQueueRemovedJobsEvent(JobQueue *queue, const QList<Job*> jobs);
140 
141         //Job notifications
142         virtual void jobChangedEvent(Job * job, Job::Status status);
143         virtual void jobChangedEvent(Job * job, Job::Policy status);
144         virtual void jobChangedEvent(Job * job, JobFailure failure);
145 
146     protected:
147         /**
148          * Updates the given queue, starting the jobs that come first in the queue
149          * and stopping all the other
150          *
151          * @param queue the queue to update
152          */
153         void updateQueue( JobQueue * queue );
154 
155         /**
156          * @return true if the given job should be running (and this depends
157          * on the job policy and on its jobQueue status)
158          *
159          * @param job the job to evaluate
160          */
161         bool shouldBeRunning( Job * job );
162 
163     private:
164         //Virtual QObject method
165         void timerEvent(QTimerEvent * event) override;
166 
167         /**
168          * Calls updateQueue for all queues
169          * @see updateQueue
170          */
171         void updateAllQueues();
172 
173         bool shouldUpdate() const;
174 
175     private:
176         QList<JobQueue *> m_queues;
177         QMap<Job *, JobFailure> m_failedJobs;
178 
179         int m_failureCheckTimer;
180 
181         const int m_stallTime;
182         int m_stallTimeout;
183         int m_abortTimeout;
184         bool m_isSuspended;
185         bool m_hasConnection;
186 };
187 
shouldUpdate()188 inline bool Scheduler::shouldUpdate() const
189 {
190     return !m_isSuspended && m_hasConnection;
191 }
192 #endif
193