1 /*
2     SPDX-FileCopyrightText: 2014 Daniel Vrátil <dvratil@redhat.com>
3 
4     SPDX-License-Identifier: LGPL-2.0-or-later
5 */
6 
7 #pragma once
8 
9 #include <QMultiMap>
10 #include <QMutex>
11 #include <QThread>
12 
13 #include "akthread.h"
14 #include "entities.h"
15 
16 namespace Akonadi
17 {
18 namespace Server
19 {
20 class Collection;
21 class PauseableTimer;
22 
23 class CollectionScheduler : public AkThread
24 {
25     Q_OBJECT
26 
27 public:
28     explicit CollectionScheduler(const QString &threadName, QThread::Priority priority, QObject *parent = nullptr);
29     ~CollectionScheduler() override;
30 
31     void collectionChanged(qint64 collectionId);
32     void collectionRemoved(qint64 collectionId);
33     void collectionAdded(qint64 collectionId);
34 
35     /**
36      * Sets the minimum timeout interval.
37      *
38      * Default value is 5.
39      *
40      * @p intervalMinutes Minimum timeout interval in minutes.
41      */
42     void setMinimumInterval(int intervalMinutes);
43     Q_REQUIRED_RESULT int minimumInterval() const;
44 
45     using TimePoint = std::chrono::steady_clock::time_point;
46 
47     /**
48      * @return the timestamp (in seconds since epoch) when collectionExpired
49      * will next be called on the given collection, or 0 if we don't know about the collection.
50      * Only used by the unittest.
51      */
52     TimePoint nextScheduledTime(qint64 collectionId) const;
53 
54     /**
55      * @return the next timeout
56      */
57     std::chrono::milliseconds currentTimerInterval() const;
58 
59 protected:
60     void init() override;
61     void quit() override;
62 
63     virtual bool shouldScheduleCollection(const Collection &collection) = 0;
64     virtual bool hasChanged(const Collection &collection, const Collection &changed) = 0;
65     /**
66      * @return Return cache timeout in minutes
67      */
68     virtual int collectionScheduleInterval(const Collection &collection) = 0;
69     /**
70      * Called when it's time to do something on that collection.
71      * Notice: this method is called in the secondary thread
72      */
73     virtual void collectionExpired(const Collection &collection) = 0;
74 
75     void inhibit(bool inhibit = true);
76 
77 private Q_SLOTS:
78     void schedulerTimeout();
79     void startScheduler();
80     void scheduleCollection(/*sic!*/ Akonadi::Server::Collection collection, bool shouldStartScheduler = true);
81 
82 private:
83     using ScheduleMap = QMultiMap<TimePoint /*timestamp*/, Collection>;
84     ScheduleMap::const_iterator constFind(qint64 collectionId) const;
85     ScheduleMap::iterator find(qint64 collectionId);
86     ScheduleMap::const_iterator constLowerBound(TimePoint timestamp) const;
87 
88     mutable QMutex mScheduleLock;
89     ScheduleMap mSchedule;
90     PauseableTimer *mScheduler = nullptr;
91     int mMinInterval = 5;
92 };
93 
94 } // namespace Server
95 } // namespace Akonadi
96 
97