kmail
jobscheduler.cppGo to the documentation of this file.00001
00029 #include "jobscheduler.h"
00030 #include "kmfolder.h"
00031 #include "folderstorage.h"
00032 #include "kmfoldermgr.h"
00033 #include <kdebug.h>
00034
00035 using namespace KMail;
00036
00037 JobScheduler::JobScheduler( QObject* parent, const char* name )
00038 : QObject( parent, name ), mTimer( this, "mTimer" ),
00039 mPendingImmediateTasks( 0 ),
00040 mCurrentTask( 0 ), mCurrentJob( 0 )
00041 {
00042 connect( &mTimer, SIGNAL( timeout() ), SLOT( slotRunNextJob() ) );
00043
00044 }
00045
00046
00047 JobScheduler::~JobScheduler()
00048 {
00049
00050 for( TaskList::Iterator it = mTaskList.begin(); it != mTaskList.end(); ++it ) {
00051 delete (*it);
00052 }
00053 delete mCurrentTask;
00054 delete mCurrentJob;
00055 }
00056
00057 void JobScheduler::registerTask( ScheduledTask* task )
00058 {
00059 bool immediate = task->isImmediate();
00060 int typeId = task->taskTypeId();
00061 if ( typeId ) {
00062 KMFolder* folder = task->folder();
00063
00064 for( TaskList::Iterator it = mTaskList.begin(); it != mTaskList.end(); ++it ) {
00065 if ( (*it)->taskTypeId() == typeId && (*it)->folder() == folder ) {
00066 #ifdef DEBUG_SCHEDULER
00067 kdDebug(5006) << "JobScheduler: already having task type " << typeId << " for folder " << folder->label() << endl;
00068 #endif
00069 delete task;
00070 if ( !mCurrentTask && immediate ) {
00071 ScheduledTask* task = *it;
00072 removeTask( it );
00073 runTaskNow( task );
00074 }
00075 return;
00076 }
00077 }
00078
00079 }
00080 if ( !mCurrentTask && immediate )
00081 runTaskNow( task );
00082 else {
00083 #ifdef DEBUG_SCHEDULER
00084 kdDebug(5006) << "JobScheduler: adding task " << task << " (type " << task->taskTypeId()
00085 << ") for folder " << task->folder() << " " << task->folder()->label() << endl;
00086 #endif
00087 mTaskList.append( task );
00088 if ( immediate )
00089 ++mPendingImmediateTasks;
00090 if ( !mCurrentTask && !mTimer.isActive() )
00091 restartTimer();
00092 }
00093 }
00094
00095 void JobScheduler::removeTask( TaskList::Iterator& it )
00096 {
00097 if ( (*it)->isImmediate() )
00098 --mPendingImmediateTasks;
00099 mTaskList.remove( it );
00100 }
00101
00102 void JobScheduler::notifyOpeningFolder( KMFolder* folder )
00103 {
00104 if ( mCurrentTask && mCurrentTask->folder() == folder ) {
00105 if ( mCurrentJob->isOpeningFolder() ) {
00106 #ifdef DEBUG_SCHEDULER
00107 kdDebug(5006) << "JobScheduler: got the opening-notification for " << folder->label() << " as expected." << endl;
00108 #endif
00109 } else {
00110
00111
00112
00113 if ( mCurrentJob->isCancellable() )
00114 interruptCurrentTask();
00115 }
00116 }
00117 }
00118
00119 void JobScheduler::interruptCurrentTask()
00120 {
00121 Q_ASSERT( mCurrentTask );
00122 #ifdef DEBUG_SCHEDULER
00123 kdDebug(5006) << "JobScheduler: interrupting job " << mCurrentJob << " for folder " << mCurrentTask->folder()->label() << endl;
00124 #endif
00125
00126 registerTask( mCurrentTask );
00127 mCurrentTask = 0;
00128 mCurrentJob->kill();
00129 }
00130
00131 void JobScheduler::slotRunNextJob()
00132 {
00133 while ( !mCurrentJob ) {
00134 #ifdef DEBUG_SCHEDULER
00135 kdDebug(5006) << "JobScheduler: slotRunNextJob" << endl;
00136 #endif
00137 Q_ASSERT( mCurrentTask == 0 );
00138 ScheduledTask* task = 0;
00139
00140 for( TaskList::Iterator it = mTaskList.begin(); it != mTaskList.end(); ++it ) {
00141
00142 KMFolder* folder = (*it)->folder();
00143 if ( folder == 0 ) {
00144 #ifdef DEBUG_SCHEDULER
00145 kdDebug(5006) << " folder for task " << (*it) << " was deleted" << endl;
00146 #endif
00147 removeTask( it );
00148 if ( !mTaskList.isEmpty() )
00149 slotRunNextJob();
00150 else
00151 mTimer.stop();
00152 return;
00153 }
00154
00155
00156 kmkernel->searchFolderMgr()->tryReleasingFolder( folder );
00157 #ifdef DEBUG_SCHEDULER
00158 kdDebug(5006) << " looking at folder " << folder->label()
00159 << " " << folder->location()
00160 << " isOpened=" << (*it)->folder()->isOpened() << endl;
00161 #endif
00162 if ( !folder->isOpened() ) {
00163 task = *it;
00164 removeTask( it );
00165 break;
00166 }
00167 }
00168
00169 if ( !task )
00170 return;
00171
00172 runTaskNow( task );
00173 }
00174 }
00175
00176 void JobScheduler::restartTimer()
00177 {
00178 if ( mPendingImmediateTasks > 0 )
00179 slotRunNextJob();
00180 else
00181 {
00182 #ifdef DEBUG_SCHEDULER
00183 mTimer.start( 10000 );
00184 #else
00185 mTimer.start( 1 * 60000 );
00186 #endif
00187 }
00188 }
00189
00190 void JobScheduler::runTaskNow( ScheduledTask* task )
00191 {
00192 Q_ASSERT( mCurrentTask == 0 );
00193 if ( mCurrentTask ) {
00194 interruptCurrentTask();
00195 }
00196 mCurrentTask = task;
00197 mTimer.stop();
00198 mCurrentJob = mCurrentTask->run();
00199 #ifdef DEBUG_SCHEDULER
00200 kdDebug(5006) << "JobScheduler: task " << mCurrentTask
00201 << " (type " << mCurrentTask->taskTypeId() << ")"
00202 << " for folder " << mCurrentTask->folder()->label()
00203 << " returned job " << mCurrentJob << " "
00204 << ( mCurrentJob?mCurrentJob->className():0 ) << endl;
00205 #endif
00206 if ( !mCurrentJob ) {
00207 delete mCurrentTask;
00208 mCurrentTask = 0;
00209 if ( !mTaskList.isEmpty() )
00210 restartTimer();
00211 return;
00212 }
00213
00214 mCurrentTask->folder()->storage()->addJob( mCurrentJob );
00215 connect( mCurrentJob, SIGNAL( finished() ), this, SLOT( slotJobFinished() ) );
00216 mCurrentJob->start();
00217 }
00218
00219 void JobScheduler::slotJobFinished()
00220 {
00221
00222 #ifdef DEBUG_SCHEDULER
00223 kdDebug(5006) << "JobScheduler: slotJobFinished" << endl;
00224 #endif
00225 delete mCurrentTask;
00226 mCurrentTask = 0;
00227 mCurrentJob = 0;
00228 if ( !mTaskList.isEmpty() )
00229 restartTimer();
00230 }
00231
00232
00233 void JobScheduler::pause()
00234 {
00235 mPendingImmediateTasks = 0;
00236 if ( mCurrentJob && mCurrentJob->isCancellable() )
00237 interruptCurrentTask();
00238 mTimer.stop();
00239 }
00240
00241 void JobScheduler::resume()
00242 {
00243 restartTimer();
00244 }
00245
00247
00248 KMail::ScheduledJob::ScheduledJob( KMFolder* folder, bool immediate )
00249 : FolderJob( 0, tOther, folder ), mImmediate( immediate ),
00250 mOpeningFolder( false )
00251 {
00252 mCancellable = true;
00253 mSrcFolder = folder;
00254 }
00255
00256 #include "jobscheduler.moc"
|