21 #include "resourcebase.h"
22 #include "agentbase_p.h"
24 #include "resourceadaptor.h"
25 #include "collectiondeletejob.h"
26 #include "collectionsync_p.h"
27 #include "dbusconnectionpool.h"
29 #include "kdepimlibs-version.h"
30 #include "resourcescheduler_p.h"
31 #include "tracerinterface.h"
32 #include "xdgbasedirs_p.h"
34 #include "changerecorder.h"
35 #include "collectionfetchjob.h"
36 #include "collectionfetchscope.h"
37 #include "collectionmodifyjob.h"
38 #include "invalidatecachejob_p.h"
39 #include "itemfetchjob.h"
40 #include "itemfetchscope.h"
41 #include "itemmodifyjob.h"
42 #include "itemmodifyjob_p.h"
44 #include "resourceselectjob_p.h"
45 #include "monitor_p.h"
46 #include "servermanager_p.h"
47 #include "recursivemover_p.h"
49 #include <kaboutdata.h>
50 #include <kcmdlineargs.h>
52 #include <klocalizedstring.h>
55 #include <QtCore/QDebug>
56 #include <QtCore/QDir>
57 #include <QtCore/QHash>
58 #include <QtCore/QSettings>
59 #include <QtCore/QTimer>
60 #include <QApplication>
61 #include <QtDBus/QtDBus>
67 using namespace Akonadi;
72 Q_CLASSINFO(
"D-Bus Interface",
"org.kde.dfaure" )
79 mItemSyncFetchScope( 0 ),
80 mItemTransactionMode(
ItemSync::SingleTransaction ),
81 mCollectionSyncer( 0 ),
82 mHierarchicalRid( false ),
83 mUnemittedProgress( 0 ),
84 mAutomaticProgressReporting( true )
86 Internal::setClientType( Internal::Resource );
87 mStatusMessage = defaultReadyMessage();
88 mProgressEmissionCompressor.setInterval( 1000 );
89 mProgressEmissionCompressor.setSingleShot(
true );
92 ~ResourceBasePrivate()
94 delete mItemSyncFetchScope;
102 if ( !DBusConnectionPool::threadConnection().registerService( serviceId ) ) {
103 QString reason = DBusConnectionPool::threadConnection().lastError().message();
104 if ( reason.isEmpty() ) {
105 reason = QString::fromLatin1(
"this service is probably running already." );
107 kError() <<
"Unable to register service" << serviceId <<
"at D-Bus:" << reason;
109 if ( QThread::currentThread() == QCoreApplication::instance()->thread() )
110 QCoreApplication::instance()->exit(1);
113 AgentBasePrivate::delayedInit();
117 virtual void changeProcessed()
119 if ( m_recursiveMover ) {
120 m_recursiveMover->changeProcessed();
121 QTimer::singleShot( 0, m_recursiveMover, SLOT(replayNext()) );
125 mChangeRecorder->changeProcessed();
126 if ( !mChangeRecorder->isEmpty() )
127 scheduler->scheduleChangeReplay();
128 scheduler->taskDone();
131 void slotAbortRequested();
133 void slotDeliveryDone( KJob* job );
134 void slotCollectionSyncDone( KJob *job );
135 void slotLocalListDone( KJob *job );
136 void slotSynchronizeCollection(
const Collection &col );
137 void slotCollectionListDone( KJob *job );
138 void slotSynchronizeCollectionAttributes(
const Collection &col );
139 void slotCollectionListForAttributesDone( KJob *job );
140 void slotCollectionAttributesSyncDone( KJob *job );
142 void slotItemSyncDone( KJob *job );
144 void slotPercent( KJob* job,
unsigned long percent );
145 void slotDelayedEmitProgress();
146 void slotDeleteResourceCollection();
147 void slotDeleteResourceCollectionDone( KJob *job );
148 void slotCollectionDeletionDone( KJob *job );
152 void slotPrepareItemRetrieval(
const Akonadi::Item &item );
153 void slotPrepareItemRetrievalResult( KJob* job );
155 void changeCommittedResult( KJob* job );
158 void slotRecursiveMoveReplayResult( KJob *job );
160 void slotSessionReconnected()
167 void createItemSyncInstanceIfMissing()
170 Q_ASSERT_X( scheduler->currentTask().type == ResourceScheduler::SyncCollection,
171 "createItemSyncInstance",
"Calling items retrieval methods although no item retrieval is in progress" );
172 if ( !mItemSyncer ) {
173 mItemSyncer =
new ItemSync( q->currentCollection() );
175 if ( mItemSyncFetchScope )
176 mItemSyncer->setFetchScope( *mItemSyncFetchScope );
177 mItemSyncer->setProperty(
"collection", QVariant::fromValue( q->currentCollection() ) );
178 connect( mItemSyncer, SIGNAL(percent(KJob*,ulong)), q, SLOT(slotPercent(KJob*,ulong)) );
179 connect( mItemSyncer, SIGNAL(result(KJob*)), q, SLOT(slotItemSyncDone(KJob*)) );
181 Q_ASSERT( mItemSyncer );
186 Q_SCRIPTABLE QString dumpNotificationListToString()
const
188 return mChangeRecorder->dumpNotificationListToString();
192 Q_SCRIPTABLE QString dumpToString()
const
196 QMetaObject::invokeMethod( const_cast<ResourceBase *>(q),
"dumpResourceToString", Qt::DirectConnection, Q_RETURN_ARG(QString, retVal) );
197 return scheduler->dumpToString() + QLatin1Char(
'\n') + retVal;
200 Q_SCRIPTABLE
void dump()
205 Q_SCRIPTABLE
void clear()
210 Q_SCRIPTABLE
void dumpMemoryInfo()
const
215 QTextStream stream( stdout );
216 stream << dumpMemoryInfoToString();
219 Q_SCRIPTABLE QString dumpMemoryInfoToString()
const
223 #if defined __GLIBC__
226 QTextStream stream( &str );
227 stream <<
"Total non-mmapped bytes (arena): " << mi.arena <<
'\n'
228 <<
"# of free chunks (ordblks): " << mi.ordblks <<
'\n'
229 <<
"# of free fastbin blocks (smblks>: " << mi.smblks <<
'\n'
230 <<
"# of mapped regions (hblks): " << mi.hblks <<
'\n'
231 <<
"Bytes in mapped regions (hblkhd): " << mi.hblkhd <<
'\n'
232 <<
"Max. total allocated space (usmblks): " << mi.usmblks <<
'\n'
233 <<
"Free bytes held in fastbins (fsmblks):" << mi.fsmblks <<
'\n'
234 <<
"Total allocated space (uordblks): " << mi.uordblks <<
'\n'
235 <<
"Total free space (fordblks): " << mi.fordblks <<
'\n'
236 <<
"Topmost releasable block (keepcost): " << mi.keepcost <<
'\n';
238 str = QLatin1String(
"mallinfo() not supported" );
251 if ( collection.
remoteId().isEmpty() ) {
255 AgentBasePrivate::itemAdded( item, collection );
258 void itemChanged(
const Akonadi::Item& item,
const QSet< QByteArray >& partIdentifiers)
260 if ( item.remoteId().isEmpty() ) {
264 AgentBasePrivate::itemChanged( item, partIdentifiers );
267 void itemsFlagsChanged(
const Item::List& items,
const QSet< QByteArray >& addedFlags,
268 const QSet< QByteArray >& removedFlags)
270 if (addedFlags.isEmpty() && removedFlags.isEmpty() ) {
275 Item::List validItems;
276 foreach (
const Akonadi::Item &item, items ) {
277 if ( !item.remoteId().isEmpty() ) {
281 if ( validItems.isEmpty() ) {
286 AgentBasePrivate::itemsFlagsChanged( validItems, addedFlags, removedFlags );
292 if ( item.remoteId().isEmpty() || destination.
remoteId().isEmpty() || destination == source ) {
296 AgentBasePrivate::itemMoved( item, source, destination );
299 void itemsMoved(
const Item::List& items,
const Collection& source,
const Collection& destination)
301 if ( destination.
remoteId().isEmpty() || destination == source ) {
306 Item::List validItems;
307 foreach (
const Akonadi::Item &item, items ) {
308 if ( !item.remoteId().isEmpty() ) {
312 if ( validItems.isEmpty() ) {
317 AgentBasePrivate::itemsMoved( validItems, source, destination );
320 void itemRemoved(
const Akonadi::Item& item)
322 if ( item.remoteId().isEmpty() ) {
326 AgentBasePrivate::itemRemoved( item );
329 void itemsRemoved(
const Item::List& items)
331 Item::List validItems;
332 foreach (
const Akonadi::Item &item, items ) {
333 if ( !item.remoteId().isEmpty() ) {
337 if ( validItems.isEmpty() ) {
342 AgentBasePrivate::itemsRemoved( validItems );
347 if ( parent.
remoteId().isEmpty() ) {
351 AgentBasePrivate::collectionAdded( collection, parent );
356 if ( collection.
remoteId().isEmpty() ) {
360 AgentBasePrivate::collectionChanged( collection );
363 void collectionChanged(
const Akonadi::Collection& collection,
const QSet< QByteArray >& partIdentifiers)
365 if ( collection.
remoteId().isEmpty() ) {
369 AgentBasePrivate::collectionChanged( collection, partIdentifiers );
375 if ( destination.
remoteId().isEmpty() || source == destination ) {
382 if ( source.
resource() == q_ptr->identifier() ) {
383 AgentBasePrivate::collectionRemoved( collection );
384 }
else if ( destination.
resource() == q_ptr->identifier() ) {
385 scheduler->taskDone();
388 scheduler->scheduleMoveReplay( collection, mover );
394 if ( collection.
remoteId().isEmpty() ) {
400 AgentBasePrivate::collectionMoved( collection, source, destination );
405 if ( collection.
remoteId().isEmpty() ) {
409 AgentBasePrivate::collectionRemoved( collection );
416 ResourceScheduler *scheduler;
421 bool mHierarchicalRid;
422 QTimer mProgressEmissionCompressor;
423 int mUnemittedProgress;
424 QMap<Akonadi::Collection::Id, QVariantMap> mUnemittedAdvancedStatus;
425 bool mAutomaticProgressReporting;
426 QPointer<RecursiveMover> m_recursiveMover;
430 :
AgentBase( new ResourceBasePrivate( this ), id )
434 new Akonadi__ResourceAdaptor(
this );
436 d->scheduler =
new ResourceScheduler(
this );
438 d->mChangeRecorder->setChangeRecordingEnabled(
true );
439 d->mChangeRecorder->setCollectionMoveTranslationEnabled(
false );
440 connect( d->mChangeRecorder, SIGNAL(changesAdded()),
441 d->scheduler, SLOT(scheduleChangeReplay()) );
443 d->mChangeRecorder->setResourceMonitored( d->mId.toLatin1() );
444 d->mChangeRecorder->fetchCollection(
true );
446 connect( d->scheduler, SIGNAL(executeFullSync()),
448 connect( d->scheduler, SIGNAL(executeCollectionTreeSync()),
454 connect( d->scheduler, SIGNAL(executeItemFetch(Akonadi::Item,QSet<QByteArray>)),
455 SLOT(slotPrepareItemRetrieval(Akonadi::Item)) );
456 connect( d->scheduler, SIGNAL(executeResourceCollectionDeletion()),
457 SLOT(slotDeleteResourceCollection()) );
460 connect( d->scheduler, SIGNAL(
status(
int,QString)),
461 SIGNAL(
status(
int,QString)) );
462 connect( d->scheduler, SIGNAL(executeChangeReplay()),
463 d->mChangeRecorder, SLOT(replayNext()) );
464 connect( d->scheduler, SIGNAL(executeRecursiveMoveReplay(
RecursiveMover*)),
466 connect( d->scheduler, SIGNAL(fullSyncComplete()), SIGNAL(
synchronized()) );
468 connect( d->mChangeRecorder, SIGNAL(nothingToReplay()), d->scheduler, SLOT(
taskDone()) );
471 connect(
this, SIGNAL(
abortRequested()),
this, SLOT(slotAbortRequested()) );
472 connect(
this, SIGNAL(
synchronized()), d->scheduler, SLOT(
taskDone()) );
477 connect( &d->mProgressEmissionCompressor, SIGNAL(timeout()),
478 this, SLOT(slotDelayedEmitProgress()) );
480 d->scheduler->setOnline( d->mOnline );
481 if ( !d->mChangeRecorder->isEmpty() )
482 d->scheduler->scheduleChangeReplay();
484 DBusConnectionPool::threadConnection().registerObject( QLatin1String(
"/Debug" ), d, QDBusConnection::ExportScriptableSlots );
488 connect( d->mChangeRecorder->session(), SIGNAL(reconnected()), SLOT(slotSessionReconnected()) );
497 d_func()->scheduler->scheduleFullSync();
510 QString ResourceBase::parseArguments(
int argc,
char **argv )
514 kDebug() <<
"Not enough arguments passed...";
518 for (
int i = 1; i < argc - 1; ++i ) {
519 if ( QLatin1String( argv[ i ] ) == QLatin1String(
"--identifier" ) )
520 identifier = QLatin1String( argv[ i + 1 ] );
523 if ( identifier.isEmpty() ) {
524 kDebug() <<
"Identifier argument missing";
528 const QFileInfo fi( QString::fromLocal8Bit( argv[0] ) );
530 const QByteArray catalog = fi.baseName().toLatin1();
533 ki18nc(
"@title application name",
"Akonadi Resource" ), KDEPIMLIBS_VERSION,
534 ki18nc(
"@title application description",
"Akonadi Resource" ) );
536 KCmdLineOptions options;
537 options.add(
"identifier <argument>",
538 ki18nc(
"@label commandline option",
"Resource identifier" ) );
539 KCmdLineArgs::addCmdLineOptions( options );
546 QApplication::setQuitOnLastWindowClosed(
false );
547 KGlobal::locale()->insertCatalog( QLatin1String(
"libakonadi" ) );
548 int rv = kapp->exec();
553 void ResourceBasePrivate::slotAbortRequested()
557 scheduler->cancelQueues();
558 QMetaObject::invokeMethod( q,
"abortActivity" );
564 Q_ASSERT( d->scheduler->currentTask().type == ResourceScheduler::FetchItem );
565 if ( !item.isValid() ) {
566 d->scheduler->currentTask().sendDBusReplies( i18nc(
"@info",
"Invalid item retrieved" ) );
567 d->scheduler->taskDone();
572 QSet<QByteArray> requestedParts = d->scheduler->currentTask().itemParts;
573 foreach (
const QByteArray &part, requestedParts ) {
574 if ( !item.loadedPayloadParts().contains( part ) ) {
575 kWarning() <<
"Item does not provide part" << part;
582 connect( job, SIGNAL(result(KJob*)), SLOT(slotDeliveryDone(KJob*)) );
585 void ResourceBasePrivate::slotDeliveryDone(KJob * job)
588 Q_ASSERT( scheduler->currentTask().type == ResourceScheduler::FetchItem );
589 if ( job->error() ) {
590 emit q->error( i18nc(
"@info",
"Error while creating item: %1", job->errorString() ) );
592 scheduler->currentTask().sendDBusReplies( job->error() ? job->errorString() : QString() );
593 scheduler->taskDone();
599 Q_ASSERT( d->scheduler->currentTask().type == ResourceScheduler::SyncCollectionAttributes );
602 d->scheduler->taskDone();
607 connect( job, SIGNAL(result(KJob*)), SLOT(slotCollectionAttributesSyncDone(KJob*)) );
610 void ResourceBasePrivate::slotCollectionAttributesSyncDone(KJob * job)
613 Q_ASSERT( scheduler->currentTask().type == ResourceScheduler::SyncCollectionAttributes );
614 if ( job->error() ) {
615 emit q->error( i18nc(
"@info",
"Error while updating collection: %1", job->errorString() ) );
617 emit q->attributesSynchronized( scheduler->currentTask().collection.id() );
618 scheduler->taskDone();
621 void ResourceBasePrivate::slotDeleteResourceCollection()
627 connect( job, SIGNAL(result(KJob*)), q, SLOT(slotDeleteResourceCollectionDone(KJob*)) );
630 void ResourceBasePrivate::slotDeleteResourceCollectionDone( KJob *job )
633 if ( job->error() ) {
634 emit q->error( job->errorString() );
635 scheduler->taskDone();
641 connect( job, SIGNAL(result(KJob*)), q, SLOT(slotCollectionDeletionDone(KJob*)) );
644 scheduler->taskDone();
649 void ResourceBasePrivate::slotCollectionDeletionDone( KJob *job )
652 if ( job->error() ) {
653 emit q->error( job->errorString() );
656 scheduler->taskDone();
663 connect( job, SIGNAL(result(KJob*)), scheduler, SLOT(taskDone()) );
674 job->d_func()->setClean();
677 connect( job, SIGNAL(finished(KJob*)),
this, SLOT(changeCommittedResult(KJob*)) );
683 connect( job, SIGNAL(result(KJob*)), SLOT(changeCommittedResult(KJob*)) );
686 void ResourceBasePrivate::changeCommittedResult( KJob *job )
689 if ( qobject_cast<CollectionModifyJob*>( job ) ) {
690 if ( job->error() ) {
691 emit q->error( i18nc(
"@info",
"Updating local collection failed: %1.", job->errorText() ) );
693 mChangeRecorder->d_ptr->invalidateCache( static_cast<CollectionModifyJob*>( job )->collection() );
702 bool ResourceBase::requestItemDelivery( qint64 uid,
const QString &remoteId,
703 const QString &mimeType,
const QStringList &parts )
705 return requestItemDeliveryV2( uid, remoteId, mimeType, parts ).isEmpty();
708 QString ResourceBase::requestItemDeliveryV2(qint64 uid,
const QString &remoteId,
const QString &mimeType,
const QStringList &_parts)
712 const QString errorMsg = i18nc(
"@info",
"Cannot fetch item in offline mode." );
713 emit
error( errorMsg );
717 setDelayedReply(
true );
720 item.setMimeType( mimeType );
721 item.setRemoteId( remoteId );
723 QSet<QByteArray> parts;
724 Q_FOREACH(
const QString &str, _parts )
725 parts.insert( str.toLatin1() );
727 d->scheduler->scheduleItemFetch( item, parts, message() );
736 Q_ASSERT_X( d->scheduler->currentTask().type == ResourceScheduler::SyncCollectionTree ||
737 d->scheduler->currentTask().type == ResourceScheduler::SyncAll,
738 "ResourceBase::collectionsRetrieved()",
739 "Calling collectionsRetrieved() although no collection retrieval is in progress" );
740 if ( !d->mCollectionSyncer ) {
742 d->mCollectionSyncer->setHierarchicalRemoteIds( d->mHierarchicalRid );
743 connect( d->mCollectionSyncer, SIGNAL(
percent(KJob*,ulong)), SLOT(slotPercent(KJob*,ulong)) );
744 connect( d->mCollectionSyncer, SIGNAL(result(KJob*)), SLOT(slotCollectionSyncDone(KJob*)) );
746 d->mCollectionSyncer->setRemoteCollections( collections );
753 Q_ASSERT_X( d->scheduler->currentTask().type == ResourceScheduler::SyncCollectionTree ||
754 d->scheduler->currentTask().type == ResourceScheduler::SyncAll,
755 "ResourceBase::collectionsRetrievedIncremental()",
756 "Calling collectionsRetrievedIncremental() although no collection retrieval is in progress" );
757 if ( !d->mCollectionSyncer ) {
759 d->mCollectionSyncer->setHierarchicalRemoteIds( d->mHierarchicalRid );
760 connect( d->mCollectionSyncer, SIGNAL(
percent(KJob*,ulong)), SLOT(slotPercent(KJob*,ulong)) );
761 connect( d->mCollectionSyncer, SIGNAL(result(KJob*)), SLOT(slotCollectionSyncDone(KJob*)) );
763 d->mCollectionSyncer->setRemoteCollections( changedCollections, removedCollections );
769 Q_ASSERT_X( d->scheduler->currentTask().type == ResourceScheduler::SyncCollectionTree ||
770 d->scheduler->currentTask().type == ResourceScheduler::SyncAll,
771 "ResourceBase::setCollectionStreamingEnabled()",
772 "Calling setCollectionStreamingEnabled() although no collection retrieval is in progress" );
773 if ( !d->mCollectionSyncer ) {
775 d->mCollectionSyncer->setHierarchicalRemoteIds( d->mHierarchicalRid );
776 connect( d->mCollectionSyncer, SIGNAL(
percent(KJob*,ulong)), SLOT(slotPercent(KJob*,ulong)) );
777 connect( d->mCollectionSyncer, SIGNAL(result(KJob*)), SLOT(slotCollectionSyncDone(KJob*)) );
779 d->mCollectionSyncer->setStreamingEnabled( enable );
785 Q_ASSERT_X( d->scheduler->currentTask().type == ResourceScheduler::SyncCollectionTree ||
786 d->scheduler->currentTask().type == ResourceScheduler::SyncAll,
787 "ResourceBase::collectionsRetrievalDone()",
788 "Calling collectionsRetrievalDone() although no collection retrieval is in progress" );
790 if ( d->mCollectionSyncer ) {
791 d->mCollectionSyncer->retrievalDone();
796 d->scheduler->taskDone();
800 void ResourceBasePrivate::slotCollectionSyncDone( KJob * job )
803 mCollectionSyncer = 0;
804 if ( job->error() ) {
806 emit q->error( job->errorString() );
808 if ( scheduler->currentTask().type == ResourceScheduler::SyncAll ) {
810 list->
setFetchScope( q->changeRecorder()->collectionFetchScope() );
812 q->connect( list, SIGNAL(result(KJob*)), q, SLOT(slotLocalListDone(KJob*)) );
814 }
else if ( scheduler->currentTask().type == ResourceScheduler::SyncCollectionTree ) {
815 scheduler->scheduleCollectionTreeSyncCompletion();
818 scheduler->taskDone();
821 void ResourceBasePrivate::slotLocalListDone( KJob * job )
824 if ( job->error() ) {
825 emit q->error( job->errorString() );
829 scheduler->scheduleSync( col );
831 scheduler->scheduleFullSyncCompletion();
833 scheduler->taskDone();
836 void ResourceBasePrivate::slotSynchronizeCollection(
const Collection &col )
844 if ( !contentTypes.isEmpty() || col.
isVirtual() ) {
845 if ( mAutomaticProgressReporting ) {
851 scheduler->taskDone();
854 void ResourceBasePrivate::slotSynchronizeCollectionAttributes(
const Collection &col )
857 QMetaObject::invokeMethod( q,
"retrieveCollectionAttributes", Q_ARG(
Akonadi::Collection, col ) );
860 void ResourceBasePrivate::slotPrepareItemRetrieval(
const Akonadi::Item &item )
868 const QSet<QByteArray> attributes = q->changeRecorder()->itemFetchScope().attributes();
869 foreach (
const QByteArray &attribute, attributes )
872 q->connect( fetch, SIGNAL(result(KJob*)), SLOT(slotPrepareItemRetrievalResult(KJob*)) );
875 void ResourceBasePrivate::slotPrepareItemRetrievalResult( KJob* job )
878 Q_ASSERT_X( scheduler->currentTask().type == ResourceScheduler::FetchItem,
879 "ResourceBasePrivate::slotPrepareItemRetrievalResult()",
880 "Preparing item retrieval although no item retrieval is in progress" );
881 if ( job->error() ) {
882 q->cancelTask( job->errorText() );
886 if ( fetch->
items().count() != 1 ) {
887 q->cancelTask( i18n(
"The requested item no longer exists" ) );
890 const Item item = fetch->
items().first();
891 const QSet<QByteArray> parts = scheduler->currentTask().itemParts;
892 if ( !q->retrieveItem( item, parts ) )
896 void ResourceBasePrivate::slotRecursiveMoveReplay(
RecursiveMover *mover )
900 Q_ASSERT( !m_recursiveMover );
901 m_recursiveMover = mover;
902 connect( mover, SIGNAL(result(KJob*)), q, SLOT(slotRecursiveMoveReplayResult(KJob*)) );
906 void ResourceBasePrivate::slotRecursiveMoveReplayResult( KJob *job )
909 m_recursiveMover = 0;
911 if ( job->error() ) {
923 if ( d->mItemSyncer ) {
924 d->mItemSyncer->deliveryDone();
928 d->scheduler->taskDone();
935 d->scheduler->scheduleResourceCollectionDeletion();
941 d->scheduler->scheduleCacheInvalidation( collection );
947 Q_ASSERT_X( d->scheduler->currentTask().type == ResourceScheduler::SyncCollection ,
948 "ResourceBase::currentCollection()",
949 "Trying to access current collection although no item retrieval is in progress" );
950 return d->currentCollection;
956 Q_ASSERT_X( d->scheduler->currentTask().type == ResourceScheduler::FetchItem ,
957 "ResourceBase::currentItem()",
958 "Trying to access current item although no item retrieval is in progress" );
959 return d->scheduler->currentTask().item;
964 d_func()->scheduler->scheduleCollectionTreeSync();
970 switch ( d->scheduler->currentTask().type ) {
971 case ResourceScheduler::FetchItem:
974 case ResourceScheduler::ChangeReplay:
975 d->changeProcessed();
977 case ResourceScheduler::SyncCollectionTree:
978 case ResourceScheduler::SyncAll:
979 if ( d->mCollectionSyncer )
980 d->mCollectionSyncer->rollback();
982 d->scheduler->taskDone();
984 case ResourceScheduler::SyncCollection:
985 if ( d->mItemSyncer ) {
986 d->mItemSyncer->rollback();
988 d->scheduler->taskDone();
992 d->scheduler->taskDone();
1006 d->scheduler->deferTask();
1011 d_func()->scheduler->setOnline( state );
1024 job->setProperty(
"recursive", recursive );
1025 connect( job, SIGNAL(result(KJob*)), SLOT(slotCollectionListDone(KJob*)) );
1028 void ResourceBasePrivate::slotCollectionListDone( KJob *job )
1030 if ( !job->error() ) {
1032 if ( !list.isEmpty() ) {
1033 if ( job->property(
"recursive" ).toBool() ) {
1034 Q_FOREACH (
const Collection &collection, list ) {
1035 scheduler->scheduleSync( collection );
1038 scheduler->scheduleSync( list.first() );
1050 connect( job, SIGNAL(result(KJob*)), SLOT(slotCollectionListForAttributesDone(KJob*)) );
1053 void ResourceBasePrivate::slotCollectionListForAttributesDone( KJob *job )
1055 if ( !job->error() ) {
1057 if ( !list.isEmpty() ) {
1059 scheduler->scheduleAttributesSync( col );
1070 if ( d->mItemSyncer ) {
1071 d->mItemSyncer->setTotalItems( amount );
1078 d->createItemSyncInstanceIfMissing();
1079 if ( d->mItemSyncer ) {
1080 d->mItemSyncer->setStreamingEnabled( enable );
1087 d->createItemSyncInstanceIfMissing();
1088 if ( d->mItemSyncer ) {
1089 d->mItemSyncer->setFullSyncItems( items );
1094 const Item::List &removedItems )
1097 d->createItemSyncInstanceIfMissing();
1098 if ( d->mItemSyncer ) {
1099 d->mItemSyncer->setIncrementalSyncItems( changedItems, removedItems );
1103 void ResourceBasePrivate::slotItemSyncDone( KJob *job )
1108 emit q->error( job->errorString() );
1110 scheduler->taskDone();
1114 void ResourceBasePrivate::slotDelayedEmitProgress()
1117 if ( mAutomaticProgressReporting ) {
1118 emit q->percent( mUnemittedProgress );
1120 Q_FOREACH(
const QVariantMap &statusMap, mUnemittedAdvancedStatus ) {
1121 emit q->advancedStatus( statusMap );
1124 mUnemittedProgress = 0;
1125 mUnemittedAdvancedStatus.clear();
1128 void ResourceBasePrivate::slotPercent( KJob *job,
unsigned long percent )
1134 QVariantMap statusMap;
1135 statusMap.insert( QLatin1String(
"key" ), QString::fromLatin1(
"collectionSyncProgress" ) );
1136 statusMap.insert( QLatin1String(
"collectionId" ), collection.
id() );
1137 statusMap.insert( QLatin1String(
"percent" ), static_cast<unsigned int>( percent ) );
1139 mUnemittedAdvancedStatus[collection.
id()] = statusMap;
1142 if ( percent == 100 ) {
1143 mProgressEmissionCompressor.stop();
1144 slotDelayedEmitProgress();
1145 }
else if ( !mProgressEmissionCompressor.isActive() ) {
1146 mProgressEmissionCompressor.start();
1153 d->mHierarchicalRid = enable;
1159 d->scheduler->scheduleCustomTask( receiver, method, argument, priority );
1165 d->scheduler->taskDone();
1181 d->mItemTransactionMode = mode;
1187 if ( !d->mItemSyncFetchScope )
1189 *(d->mItemSyncFetchScope) = fetchScope;
1195 d->mAutomaticProgressReporting = enabled;
1201 return d->dumpNotificationListToString();
1207 return d->dumpToString();
1213 return d->dumpMemoryInfo();
1219 return d->dumpMemoryInfoToString();
1222 #include "resourcebase.moc"
1223 #include "moc_resourcebase.cpp"
Job that modifies a collection in the Akonadi storage.
Helper class for expanding inter-resource collection moves inside ResourceBase.
void fetchAttribute(const QByteArray &type, bool fetch=true)
Sets whether the attribute of the given type should be fetched.
void retrieveCollectionAttributes(const Akonadi::Collection &collection)
Retrieve the attributes of a single collection from the backend.
void abortActivity()
Abort any activity in progress in the backend.
void disableRevisionCheck()
Disables the check of the revision number.
void percent(int progress)
This signal should be emitted whenever the progress of an action in the agent (e.g.
virtual void retrieveCollections()=0
Retrieve the collection tree from the remote server and supply it via collectionsRetrieved() or colle...
Collection::List collections() const
Returns the list of fetched collection.
void abortRequested()
Emitted when another application has remotely asked the agent to abort its current operation...
QString dumpNotificationListToString() const
Dump the contents of the current ChangeReplay.
QString displayName() const
Returns the display name (EntityDisplayAttribute::displayName()) if set, and Collection::name() other...
void attributesSynchronized(qlonglong collectionId)
Emitted when a collection attributes synchronization has been completed.
void collectionsRetrievalDone()
Call this method to indicate you finished synchronizing the collection tree.
void setAutomaticProgressReporting(bool enabled)
Enable or disable automatic progress reporting.
void setCollectionStreamingEnabled(bool enable)
Enable collection streaming, that is collections don't have to be delivered at once as result of a re...
void synchronizeCollectionAttributes(qint64 id)
This method is called whenever the collection with the given id shall have its attributes synchronize...
Only list direct sub-collections of the base collection.
CollectionFetchScope & fetchScope()
Returns the collection fetch scope.
void setResource(const QString &resource)
Sets a resource filter, that is only collections owned by the specified resource are retrieved...
Represents a collection of PIM items.
Job that fetches collections from the Akonadi storage.
void itemsRetrieved(const Item::List &items)
Call this method to supply the full collection listing from the remote server.
static QString virtualMimeType()
Returns the mimetype used for virtual collections.
void agentNameChanged(const QString &name)
This signal is emitted whenever the name of the agent has changed.
static QString mimeType()
Returns the mimetype used for collections.
void setItemSynchronizationFetchScope(const ItemFetchScope &fetchScope)
Set the fetch scope applied for item synchronization.
void synchronizeCollectionTree()
Refetches the Collections.
void setTotalItems(int amount)
Call this method when you want to use the itemsRetrieved() method in streaming mode and indicate the ...
void nameChanged(const QString &name)
This signal is emitted whenever the name of the resource has changed.
void changesCommitted(const Item::List &items)
Resets the dirty flag of all given items and updates remote ids.
Item::List items() const
Returns the fetched item.
The base class for all Akonadi agents and resources.
Only fetch the base collection.
Syncs between items known to a client (usually a resource) and the Akonadi storage.
void itemsRetrievalDone()
Call this method to indicate you finished synchronizing the current collection.
void deferTask()
Stops the execution of the current task and continues with the next one.
ItemFetchScope & fetchScope()
Returns the item fetch scope.
void setAgentName(const QString &name)
This method is used to set the name of the agent.
SchedulePriority
Describes the scheduling priority of a task that has been queued for execution.
void synchronize()
This method is called whenever the resource should start synchronize all data.
void error(const QString &message)
This signal shall be used to report errors.
virtual int status() const
This method returns the current status code of the agent.
void clearCache()
Call this method to remove all items and collections of the resource from the server cache...
void collectionAttributesRetrieved(const Collection &collection)
Call this method from retrieveCollectionAttributes() once the result is available.
QString remoteId() const
Returns the remote id of the entity.
void collectionsRetrieved(const Collection::List &collections)
Call this to supply the full folder tree retrieved from the remote server.
static Collection root()
Returns the root collection.
Item currentItem() const
Returns the item that is currently retrieved.
Job that deletes a collection in the Akonadi storage.
void itemsRetrievedIncremental(const Item::List &changedItems, const Item::List &removedItems)
Call this method to supply incrementally retrieved items from the remote server.
static QString agentServiceName(ServiceAgentType agentType, const QString &identifier)
Returns the namespaced D-Bus service name for an agent of type agentType with agent identifier identi...
void doSetOnline(bool online)
Inherited from AgentBase.
Id id() const
Returns the unique identifier of the entity.
void collectionTreeSynchronized()
Emitted when a collection tree synchronization has been completed.
void setFetchScope(const CollectionFetchScope &fetchScope)
Sets the collection fetch scope.
void synchronizeCollection(qint64 id)
This method is called whenever the collection with the given id shall be synchronized.
Specifies which parts of an item should be fetched from the Akonadi storage.
void setAncestorRetrieval(AncestorRetrieval ancestorDepth)
Sets how many levels of ancestor collections should be included in the retrieval. ...
void setItemTransactionMode(ItemSync::TransactionMode mode)
Set transaction mode for item sync'ing.
Helper job to invalidate item cache for an entire collection.
QString identifier() const
Returns the instance identifier of this agent.
void setIgnorePayload(bool ignore)
Sets whether the payload of the modified item shall be omitted from transmission to the Akonadi stora...
TransactionMode
Transaction mode used by ItemSync.
void changeCommitted(const Item &item)
Resets the dirty flag of the given item and updates the remote id.
ChangeRecorder * changeRecorder() const
Returns the Akonadi::ChangeRecorder object used for monitoring.
void dumpMemoryInfo() const
Dumps memory usage information to stdout.
void setHierarchicalRemoteIdentifiersEnabled(bool enable)
Indicate the use of hierarchical remote identifiers.
bool isOnline() const
Returns whether the agent is currently online.
void itemRetrieved(const Item &item)
Call this method from retrieveItem() once the result is available.
void changeProcessed()
Marks the current change as processes and replays the next change if change recording is enabled (noo...
void setCollection(const Akonadi::Collection &collection, const Akonadi::Collection &parentCollection)
Set the collection that is actually moved.
Job that modifies an existing item in the Akonadi storage.
Job that fetches items from the Akonadi storage.
Job that selects a resource context for remote identifier based operations.
~ResourceBase()
Destroys the base resource.
QStringList contentMimeTypes() const
Returns a list of possible content mimetypes, e.g.
static int init(int argc, char **argv)
Use this method in the main function of your resource application to initialize your resource subclas...
void setItemStreamingEnabled(bool enable)
Enable item streaming.
QString name() const
Returns the name of the resource.
void taskDone()
Indicate that the current task is finished.
void cancelTask()
Stops the execution of the current task and continues with the next one.
Collection currentCollection() const
Returns the collection that is currently synchronized.
QString resource() const
Returns the identifier of the resource owning the collection.
The user canceld this job.
ResourceBase(const QString &id)
Creates a base resource.
The agent is working on something.
bool isValid() const
Returns whether the entity is valid.
void setTransactionMode(TransactionMode mode)
Set the transaction mode to use for this sync.
void collectionsRetrievedIncremental(const Collection::List &changedCollections, const Collection::List &removedCollections)
Call this to supply incrementally retrieved collections from the remote server.
static QString addNamespace(const QString &string)
Adds the multi-instance namespace to string if required (with '_' as separator).
void setName(const QString &name)
This method is used to set the name of the resource.
List all sub-collections.
QString dumpMemoryInfoToString() const
Returns a string with memory usage information.
QList< Collection > List
Describes a list of collections.
QString agentName() const
Returns the name of the agent.
The base class for all Akonadi resources.
bool isVirtual() const
Returns whether the collection is virtual, for example a search collection.
QString dumpSchedulerToString() const
Dump the state of the scheduler.
void scheduleCustomTask(QObject *receiver, const char *method, const QVariant &argument, SchedulePriority priority=Append)
Schedules a custom task in the internal scheduler.
void setCacheOnly(bool cacheOnly)
Sets whether payload data should be requested from remote sources or just from the local cache...
void invalidateCache(const Collection &collection)
Call this method to invalidate all cached content in collection.