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 ),
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
00233
00234 KMail::ScheduledJob::ScheduledJob(
KMFolder* folder,
bool immediate )
00235 : FolderJob( 0, tOther, folder ), mImmediate( immediate ),
00236 mOpeningFolder( false )
00237 {
00238 mCancellable =
true;
00239 mSrcFolder = folder;
00240 }
00241
00242
#include "jobscheduler.moc"