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 :QObject(kapp, "scheduler"),
00128 DCOPObject( "KIO::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->connection()->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 }
00212
00213 void Scheduler::_scheduleJob(SimpleJob *job) {
00214 newJobs.removeRef(job);
00215 JobData *jobData = extraJobData->find(job);
00216 if (!jobData)
00217 {
00218 kdFatal(7006) << "BUG! _ScheduleJob(): No extraJobData for job!" << endl;
00219 return;
00220 }
00221 QString protocol = jobData->protocol;
00222
00223 ProtocolInfo *protInfo = protInfoDict->get(protocol);
00224 protInfo->joblist.append(job);
00225
00226 slaveTimer.start(0, true);
00227 }
00228
00229 void Scheduler::_cancelJob(SimpleJob *job) {
00230
00231 Slave *slave = job->slave();
00232 if ( !slave )
00233 {
00234
00235 JobData *jobData = extraJobData->find(job);
00236 if (!jobData)
00237 return;
00238
00239 newJobs.removeRef(job);
00240 ProtocolInfo *protInfo = protInfoDict->get(jobData->protocol);
00241 protInfo->joblist.removeRef(job);
00242
00243
00244 slave = slaveList->first();
00245 for(; slave; slave = slaveList->next())
00246 {
00247 JobList *list = coSlaves.find(slave);
00248 if (list && list->removeRef(job))
00249 break;
00250
00251 }
00252 if (!slave)
00253 {
00254 extraJobData->remove(job);
00255 return;
00256 }
00257 }
00258 kdDebug(7006) << "Scheduler: killing slave " << slave->slave_pid() << endl;
00259 slave->kill();
00260 _jobFinished( job, slave );
00261 slotSlaveDied( slave);
00262 }
00263
00264 void Scheduler::startStep()
00265 {
00266 while(newJobs.count())
00267 {
00268 (void) startJobDirect();
00269 }
00270 QDictIterator<KIO::Scheduler::ProtocolInfo> it(*protInfoDict);
00271 while(it.current())
00272 {
00273 if (startJobScheduled(it.current())) return;
00274 ++it;
00275 }
00276 }
00277
00278 void Scheduler::setupSlave(KIO::Slave *slave, const KURL &url, const QString &protocol, const QString &proxy , bool newSlave, const KIO::MetaData *config)
00279 {
00280 QString host = url.host();
00281 int port = url.port();
00282 QString user = url.user();
00283 QString passwd = url.pass();
00284
00285 if ((newSlave) ||
00286 (slave->host() != host) ||
00287 (slave->port() != port) ||
00288 (slave->user() != user) ||
00289 (slave->passwd() != passwd))
00290 {
00291 MetaData configData = slaveConfig->configData(protocol, host);
00292 sessionData->configDataFor( configData, protocol, host );
00293
00294 configData["UseProxy"] = proxy;
00295
00296 QString autoLogin = configData["EnableAutoLogin"].lower();
00297 if ( autoLogin == "true" )
00298 {
00299 NetRC::AutoLogin l;
00300 l.login = user;
00301 bool usern = (protocol == "ftp");
00302 if ( NetRC::self()->lookup( url, l, usern) )
00303 {
00304 configData["autoLoginUser"] = l.login;
00305 configData["autoLoginPass"] = l.password;
00306 if ( usern )
00307 {
00308 QString macdef;
00309 QMap<QString, QStringList>::ConstIterator it = l.macdef.begin();
00310 for ( ; it != l.macdef.end(); ++it )
00311 macdef += it.key() + '\\' + it.data().join( "\\" ) + '\n';
00312 configData["autoLoginMacro"] = macdef;
00313 }
00314 }
00315 }
00316 if (config)
00317 configData += *config;
00318 slave->setConfig(configData);
00319 slave->setProtocol(url.protocol());
00320 slave->setHost(host, port, user, passwd);
00321 }
00322 }
00323
00324 bool Scheduler::startJobScheduled(ProtocolInfo *protInfo)
00325 {
00326 if (protInfo->joblist.isEmpty())
00327 return false;
00328
00329
00330 debug_info();
00331 bool newSlave = false;
00332
00333 SimpleJob *job = 0;
00334 Slave *slave = 0;
00335
00336 if (protInfo->skipCount > 2)
00337 {
00338 bool dummy;
00339
00340
00341 protInfo->skipCount = 0;
00342 job = protInfo->joblist.at(0);
00343 slave = findIdleSlave(protInfo, job, dummy );
00344 }
00345 else
00346 {
00347 bool exact=false;
00348 SimpleJob *firstJob = 0;
00349 Slave *firstSlave = 0;
00350 for(uint i = 0; (i < protInfo->joblist.count()) && (i < 10); i++)
00351 {
00352 job = protInfo->joblist.at(i);
00353 slave = findIdleSlave(protInfo, job, exact);
00354 if (!firstSlave)
00355 {
00356 firstJob = job;
00357 firstSlave = slave;
00358 }
00359 if (!slave) break;
00360 if (exact) break;
00361 }
00362
00363 if (!exact)
00364 {
00365 slave = firstSlave;
00366 job = firstJob;
00367 }
00368 if (job == firstJob)
00369 protInfo->skipCount = 0;
00370 else
00371 protInfo->skipCount++;
00372 }
00373
00374 if (!slave)
00375 {
00376 if ( protInfo->maxSlaves > static_cast<int>(protInfo->activeSlaves.count()) )
00377 {
00378 newSlave = true;
00379 slave = createSlave(protInfo, job, job->url());
00380 }
00381 }
00382
00383 if (!slave)
00384 {
00385
00386
00387 return false;
00388 }
00389
00390 protInfo->activeSlaves.append(slave);
00391 idleSlaves->removeRef(slave);
00392 protInfo->joblist.removeRef(job);
00393
00394
00395
00396 JobData *jobData = extraJobData->find(job);
00397 setupSlave(slave, job->url(), jobData->protocol, jobData->proxy, newSlave);
00398 job->start(slave);
00399
00400 slaveTimer.start(0, true);
00401 return true;
00402 }
00403
00404 bool Scheduler::startJobDirect()
00405 {
00406 debug_info();
00407 SimpleJob *job = newJobs.take(0);
00408 JobData *jobData = extraJobData->find(job);
00409 if (!jobData)
00410 {
00411 kdFatal(7006) << "BUG! startjobDirect(): No extraJobData for job!"
00412 << endl;
00413 return false;
00414 }
00415 QString protocol = jobData->protocol;
00416 ProtocolInfo *protInfo = protInfoDict->get(protocol);
00417
00418 bool newSlave = false;
00419 bool dummy;
00420
00421
00422 Slave *slave = findIdleSlave(protInfo, job, dummy);
00423
00424 if (!slave)
00425 {
00426 newSlave = true;
00427 slave = createSlave(protInfo, job, job->url());
00428 }
00429
00430 if (!slave)
00431 return false;
00432
00433 idleSlaves->removeRef(slave);
00434
00435
00436 setupSlave(slave, job->url(), protocol, jobData->proxy, newSlave);
00437 job->start(slave);
00438 return true;
00439 }
00440
00441 static Slave *searchIdleList(SlaveList *idleSlaves, const KURL &url, const QString &protocol, bool &exact)
00442 {
00443 QString host = url.host();
00444 int port = url.port();
00445 QString user = url.user();
00446 exact = true;
00447
00448 for( Slave *slave = idleSlaves->first();
00449 slave;
00450 slave = idleSlaves->next())
00451 {
00452 if ((protocol == slave->slaveProtocol()) &&
00453 (host == slave->host()) &&
00454 (port == slave->port()) &&
00455 (user == slave->user()))
00456 return slave;
00457 }
00458
00459 exact = false;
00460
00461
00462 for( Slave *slave = idleSlaves->first();
00463 slave;
00464 slave = idleSlaves->next())
00465 {
00466 if (protocol == slave->slaveProtocol())
00467 return slave;
00468 }
00469 return 0;
00470 }
00471
00472 Slave *Scheduler::findIdleSlave(ProtocolInfo *, SimpleJob *job, bool &exact)
00473 {
00474 Slave *slave = 0;
00475 JobData *jobData = extraJobData->find(job);
00476 if (!jobData)
00477 {
00478 kdFatal(7006) << "BUG! findIdleSlave(): No extraJobData for job!" << endl;
00479 return 0;
00480 }
00481 if (jobData->checkOnHold)
00482 {
00483 slave = Slave::holdSlave(jobData->protocol, job->url());
00484 if (slave)
00485 return slave;
00486 }
00487 if (slaveOnHold)
00488 {
00489
00490 bool bCanReuse = (job->command() == CMD_GET);
00491 KIO::TransferJob * tJob = dynamic_cast<KIO::TransferJob *>(job);
00492 if ( tJob )
00493 {
00494 bCanReuse = (job->command() == CMD_GET || job->command() == CMD_SPECIAL);
00495 if ( bCanReuse )
00496 {
00497 KIO::MetaData outgoing = tJob->outgoingMetaData();
00498 QString resume = (!outgoing.contains("resume")) ? QString::null : outgoing["resume"];
00499 kdDebug(7006) << "Resume metadata is '" << resume << "'" << endl;
00500 bCanReuse = (resume.isEmpty() || resume == "0");
00501 }
00502 }
00503
00504 if (bCanReuse)
00505 {
00506 if (job->url() == urlOnHold)
00507 {
00508 kdDebug(7006) << "HOLD: Reusing held slave for " << urlOnHold.prettyURL() << endl;
00509 slave = slaveOnHold;
00510 }
00511 else
00512 {
00513 kdDebug(7006) << "HOLD: Discarding held slave (" << urlOnHold.prettyURL() << ")" << endl;
00514 slaveOnHold->kill();
00515 }
00516 slaveOnHold = 0;
00517 urlOnHold = KURL();
00518 }
00519 if (slave)
00520 return slave;
00521 }
00522
00523 return searchIdleList(idleSlaves, job->url(), jobData->protocol, exact);
00524 }
00525
00526 Slave *Scheduler::createSlave(ProtocolInfo *protInfo, SimpleJob *job, const KURL &url)
00527 {
00528 int error;
00529 QString errortext;
00530 Slave *slave = Slave::createSlave(protInfo->protocol, url, error, errortext);
00531 if (slave)
00532 {
00533 slaveList->append(slave);
00534 idleSlaves->append(slave);
00535 connect(slave, SIGNAL(slaveDied(KIO::Slave *)),
00536 SLOT(slotSlaveDied(KIO::Slave *)));
00537 connect(slave, SIGNAL(slaveStatus(pid_t,const QCString &,const QString &, bool)),
00538 SLOT(slotSlaveStatus(pid_t,const QCString &, const QString &, bool)));
00539
00540 connect(slave,SIGNAL(authorizationKey(const QCString&, const QCString&, bool)),
00541 sessionData,SLOT(slotAuthData(const QCString&, const QCString&, bool)));
00542 connect(slave,SIGNAL(delAuthorization(const QCString&)), sessionData,
00543 SLOT(slotDelAuthData(const QCString&)));
00544 }
00545 else
00546 {
00547 kdError() << "ERROR " << error << ": couldn't create slave : "
00548 << errortext << endl;
00549 if (job)
00550 {
00551 protInfo->joblist.removeRef(job);
00552 extraJobData->remove(job);
00553 job->slotError( error, errortext );
00554 }
00555 }
00556 return slave;
00557 }
00558
00559 void Scheduler::slotSlaveStatus(pid_t, const QCString &, const QString &, bool)
00560 {
00561 }
00562
00563 void Scheduler::_jobFinished(SimpleJob *job, Slave *slave)
00564 {
00565 JobData *jobData = extraJobData->take(job);
00566 if (!jobData)
00567 {
00568 kdFatal(7006) << "BUG! _jobFinished(): No extraJobData for job!" << endl;
00569 return;
00570 }
00571 ProtocolInfo *protInfo = protInfoDict->get(jobData->protocol);
00572 delete jobData;
00573 slave->disconnect(job);
00574 protInfo->activeSlaves.removeRef(slave);
00575 if (slave->isAlive())
00576 {
00577 JobList *list = coSlaves.find(slave);
00578 if (list)
00579 {
00580 assert(slave->isConnected());
00581 assert(!coIdleSlaves->contains(slave));
00582 coIdleSlaves->append(slave);
00583 if (!list->isEmpty())
00584 coSlaveTimer.start(0, true);
00585 return;
00586 }
00587 else
00588 {
00589 assert(!slave->isConnected());
00590 idleSlaves->append(slave);
00591 slave->setIdle();
00592 _scheduleCleanup();
00593
00594 }
00595 }
00596 if (protInfo->joblist.count())
00597 {
00598 slaveTimer.start(0, true);
00599 }
00600 }
00601
00602 void Scheduler::slotSlaveDied(KIO::Slave *slave)
00603 {
00604 assert(!slave->isAlive());
00605 ProtocolInfo *protInfo = protInfoDict->get(slave->slaveProtocol());
00606 protInfo->activeSlaves.removeRef(slave);
00607 if (slave == slaveOnHold)
00608 {
00609 slaveOnHold = 0;
00610 urlOnHold = KURL();
00611 }
00612 idleSlaves->removeRef(slave);
00613 JobList *list = coSlaves.find(slave);
00614 if (list)
00615 {
00616
00617 disconnectSlave(slave);
00618 }
00619
00620 if (!slaveList->removeRef(slave))
00621 kdDebug(7006) << "Scheduler: BUG!! Slave died, but is NOT in slaveList!!!\n" << endl;
00622 slave->deref();
00623 }
00624
00625 void Scheduler::slotCleanIdleSlaves()
00626 {
00627 for(Slave *slave = idleSlaves->first();slave;)
00628 {
00629 if (slave->idleTime() >= MAX_SLAVE_IDLE)
00630 {
00631
00632 Slave *removeSlave = slave;
00633 slave = idleSlaves->next();
00634 idleSlaves->removeRef(removeSlave);
00635 slaveList->removeRef(removeSlave);
00636 removeSlave->connection()->close();
00637 removeSlave->deref();
00638 }
00639 else
00640 {
00641 slave = idleSlaves->next();
00642 }
00643 }
00644 _scheduleCleanup();
00645 }
00646
00647 void Scheduler::_scheduleCleanup()
00648 {
00649 if (idleSlaves->count())
00650 {
00651 if (!cleanupTimer.isActive())
00652 cleanupTimer.start( MAX_SLAVE_IDLE*1000, true );
00653 }
00654 }
00655
00656 void Scheduler::_putSlaveOnHold(KIO::SimpleJob *job, const KURL &url)
00657 {
00658 Slave *slave = job->slave();
00659 slave->disconnect(job);
00660
00661 if (slaveOnHold)
00662 {
00663 slaveOnHold->kill();
00664 }
00665 slaveOnHold = slave;
00666 urlOnHold = url;
00667 slaveOnHold->suspend();
00668 }
00669
00670 void Scheduler::_publishSlaveOnHold()
00671 {
00672 if (!slaveOnHold)
00673 return;
00674
00675 slaveOnHold->hold(urlOnHold);
00676 }
00677
00678 void Scheduler::_removeSlaveOnHold()
00679 {
00680 if (slaveOnHold)
00681 {
00682 slaveOnHold->kill();
00683 }
00684 slaveOnHold = 0;
00685 urlOnHold = KURL();
00686 }
00687
00688 Slave *
00689 Scheduler::_getConnectedSlave(const KURL &url, const KIO::MetaData &config )
00690 {
00691 QString proxy;
00692 QString protocol = KProtocolManager::slaveProtocol(url, proxy);
00693 bool dummy;
00694 Slave *slave = searchIdleList(idleSlaves, url, protocol, dummy);
00695 if (!slave)
00696 {
00697 ProtocolInfo *protInfo = protInfoDict->get(protocol);
00698 slave = createSlave(protInfo, 0, url);
00699 }
00700 if (!slave)
00701 return 0;
00702 idleSlaves->removeRef(slave);
00703
00704 setupSlave(slave, url, protocol, proxy, true, &config);
00705
00706 slave->connection()->send( CMD_CONNECT );
00707 connect(slave, SIGNAL(connected()),
00708 SLOT(slotSlaveConnected()));
00709 connect(slave, SIGNAL(error(int, const QString &)),
00710 SLOT(slotSlaveError(int, const QString &)));
00711
00712 coSlaves.insert(slave, new QPtrList<SimpleJob>());
00713
00714 return slave;
00715 }
00716
00717 void
00718 Scheduler::slotScheduleCoSlave()
00719 {
00720 Slave *nextSlave;
00721 for(Slave *slave = coIdleSlaves->first();
00722 slave;
00723 slave = nextSlave)
00724 {
00725 nextSlave = coIdleSlaves->next();
00726 JobList *list = coSlaves.find(slave);
00727 assert(list);
00728 if (list && !list->isEmpty())
00729 {
00730 SimpleJob *job = list->take(0);
00731 coIdleSlaves->removeRef(slave);
00732
00733
00734 assert(!coIdleSlaves->contains(slave));
00735
00736 KURL url =job->url();
00737 QString host = url.host();
00738 int port = url.port();
00739
00740 if (slave->host() == "<reset>")
00741 {
00742 QString user = url.user();
00743 QString passwd = url.pass();
00744
00745 MetaData configData = slaveConfig->configData(url.protocol(), url.host());
00746 slave->setConfig(configData);
00747 slave->setProtocol(url.protocol());
00748 slave->setHost(host, port, user, passwd);
00749 }
00750
00751 assert(slave->protocol() == url.protocol());
00752 assert(slave->host() == host);
00753 assert(slave->port() == port);
00754 job->start(slave);
00755 }
00756 }
00757 }
00758
00759 void
00760 Scheduler::slotSlaveConnected()
00761 {
00762 Slave *slave = (Slave *)sender();
00763
00764 slave->setConnected(true);
00765 disconnect(slave, SIGNAL(connected()),
00766 this, SLOT(slotSlaveConnected()));
00767 emit slaveConnected(slave);
00768 assert(!coIdleSlaves->contains(slave));
00769 coIdleSlaves->append(slave);
00770 coSlaveTimer.start(0, true);
00771 }
00772
00773 void
00774 Scheduler::slotSlaveError(int errorNr, const QString &errorMsg)
00775 {
00776 Slave *slave = (Slave *)sender();
00777 if (!slave->isConnected() || (coIdleSlaves->find(slave) != -1))
00778 {
00779
00780 emit slaveError(slave, errorNr, errorMsg);
00781 }
00782 }
00783
00784 bool
00785 Scheduler::_assignJobToSlave(KIO::Slave *slave, SimpleJob *job)
00786 {
00787
00788 QString dummy;
00789 if ((slave->slaveProtocol() != KProtocolManager::slaveProtocol( job->url(), dummy ))
00790 ||
00791 (!newJobs.removeRef(job)))
00792 {
00793 kdDebug(7006) << "_assignJobToSlave(): ERROR, nonmatching or unknown job." << endl;
00794 job->kill();
00795 return false;
00796 }
00797
00798 JobList *list = coSlaves.find(slave);
00799 assert(list);
00800 if (!list)
00801 {
00802 kdDebug(7006) << "_assignJobToSlave(): ERROR, unknown slave." << endl;
00803 job->kill();
00804 return false;
00805 }
00806
00807 assert(list->contains(job) == 0);
00808 list->append(job);
00809 coSlaveTimer.start(0, true);
00810
00811 return true;
00812 }
00813
00814 bool
00815 Scheduler::_disconnectSlave(KIO::Slave *slave)
00816 {
00817
00818 JobList *list = coSlaves.take(slave);
00819 assert(list);
00820 if (!list)
00821 return false;
00822
00823 while(!list->isEmpty())
00824 {
00825 Job *job = list->take(0);
00826 job->kill();
00827 }
00828 delete list;
00829 coIdleSlaves->removeRef(slave);
00830 assert(!coIdleSlaves->contains(slave));
00831 disconnect(slave, SIGNAL(connected()),
00832 this, SLOT(slotSlaveConnected()));
00833 disconnect(slave, SIGNAL(error(int, const QString &)),
00834 this, SLOT(slotSlaveError(int, const QString &)));
00835 if (slave->isAlive())
00836 {
00837 idleSlaves->append(slave);
00838 slave->connection()->send( CMD_DISCONNECT );
00839 slave->setIdle();
00840 slave->setConnected(false);
00841 _scheduleCleanup();
00842 }
00843 return true;
00844 }
00845
00846 void
00847 Scheduler::_checkSlaveOnHold(bool b)
00848 {
00849 checkOnHold = b;
00850 }
00851
00852 void
00853 Scheduler::_registerWindow(QWidget *wid)
00854 {
00855 if (!wid)
00856 return;
00857
00858 QObject *obj = static_cast<QObject *>(wid);
00859 if (!m_windowList.contains(obj))
00860 {
00861
00862
00863
00864 long windowId = wid->winId();
00865 m_windowList.insert(obj, windowId);
00866 connect(wid, SIGNAL(destroyed(QObject *)),
00867 this, SLOT(slotUnregisterWindow(QObject*)));
00868 QByteArray params;
00869 QDataStream stream(params, IO_WriteOnly);
00870 stream << windowId;
00871 if( !kapp->dcopClient()->send( "kded", "kded",
00872 "registerWindowId(long int)", params ) )
00873 kdDebug(7006) << "Could not register window with kded!" << endl;
00874 }
00875 }
00876
00877 void
00878 Scheduler::slotUnregisterWindow(QObject *obj)
00879 {
00880 if (!obj)
00881 return;
00882
00883 QMap<QObject *, long>::Iterator it = m_windowList.find(obj);
00884 if (it == m_windowList.end())
00885 return;
00886 long windowId = it.data();
00887 if (kapp)
00888 {
00889 QByteArray params;
00890 QDataStream stream(params, IO_WriteOnly);
00891 stream << windowId;
00892 kapp->dcopClient()->send( "kded", "kded",
00893 "unregisterWindowId(long int)", params );
00894 }
00895 }
00896
00897 Scheduler* Scheduler::self() {
00898 if ( !instance ) {
00899 instance = new Scheduler;
00900 }
00901 return instance;
00902 }
00903
00904 void Scheduler::virtual_hook( int id, void* data )
00905 { DCOPObject::virtual_hook( id, data ); }
00906
00907
00908
00909 #include "scheduler.moc"