1 /* 2 SPDX-FileCopyrightText: 2007 Volker Krause <vkrause@kde.org> 3 4 SPDX-License-Identifier: LGPL-2.0-or-later 5 */ 6 7 #pragma once 8 9 #include "agentbase.h" 10 #include "collection.h" 11 #include "item.h" 12 #include "resourcebase.h" 13 14 #include <QDBusMessage> 15 #include <QObject> 16 17 namespace Akonadi 18 { 19 class RecursiveMover; 20 21 /// @cond PRIVATE 22 23 /** 24 @internal 25 26 Manages synchronization and fetch requests for a resource. 27 28 @todo Attach to the ResourceBase Monitor, 29 */ 30 class ResourceScheduler : public QObject 31 { 32 Q_OBJECT 33 34 public: 35 // If you change this enum, keep s_taskTypes in sync in resourcescheduler.cpp 36 enum TaskType { 37 Invalid, 38 SyncAll, 39 SyncCollectionTree, 40 SyncCollection, 41 SyncCollectionAttributes, 42 SyncTags, 43 FetchItem, 44 FetchItems, 45 ChangeReplay, 46 RecursiveMoveReplay, 47 DeleteResourceCollection, 48 InvalideCacheForCollection, 49 SyncAllDone, 50 SyncCollectionTreeDone, 51 SyncRelations, 52 Custom 53 }; 54 55 class Task 56 { 57 static qint64 latestSerial; 58 59 public: Task()60 Task() 61 : serial(++latestSerial) 62 , type(Invalid) 63 { 64 } 65 qint64 serial; 66 TaskType type; 67 Collection collection; 68 QVector<Item> items; 69 QSet<QByteArray> itemParts; 70 QList<QDBusMessage> dbusMsgs; 71 QObject *receiver = nullptr; 72 QByteArray methodName; 73 QVariant argument; 74 75 void sendDBusReplies(const QString &errorMsg); 76 77 bool operator==(const Task &other) const 78 { 79 return type == other.type && (collection == other.collection || (!collection.isValid() && !other.collection.isValid())) && items == other.items 80 && itemParts == other.itemParts && receiver == other.receiver && methodName == other.methodName && argument == other.argument; 81 } 82 }; 83 84 explicit ResourceScheduler(QObject *parent = nullptr); 85 86 /** 87 Schedules a full synchronization. 88 */ 89 void scheduleFullSync(); 90 91 /** 92 Schedules a collection tree sync. 93 */ 94 void scheduleCollectionTreeSync(); 95 96 /** 97 Schedules the synchronization of a single collection. 98 @param col The collection to synchronize. 99 */ 100 void scheduleSync(const Collection &col); 101 102 /** 103 Schedules synchronizing the attributes of a single collection. 104 @param collection The collection to synchronize attributes from. 105 */ 106 void scheduleAttributesSync(const Collection &collection); 107 108 void scheduleTagSync(); 109 void scheduleRelationSync(); 110 111 /** 112 Schedules fetching of a single PIM item. 113 114 This task is only ever used if the resource still uses the old deprecated 115 retrieveItem() (instead of retrieveItems(Item::List)) method. This task has 116 a special meaning to the scheduler and instead of replying to the DBus message 117 after the single @p item is retrieved, the items are accumulated until all 118 tasks from the same messages are fetched. 119 120 @param items The items to fetch. 121 @param parts List of names of the parts of the item to fetch. 122 @param msg The associated D-Bus message. 123 @param parentId ID of the original ItemsFetch task that this task was created from. 124 We can use this ID to group the tasks together 125 */ 126 void scheduleItemFetch(const Item &item, const QSet<QByteArray> &parts, const QList<QDBusMessage> &msgs, const qint64 parentId); 127 128 /** 129 Schedules batch-fetching of PIM items. 130 @param items The items to fetch. 131 @param parts List of names of the parts of the item to fetch. 132 @param msg The associated D-Bus message. 133 */ 134 void scheduleItemsFetch(const Item::List &item, const QSet<QByteArray> &parts, const QDBusMessage &msg); 135 136 /** 137 Schedules deletion of the resource collection. 138 This method is used to implement the ResourceBase::clearCache() functionality. 139 */ 140 void scheduleResourceCollectionDeletion(); 141 142 /** 143 * Schedule cache invalidation for @p collection. 144 * @see ResourceBase::invalidateCache() 145 */ 146 void scheduleCacheInvalidation(const Collection &collection); 147 148 /** 149 Insert synchronization completion marker into the task queue. 150 */ 151 void scheduleFullSyncCompletion(); 152 153 /** 154 Insert collection tree synchronization completion marker into the task queue. 155 */ 156 void scheduleCollectionTreeSyncCompletion(); 157 158 /** 159 Insert a custom task. 160 @param methodName The method name, without signature, do not use the SLOT() macro 161 */ 162 void 163 scheduleCustomTask(QObject *receiver, const char *methodName, const QVariant &argument, ResourceBase::SchedulePriority priority = ResourceBase::Append); 164 165 /** 166 * Schedule a recursive move replay. 167 */ 168 void scheduleMoveReplay(const Collection &movedCollection, RecursiveMover *mover); 169 170 /** 171 Returns true if no tasks are running or in the queue. 172 */ 173 bool isEmpty(); 174 175 /** 176 Returns the current task. 177 */ 178 Task currentTask() const; 179 180 Task ¤tTask(); 181 182 /** 183 Sets the online state. 184 */ 185 void setOnline(bool state); 186 187 /** 188 Print debug output showing the state of the scheduler. 189 */ 190 void dump() const; 191 /** 192 Print debug output showing the state of the scheduler. 193 */ 194 QString dumpToString() const; 195 196 /** 197 Clear the state of the scheduler. Warning: this is intended to be 198 used purely in debugging scenarios, as it might cause loss of uncommitted 199 local changes. 200 */ 201 void clear(); 202 203 /** 204 Cancel everything the scheduler has still in queue. Keep the current task running though. 205 It can be seen as a less aggressive clear() used when the user requested the resource to 206 abort its activities. It properly cancel all the tasks in there. 207 */ 208 void cancelQueues(); 209 210 public Q_SLOTS: 211 /** 212 Schedules replaying changes. 213 */ 214 void scheduleChangeReplay(); 215 216 /** 217 The current task has been finished 218 */ 219 void taskDone(); 220 221 /** 222 Like taskDone(), but special case for ItemFetch task 223 */ 224 void itemFetchDone(const QString &msg); 225 226 /** 227 The current task can't be finished now and will be rescheduled later 228 */ 229 void deferTask(); 230 231 /** 232 Remove tasks that affect @p collection. 233 */ 234 void collectionRemoved(const Akonadi::Collection &collection); 235 236 Q_SIGNALS: 237 void executeFullSync(); 238 void executeCollectionAttributesSync(const Akonadi::Collection &col); 239 void executeCollectionSync(const Akonadi::Collection &col); 240 void executeCollectionTreeSync(); 241 void executeTagSync(); 242 void executeRelationSync(); 243 void executeItemFetch(const Akonadi::Item &item, const QSet<QByteArray> &parts); 244 void executeItemsFetch(const QVector<Akonadi::Item> &items, const QSet<QByteArray> &parts); 245 void executeResourceCollectionDeletion(); 246 void executeCacheInvalidation(const Akonadi::Collection &collection); 247 void executeChangeReplay(); 248 void executeRecursiveMoveReplay(RecursiveMover *mover); 249 void collectionTreeSyncComplete(); 250 void fullSyncComplete(); 251 void status(int status, const QString &message = QString()); 252 253 private Q_SLOTS: 254 void scheduleNext(); 255 void executeNext(); 256 257 private: 258 void signalTaskToTracker(const Task &task, const QByteArray &taskType, const QString &debugString = QString()); 259 260 // We have a number of task queues, by order of priority. 261 // * PrependTaskQueue is for deferring the current task 262 // * ChangeReplay must be first: 263 // change replays have to happen before we pull changes from the backend, otherwise 264 // we will overwrite our still unsaved local changes if the backend can't do 265 // incremental retrieval 266 // 267 // * then the stuff that is "immediately after change replay", like writeFile calls. 268 // * then tasks which the user is waiting for, like ItemFetch (clicking on a mail) or 269 // SyncCollectionAttributes (folder properties dialog in kmail) 270 // * then everything else (which includes the background email checking, which can take quite some time). 271 enum QueueType { 272 PrependTaskQueue, 273 ChangeReplayQueue, // one task at most 274 AfterChangeReplayQueue, // also one task at most, currently 275 UserActionQueue, 276 GenericTaskQueue, 277 NQueueCount 278 }; 279 using TaskList = QList<Task>; 280 281 static QueueType queueTypeForTaskType(TaskType type); 282 TaskList &queueForTaskType(TaskType type); 283 284 TaskList mTaskList[NQueueCount]; 285 286 Task mCurrentTask; 287 int mCurrentTasksQueue = -1; // queue mCurrentTask came from 288 bool mOnline = false; 289 }; 290 291 QDebug operator<<(QDebug, const ResourceScheduler::Task &task); 292 QTextStream &operator<<(QTextStream &, const ResourceScheduler::Task &task); 293 294 /// @endcond 295 296 } 297 298