1 /*
2     SPDX-FileCopyrightText: 2005 Joris Guisson <joris.guisson@gmail.com>
3     SPDX-License-Identifier: GPL-2.0-or-later
4 */
5 
6 #ifndef KTQUEUEMANAGER_H
7 #define KTQUEUEMANAGER_H
8 
9 #include <set>
10 
11 #include <KSharedConfig>
12 #include <QObject>
13 
14 #include <interfaces/queuemanagerinterface.h>
15 #include <interfaces/torrentinterface.h>
16 #include <ktcore_export.h>
17 
18 namespace bt
19 {
20 class SHA1Hash;
21 struct TrackerTier;
22 class WaitJob;
23 }
24 
25 namespace kt
26 {
27 class KTCORE_EXPORT QueuePtrList : public QList<bt::TorrentInterface *>
28 {
29 public:
30     QueuePtrList();
31     ~QueuePtrList();
32 
33     /**
34      * Sort based upon priority
35      */
36     void sort();
37 
38 protected:
39     static bool biggerThan(bt::TorrentInterface *tc1, bt::TorrentInterface *tc2);
40 };
41 
42 /**
43  * @author Ivan Vasic
44  * @brief This class contains list of all TorrentControls and is responsible for starting/stopping them
45  */
46 class KTCORE_EXPORT QueueManager : public QObject, public bt::QueueManagerInterface
47 {
48     Q_OBJECT
49 
50 public:
51     QueueManager();
52     ~QueueManager() override;
53 
54     void append(bt::TorrentInterface *tc);
55     void remove(bt::TorrentInterface *tc);
56     void clear();
57 
58     /**
59         Save the state of the QueueManager
60         @param cfg The config
61     */
62     void saveState(KSharedConfigPtr cfg);
63 
64     /**
65         Load the state of the QueueManager
66         @param cfg The config
67     */
68     void loadState(KSharedConfigPtr cfg);
69 
70     /**
71      * Check if we need to decrease the priority of stalled torrents
72      * @param min_stall_time Stall time in minutes
73      * @param now The current time
74      */
75     void checkStalledTorrents(bt::TimeStamp now, bt::Uint32 min_stall_time);
76 
77     /**
78      * Start a torrent
79      * @param tc The torrent
80      * @return What happened
81      */
82     bt::TorrentStartResponse start(bt::TorrentInterface *tc);
83 
84     /**
85      * Stop a torrent
86      * @param tc The torrent
87      */
88     void stop(bt::TorrentInterface *tc);
89 
90     /**
91      * Start a list of torrents.
92      * @param todo The list of torrents
93      */
94     void start(QList<bt::TorrentInterface *> &todo);
95 
96     /**
97      * Stop a list of torrents
98      * @param todo The list of torrents
99      */
100     void stop(QList<bt::TorrentInterface *> &todo);
101 
102     /// Stop all torrents
103     void stopAll();
104 
105     /// Start all torrents
106     void startAll();
107 
108     /**
109      * Stop all running torrents
110      * @param wjob WaitJob which waits for stopped events to reach the tracker
111      */
112     void onExit(bt::WaitJob *wjob);
113 
114     /// Get the number of torrents
count()115     int count()
116     {
117         return downloads.count();
118     }
119 
120     /// Get the number of downloads
121     int countDownloads();
122 
123     /// Get the number of seeds
124     int countSeeds();
125 
126     enum Flags {
127         SEEDS = 1,
128         DOWNLOADS = 2,
129         ALL = 3,
130     };
131 
132     /**
133      * Get the number of running torrents
134      * @param flags Which torrents to choose
135      */
136     int getNumRunning(Flags flags = ALL);
137 
138     /**
139      * Start the next torrent.
140      */
141     void startNext();
142 
143     /**
144         If the QM is disabled this function needs to be called to start
145         all the torrents which were running at the time of the previous exit.
146     */
147     void startAutoStartTorrents();
148 
149     typedef QList<bt::TorrentInterface *>::iterator iterator;
150     typedef QList<bt::TorrentInterface *>::const_iterator const_iterator;
151 
152     iterator begin();
153     iterator end();
154 
155     const_iterator begin() const;
156     const_iterator end() const;
157 
158     /**
159      * Get the torrent at index idx in the list.
160      * @param idx Index of the torrent
161      * @return The torrent or 0 if the index is out of bounds
162      */
163     const bt::TorrentInterface *getTorrent(bt::Uint32 idx) const;
164 
165     /**
166      * Get the torrent at index idx in the list.
167      * @param idx Index of the torrent
168      * @return The torrent or 0 if the index is out of bounds
169      */
170     bt::TorrentInterface *getTorrent(bt::Uint32 idx);
171 
172     /**
173      * See if we already loaded a torrent.
174      * @param ih The info hash of a torrent
175      * @return true if we do, false if we don't
176      */
177     bool alreadyLoaded(const bt::SHA1Hash &ih) const override;
178 
179     /**
180      * Merge announce lists to a torrent
181      * @param ih The info_hash of the torrent to merge to
182      * @param trk First tier of trackers
183      */
184     void mergeAnnounceList(const bt::SHA1Hash &ih, const bt::TrackerTier *trk) override;
185 
186     /**
187      * Requested by each TorrentControl during its update to
188      * get permission on saving Stats file to disk. May be
189      * overriden to balance I/O operations.
190      * @param tc Pointer to TorrentControl instance
191      * @return true if file save is permitted, false otherwise
192      */
193 
194     bool permitStatsSync(bt::TorrentControl *tc) override;
195 
196     /**
197      * Set the maximum number of downloads
198      * @param m Max downloads
199      */
200     void setMaxDownloads(int m);
201 
202     /**
203      * Set the maximum number of seeds
204      * @param m Max seeds
205      */
206     void setMaxSeeds(int m);
207 
208     /**
209      * Enable or disable keep seeding (after a torrent has finished)
210      * @param ks Keep seeding
211      */
212     void setKeepSeeding(bool ks);
213 
214     /**
215      * Sets global suspended state for QueueManager and stopps all running torrents.
216      * No torrents will be automatically started/stopped with QM.
217      */
218     void setSuspendedState(bool suspend);
219 
220     /// Get the suspended state
getSuspendedState()221     bool getSuspendedState() const
222     {
223         return suspended_state;
224     }
225 
226     /**
227      * Reindex the queue priorities.
228      */
229     void reindexQueue();
230 
231     /**
232      * Check if a torrent has file conflicts with other torrents.
233      * If conflicting are found, a list of names of the conflicting torrents is filled in.
234      * @param tc The torrent
235      * @param conflicting List of conflicting torrents
236      */
237     bool checkFileConflicts(bt::TorrentInterface *tc, QStringList &conflicting) const;
238 
239     /**
240      * Places all torrents from downloads in the right order in queue.
241      * Use this when torrent priorities get changed
242      */
243     void orderQueue();
244 
245 Q_SIGNALS:
246     /**
247      * User tried to enqueue a torrent that has reached max share ratio. It's not possible.
248      * Signal should be connected to SysTray slot which shows appropriate KPassivePopup info.
249      * @param tc The torrent in question.
250      */
251     void queuingNotPossible(bt::TorrentInterface *tc);
252 
253     /**
254      * Diskspace is running low.
255      * Signal should be connected to SysTray slot which shows appropriate KPassivePopup info.
256      * @param tc The torrent in question.
257      */
258     void lowDiskSpace(bt::TorrentInterface *tc, bool stopped);
259 
260     /// Emitted before the queue is reordered
261     void orderingQueue();
262 
263     /**
264      * Emitted when the QM has reordered it's queue
265      */
266     void queueOrdered();
267 
268     /**
269      * Emitted when the suspended state changes.
270      * @param suspended The suspended state
271      */
272     void suspendStateChanged(bool suspended);
273 
274 public Q_SLOTS:
275     void torrentFinished(bt::TorrentInterface *tc);
276     void torrentAdded(bt::TorrentInterface *tc, bool start_torrent);
277     void torrentRemoved(bt::TorrentInterface *tc);
278     void torrentsRemoved(QList<bt::TorrentInterface *> &tors);
279     void torrentStopped(bt::TorrentInterface *tc);
280     void onLowDiskSpace(bt::TorrentInterface *tc, bool toStop);
281     void onOnlineStateChanged(bool);
282 
283 private:
284     void startSafely(bt::TorrentInterface *tc);
285     void stopSafely(bt::TorrentInterface *tc, bt::WaitJob *wjob = nullptr);
286     void checkDiskSpace(QList<bt::TorrentInterface *> &todo);
287     void checkMaxSeedTime(QList<bt::TorrentInterface *> &todo);
288     void checkMaxRatio(QList<bt::TorrentInterface *> &todo);
289     void rearrangeQueue();
290     bt::TorrentStartResponse startInternal(bt::TorrentInterface *tc);
291     bool checkLimits(bt::TorrentInterface *tc, bool interactive);
292     bool checkDiskSpace(bt::TorrentInterface *tc, bool interactive);
293 
294 private:
295     QueuePtrList downloads;
296     std::set<bt::TorrentInterface *> suspended_torrents;
297     int max_downloads;
298     int max_seeds;
299     bool suspended_state;
300     bool keep_seeding;
301     bool exiting;
302     bool ordering;
303     QDateTime network_down_time;
304     bt::TimeStamp last_stats_sync_permitted;
305 };
306 }
307 #endif
308