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