• Skip to content
  • Skip to link menu
KDE 4.4 API Reference
  • KDE API Reference
  • KDE-PIM Libraries
  • Sitemap
  • Contact Us
 

akonadi

resourcescheduler.cpp

00001 /*
00002     Copyright (c) 2007 Volker Krause <vkrause@kde.org>
00003 
00004     This library is free software; you can redistribute it and/or modify it
00005     under the terms of the GNU Library General Public License as published by
00006     the Free Software Foundation; either version 2 of the License, or (at your
00007     option) any later version.
00008 
00009     This library is distributed in the hope that it will be useful, but WITHOUT
00010     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00011     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
00012     License for more details.
00013 
00014     You should have received a copy of the GNU Library General Public License
00015     along with this library; see the file COPYING.LIB.  If not, write to the
00016     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00017     02110-1301, USA.
00018 */
00019 
00020 #include "resourcescheduler_p.h"
00021 
00022 #include <kdebug.h>
00023 #include <klocale.h>
00024 
00025 #include <QtCore/QTimer>
00026 #include <QtDBus/QDBusInterface>
00027 #include <QtDBus/QDBusConnectionInterface>
00028 #include <boost/graph/graph_concepts.hpp>
00029 
00030 using namespace Akonadi;
00031 
00032 qint64 ResourceScheduler::Task::latestSerial = 0;
00033 static QDBusAbstractInterface *s_resourcetracker = 0;
00034 
00035 //@cond PRIVATE
00036 
00037 ResourceScheduler::ResourceScheduler( QObject *parent ) :
00038     QObject( parent ),
00039     mOnline( false )
00040 {
00041 }
00042 
00043 void ResourceScheduler::scheduleFullSync()
00044 {
00045   Task t;
00046   t.type = SyncAll;
00047   if ( !mTaskList.isEmpty() && ( mTaskList.last() == t || mCurrentTask == t ) )
00048     return;
00049   mTaskList << t;
00050   signalTaskToTracker( t, "SyncAll" );
00051   scheduleNext();
00052 }
00053 
00054 void ResourceScheduler::scheduleCollectionTreeSync()
00055 {
00056   Task t;
00057   t.type = SyncCollectionTree;
00058   if ( !mTaskList.isEmpty() && ( mTaskList.last() == t || mCurrentTask == t ) )
00059     return;
00060   mTaskList << t;
00061   signalTaskToTracker( t, "SyncCollectionTree" );
00062   scheduleNext();
00063 }
00064 
00065 void ResourceScheduler::scheduleSync(const Collection & col)
00066 {
00067   Task t;
00068   t.type = SyncCollection;
00069   t.collection = col;
00070   if ( !mTaskList.isEmpty() && ( mTaskList.last() == t || mCurrentTask == t ) )
00071     return;
00072   mTaskList << t;
00073   signalTaskToTracker( t, "SyncCollection" );
00074   scheduleNext();
00075 }
00076 
00077 void ResourceScheduler::scheduleItemFetch(const Item & item, const QSet<QByteArray> &parts, const QDBusMessage & msg)
00078 {
00079   Task t;
00080   t.type = FetchItem;
00081   t.item = item;
00082   t.itemParts = parts;
00083   t.dbusMsg = msg;
00084   if ( !mTaskList.isEmpty() && ( mTaskList.last() == t || mCurrentTask == t ) )
00085     return;
00086   mTaskList << t;
00087   signalTaskToTracker( t, "FetchItem" );
00088   scheduleNext();
00089 }
00090 
00091 void ResourceScheduler::scheduleResourceCollectionDeletion()
00092 {
00093   Task t;
00094   t.type = DeleteResourceCollection;
00095   if ( !mTaskList.isEmpty() && ( mTaskList.last() == t || mCurrentTask == t ) )
00096     return;
00097   mTaskList << t;
00098   signalTaskToTracker( t, "DeleteResourceCollection" );
00099   scheduleNext();
00100 }
00101 
00102 void ResourceScheduler::scheduleChangeReplay()
00103 {
00104   Task t;
00105   t.type = ChangeReplay;
00106   if ( mTaskList.contains( t ) )
00107     return;
00108   // change replays have to happen before we pull changes from the backend, otherwise
00109   // we will overwrite our still unsaved local changes if the backend can't do
00110   // incremental retrieval
00111   mTaskList.prepend( t );
00112   signalTaskToTracker( t, "ChangeReplay" );
00113   scheduleNext();
00114 }
00115 
00116 void Akonadi::ResourceScheduler::scheduleFullSyncCompletion()
00117 {
00118   Task t;
00119   t.type = SyncAllDone;
00120   mTaskList << t;
00121   signalTaskToTracker( t, "SyncAllDone" );
00122   scheduleNext();
00123 }
00124 
00125 void Akonadi::ResourceScheduler::scheduleCustomTask( QObject *receiver, const char* methodName, const QVariant &argument, ResourceBase::SchedulePriority priority )
00126 {
00127   Task t;
00128   t.type = Custom;
00129   t.receiver = receiver;
00130   t.methodName = methodName;
00131   t.argument = argument;
00132   if ( mTaskList.contains( t ) )
00133     return;
00134 
00135   switch (priority) {
00136   case ResourceBase::Prepend:
00137     mTaskList.prepend(t);
00138     break;
00139   case ResourceBase::AfterChangeReplay:
00140     {
00141       QMutableListIterator<Task> it(mTaskList);
00142       bool inserted = false;
00143       while (it.hasNext() && !inserted) {
00144         if (it.next().type != ChangeReplay) {
00145           it.previous(); // next returns the item *and* advances the iterator.
00146           it.insert(t);
00147           inserted = true;
00148         }
00149       }
00150       if (!inserted)
00151         mTaskList.append(t);
00152     }
00153     break;
00154   default:
00155     mTaskList.append(t);
00156   }
00157 
00158   signalTaskToTracker( t, "Custom-" + t.methodName );
00159   scheduleNext();
00160 }
00161 
00162 void ResourceScheduler::taskDone()
00163 {
00164   if ( isEmpty() )
00165     emit status( AgentBase::Idle, i18nc( "@info:status Application ready for work", "Ready" ) );
00166 
00167   if ( s_resourcetracker ) {
00168     QList<QVariant> argumentList;
00169     argumentList << QString::number( mCurrentTask.serial )
00170                  << QString();
00171     s_resourcetracker->asyncCallWithArgumentList(QLatin1String("jobEnded"), argumentList);
00172   }
00173 
00174   mCurrentTask = Task();
00175   scheduleNext();
00176 }
00177 
00178 void ResourceScheduler::deferTask()
00179 {
00180   if ( s_resourcetracker ) {
00181     QList<QVariant> argumentList;
00182     argumentList << QString::number( mCurrentTask.serial )
00183                  << QString();
00184     s_resourcetracker->asyncCallWithArgumentList(QLatin1String("jobEnded"), argumentList);
00185   }
00186 
00187   Task t = mCurrentTask;
00188   mCurrentTask = Task();
00189   mTaskList << t;
00190   signalTaskToTracker( t, "DeferedTask" );
00191 
00192   scheduleNext();
00193 }
00194 
00195 bool ResourceScheduler::isEmpty()
00196 {
00197   return mTaskList.isEmpty();
00198 }
00199 
00200 void ResourceScheduler::scheduleNext()
00201 {
00202   if ( mCurrentTask.type != Invalid || mTaskList.isEmpty() || !mOnline )
00203     return;
00204   QTimer::singleShot( 0, this, SLOT(executeNext()) );
00205 }
00206 
00207 void ResourceScheduler::executeNext()
00208 {
00209   if( mCurrentTask.type != Invalid || mTaskList.isEmpty() )
00210     return;
00211 
00212   mCurrentTask = mTaskList.takeFirst();
00213 
00214   if ( s_resourcetracker ) {
00215     QList<QVariant> argumentList;
00216     argumentList << QString::number( mCurrentTask.serial );
00217     s_resourcetracker->asyncCallWithArgumentList(QLatin1String("jobStarted"), argumentList);
00218   }
00219 
00220   switch ( mCurrentTask.type ) {
00221     case SyncAll:
00222       emit executeFullSync();
00223       break;
00224     case SyncCollectionTree:
00225       emit executeCollectionTreeSync();
00226       break;
00227     case SyncCollection:
00228       emit executeCollectionSync( mCurrentTask.collection );
00229       break;
00230     case FetchItem:
00231       emit executeItemFetch( mCurrentTask.item, mCurrentTask.itemParts );
00232       break;
00233     case DeleteResourceCollection:
00234       emit executeResourceCollectionDeletion();
00235       break;
00236     case ChangeReplay:
00237       emit executeChangeReplay();
00238       break;
00239     case SyncAllDone:
00240       emit fullSyncComplete();
00241       break;
00242     case Custom:
00243     {
00244       bool success = QMetaObject::invokeMethod( mCurrentTask.receiver, mCurrentTask.methodName, Q_ARG(QVariant, mCurrentTask.argument) );;
00245       if ( !success )
00246         success = QMetaObject::invokeMethod( mCurrentTask.receiver, mCurrentTask.methodName );
00247 
00248       if ( !success )
00249         kError() << "Could not invoke slot" << mCurrentTask.methodName << "on" << mCurrentTask.receiver << "with argument" << mCurrentTask.argument;
00250       break;
00251     }
00252     default:
00253       Q_ASSERT( false );
00254   }
00255 }
00256 
00257 ResourceScheduler::Task ResourceScheduler::currentTask() const
00258 {
00259   return mCurrentTask;
00260 }
00261 
00262 void ResourceScheduler::setOnline(bool state)
00263 {
00264   if ( mOnline == state )
00265     return;
00266   mOnline = state;
00267   if ( mOnline ) {
00268     scheduleNext();
00269   } else if ( mCurrentTask.type != Invalid ) {
00270     // abort running task
00271     mTaskList.prepend( mCurrentTask );
00272     mCurrentTask = Task();
00273   }
00274 }
00275 
00276 void ResourceScheduler::signalTaskToTracker( const Task &task, const QByteArray &taskType )
00277 {
00278   // if there's a job tracer running, tell it about the new job
00279   if ( !s_resourcetracker && QDBusConnection::sessionBus().interface()->isServiceRegistered(QLatin1String("org.kde.akonadiconsole") ) ) {
00280     s_resourcetracker = new QDBusInterface( QLatin1String("org.kde.akonadiconsole"),
00281                                        QLatin1String("/resourcesJobtracker"),
00282                                        QLatin1String("org.freedesktop.Akonadi.JobTracker"),
00283                                        QDBusConnection::sessionBus(), 0 );
00284   }
00285 
00286   if ( s_resourcetracker ) {
00287     QList<QVariant> argumentList;
00288     argumentList << static_cast<AgentBase*>(  parent() )->identifier()
00289                  << QString::number( task.serial )
00290                  << QString()
00291                  << QString::fromLatin1( taskType );
00292     s_resourcetracker->asyncCallWithArgumentList(QLatin1String("jobCreated"), argumentList);
00293   }
00294 }
00295 
00296 void ResourceScheduler::collectionRemoved( const Akonadi::Collection &collection )
00297 {
00298   if ( !collection.isValid() ) // should not happen, but you never know...
00299     return;
00300   for ( QList<Task>::iterator it = mTaskList.begin(); it != mTaskList.end(); ) {
00301     if ( (*it).type == SyncCollection && (*it).collection == collection ) {
00302       it = mTaskList.erase( it );
00303       kDebug() << " erasing";
00304     } else
00305       ++it;
00306   }
00307 }
00308 
00309 //@endcond
00310 
00311 #include "resourcescheduler_p.moc"

akonadi

Skip menu "akonadi"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

KDE-PIM Libraries

Skip menu "KDE-PIM Libraries"
  • akonadi
  •   contact
  •   kmime
  • kabc
  • kblog
  • kcal
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  •   richtextbuilders
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • microblog
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2
Generated for KDE-PIM Libraries by doxygen 1.6.2-20100208
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal