| 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 "worker_p.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 | private: |
| 102 | static const uint m_jobsPerPriority = 100000000; |
| 103 | uint m_offset = 1; |
| 104 | |
| 105 | public: |
| 106 | static const int maxSerial = m_jobsPerPriority * 20; |
| 107 | }; |
| 108 | |
| 109 | class ProtoQueue : public QObject |
| 110 | { |
| 111 | Q_OBJECT |
| 112 | public: |
| 113 | ProtoQueue(int maxWorkers, int maxWorkersPerHost); |
| 114 | ~ProtoQueue() override; |
| 115 | |
| 116 | void queueJob(KIO::SimpleJob *job); |
| 117 | void removeJob(KIO::SimpleJob *job); |
| 118 | KIO::Worker *createWorker(const QString &protocol, KIO::SimpleJob *job, const QUrl &url); |
| 119 | bool removeWorker(KIO::Worker *worker); |
| 120 | QList<KIO::Worker *> allWorkers() const; |
| 121 | |
| 122 | private Q_SLOTS: |
| 123 | // start max one (non-connected) job and return |
| 124 | void startAJob(); |
| 125 | |
| 126 | private: |
| 127 | SerialPicker m_serialPicker; |
| 128 | QTimer m_startJobTimer; |
| 129 | QMap<int, HostQueue *> m_queuesBySerial; |
| 130 | std::unordered_map<QString, HostQueue> m_queuesByHostname; |
| 131 | WorkerManager m_workerManager; |
| 132 | int m_maxConnectionsPerHost; |
| 133 | int m_maxConnectionsTotal; |
| 134 | int m_runningJobsCount; |
| 135 | }; |
| 136 | |
| 137 | } // namespace KIO |
| 138 | |
| 139 | #endif // SCHEDULER_P_H |
| 140 | |