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(
QValueList<ScheduledTask *>::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(
QValueList<ScheduledTask *>::ConstIterator 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 runTaskNow( task );
00073 }
00074
return;
00075 }
00076 }
00077
00078 }
00079
if ( !mCurrentTask && immediate )
00080 runTaskNow( task );
00081
else {
00082
#ifdef DEBUG_SCHEDULER
00083
kdDebug(5006) <<
"JobScheduler: adding task " << task <<
" (type " << task->
taskTypeId()
00084 <<
") for folder " << task->
folder() <<
" " << task->
folder()->
label() << endl;
00085
#endif
00086
mTaskList.append( task );
00087
if ( immediate )
00088 ++mPendingImmediateTasks;
00089
if ( !mCurrentTask && !mTimer.isActive() )
00090 restartTimer();
00091 }
00092 }
00093
00094 void JobScheduler::notifyOpeningFolder(
KMFolder* folder )
00095 {
00096
if ( mCurrentTask && mCurrentTask->
folder() == folder ) {
00097
if ( mCurrentJob->
isOpeningFolder() ) {
00098
#ifdef DEBUG_SCHEDULER
00099
kdDebug(5006) <<
"JobScheduler: got the opening-notification for " << folder->
label() <<
" as expected." << endl;
00100
#endif
00101
}
else {
00102
00103
00104
00105
if ( mCurrentJob->isCancellable() )
00106 interruptCurrentTask();
00107 }
00108 }
00109 }
00110
00111
void JobScheduler::interruptCurrentTask()
00112 {
00113 Q_ASSERT( mCurrentTask );
00114
#ifdef DEBUG_SCHEDULER
00115
kdDebug(5006) <<
"JobScheduler: interrupting job " << mCurrentJob <<
" for folder " << mCurrentTask->
folder()->
label() << endl;
00116
#endif
00117
00118
registerTask( mCurrentTask );
00119 mCurrentTask = 0;
00120 mCurrentJob->kill();
00121 }
00122
00123
void JobScheduler::slotRunNextJob()
00124 {
00125
while ( !mCurrentJob ) {
00126
#ifdef DEBUG_SCHEDULER
00127
kdDebug(5006) <<
"JobScheduler: slotRunNextJob" << endl;
00128
#endif
00129
Q_ASSERT( mCurrentTask == 0 );
00130
ScheduledTask* task = 0;
00131
00132
for(
QValueList<ScheduledTask *>::Iterator it = mTaskList.begin(); it != mTaskList.end(); ++it ) {
00133
00134
KMFolder* folder = (*it)->folder();
00135
if ( folder == 0 ) {
00136
#ifdef DEBUG_SCHEDULER
00137
kdDebug(5006) <<
" folder for task " << (*it) <<
" was deleted" << endl;
00138
#endif
00139
if ( (*it)->isImmediate() )
00140 --mPendingImmediateTasks;
00141 mTaskList.remove( it );
00142
if ( !mTaskList.isEmpty() )
00143 slotRunNextJob();
00144
else
00145 mTimer.stop();
00146
return;
00147 }
00148
00149
00150 kmkernel->searchFolderMgr()->tryReleasingFolder( folder );
00151
#ifdef DEBUG_SCHEDULER
00152
kdDebug(5006) <<
" looking at folder " << folder->
label()
00153 <<
" " << folder->
location()
00154 <<
" isOpened=" << (*it)->folder()->isOpened() << endl;
00155
#endif
00156
if ( !folder->
isOpened() ) {
00157 task = *it;
00158 mTaskList.remove( it );
00159
if ( task->
isImmediate() )
00160 --mPendingImmediateTasks;
00161
break;
00162 }
00163 }
00164
00165
if ( !task )
00166
return;
00167
00168 runTaskNow( task );
00169 }
00170 }
00171
00172
void JobScheduler::restartTimer()
00173 {
00174
if ( mPendingImmediateTasks > 0 )
00175 slotRunNextJob();
00176
else
00177 {
00178
#ifdef DEBUG_SCHEDULER
00179
mTimer.start( 10000 );
00180
#else
00181
mTimer.start( 1 * 60000 );
00182
#endif
00183
}
00184 }
00185
00186
void JobScheduler::runTaskNow(
ScheduledTask* task )
00187 {
00188 Q_ASSERT( mCurrentTask == 0 );
00189
if ( mCurrentTask ) {
00190 interruptCurrentTask();
00191 }
00192 mCurrentTask = task;
00193 mTimer.stop();
00194 mCurrentJob = mCurrentTask->
run();
00195
#ifdef DEBUG_SCHEDULER
00196
kdDebug(5006) <<
"JobScheduler: task " << mCurrentTask
00197 <<
" (type " << mCurrentTask->
taskTypeId() <<
")"
00198 <<
" for folder " << mCurrentTask->
folder()->
label()
00199 <<
" returned job " << mCurrentJob <<
" "
00200 << ( mCurrentJob?mCurrentJob->className():0 ) << endl;
00201
#endif
00202
if ( !mCurrentJob ) {
00203
delete mCurrentTask;
00204 mCurrentTask = 0;
00205
if ( !mTaskList.isEmpty() )
00206 restartTimer();
00207
return;
00208 }
00209
00210 mCurrentTask->
folder()->
storage()->
addJob( mCurrentJob );
00211 connect( mCurrentJob, SIGNAL( finished() ),
this, SLOT( slotJobFinished() ) );
00212 mCurrentJob->start();
00213 }
00214
00215
void JobScheduler::slotJobFinished()
00216 {
00217
00218
#ifdef DEBUG_SCHEDULER
00219
kdDebug(5006) <<
"JobScheduler: slotJobFinished" << endl;
00220
#endif
00221
delete mCurrentTask;
00222 mCurrentTask = 0;
00223 mCurrentJob = 0;
00224
if ( !mTaskList.isEmpty() )
00225 restartTimer();
00226 }
00227
00229
00230 KMail::ScheduledJob::ScheduledJob(
KMFolder* folder,
bool immediate )
00231 : FolderJob( 0, tOther, folder ), mImmediate( immediate ),
00232 mOpeningFolder( false )
00233 {
00234 mCancellable =
true;
00235 mSrcFolder = folder;
00236 }
00237
00238
#include "jobscheduler.moc"