File indexing completed on 2024-05-26 05:13:54
0001 /* 0002 SPDX-FileCopyrightText: 2007 Volker Krause <vkrause@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #pragma once 0008 0009 #include "agentbase.h" 0010 #include "collection.h" 0011 #include "item.h" 0012 #include "resourcebase.h" 0013 0014 #include <QDBusMessage> 0015 #include <QObject> 0016 0017 namespace Akonadi 0018 { 0019 class RecursiveMover; 0020 0021 /// @cond PRIVATE 0022 0023 /** 0024 @internal 0025 0026 Manages synchronization and fetch requests for a resource. 0027 0028 @todo Attach to the ResourceBase Monitor, 0029 */ 0030 class ResourceScheduler : public QObject 0031 { 0032 Q_OBJECT 0033 0034 public: 0035 // If you change this enum, keep s_taskTypes in sync in resourcescheduler.cpp 0036 enum TaskType { 0037 Invalid, 0038 SyncAll, 0039 SyncCollectionTree, 0040 SyncCollection, 0041 SyncCollectionAttributes, 0042 SyncTags, 0043 FetchItem, 0044 FetchItems, 0045 ChangeReplay, 0046 RecursiveMoveReplay, 0047 DeleteResourceCollection, 0048 InvalideCacheForCollection, 0049 SyncAllDone, 0050 SyncCollectionTreeDone, 0051 SyncRelations, 0052 Custom 0053 }; 0054 0055 class Task 0056 { 0057 static qint64 latestSerial; 0058 0059 public: 0060 Task() 0061 : serial(++latestSerial) 0062 , type(Invalid) 0063 { 0064 } 0065 qint64 serial; 0066 TaskType type; 0067 Collection collection; 0068 QList<Item> items; 0069 QSet<QByteArray> itemParts; 0070 QList<QDBusMessage> dbusMsgs; 0071 QObject *receiver = nullptr; 0072 QByteArray methodName; 0073 QVariant argument; 0074 0075 void sendDBusReplies(const QString &errorMsg); 0076 0077 bool operator==(const Task &other) const 0078 { 0079 return type == other.type && (collection == other.collection || (!collection.isValid() && !other.collection.isValid())) && items == other.items 0080 && itemParts == other.itemParts && receiver == other.receiver && methodName == other.methodName && argument == other.argument; 0081 } 0082 }; 0083 0084 explicit ResourceScheduler(QObject *parent = nullptr); 0085 0086 /** 0087 Schedules a full synchronization. 0088 */ 0089 void scheduleFullSync(); 0090 0091 /** 0092 Schedules a collection tree sync. 0093 */ 0094 void scheduleCollectionTreeSync(); 0095 0096 /** 0097 Schedules the synchronization of a single collection. 0098 @param col The collection to synchronize. 0099 */ 0100 void scheduleSync(const Collection &col); 0101 0102 /** 0103 Schedules synchronizing the attributes of a single collection. 0104 @param collection The collection to synchronize attributes from. 0105 */ 0106 void scheduleAttributesSync(const Collection &collection); 0107 0108 void scheduleTagSync(); 0109 void scheduleRelationSync(); 0110 0111 /** 0112 Schedules fetching of a single PIM item. 0113 0114 This task is only ever used if the resource still uses the old deprecated 0115 retrieveItem() (instead of retrieveItems(Item::List)) method. This task has 0116 a special meaning to the scheduler and instead of replying to the DBus message 0117 after the single @p item is retrieved, the items are accumulated until all 0118 tasks from the same messages are fetched. 0119 0120 @param items The items to fetch. 0121 @param parts List of names of the parts of the item to fetch. 0122 @param msg The associated D-Bus message. 0123 @param parentId ID of the original ItemsFetch task that this task was created from. 0124 We can use this ID to group the tasks together 0125 */ 0126 void scheduleItemFetch(const Item &item, const QSet<QByteArray> &parts, const QList<QDBusMessage> &msgs, const qint64 parentId); 0127 0128 /** 0129 Schedules batch-fetching of PIM items. 0130 @param items The items to fetch. 0131 @param parts List of names of the parts of the item to fetch. 0132 @param msg The associated D-Bus message. 0133 */ 0134 void scheduleItemsFetch(const Item::List &item, const QSet<QByteArray> &parts, const QDBusMessage &msg); 0135 0136 /** 0137 Schedules deletion of the resource collection. 0138 This method is used to implement the ResourceBase::clearCache() functionality. 0139 */ 0140 void scheduleResourceCollectionDeletion(); 0141 0142 /** 0143 * Schedule cache invalidation for @p collection. 0144 * @see ResourceBase::invalidateCache() 0145 */ 0146 void scheduleCacheInvalidation(const Collection &collection); 0147 0148 /** 0149 Insert synchronization completion marker into the task queue. 0150 */ 0151 void scheduleFullSyncCompletion(); 0152 0153 /** 0154 Insert collection tree synchronization completion marker into the task queue. 0155 */ 0156 void scheduleCollectionTreeSyncCompletion(); 0157 0158 /** 0159 Insert a custom task. 0160 @param methodName The method name, without signature, do not use the SLOT() macro 0161 */ 0162 void 0163 scheduleCustomTask(QObject *receiver, const char *methodName, const QVariant &argument, ResourceBase::SchedulePriority priority = ResourceBase::Append); 0164 0165 /** 0166 * Schedule a recursive move replay. 0167 */ 0168 void scheduleMoveReplay(const Collection &movedCollection, RecursiveMover *mover); 0169 0170 /** 0171 Returns true if no tasks are running or in the queue. 0172 */ 0173 bool isEmpty(); 0174 0175 /** 0176 Returns the current task. 0177 */ 0178 Task currentTask() const; 0179 0180 Task ¤tTask(); 0181 0182 /** 0183 Sets the online state. 0184 */ 0185 void setOnline(bool state); 0186 0187 /** 0188 Print debug output showing the state of the scheduler. 0189 */ 0190 void dump() const; 0191 /** 0192 Print debug output showing the state of the scheduler. 0193 */ 0194 QString dumpToString() const; 0195 0196 /** 0197 Clear the state of the scheduler. Warning: this is intended to be 0198 used purely in debugging scenarios, as it might cause loss of uncommitted 0199 local changes. 0200 */ 0201 void clear(); 0202 0203 /** 0204 Cancel everything the scheduler has still in queue. Keep the current task running though. 0205 It can be seen as a less aggressive clear() used when the user requested the resource to 0206 abort its activities. It properly cancel all the tasks in there. 0207 */ 0208 void cancelQueues(); 0209 0210 public Q_SLOTS: 0211 /** 0212 Schedules replaying changes. 0213 */ 0214 void scheduleChangeReplay(); 0215 0216 /** 0217 The current task has been finished 0218 */ 0219 void taskDone(); 0220 0221 /** 0222 Like taskDone(), but special case for ItemFetch task 0223 */ 0224 void itemFetchDone(const QString &msg); 0225 0226 /** 0227 The current task can't be finished now and will be rescheduled later 0228 */ 0229 void deferTask(); 0230 0231 /** 0232 Remove tasks that affect @p collection. 0233 */ 0234 void collectionRemoved(const Akonadi::Collection &collection); 0235 0236 Q_SIGNALS: 0237 void executeFullSync(); 0238 void executeCollectionAttributesSync(const Akonadi::Collection &col); 0239 void executeCollectionSync(const Akonadi::Collection &col); 0240 void executeCollectionTreeSync(); 0241 void executeTagSync(); 0242 void executeRelationSync(); 0243 void executeItemFetch(const Akonadi::Item &item, const QSet<QByteArray> &parts); 0244 void executeItemsFetch(const QList<Akonadi::Item> &items, const QSet<QByteArray> &parts); 0245 void executeResourceCollectionDeletion(); 0246 void executeCacheInvalidation(const Akonadi::Collection &collection); 0247 void executeChangeReplay(); 0248 void executeRecursiveMoveReplay(RecursiveMover *mover); 0249 void collectionTreeSyncComplete(); 0250 void fullSyncComplete(); 0251 void status(int status, const QString &message = QString()); 0252 0253 private Q_SLOTS: 0254 void scheduleNext(); 0255 void executeNext(); 0256 0257 private: 0258 void signalTaskToTracker(const Task &task, const QByteArray &taskType, const QString &debugString = QString()); 0259 0260 // We have a number of task queues, by order of priority. 0261 // * PrependTaskQueue is for deferring the current task 0262 // * ChangeReplay must be first: 0263 // change replays have to happen before we pull changes from the backend, otherwise 0264 // we will overwrite our still unsaved local changes if the backend can't do 0265 // incremental retrieval 0266 // 0267 // * then the stuff that is "immediately after change replay", like writeFile calls. 0268 // * then tasks which the user is waiting for, like ItemFetch (clicking on a mail) or 0269 // SyncCollectionAttributes (folder properties dialog in kmail) 0270 // * then everything else (which includes the background email checking, which can take quite some time). 0271 enum QueueType { 0272 PrependTaskQueue, 0273 ChangeReplayQueue, // one task at most 0274 AfterChangeReplayQueue, // also one task at most, currently 0275 UserActionQueue, 0276 GenericTaskQueue, 0277 NQueueCount 0278 }; 0279 using TaskList = QList<Task>; 0280 0281 static QueueType queueTypeForTaskType(TaskType type); 0282 TaskList &queueForTaskType(TaskType type); 0283 0284 TaskList mTaskList[NQueueCount]; 0285 0286 Task mCurrentTask; 0287 int mCurrentTasksQueue = -1; // queue mCurrentTask came from 0288 bool mOnline = false; 0289 }; 0290 0291 QDebug operator<<(QDebug, const ResourceScheduler::Task &task); 0292 QTextStream &operator<<(QTextStream &, const ResourceScheduler::Task &task); 0293 0294 /// @endcond 0295 0296 }