/* Copyright (c) 2007 Volker Krause This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef AKONADI_RESOURCESCHEDULER_P_H #define AKONADI_RESOURCESCHEDULER_P_H #include #include #include #include #include #include #include namespace Akonadi { class RecursiveMover; //@cond PRIVATE /** @internal Manages synchronization and fetch requests for a resource. @todo Attach to the ResourceBase Monitor, */ class ResourceScheduler : public QObject { Q_OBJECT public: // If you change this enum, keep s_taskTypes in sync in resourcescheduler.cpp enum TaskType { Invalid, SyncAll, SyncCollectionTree, SyncCollection, SyncCollectionAttributes, FetchItem, ChangeReplay, RecursiveMoveReplay, DeleteResourceCollection, InvalideCacheForCollection, SyncAllDone, SyncCollectionTreeDone, Custom }; class Task { static qint64 latestSerial; public: Task() : serial( ++latestSerial ), type( Invalid ), receiver( 0 ) {} qint64 serial; TaskType type; Collection collection; Item item; QSet itemParts; QList dbusMsgs; QObject *receiver; QByteArray methodName; QVariant argument; void sendDBusReplies( const QString &errorMsg ); bool operator==( const Task &other ) const { return type == other.type && (collection == other.collection || (!collection.isValid() && !other.collection.isValid())) && (item == other.item || (!item.isValid() && !other.item.isValid())) && itemParts == other.itemParts && receiver == other.receiver && methodName == other.methodName && argument == other.argument; } }; ResourceScheduler( QObject *parent = 0 ); /** Schedules a full synchronization. */ void scheduleFullSync(); /** Schedules a collection tree sync. */ void scheduleCollectionTreeSync(); /** Schedules the synchronization of a single collection. @param col The collection to synchronize. */ void scheduleSync( const Collection &col ); /** Schedules synchronizing the attributes of a single collection. @param collection The collection to synchronize attributes from. */ void scheduleAttributesSync( const Collection &collection ); /** Schedules fetching of a single PIM item. @param item The item to fetch. @param parts List of names of the parts of the item to fetch. @param msg The associated D-Bus message. */ void scheduleItemFetch( const Item &item, const QSet &parts, const QDBusMessage &msg ); /** Schedules deletion of the resource collection. This method is used to implement the ResourceBase::clearCache() functionality. */ void scheduleResourceCollectionDeletion(); /** * Schedule cache invalidation for @p collection. * @see ResourceBase::invalidateCache() */ void scheduleCacheInvalidation( const Collection &collection ); /** Insert synchronization completion marker into the task queue. */ void scheduleFullSyncCompletion(); /** Insert collection tree synchronization completion marker into the task queue. */ void scheduleCollectionTreeSyncCompletion(); /** Insert a custom task. @param methodName The method name, without signature, do not use the SLOT() macro */ void scheduleCustomTask( QObject *receiver, const char *methodName, const QVariant &argument, ResourceBase::SchedulePriority priority = ResourceBase::Append ); /** * Schedule a recursive move replay. */ void scheduleMoveReplay( const Collection &movedCollection, RecursiveMover *mover ); /** Returns true if no tasks are running or in the queue. */ bool isEmpty(); /** Returns the current task. */ Task currentTask() const; /** Sets the online state. */ void setOnline( bool state ); /** Print debug output showing the state of the scheduler. */ void dump(); /** Print debug output showing the state of the scheduler. */ QString dumpToString() const; /** Clear the state of the scheduler. Warning: this is intended to be used purely in debugging scenarios, as it might cause loss of uncommitted local changes. */ void clear(); /** Cancel everything the scheduler has still in queue. Keep the current task running though. It can be seen as a less aggressive clear() used when the user requested the resource to abort its activities. It properly cancel all the tasks in there. */ void cancelQueues(); public Q_SLOTS: /** Schedules replaying changes. */ void scheduleChangeReplay(); /** The current task has been finished */ void taskDone(); /** The current task can't be finished now and will be rescheduled later */ void deferTask(); /** Remove tasks that affect @p collection. */ void collectionRemoved( const Akonadi::Collection &collection ); Q_SIGNALS: void executeFullSync(); void executeCollectionAttributesSync( const Akonadi::Collection &col ); void executeCollectionSync( const Akonadi::Collection &col ); void executeCollectionTreeSync(); void executeItemFetch( const Akonadi::Item &item, const QSet &parts ); void executeResourceCollectionDeletion(); void executeCacheInvalidation( const Akonadi::Collection &collection ); void executeChangeReplay(); void executeRecursiveMoveReplay( RecursiveMover *mover ); void collectionTreeSyncComplete(); void fullSyncComplete(); void status( int status, const QString &message = QString() ); private slots: void scheduleNext(); void executeNext(); private: void signalTaskToTracker( const Task &task, const QByteArray &taskType ); // We have a number of task queues, by order of priority. // * ChangeReplay must be first: // change replays have to happen before we pull changes from the backend, otherwise // we will overwrite our still unsaved local changes if the backend can't do // incremental retrieval // // * then the stuff that is "immediately after change replay", like writeFile calls. // * then ItemFetch tasks, because they are made by blocking DBus calls // * then everything else. enum QueueType { PrependTaskQueue, ChangeReplayQueue, // one task at most AfterChangeReplayQueue, // also one task at most, currently ItemFetchQueue, GenericTaskQueue, NQueueCount }; typedef QList TaskList; static QueueType queueTypeForTaskType( TaskType type ); TaskList& queueForTaskType( TaskType type ); TaskList mTaskList[ NQueueCount ]; Task mCurrentTask; int mCurrentTasksQueue; // queue mCurrentTask came from bool mOnline; }; QDebug operator<<( QDebug, const ResourceScheduler::Task& task ); QTextStream& operator<<( QTextStream&, const ResourceScheduler::Task& task ); //@endcond } #endif