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