1 | /* |
2 | This file is part of the KDE libraries |
3 | SPDX-FileCopyrightText: 2009, 2010 Andreas Hartmetz <ahartmetz@gmail.com> |
4 | |
5 | SPDX-License-Identifier: LGPL-2.0-only |
6 | */ |
7 | |
8 | #ifndef SCHEDULER_P_H |
9 | #define SCHEDULER_P_H |
10 | |
11 | #include "kiocore_export.h" |
12 | |
13 | #include <QSet> |
14 | #include <QTimer> |
15 | // #define SCHEDULER_DEBUG |
16 | |
17 | namespace KIO |
18 | { |
19 | // The worker manager manages the list of idle workers that can be reused |
20 | class WorkerManager : public QObject |
21 | { |
22 | Q_OBJECT |
23 | public: |
24 | WorkerManager(); |
25 | ~WorkerManager() override; |
26 | void returnWorker(KIO::Worker *worker); |
27 | // pick suitable worker for job and return it, return null if no worker found. |
28 | // the worker is removed from the manager. |
29 | KIO::Worker *takeWorkerForJob(KIO::SimpleJob *job); |
30 | // remove worker from manager |
31 | bool removeWorker(KIO::Worker *worker); |
32 | // remove all workers from manager |
33 | void clear(); |
34 | QList<KIO::Worker *> allWorkers() const; |
35 | |
36 | private: |
37 | void scheduleGrimReaper(); |
38 | |
39 | private Q_SLOTS: |
40 | void grimReaper(); |
41 | |
42 | private: |
43 | QMultiHash<QString, KIO::Worker *> m_idleWorkers; |
44 | QTimer m_grimTimer; |
45 | }; |
46 | |
47 | class HostQueue |
48 | { |
49 | public: |
50 | int lowestSerial() const; |
51 | |
52 | bool isQueueEmpty() const |
53 | { |
54 | return m_queuedJobs.isEmpty(); |
55 | } |
56 | bool isEmpty() const |
57 | { |
58 | return m_queuedJobs.isEmpty() && m_runningJobs.isEmpty(); |
59 | } |
60 | int runningJobsCount() const |
61 | { |
62 | return m_runningJobs.count(); |
63 | } |
64 | #ifdef SCHEDULER_DEBUG |
65 | QList<KIO::SimpleJob *> runningJobs() const |
66 | { |
67 | return QList<KIO::SimpleJob *>(m_runningJobs.cbegin(), m_runningJobs.cend()); |
68 | } |
69 | #endif |
70 | bool isJobRunning(KIO::SimpleJob *job) const |
71 | { |
72 | return m_runningJobs.contains(value: job); |
73 | } |
74 | |
75 | void queueJob(KIO::SimpleJob *job); |
76 | KIO::SimpleJob *takeFirstInQueue(); |
77 | bool removeJob(KIO::SimpleJob *job); |
78 | |
79 | QList<KIO::Worker *> allWorkers() const; |
80 | |
81 | private: |
82 | QMap<int, KIO::SimpleJob *> m_queuedJobs; |
83 | QSet<KIO::SimpleJob *> m_runningJobs; |
84 | }; |
85 | |
86 | class SchedulerPrivate; |
87 | |
88 | class SerialPicker |
89 | { |
90 | public: |
91 | // note that serial number zero is the default value from job_p.h and invalid! |
92 | |
93 | int next() |
94 | { |
95 | if (m_offset >= m_jobsPerPriority) { |
96 | m_offset = 1; |
97 | } |
98 | return m_offset++; |
99 | } |
100 | |
101 | int changedPrioritySerial(int oldSerial, int newPriority) const; |
102 | |
103 | private: |
104 | static const uint m_jobsPerPriority = 100000000; |
105 | uint m_offset = 1; |
106 | |
107 | public: |
108 | static const int maxSerial = m_jobsPerPriority * 20; |
109 | }; |
110 | |
111 | class ProtoQueue : public QObject |
112 | { |
113 | Q_OBJECT |
114 | public: |
115 | ProtoQueue(int maxWorkers, int maxWorkersPerHost); |
116 | ~ProtoQueue() override; |
117 | |
118 | void queueJob(KIO::SimpleJob *job); |
119 | void changeJobPriority(KIO::SimpleJob *job, int newPriority); |
120 | void removeJob(KIO::SimpleJob *job); |
121 | KIO::Worker *createWorker(const QString &protocol, KIO::SimpleJob *job, const QUrl &url); |
122 | bool removeWorker(KIO::Worker *worker); |
123 | QList<KIO::Worker *> allWorkers() const; |
124 | |
125 | private Q_SLOTS: |
126 | // start max one (non-connected) job and return |
127 | void startAJob(); |
128 | |
129 | private: |
130 | SerialPicker m_serialPicker; |
131 | QTimer m_startJobTimer; |
132 | QMap<int, HostQueue *> m_queuesBySerial; |
133 | QHash<QString, HostQueue> m_queuesByHostname; |
134 | WorkerManager m_workerManager; |
135 | int m_maxConnectionsPerHost; |
136 | int m_maxConnectionsTotal; |
137 | int m_runningJobsCount; |
138 | }; |
139 | |
140 | } // namespace KIO |
141 | |
142 | #endif // SCHEDULER_P_H |
143 | |