00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "kio/sessiondata.h"
00021 #include "kio/slaveconfig.h"
00022 #include "kio/scheduler.h"
00023 #include "kio/authinfo.h"
00024 #include "kio/slave.h"
00025 #include <qptrlist.h>
00026 #include <qdict.h>
00027
00028 #include <dcopclient.h>
00029
00030 #include <kdebug.h>
00031 #include <kglobal.h>
00032 #include <kprotocolmanager.h>
00033 #include <kprotocolinfo.h>
00034 #include <assert.h>
00035 #include <kstaticdeleter.h>
00036 #include <kdesu/client.h>
00037
00038
00039
00040
00041 #define MAX_SLAVE_IDLE (3*60)
00042
00043 using namespace KIO;
00044
00045 template class QDict<KIO::Scheduler::ProtocolInfo>;
00046
00047 Scheduler *Scheduler::instance = 0;
00048
00049 class KIO::SlaveList: public QPtrList<Slave>
00050 {
00051 public:
00052 SlaveList() { }
00053 };
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070 class KIO::Scheduler::JobData
00071 {
00072 public:
00073 JobData() : checkOnHold(false) { }
00074
00075 public:
00076 QString protocol;
00077 QString proxy;
00078 bool checkOnHold;
00079 };
00080
00081 class KIO::Scheduler::ExtraJobData: public QPtrDict<KIO::Scheduler::JobData>
00082 {
00083 public:
00084 ExtraJobData() { setAutoDelete(true); }
00085 };
00086
00087 class KIO::Scheduler::ProtocolInfo
00088 {
00089 public:
00090 ProtocolInfo() : maxSlaves(1), skipCount(0)
00091 {
00092 joblist.setAutoDelete(false);
00093 }
00094
00095 QPtrList<SimpleJob> joblist;
00096 SlaveList activeSlaves;
00097 int maxSlaves;
00098 int skipCount;
00099 QString protocol;
00100 };
00101
00102 class KIO::Scheduler::ProtocolInfoDict : public QDict<KIO::Scheduler::ProtocolInfo>
00103 {
00104 public:
00105 ProtocolInfoDict() { }
00106
00107 KIO::Scheduler::ProtocolInfo *get( const QString &protocol);
00108 };
00109
00110 KIO::Scheduler::ProtocolInfo *
00111 KIO::Scheduler::ProtocolInfoDict::get(const QString &protocol)
00112 {
00113 ProtocolInfo *info = find(protocol);
00114 if (!info)
00115 {
00116 info = new ProtocolInfo;
00117 info->protocol = protocol;
00118 info->maxSlaves = KProtocolInfo::maxSlaves( protocol );
00119
00120 insert(protocol, info);
00121 }
00122 return info;
00123 }
00124
00125
00126 Scheduler::Scheduler()
00127 : DCOPObject( "KIO::Scheduler" ),
00128 QObject(kapp, "scheduler"),
00129 slaveTimer(0, "Scheduler::slaveTimer"),
00130 coSlaveTimer(0, "Scheduler::coSlaveTimer"),
00131 cleanupTimer(0, "Scheduler::cleanupTimer")
00132 {
00133 checkOnHold = true;
00134 slaveOnHold = 0;
00135 protInfoDict = new ProtocolInfoDict;
00136 slaveList = new SlaveList;
00137 idleSlaves = new SlaveList;
00138 coIdleSlaves = new SlaveList;
00139 extraJobData = new ExtraJobData;
00140 sessionData = new SessionData;
00141 slaveConfig = SlaveConfig::self();
00142 connect(&slaveTimer, SIGNAL(timeout()), SLOT(startStep()));
00143 connect(&coSlaveTimer, SIGNAL(timeout()), SLOT(slotScheduleCoSlave()));
00144 connect(&cleanupTimer, SIGNAL(timeout()), SLOT(slotCleanIdleSlaves()));
00145 busy = false;
00146 }
00147
00148 Scheduler::~Scheduler()
00149 {
00150 protInfoDict->setAutoDelete(true);
00151 delete protInfoDict; protInfoDict = 0;
00152 delete idleSlaves; idleSlaves = 0;
00153 delete coIdleSlaves; coIdleSlaves = 0;
00154 slaveList->setAutoDelete(true);
00155 delete slaveList; slaveList = 0;
00156 delete extraJobData; extraJobData = 0;
00157 delete sessionData; sessionData = 0;
00158 instance = 0;
00159 }
00160
00161 void
00162 Scheduler::debug_info()
00163 {
00164 }
00165
00166 bool Scheduler::process(const QCString &fun, const QByteArray &data, QCString &replyType, QByteArray &replyData )
00167 {
00168 if ( fun != "reparseSlaveConfiguration(QString)" )
00169 return DCOPObject::process( fun, data, replyType, replyData );
00170
00171 replyType = "void";
00172 QDataStream stream( data, IO_ReadOnly );
00173 QString proto;
00174 stream >> proto;
00175
00176 kdDebug( 7006 ) << "reparseConfiguration( " << proto << " )" << endl;
00177 KProtocolManager::reparseConfiguration();
00178 slaveConfig->reset();
00179 sessionData->reset();
00180 NetRC::self()->reload();
00181
00182 Slave *slave = slaveList->first();
00183 for (; slave; slave = slaveList->next() )
00184 if ( slave->slaveProtocol() == proto || proto.isEmpty() )
00185 {
00186 slave->send( CMD_REPARSECONFIGURATION );
00187 slave->resetHost();
00188 }
00189 return true;
00190 }
00191
00192 QCStringList Scheduler::functions()
00193 {
00194 QCStringList funcs = DCOPObject::functions();
00195 funcs << "void reparseSlaveConfiguration(QString)";
00196 return funcs;
00197 }
00198
00199 void Scheduler::_doJob(SimpleJob *job) {
00200 JobData *jobData = new JobData;
00201 jobData->protocol = KProtocolManager::slaveProtocol(job->url(), jobData->proxy);
00202
00203 if (job->command() == CMD_GET)
00204 {
00205 jobData->checkOnHold = checkOnHold;
00206 checkOnHold = false;
00207 }
00208 extraJobData->replace(job, jobData);
00209 newJobs.append(job);
00210 slaveTimer.start(0, true);
00211 #ifndef NDEBUG
00212 if (newJobs.count() > 150)
00213 kdDebug() << "WARNING - KIO::Scheduler got more than 150 jobs! This shows a misuse in your app (yes, a job is a QObject)." << endl;
00214 #endif
00215 }
00216
00217 void Scheduler::_scheduleJob(SimpleJob *job) {
00218 newJobs.removeRef(job);
00219 JobData *jobData = extraJobData->find(job);
00220 if (!jobData)
00221 {
00222 kdFatal(7006) << "BUG! _ScheduleJob(): No extraJobData for job!" << endl;
00223 return;
00224 }
00225 QString protocol = jobData->protocol;
00226
00227 ProtocolInfo *protInfo = protInfoDict->get(protocol);
00228 protInfo->joblist.append(job);
00229
00230 slaveTimer.start(0, true);
00231 }
00232
00233 void Scheduler::_cancelJob(SimpleJob *job) {
00234
00235 Slave *slave = job->slave();
00236 if ( !slave )
00237 {
00238
00239 JobData *jobData = extraJobData->find(job);
00240 if (!jobData)
00241 return;
00242
00243 newJobs.removeRef(job);
00244 ProtocolInfo *protInfo = protInfoDict->get(jobData->protocol);
00245 protInfo->joblist.removeRef(job);
00246
00247
00248 slave = slaveList->first();
00249 for(; slave; slave = slaveList->next())
00250 {
00251 JobList *list = coSlaves.find(slave);
00252 if (list && list->removeRef(job))
00253 break;
00254
00255 }
00256 if (!slave)
00257 {
00258 extraJobData->remove(job);
00259 return;
00260 }
00261 }
00262 kdDebug(7006) << "Scheduler: killing slave " << slave->slave_pid() << endl;
00263 slave->kill();
00264 _jobFinished( job, slave );
00265 slotSlaveDied( slave);
00266 }
00267
00268 void Scheduler::startStep()
00269 {
00270 while(newJobs.count())
00271 {
00272 (void) startJobDirect();
00273 }
00274 QDictIterator<KIO::Scheduler::ProtocolInfo> it(*protInfoDict);
00275 while(it.current())
00276 {
00277 if (startJobScheduled(it.current())) return;
00278 ++it;
00279 }
00280 }
00281
00282 void Scheduler::setupSlave(KIO::Slave *slave, const KURL &url, const QString &protocol, const QString &proxy , bool newSlave, const KIO::MetaData *config)
00283 {
00284 QString host = url.host();
00285 int port = url.port();
00286 QString user = url.user();
00287 QString passwd = url.pass();
00288
00289 if ((newSlave) ||
00290 (slave->host() != host) ||
00291 (slave->port() != port) ||
00292 (slave->user() != user) ||
00293 (slave->passwd() != passwd))
00294 {
00295 MetaData configData = slaveConfig->configData(protocol, host);
00296 sessionData->configDataFor( configData, protocol, host );
00297
00298 configData["UseProxy"] = proxy;
00299
00300 QString autoLogin = configData["EnableAutoLogin"].lower();
00301 if ( autoLogin == "true" )
00302 {
00303 NetRC::AutoLogin l;
00304 l.login = user;
00305 bool usern = (protocol == "ftp");
00306 if ( NetRC::self()->lookup( url, l, usern) )
00307 {
00308 configData["autoLoginUser"] = l.login;
00309 configData["autoLoginPass"] = l.password;
00310 if ( usern )
00311 {
00312 QString macdef;
00313 QMap<QString, QStringList>::ConstIterator it = l.macdef.begin();
00314 for ( ; it != l.macdef.end(); ++it )
00315 macdef += it.key() + '\\' + it.data().join( "\\" ) + '\n';
00316 configData["autoLoginMacro"] = macdef;
00317 }
00318 }
00319 }
00320 if (config)
00321 configData += *config;
00322 slave->setConfig(configData);
00323 slave->setProtocol(url.protocol());
00324 slave->setHost(host, port, user, passwd);
00325 }
00326 }
00327
00328 bool Scheduler::startJobScheduled(ProtocolInfo *protInfo)
00329 {
00330 if (protInfo->joblist.isEmpty())
00331 return false;
00332
00333
00334 debug_info();
00335 bool newSlave = false;
00336
00337 SimpleJob *job = 0;
00338 Slave *slave = 0;
00339
00340 if (protInfo->skipCount > 2)
00341 {
00342 bool dummy;
00343
00344
00345 protInfo->skipCount = 0;
00346 job = protInfo->joblist.at(0);
00347 slave = findIdleSlave(protInfo, job, dummy );
00348 }
00349 else
00350 {
00351 bool exact=false;
00352 SimpleJob *firstJob = 0;
00353 Slave *firstSlave = 0;
00354 for(uint i = 0; (i < protInfo->joblist.count()) && (i < 10); i++)
00355 {
00356 job = protInfo->joblist.at(i);
00357 slave = findIdleSlave(protInfo, job, exact);
00358 if (!firstSlave)
00359 {
00360 firstJob = job;
00361 firstSlave = slave;
00362 }
00363 if (!slave) break;
00364 if (exact) break;
00365 }
00366
00367 if (!exact)
00368 {
00369 slave = firstSlave;
00370 job = firstJob;
00371 }
00372 if (job == firstJob)
00373 protInfo->skipCount = 0;
00374 else
00375 protInfo->skipCount++;
00376 }
00377
00378 if (!slave)
00379 {
00380 if ( protInfo->maxSlaves > static_cast<int>(protInfo->activeSlaves.count()) )
00381 {
00382 newSlave = true;
00383 slave = createSlave(protInfo, job, job->url());
00384 }
00385 }
00386
00387 if (!slave)
00388 {
00389
00390
00391 return false;
00392 }
00393
00394 protInfo->activeSlaves.append(slave);
00395 idleSlaves->removeRef(slave);
00396 protInfo->joblist.removeRef(job);
00397
00398
00399
00400 JobData *jobData = extraJobData->find(job);
00401 setupSlave(slave, job->url(), jobData->protocol, jobData->proxy, newSlave);
00402 job->start(slave);
00403
00404 slaveTimer.start(0, true);
00405 return true;
00406 }
00407
00408 bool Scheduler::startJobDirect()
00409 {
00410 debug_info();
00411 SimpleJob *job = newJobs.take(0);
00412 JobData *jobData = extraJobData->find(job);
00413 if (!jobData)
00414 {
00415 kdFatal(7006) << "BUG! startjobDirect(): No extraJobData for job!"
00416 << endl;
00417 return false;
00418 }
00419 QString protocol = jobData->protocol;
00420 ProtocolInfo *protInfo = protInfoDict->get(protocol);
00421
00422 bool newSlave = false;
00423 bool dummy;
00424
00425
00426 Slave *slave = findIdleSlave(protInfo, job, dummy);
00427
00428 if (!slave)
00429 {
00430 newSlave = true;
00431 slave = createSlave(protInfo, job, job->url());
00432 }
00433
00434 if (!slave)
00435 return false;
00436
00437 idleSlaves->removeRef(slave);
00438
00439
00440 setupSlave(slave, job->url(), protocol, jobData->proxy, newSlave);
00441 job->start(slave);
00442 return true;
00443 }
00444
00445 static Slave *searchIdleList(SlaveList *idleSlaves, const KURL &url, const QString &protocol, bool &exact)
00446 {
00447 QString host = url.host();
00448 int port = url.port();
00449 QString user = url.user();
00450 exact = true;
00451
00452 for( Slave *slave = idleSlaves->first();
00453 slave;
00454 slave = idleSlaves->next())
00455 {
00456 if ((protocol == slave->slaveProtocol()) &&
00457 (host == slave->host()) &&
00458 (port == slave->port()) &&
00459 (user == slave->user()))
00460 return slave;
00461 }
00462
00463 exact = false;
00464
00465
00466 for( Slave *slave = idleSlaves->first();
00467 slave;
00468 slave = idleSlaves->next())
00469 {
00470 if (protocol == slave->slaveProtocol())
00471 return slave;
00472 }
00473 return 0;
00474 }
00475
00476 Slave *Scheduler::findIdleSlave(ProtocolInfo *, SimpleJob *job, bool &exact)
00477 {
00478 Slave *slave = 0;
00479 JobData *jobData = extraJobData->find(job);
00480 if (!jobData)
00481 {
00482 kdFatal(7006) << "BUG! findIdleSlave(): No extraJobData for job!" << endl;
00483 return 0;
00484 }
00485 if (jobData->checkOnHold)
00486 {
00487 slave = Slave::holdSlave(jobData->protocol, job->url());
00488 if (slave)
00489 return slave;
00490 }
00491 if (slaveOnHold)
00492 {
00493
00494 bool bCanReuse = (job->command() == CMD_GET);
00495 KIO::TransferJob * tJob = dynamic_cast<KIO::TransferJob *>(job);
00496 if ( tJob )
00497 {
00498 bCanReuse = (job->command() == CMD_GET || job->command() == CMD_SPECIAL);
00499 if ( bCanReuse )
00500 {
00501 KIO::MetaData outgoing = tJob->outgoingMetaData();
00502 QString resume = (!outgoing.contains("resume")) ? QString::null : outgoing["resume"];
00503 kdDebug(7006) << "Resume metadata is '" << resume << "'" << endl;
00504 bCanReuse = (resume.isEmpty() || resume == "0");
00505 }
00506 }
00507
00508 if (bCanReuse)
00509 {
00510 if (job->url() == urlOnHold)
00511 {
00512 kdDebug(7006) << "HOLD: Reusing held slave for " << urlOnHold.prettyURL() << endl;
00513 slave = slaveOnHold;
00514 }
00515 else
00516 {
00517 kdDebug(7006) << "HOLD: Discarding held slave (" << urlOnHold.prettyURL() << ")" << endl;
00518 slaveOnHold->kill();
00519 }
00520 slaveOnHold = 0;
00521 urlOnHold = KURL();
00522 }
00523 if (slave)
00524 return slave;
00525 }
00526
00527 return searchIdleList(idleSlaves, job->url(), jobData->protocol, exact);
00528 }
00529
00530 Slave *Scheduler::createSlave(ProtocolInfo *protInfo, SimpleJob *job, const KURL &url)
00531 {
00532 int error;
00533 QString errortext;
00534 Slave *slave = Slave::createSlave(protInfo->protocol, url, error, errortext);
00535 if (slave)
00536 {
00537 slaveList->append(slave);
00538 idleSlaves->append(slave);
00539 connect(slave, SIGNAL(slaveDied(KIO::Slave *)),
00540 SLOT(slotSlaveDied(KIO::Slave *)));
00541 connect(slave, SIGNAL(slaveStatus(pid_t,const QCString &,const QString &, bool)),
00542 SLOT(slotSlaveStatus(pid_t,const QCString &, const QString &, bool)));
00543
00544 connect(slave,SIGNAL(authorizationKey(const QCString&, const QCString&, bool)),
00545 sessionData,SLOT(slotAuthData(const QCString&, const QCString&, bool)));
00546 connect(slave,SIGNAL(delAuthorization(const QCString&)), sessionData,
00547 SLOT(slotDelAuthData(const QCString&)));
00548 }
00549 else
00550 {
00551 kdError() << "ERROR " << error << ": couldn't create slave : "
00552 << errortext << endl;
00553 if (job)
00554 {
00555 protInfo->joblist.removeRef(job);
00556 extraJobData->remove(job);
00557 job->slotError( error, errortext );
00558 }
00559 }
00560 return slave;
00561 }
00562
00563 void Scheduler::slotSlaveStatus(pid_t, const QCString &, const QString &, bool)
00564 {
00565 }
00566
00567 void Scheduler::_jobFinished(SimpleJob *job, Slave *slave)
00568 {
00569 JobData *jobData = extraJobData->take(job);
00570 if (!jobData)
00571 {
00572 kdFatal(7006) << "BUG! _jobFinished(): No extraJobData for job!" << endl;
00573 return;
00574 }
00575 ProtocolInfo *protInfo = protInfoDict->get(jobData->protocol);
00576 delete jobData;
00577 slave->disconnect(job);
00578 protInfo->activeSlaves.removeRef(slave);
00579 if (slave->isAlive())
00580 {
00581 JobList *list = coSlaves.find(slave);
00582 if (list)
00583 {
00584 assert(slave->isConnected());
00585 assert(!coIdleSlaves->contains(slave));
00586 coIdleSlaves->append(slave);
00587 if (!list->isEmpty())
00588 coSlaveTimer.start(0, true);
00589 return;
00590 }
00591 else
00592 {
00593 assert(!slave->isConnected());
00594 idleSlaves->append(slave);
00595 slave->setIdle();
00596 _scheduleCleanup();
00597
00598 }
00599 }
00600 if (protInfo->joblist.count())
00601 {
00602 slaveTimer.start(0, true);
00603 }
00604 }
00605
00606 void Scheduler::slotSlaveDied(KIO::Slave *slave)
00607 {
00608 assert(!slave->isAlive());
00609 ProtocolInfo *protInfo = protInfoDict->get(slave->slaveProtocol());
00610 protInfo->activeSlaves.removeRef(slave);
00611 if (slave == slaveOnHold)
00612 {
00613 slaveOnHold = 0;
00614 urlOnHold = KURL();
00615 }
00616 idleSlaves->removeRef(slave);
00617 JobList *list = coSlaves.find(slave);
00618 if (list)
00619 {
00620
00621 disconnectSlave(slave);
00622 }
00623
00624 if (!slaveList->removeRef(slave))
00625 kdDebug(7006) << "Scheduler: BUG!! Slave died, but is NOT in slaveList!!!\n" << endl;
00626 slave->deref();
00627 }
00628
00629 void Scheduler::slotCleanIdleSlaves()
00630 {
00631 for(Slave *slave = idleSlaves->first();slave;)
00632 {
00633 if (slave->idleTime() >= MAX_SLAVE_IDLE)
00634 {
00635
00636 Slave *removeSlave = slave;
00637 slave = idleSlaves->next();
00638 idleSlaves->removeRef(removeSlave);
00639 slaveList->removeRef(removeSlave);
00640 removeSlave->connection()->close();
00641 removeSlave->deref();
00642 }
00643 else
00644 {
00645 slave = idleSlaves->next();
00646 }
00647 }
00648 _scheduleCleanup();
00649 }
00650
00651 void Scheduler::_scheduleCleanup()
00652 {
00653 if (idleSlaves->count())
00654 {
00655 if (!cleanupTimer.isActive())
00656 cleanupTimer.start( MAX_SLAVE_IDLE*1000, true );
00657 }
00658 }
00659
00660 void Scheduler::_putSlaveOnHold(KIO::SimpleJob *job, const KURL &url)
00661 {
00662 Slave *slave = job->slave();
00663 slave->disconnect(job);
00664
00665 if (slaveOnHold)
00666 {
00667 slaveOnHold->kill();
00668 }
00669 slaveOnHold = slave;
00670 urlOnHold = url;
00671 slaveOnHold->suspend();
00672 }
00673
00674 void Scheduler::_publishSlaveOnHold()
00675 {
00676 if (!slaveOnHold)
00677 return;
00678
00679 slaveOnHold->hold(urlOnHold);
00680 }
00681
00682 void Scheduler::_removeSlaveOnHold()
00683 {
00684 if (slaveOnHold)
00685 {
00686 slaveOnHold->kill();
00687 }
00688 slaveOnHold = 0;
00689 urlOnHold = KURL();
00690 }
00691
00692 Slave *
00693 Scheduler::_getConnectedSlave(const KURL &url, const KIO::MetaData &config )
00694 {
00695 QString proxy;
00696 QString protocol = KProtocolManager::slaveProtocol(url, proxy);
00697 bool dummy;
00698 Slave *slave = searchIdleList(idleSlaves, url, protocol, dummy);
00699 if (!slave)
00700 {
00701 ProtocolInfo *protInfo = protInfoDict->get(protocol);
00702 slave = createSlave(protInfo, 0, url);
00703 }
00704 if (!slave)
00705 return 0;
00706 idleSlaves->removeRef(slave);
00707
00708 setupSlave(slave, url, protocol, proxy, true, &config);
00709
00710 slave->send( CMD_CONNECT );
00711 connect(slave, SIGNAL(connected()),
00712 SLOT(slotSlaveConnected()));
00713 connect(slave, SIGNAL(error(int, const QString &)),
00714 SLOT(slotSlaveError(int, const QString &)));
00715
00716 coSlaves.insert(slave, new QPtrList<SimpleJob>());
00717
00718 return slave;
00719 }
00720
00721 void
00722 Scheduler::slotScheduleCoSlave()
00723 {
00724 Slave *nextSlave;
00725 for(Slave *slave = coIdleSlaves->first();
00726 slave;
00727 slave = nextSlave)
00728 {
00729 nextSlave = coIdleSlaves->next();
00730 JobList *list = coSlaves.find(slave);
00731 assert(list);
00732 if (list && !list->isEmpty())
00733 {
00734 SimpleJob *job = list->take(0);
00735 coIdleSlaves->removeRef(slave);
00736
00737
00738 assert(!coIdleSlaves->contains(slave));
00739
00740 KURL url =job->url();
00741 QString host = url.host();
00742 int port = url.port();
00743
00744 if (slave->host() == "<reset>")
00745 {
00746 QString user = url.user();
00747 QString passwd = url.pass();
00748
00749 MetaData configData = slaveConfig->configData(url.protocol(), url.host());
00750 slave->setConfig(configData);
00751 slave->setProtocol(url.protocol());
00752 slave->setHost(host, port, user, passwd);
00753 }
00754
00755 assert(slave->protocol() == url.protocol());
00756 assert(slave->host() == host);
00757 assert(slave->port() == port);
00758 job->start(slave);
00759 }
00760 }
00761 }
00762
00763 void
00764 Scheduler::slotSlaveConnected()
00765 {
00766 Slave *slave = (Slave *)sender();
00767
00768 slave->setConnected(true);
00769 disconnect(slave, SIGNAL(connected()),
00770 this, SLOT(slotSlaveConnected()));
00771 emit slaveConnected(slave);
00772 assert(!coIdleSlaves->contains(slave));
00773 coIdleSlaves->append(slave);
00774 coSlaveTimer.start(0, true);
00775 }
00776
00777 void
00778 Scheduler::slotSlaveError(int errorNr, const QString &errorMsg)
00779 {
00780 Slave *slave = (Slave *)sender();
00781 if (!slave->isConnected() || (coIdleSlaves->find(slave) != -1))
00782 {
00783
00784 emit slaveError(slave, errorNr, errorMsg);
00785 }
00786 }
00787
00788 bool
00789 Scheduler::_assignJobToSlave(KIO::Slave *slave, SimpleJob *job)
00790 {
00791
00792 QString dummy;
00793 if ((slave->slaveProtocol() != KProtocolManager::slaveProtocol( job->url(), dummy ))
00794 ||
00795 (!newJobs.removeRef(job)))
00796 {
00797 kdDebug(7006) << "_assignJobToSlave(): ERROR, nonmatching or unknown job." << endl;
00798 job->kill();
00799 return false;
00800 }
00801
00802 JobList *list = coSlaves.find(slave);
00803 assert(list);
00804 if (!list)
00805 {
00806 kdDebug(7006) << "_assignJobToSlave(): ERROR, unknown slave." << endl;
00807 job->kill();
00808 return false;
00809 }
00810
00811 assert(list->contains(job) == 0);
00812 list->append(job);
00813 coSlaveTimer.start(0, true);
00814
00815 return true;
00816 }
00817
00818 bool
00819 Scheduler::_disconnectSlave(KIO::Slave *slave)
00820 {
00821
00822 JobList *list = coSlaves.take(slave);
00823 assert(list);
00824 if (!list)
00825 return false;
00826
00827 while(!list->isEmpty())
00828 {
00829 Job *job = list->take(0);
00830 job->kill();
00831 }
00832 delete list;
00833 coIdleSlaves->removeRef(slave);
00834 assert(!coIdleSlaves->contains(slave));
00835 disconnect(slave, SIGNAL(connected()),
00836 this, SLOT(slotSlaveConnected()));
00837 disconnect(slave, SIGNAL(error(int, const QString &)),
00838 this, SLOT(slotSlaveError(int, const QString &)));
00839 if (slave->isAlive())
00840 {
00841 idleSlaves->append(slave);
00842 slave->send( CMD_DISCONNECT );
00843 slave->setIdle();
00844 slave->setConnected(false);
00845 _scheduleCleanup();
00846 }
00847 return true;
00848 }
00849
00850 void
00851 Scheduler::_checkSlaveOnHold(bool b)
00852 {
00853 checkOnHold = b;
00854 }
00855
00856 void
00857 Scheduler::_registerWindow(QWidget *wid)
00858 {
00859 if (!wid)
00860 return;
00861
00862 QObject *obj = static_cast<QObject *>(wid);
00863 if (!m_windowList.contains(obj))
00864 {
00865
00866
00867
00868 long windowId = wid->winId();
00869 m_windowList.insert(obj, windowId);
00870 connect(wid, SIGNAL(destroyed(QObject *)),
00871 this, SLOT(slotUnregisterWindow(QObject*)));
00872 QByteArray params;
00873 QDataStream stream(params, IO_WriteOnly);
00874 stream << windowId;
00875 if( !kapp->dcopClient()->send( "kded", "kded",
00876 "registerWindowId(long int)", params ) )
00877 kdDebug(7006) << "Could not register window with kded!" << endl;
00878 }
00879 }
00880
00881 void
00882 Scheduler::slotUnregisterWindow(QObject *obj)
00883 {
00884 if (!obj)
00885 return;
00886
00887 QMap<QObject *, long>::Iterator it = m_windowList.find(obj);
00888 if (it == m_windowList.end())
00889 return;
00890 long windowId = it.data();
00891 disconnect( it.key(), SIGNAL(destroyed(QObject *)),
00892 this, SLOT(slotUnregisterWindow(QObject*)));
00893 m_windowList.remove( it );
00894 if (kapp)
00895 {
00896 QByteArray params;
00897 QDataStream stream(params, IO_WriteOnly);
00898 stream << windowId;
00899 kapp->dcopClient()->send( "kded", "kded",
00900 "unregisterWindowId(long int)", params );
00901 }
00902 }
00903
00904 Scheduler* Scheduler::self() {
00905 if ( !instance ) {
00906 instance = new Scheduler;
00907 }
00908 return instance;
00909 }
00910
00911 void Scheduler::virtual_hook( int id, void* data )
00912 { DCOPObject::virtual_hook( id, data ); }
00913
00914
00915
00916 #include "scheduler.moc"