File indexing completed on 2024-04-28 11:41:08

0001 /*
0002     This file is part of the KDE libraries
0003     SPDX-FileCopyrightText: 2009, 2010 Andreas Hartmetz <ahartmetz@gmail.com>
0004 
0005     SPDX-License-Identifier: LGPL-2.0-only
0006 */
0007 
0008 #ifndef SCHEDULER_P_H
0009 #define SCHEDULER_P_H
0010 
0011 #include "kiocore_export.h"
0012 
0013 #include <QSet>
0014 #include <QTimer>
0015 // #define SCHEDULER_DEBUG
0016 
0017 namespace KIO
0018 {
0019 // The slave keeper manages the list of idle slaves that can be reused
0020 class SlaveKeeper : public QObject
0021 {
0022     Q_OBJECT
0023 public:
0024     SlaveKeeper();
0025     ~SlaveKeeper() override;
0026     void returnSlave(KIO::Slave *slave);
0027     // pick suitable slave for job and return it, return null if no slave found.
0028     // the slave is removed from the keeper.
0029     KIO::Slave *takeSlaveForJob(KIO::SimpleJob *job);
0030     // remove slave from keeper
0031     bool removeSlave(KIO::Slave *slave);
0032     // remove all slaves from keeper
0033     void clear();
0034     QList<KIO::Slave *> allSlaves() const;
0035 
0036 private:
0037     void scheduleGrimReaper();
0038 
0039 private Q_SLOTS:
0040     void grimReaper();
0041 
0042 private:
0043     QMultiHash<QString, KIO::Slave *> m_idleSlaves;
0044     QTimer m_grimTimer;
0045 };
0046 
0047 class HostQueue
0048 {
0049 public:
0050     int lowestSerial() const;
0051 
0052     bool isQueueEmpty() const
0053     {
0054         return m_queuedJobs.isEmpty();
0055     }
0056     bool isEmpty() const
0057     {
0058         return m_queuedJobs.isEmpty() && m_runningJobs.isEmpty();
0059     }
0060     int runningJobsCount() const
0061     {
0062         return m_runningJobs.count();
0063     }
0064 #ifdef SCHEDULER_DEBUG
0065     QList<KIO::SimpleJob *> runningJobs() const
0066     {
0067         return QList<KIO::SimpleJob *>(m_runningJobs.cbegin(), m_runningJobs.cend());
0068     }
0069 #endif
0070     bool isJobRunning(KIO::SimpleJob *job) const
0071     {
0072         return m_runningJobs.contains(job);
0073     }
0074 
0075     void queueJob(KIO::SimpleJob *job);
0076     KIO::SimpleJob *takeFirstInQueue();
0077     bool removeJob(KIO::SimpleJob *job);
0078 
0079     QList<KIO::Slave *> allSlaves() const;
0080 
0081 private:
0082     QMap<int, KIO::SimpleJob *> m_queuedJobs;
0083     QSet<KIO::SimpleJob *> m_runningJobs;
0084 };
0085 
0086 #if KIOCORE_BUILD_DEPRECATED_SINCE(5, 91)
0087 struct PerSlaveQueue {
0088     PerSlaveQueue()
0089         : runningJob(nullptr)
0090     {
0091     }
0092     QList<SimpleJob *> waitingList;
0093     SimpleJob *runningJob;
0094 };
0095 
0096 class ConnectedSlaveQueue : public QObject
0097 {
0098     Q_OBJECT
0099 public:
0100     ConnectedSlaveQueue();
0101 
0102     bool queueJob(KIO::SimpleJob *job, KIO::Slave *slave);
0103     bool removeJob(KIO::SimpleJob *job);
0104 
0105     void addSlave(KIO::Slave *slave);
0106     bool removeSlave(KIO::Slave *slave);
0107 
0108     // KDE5: only one caller, for doubtful reasons. remove this if possible.
0109     bool isIdle(KIO::Slave *slave);
0110     bool isEmpty() const
0111     {
0112         return m_connectedSlaves.isEmpty();
0113     }
0114     QList<KIO::Slave *> allSlaves() const
0115     {
0116         return m_connectedSlaves.keys();
0117     }
0118 
0119 private Q_SLOTS:
0120     void startRunnableJobs();
0121 
0122 private:
0123     // note that connected slaves stay here when idle, they are not returned to SlaveKeeper
0124     QHash<KIO::Slave *, PerSlaveQueue> m_connectedSlaves;
0125     QSet<KIO::Slave *> m_runnableSlaves;
0126     QTimer m_startJobsTimer;
0127 };
0128 #endif
0129 
0130 class SchedulerPrivate;
0131 
0132 class SerialPicker
0133 {
0134 public:
0135     // note that serial number zero is the default value from job_p.h and invalid!
0136 
0137     int next()
0138     {
0139         if (m_offset >= m_jobsPerPriority) {
0140             m_offset = 1;
0141         }
0142         return m_offset++;
0143     }
0144 
0145     int changedPrioritySerial(int oldSerial, int newPriority) const;
0146 
0147 private:
0148     static const uint m_jobsPerPriority = 100000000;
0149     uint m_offset = 1;
0150 
0151 public:
0152     static const int maxSerial = m_jobsPerPriority * 20;
0153 };
0154 
0155 class ProtoQueue : public QObject
0156 {
0157     Q_OBJECT
0158 public:
0159     ProtoQueue(int maxWorkers, int maxWorkersPerHost);
0160     ~ProtoQueue() override;
0161 
0162     void queueJob(KIO::SimpleJob *job);
0163     void changeJobPriority(KIO::SimpleJob *job, int newPriority);
0164     void removeJob(KIO::SimpleJob *job);
0165     KIO::Slave *createSlave(const QString &protocol, KIO::SimpleJob *job, const QUrl &url);
0166     bool removeSlave(KIO::Slave *slave);
0167     QList<KIO::Slave *> allSlaves() const;
0168 #if KIOCORE_BUILD_DEPRECATED_SINCE(5, 91)
0169     ConnectedSlaveQueue m_connectedSlaveQueue; // KF6 TODO: remove
0170 #endif
0171 
0172 private Q_SLOTS:
0173     // start max one (non-connected) job and return
0174     void startAJob();
0175 
0176 private:
0177     SerialPicker m_serialPicker;
0178     QTimer m_startJobTimer;
0179     QMap<int, HostQueue *> m_queuesBySerial;
0180     QHash<QString, HostQueue> m_queuesByHostname;
0181     SlaveKeeper m_slaveKeeper;
0182     int m_maxConnectionsPerHost;
0183     int m_maxConnectionsTotal;
0184     int m_runningJobsCount;
0185 };
0186 
0187 } // namespace KIO
0188 
0189 #endif // SCHEDULER_P_H