• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • tdeio/tdeio
 

tdeio/tdeio

  • tdeio
  • tdeio
scheduler.cpp
1/* This file is part of the KDE libraries
2 Copyright (C) 2000 Stephan Kulow <coolo@kde.org>
3 Waldo Bastian <bastian@kde.org>
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License version 2 as published by the Free Software Foundation.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 Boston, MA 02110-1301, USA.
18*/
19
20#include "tdeio/sessiondata.h"
21#include "tdeio/slaveconfig.h"
22#include "tdeio/scheduler.h"
23#include "tdeio/authinfo.h"
24#include "tdeio/slave.h"
25#include <tqptrlist.h>
26#include <tqdict.h>
27
28#include <dcopclient.h>
29
30#include <kdebug.h>
31#include <tdeglobal.h>
32#include <tdeprotocolmanager.h>
33#include <kprotocolinfo.h>
34#include <assert.h>
35#include <kstaticdeleter.h>
36#include <tdesu/client.h>
37
38
39// Slaves may be idle for MAX_SLAVE_IDLE time before they are being returned
40// to the system wide slave pool. (3 minutes)
41#define MAX_SLAVE_IDLE (3*60)
42
43using namespace TDEIO;
44
45template class TQDict<TDEIO::Scheduler::ProtocolInfo>;
46
47Scheduler *Scheduler::instance = 0;
48
49class TDEIO::SlaveList: public TQPtrList<Slave>
50{
51 public:
52 SlaveList() { }
53};
54
55//
56// There are two kinds of protocol:
57// (1) The protocol of the url
58// (2) The actual protocol that the io-slave uses.
59//
60// These two often match, but not necasserily. Most notably, they don't
61// match when doing ftp via a proxy.
62// In that case (1) is ftp, but (2) is http.
63//
64// JobData::protocol stores (2) while Job::url().protocol() returns (1).
65// The ProtocolInfoDict is indexed with (2).
66//
67// We schedule slaves based on (2) but tell the slave about (1) via
68// Slave::setProtocol().
69
70class TDEIO::Scheduler::JobData
71{
72public:
73 JobData() : checkOnHold(false) { }
74
75public:
76 TQString protocol;
77 TQString proxy;
78 bool checkOnHold;
79};
80
81class TDEIO::Scheduler::ExtraJobData: public TQPtrDict<TDEIO::Scheduler::JobData>
82{
83public:
84 ExtraJobData() { setAutoDelete(true); }
85};
86
87class TDEIO::Scheduler::ProtocolInfo
88{
89public:
90 ProtocolInfo() : maxSlaves(1), skipCount(0)
91 {
92 joblist.setAutoDelete(false);
93 }
94
95 TQPtrList<SimpleJob> joblist;
96 SlaveList activeSlaves;
97 int maxSlaves;
98 int skipCount;
99 TQString protocol;
100};
101
102class TDEIO::Scheduler::ProtocolInfoDict : public TQDict<TDEIO::Scheduler::ProtocolInfo>
103{
104 public:
105 ProtocolInfoDict() { }
106
107 TDEIO::Scheduler::ProtocolInfo *get( const TQString &protocol);
108};
109
110TDEIO::Scheduler::ProtocolInfo *
111TDEIO::Scheduler::ProtocolInfoDict::get(const TQString &protocol)
112{
113 ProtocolInfo *info = find(protocol);
114 if (!info)
115 {
116 info = new ProtocolInfo;
117 info->protocol = protocol;
118 info->maxSlaves = KProtocolInfo::maxSlaves( protocol );
119
120 insert(protocol, info);
121 }
122 return info;
123}
124
125
126Scheduler::Scheduler()
127 : DCOPObject( "TDEIO::Scheduler" ),
128 TQObject(tdeApp, "scheduler"),
129 slaveTimer(0, "Scheduler::slaveTimer"),
130 coSlaveTimer(0, "Scheduler::coSlaveTimer"),
131 cleanupTimer(0, "Scheduler::cleanupTimer")
132{
133 checkOnHold = true; // !! Always check with TDELauncher for the first request.
134 slaveOnHold = 0;
135 protInfoDict = new ProtocolInfoDict;
136 slaveList = new SlaveList;
137 idleSlaves = new SlaveList;
138 coIdleSlaves = new SlaveList;
139 extraJobData = new ExtraJobData;
140 sessionData = new SessionData;
141 slaveConfig = SlaveConfig::self();
142 connect(&slaveTimer, TQ_SIGNAL(timeout()), TQ_SLOT(startStep()));
143 connect(&coSlaveTimer, TQ_SIGNAL(timeout()), TQ_SLOT(slotScheduleCoSlave()));
144 connect(&cleanupTimer, TQ_SIGNAL(timeout()), TQ_SLOT(slotCleanIdleSlaves()));
145 busy = false;
146}
147
148Scheduler::~Scheduler()
149{
150 protInfoDict->setAutoDelete(true);
151 delete protInfoDict; protInfoDict = 0;
152 delete idleSlaves; idleSlaves = 0;
153 delete coIdleSlaves; coIdleSlaves = 0;
154 slaveList->setAutoDelete(true);
155 delete slaveList; slaveList = 0;
156 delete extraJobData; extraJobData = 0;
157 delete sessionData; sessionData = 0;
158 instance = 0;
159}
160
161void
162Scheduler::debug_info()
163{
164}
165
166bool Scheduler::process(const TQCString &fun, const TQByteArray &data, TQCString &replyType, TQByteArray &replyData )
167{
168 if ( fun != "reparseSlaveConfiguration(TQString)" )
169 return DCOPObject::process( fun, data, replyType, replyData );
170
171 slaveConfig = SlaveConfig::self();
172 replyType = "void";
173 TQDataStream stream( data, IO_ReadOnly );
174 TQString proto;
175 stream >> proto;
176
177 kdDebug( 7006 ) << "reparseConfiguration( " << proto << " )" << endl;
178 KProtocolManager::reparseConfiguration();
179 slaveConfig->reset();
180 sessionData->reset();
181 NetRC::self()->reload();
182
183 Slave *slave = slaveList->first();
184 for (; slave; slave = slaveList->next() )
185 if ( slave->slaveProtocol() == proto || proto.isEmpty() )
186 {
187 slave->send( CMD_REPARSECONFIGURATION );
188 slave->resetHost();
189 }
190 return true;
191}
192
193QCStringList Scheduler::functions()
194{
195 QCStringList funcs = DCOPObject::functions();
196 funcs << "void reparseSlaveConfiguration(TQString)";
197 return funcs;
198}
199
200void Scheduler::_doJob(SimpleJob *job) {
201 JobData *jobData = new JobData;
202 jobData->protocol = KProtocolManager::slaveProtocol(job->url(), jobData->proxy);
203// kdDebug(7006) << "Scheduler::_doJob protocol=" << jobData->protocol << endl;
204 if (job->command() == CMD_GET)
205 {
206 jobData->checkOnHold = checkOnHold;
207 checkOnHold = false;
208 }
209 extraJobData->replace(job, jobData);
210 newJobs.append(job);
211 slaveTimer.start(0, true);
212#ifndef NDEBUG
213 if (newJobs.count() > 150)
214 kdDebug() << "WARNING - TDEIO::Scheduler got more than 150 jobs! This shows a misuse in your app (yes, a job is a TQObject)." << endl;
215#endif
216}
217
218void Scheduler::_scheduleJob(SimpleJob *job) {
219 newJobs.removeRef(job);
220 JobData *jobData = extraJobData->find(job);
221 if (!jobData)
222{
223 kdFatal(7006) << "BUG! _ScheduleJob(): No extraJobData for job!" << endl;
224 return;
225}
226 TQString protocol = jobData->protocol;
227// kdDebug(7006) << "Scheduler::_scheduleJob protocol=" << protocol << endl;
228 ProtocolInfo *protInfo = protInfoDict->get(protocol);
229 protInfo->joblist.append(job);
230
231 slaveTimer.start(0, true);
232}
233
234void Scheduler::_cancelJob(SimpleJob *job) {
235// kdDebug(7006) << "Scheduler: canceling job " << job << endl;
236 Slave *slave = job->slave();
237 if ( !slave )
238 {
239 // was not yet running (don't call this on a finished job!)
240 JobData *jobData = extraJobData->find(job);
241 if (!jobData)
242 return; // I said: "Don't call this on a finished job!"
243
244 newJobs.removeRef(job);
245 ProtocolInfo *protInfo = protInfoDict->get(jobData->protocol);
246 protInfo->joblist.removeRef(job);
247
248 // Search all slaves to see if job is in the queue of a coSlave
249 slave = slaveList->first();
250 for(; slave; slave = slaveList->next())
251 {
252 JobList *list = coSlaves.find(slave);
253 if (list && list->removeRef(job))
254 break; // Job was found and removed.
255 // Fall through to kill the slave as well!
256 }
257 if (!slave)
258 {
259 extraJobData->remove(job);
260 return; // Job was not yet running and not in a coSlave queue.
261 }
262 }
263 kdDebug(7006) << "Scheduler: killing slave " << slave->slave_pid() << endl;
264 slave->kill();
265 _jobFinished( job, slave );
266 slotSlaveDied( slave);
267}
268
269void Scheduler::startStep()
270{
271 while(newJobs.count())
272 {
273 (void) startJobDirect();
274 }
275 TQDictIterator<TDEIO::Scheduler::ProtocolInfo> it(*protInfoDict);
276 while(it.current())
277 {
278 if (startJobScheduled(it.current())) return;
279 ++it;
280 }
281}
282
283void Scheduler::setupSlave(TDEIO::Slave *slave, const KURL &url, const TQString &protocol, const TQString &proxy , bool newSlave, const TDEIO::MetaData *config)
284{
285 TQString host = url.host();
286 int port = url.port();
287 TQString user = url.user();
288 TQString passwd = url.pass();
289
290 if ((newSlave) ||
291 (slave->host() != host) ||
292 (slave->port() != port) ||
293 (slave->user() != user) ||
294 (slave->passwd() != passwd))
295 {
296 slaveConfig = SlaveConfig::self();
297
298 MetaData configData = slaveConfig->configData(protocol, host);
299 sessionData->configDataFor( configData, protocol, host );
300
301 configData["UseProxy"] = proxy;
302
303 TQString autoLogin = configData["EnableAutoLogin"].lower();
304 if ( autoLogin == "true" )
305 {
306 NetRC::AutoLogin l;
307 l.login = user;
308 bool usern = (protocol == "ftp");
309 if ( NetRC::self()->lookup( url, l, usern) )
310 {
311 configData["autoLoginUser"] = l.login;
312 configData["autoLoginPass"] = l.password;
313 if ( usern )
314 {
315 TQString macdef;
316 TQMap<TQString, TQStringList>::ConstIterator it = l.macdef.begin();
317 for ( ; it != l.macdef.end(); ++it )
318 macdef += it.key() + '\\' + it.data().join( "\\" ) + '\n';
319 configData["autoLoginMacro"] = macdef;
320 }
321 }
322 }
323 if (config)
324 configData += *config;
325 slave->setConfig(configData);
326 slave->setProtocol(url.protocol());
327 slave->setHost(host, port, user, passwd);
328 }
329}
330
331bool Scheduler::startJobScheduled(ProtocolInfo *protInfo)
332{
333 if (protInfo->joblist.isEmpty())
334 return false;
335
336// kdDebug(7006) << "Scheduling job" << endl;
337 debug_info();
338 bool newSlave = false;
339
340 SimpleJob *job = 0;
341 Slave *slave = 0;
342
343 if (protInfo->skipCount > 2)
344 {
345 bool dummy;
346 // Prevent starvation. We skip the first entry in the queue at most
347 // 2 times in a row. The
348 protInfo->skipCount = 0;
349 job = protInfo->joblist.at(0);
350 slave = findIdleSlave(protInfo, job, dummy );
351 }
352 else
353 {
354 bool exact=false;
355 SimpleJob *firstJob = 0;
356 Slave *firstSlave = 0;
357 for(uint i = 0; (i < protInfo->joblist.count()) && (i < 10); i++)
358 {
359 job = protInfo->joblist.at(i);
360 slave = findIdleSlave(protInfo, job, exact);
361 if (!firstSlave)
362 {
363 firstJob = job;
364 firstSlave = slave;
365 }
366 if (!slave) break;
367 if (exact) break;
368 }
369
370 if (!exact)
371 {
372 slave = firstSlave;
373 job = firstJob;
374 }
375 if (job == firstJob)
376 protInfo->skipCount = 0;
377 else
378 protInfo->skipCount++;
379 }
380
381 if (!slave)
382 {
383 if ( protInfo->maxSlaves > static_cast<int>(protInfo->activeSlaves.count()) )
384 {
385 newSlave = true;
386 slave = createSlave(protInfo, job, job->url());
387 if (!slave)
388 slaveTimer.start(0, true);
389 }
390 }
391
392 if (!slave)
393 {
394// kdDebug(7006) << "No slaves available" << endl;
395// kdDebug(7006) << " -- active: " << protInfo->activeSlaves.count() << endl;
396 return false;
397 }
398
399 protInfo->activeSlaves.append(slave);
400 idleSlaves->removeRef(slave);
401 protInfo->joblist.removeRef(job);
402// kdDebug(7006) << "scheduler: job started " << job << endl;
403
404
405 JobData *jobData = extraJobData->find(job);
406 setupSlave(slave, job->url(), jobData->protocol, jobData->proxy, newSlave);
407 job->start(slave);
408
409 slaveTimer.start(0, true);
410 return true;
411}
412
413bool Scheduler::startJobDirect()
414{
415 debug_info();
416 SimpleJob *job = newJobs.take(0);
417 JobData *jobData = extraJobData->find(job);
418 if (!jobData)
419 {
420 kdFatal(7006) << "BUG! startjobDirect(): No extraJobData for job!"
421 << endl;
422 return false;
423 }
424 TQString protocol = jobData->protocol;
425 ProtocolInfo *protInfo = protInfoDict->get(protocol);
426
427 bool newSlave = false;
428 bool dummy;
429
430 // Look for matching slave
431 Slave *slave = findIdleSlave(protInfo, job, dummy);
432
433 if (!slave)
434 {
435 newSlave = true;
436 slave = createSlave(protInfo, job, job->url());
437 }
438
439 if (!slave)
440 return false;
441
442 idleSlaves->removeRef(slave);
443// kdDebug(7006) << "scheduler: job started " << job << endl;
444
445 setupSlave(slave, job->url(), protocol, jobData->proxy, newSlave);
446 job->start(slave);
447 return true;
448}
449
450static Slave *searchIdleList(SlaveList *idleSlaves, const KURL &url, const TQString &protocol, bool &exact)
451{
452 TQString host = url.host();
453 int port = url.port();
454 TQString user = url.user();
455 exact = true;
456
457 for( Slave *slave = idleSlaves->first();
458 slave;
459 slave = idleSlaves->next())
460 {
461 if ((protocol == slave->slaveProtocol()) &&
462 (host == slave->host()) &&
463 (port == slave->port()) &&
464 (user == slave->user()))
465 return slave;
466 }
467
468 exact = false;
469
470 // Look for slightly matching slave
471 for( Slave *slave = idleSlaves->first();
472 slave;
473 slave = idleSlaves->next())
474 {
475 if (protocol == slave->slaveProtocol())
476 return slave;
477 }
478 return 0;
479}
480
481Slave *Scheduler::findIdleSlave(ProtocolInfo *, SimpleJob *job, bool &exact)
482{
483 Slave *slave = 0;
484 JobData *jobData = extraJobData->find(job);
485 if (!jobData)
486 {
487 kdFatal(7006) << "BUG! findIdleSlave(): No extraJobData for job!" << endl;
488 return 0;
489 }
490 if (jobData->checkOnHold)
491 {
492 slave = Slave::holdSlave(jobData->protocol, job->url());
493 if (slave)
494 return slave;
495 }
496 if (slaveOnHold)
497 {
498 // Make sure that the job wants to do a GET or a POST, and with no offset
499 bool bCanReuse = (job->command() == CMD_GET);
500 TDEIO::TransferJob * tJob = dynamic_cast<TDEIO::TransferJob *>(job);
501 if ( tJob )
502 {
503 bCanReuse = (job->command() == CMD_GET || job->command() == CMD_SPECIAL);
504 if ( bCanReuse )
505 {
506 TDEIO::MetaData outgoing = tJob->outgoingMetaData();
507 TQString resume = (!outgoing.contains("resume")) ? TQString() : outgoing["resume"];
508 kdDebug(7006) << "Resume metadata is '" << resume << "'" << endl;
509 bCanReuse = (resume.isEmpty() || resume == "0");
510 }
511 }
512// kdDebug(7006) << "bCanReuse = " << bCanReuse << endl;
513 if (bCanReuse)
514 {
515 if (job->url() == urlOnHold)
516 {
517 kdDebug(7006) << "HOLD: Reusing held slave for " << urlOnHold.prettyURL() << endl;
518 slave = slaveOnHold;
519 }
520 else
521 {
522 kdDebug(7006) << "HOLD: Discarding held slave (" << urlOnHold.prettyURL() << ")" << endl;
523 slaveOnHold->kill();
524 }
525 slaveOnHold = 0;
526 urlOnHold = KURL();
527 }
528 if (slave)
529 return slave;
530 }
531
532 return searchIdleList(idleSlaves, job->url(), jobData->protocol, exact);
533}
534
535Slave *Scheduler::createSlave(ProtocolInfo *protInfo, SimpleJob *job, const KURL &url)
536{
537 int error;
538 TQString errortext;
539 Slave *slave = Slave::createSlave(protInfo->protocol, url, error, errortext);
540 if (slave)
541 {
542 slaveList->append(slave);
543 idleSlaves->append(slave);
544 connect(slave, TQ_SIGNAL(slaveDied(TDEIO::Slave *)),
545 TQ_SLOT(slotSlaveDied(TDEIO::Slave *)));
546 connect(slave, TQ_SIGNAL(slaveStatus(pid_t,const TQCString &,const TQString &, bool)),
547 TQ_SLOT(slotSlaveStatus(pid_t,const TQCString &, const TQString &, bool)));
548
549 connect(slave,TQ_SIGNAL(authorizationKey(const TQCString&, const TQCString&, bool)),
550 sessionData,TQ_SLOT(slotAuthData(const TQCString&, const TQCString&, bool)));
551 connect(slave,TQ_SIGNAL(delAuthorization(const TQCString&)), sessionData,
552 TQ_SLOT(slotDelAuthData(const TQCString&)));
553 }
554 else
555 {
556 kdError() <<": couldn't create slave : " << errortext << endl;
557 if (job)
558 {
559 protInfo->joblist.removeRef(job);
560 extraJobData->remove(job);
561 job->slotError( error, errortext );
562 }
563 }
564 return slave;
565}
566
567void Scheduler::slotSlaveStatus(pid_t, const TQCString &, const TQString &, bool)
568{
569}
570
571void Scheduler::_jobFinished(SimpleJob *job, Slave *slave)
572{
573 JobData *jobData = extraJobData->take(job);
574 if (!jobData)
575 {
576 kdFatal(7006) << "BUG! _jobFinished(): No extraJobData for job!" << endl;
577 return;
578 }
579 ProtocolInfo *protInfo = protInfoDict->get(jobData->protocol);
580 delete jobData;
581 slave->disconnect(job);
582 protInfo->activeSlaves.removeRef(slave);
583 if (slave->isAlive())
584 {
585 JobList *list = coSlaves.find(slave);
586 if (list)
587 {
588 assert(slave->isConnected());
589 assert(!coIdleSlaves->contains(slave));
590 coIdleSlaves->append(slave);
591 if (!list->isEmpty())
592 coSlaveTimer.start(0, true);
593 return;
594 }
595 else
596 {
597 assert(!slave->isConnected());
598 idleSlaves->append(slave);
599 slave->setIdle();
600 _scheduleCleanup();
601// slave->send( CMD_SLAVE_STATUS );
602 }
603 }
604 if (protInfo->joblist.count())
605 {
606 slaveTimer.start(0, true);
607 }
608}
609
610void Scheduler::slotSlaveDied(TDEIO::Slave *slave)
611{
612 assert(!slave->isAlive());
613 ProtocolInfo *protInfo = protInfoDict->get(slave->slaveProtocol());
614 protInfo->activeSlaves.removeRef(slave);
615 if (slave == slaveOnHold)
616 {
617 slaveOnHold = 0;
618 urlOnHold = KURL();
619 }
620 idleSlaves->removeRef(slave);
621 JobList *list = coSlaves.find(slave);
622 if (list)
623 {
624 // coSlave dies, kill jobs waiting in queue
625 disconnectSlave(slave);
626 }
627
628 if (!slaveList->removeRef(slave))
629 kdDebug(7006) << "Scheduler: BUG!! Slave " << slave << "/" << slave->slave_pid() << " died, but is NOT in slaveList!!!\n" << endl;
630 else
631 slave->deref(); // Delete slave
632}
633
634void Scheduler::slotCleanIdleSlaves()
635{
636 for(Slave *slave = idleSlaves->first();slave;)
637 {
638 if (slave->idleTime() >= MAX_SLAVE_IDLE)
639 {
640 // kdDebug(7006) << "Removing idle slave: " << slave->slaveProtocol() << " " << slave->host() << endl;
641 Slave *removeSlave = slave;
642 slave = idleSlaves->next();
643 idleSlaves->removeRef(removeSlave);
644 slaveList->removeRef(removeSlave);
645 removeSlave->connection()->close();
646 removeSlave->deref();
647 }
648 else
649 {
650 slave = idleSlaves->next();
651 }
652 }
653 _scheduleCleanup();
654}
655
656void Scheduler::_scheduleCleanup()
657{
658 if (idleSlaves->count())
659 {
660 if (!cleanupTimer.isActive())
661 cleanupTimer.start( MAX_SLAVE_IDLE*1000, true );
662 }
663}
664
665void Scheduler::_putSlaveOnHold(TDEIO::SimpleJob *job, const KURL &url)
666{
667 Slave *slave = job->slave();
668 slave->disconnect(job);
669
670 if (slaveOnHold)
671 {
672 slaveOnHold->kill();
673 }
674 slaveOnHold = slave;
675 urlOnHold = url;
676 slaveOnHold->suspend();
677}
678
679void Scheduler::_publishSlaveOnHold()
680{
681 if (!slaveOnHold)
682 return;
683
684 slaveOnHold->hold(urlOnHold);
685}
686
687void Scheduler::_removeSlaveOnHold()
688{
689 if (slaveOnHold)
690 {
691 slaveOnHold->kill();
692 }
693 slaveOnHold = 0;
694 urlOnHold = KURL();
695}
696
697Slave *
698Scheduler::_getConnectedSlave(const KURL &url, const TDEIO::MetaData &config )
699{
700 TQString proxy;
701 TQString protocol = KProtocolManager::slaveProtocol(url, proxy);
702 bool dummy;
703 Slave *slave = searchIdleList(idleSlaves, url, protocol, dummy);
704 if (!slave)
705 {
706 ProtocolInfo *protInfo = protInfoDict->get(protocol);
707 slave = createSlave(protInfo, 0, url);
708 }
709 if (!slave)
710 return 0; // Error
711 idleSlaves->removeRef(slave);
712
713 setupSlave(slave, url, protocol, proxy, true, &config);
714
715 slave->send( CMD_CONNECT );
716 connect(slave, TQ_SIGNAL(connected()),
717 TQ_SLOT(slotSlaveConnected()));
718 connect(slave, TQ_SIGNAL(error(int, const TQString &)),
719 TQ_SLOT(slotSlaveError(int, const TQString &)));
720
721 coSlaves.insert(slave, new TQPtrList<SimpleJob>());
722// kdDebug(7006) << "_getConnectedSlave( " << slave << ")" << endl;
723 return slave;
724}
725
726void
727Scheduler::slotScheduleCoSlave()
728{
729 Slave *nextSlave;
730 slaveConfig = SlaveConfig::self();
731 for(Slave *slave = coIdleSlaves->first();
732 slave;
733 slave = nextSlave)
734 {
735 nextSlave = coIdleSlaves->next();
736 JobList *list = coSlaves.find(slave);
737 assert(list);
738 if (list && !list->isEmpty())
739 {
740 SimpleJob *job = list->take(0);
741 coIdleSlaves->removeRef(slave);
742// kdDebug(7006) << "scheduler: job started " << job << endl;
743
744 assert(!coIdleSlaves->contains(slave));
745
746 KURL url =job->url();
747 TQString host = url.host();
748 int port = url.port();
749
750 if (slave->host() == "<reset>")
751 {
752 TQString user = url.user();
753 TQString passwd = url.pass();
754
755 MetaData configData = slaveConfig->configData(url.protocol(), url.host());
756 slave->setConfig(configData);
757 slave->setProtocol(url.protocol());
758 slave->setHost(host, port, user, passwd);
759 }
760
761 assert(slave->protocol() == url.protocol());
762 assert(slave->host() == host);
763 assert(slave->port() == port);
764 job->start(slave);
765 }
766 }
767}
768
769void
770Scheduler::slotSlaveConnected()
771{
772 Slave *slave = (Slave *)sender();
773// kdDebug(7006) << "slotSlaveConnected( " << slave << ")" << endl;
774 slave->setConnected(true);
775 disconnect(slave, TQ_SIGNAL(connected()),
776 this, TQ_SLOT(slotSlaveConnected()));
777 emit slaveConnected(slave);
778 assert(!coIdleSlaves->contains(slave));
779 coIdleSlaves->append(slave);
780 coSlaveTimer.start(0, true);
781}
782
783void
784Scheduler::slotSlaveError(int errorNr, const TQString &errorMsg)
785{
786 Slave *slave = (Slave *)sender();
787 if (!slave->isConnected() || (coIdleSlaves->find(slave) != -1))
788 {
789 // Only forward to application if slave is idle or still connecting.
790 emit slaveError(slave, errorNr, errorMsg);
791 }
792}
793
794bool
795Scheduler::_assignJobToSlave(TDEIO::Slave *slave, SimpleJob *job)
796{
797// kdDebug(7006) << "_assignJobToSlave( " << job << ", " << slave << ")" << endl;
798 TQString dummy;
799 if (!job)
800 {
801 kdDebug(7006) << "_assignJobToSlave(): ERROR, non-existing job." << endl;
802 return false;
803 }
804 if (!slave)
805 {
806 kdDebug(7006) << "_assignJobToSlave(): ERROR, non-existing slave." << endl;
807 job->kill();
808 return false;
809 }
810
811 if ((slave->slaveProtocol() != KProtocolManager::slaveProtocol( job->url(), dummy ))
812 ||
813 (!newJobs.removeRef(job)))
814 {
815 kdDebug(7006) << "_assignJobToSlave(): ERROR, nonmatching or unknown job." << endl;
816 job->kill();
817 return false;
818 }
819
820 JobList *list = coSlaves.find(slave);
821 assert(list);
822 if (!list)
823 {
824 kdDebug(7006) << "_assignJobToSlave(): ERROR, unknown slave." << endl;
825 job->kill();
826 return false;
827 }
828
829 assert(list->contains(job) == 0);
830 list->append(job);
831 coSlaveTimer.start(0, true); // Start job on timer event
832
833 return true;
834}
835
836bool
837Scheduler::_disconnectSlave(TDEIO::Slave *slave)
838{
839// kdDebug(7006) << "_disconnectSlave( " << slave << ")" << endl;
840 JobList *list = coSlaves.take(slave);
841 assert(list);
842 if (!list)
843 return false;
844 // Kill jobs still in queue.
845 while(!list->isEmpty())
846 {
847 Job *job = list->take(0);
848 job->kill();
849 }
850 delete list;
851 coIdleSlaves->removeRef(slave);
852 assert(!coIdleSlaves->contains(slave));
853 disconnect(slave, TQ_SIGNAL(connected()),
854 this, TQ_SLOT(slotSlaveConnected()));
855 disconnect(slave, TQ_SIGNAL(error(int, const TQString &)),
856 this, TQ_SLOT(slotSlaveError(int, const TQString &)));
857 if (slave->isAlive())
858 {
859 idleSlaves->append(slave);
860 slave->send( CMD_DISCONNECT );
861 slave->setIdle();
862 slave->setConnected(false);
863 _scheduleCleanup();
864 }
865 return true;
866}
867
868void
869Scheduler::_checkSlaveOnHold(bool b)
870{
871 checkOnHold = b;
872}
873
874void
875Scheduler::_registerWindow(TQWidget *wid)
876{
877 if (!wid)
878 return;
879
880 TQObject *obj = wid;
881 if (!m_windowList.contains(obj))
882 {
883 // We must store the window Id because by the time
884 // the destroyed signal is emitted we can no longer
885 // access TQWidget::winId() (already destructed)
886 WId windowId = wid->winId();
887 m_windowList.insert(obj, windowId);
888 connect(wid, TQ_SIGNAL(destroyed(TQObject *)),
889 this, TQ_SLOT(slotUnregisterWindow(TQObject*)));
890 TQByteArray params;
891 TQDataStream stream(params, IO_WriteOnly);
892 stream << windowId;
893 if( !tdeApp->dcopClient()->send( "kded", "kded",
894 "registerWindowId(long int)", params ) )
895 kdDebug(7006) << "Could not register window with kded!" << endl;
896 }
897}
898
899void
900Scheduler::slotUnregisterWindow(TQObject *obj)
901{
902 if (!obj)
903 return;
904
905 TQMap<TQObject *, WId>::Iterator it = m_windowList.find(obj);
906 if (it == m_windowList.end())
907 return;
908 WId windowId = it.data();
909 disconnect( it.key(), TQ_SIGNAL(destroyed(TQObject *)),
910 this, TQ_SLOT(slotUnregisterWindow(TQObject*)));
911 m_windowList.remove( it );
912 if (tdeApp)
913 {
914 TQByteArray params;
915 TQDataStream stream(params, IO_WriteOnly);
916 stream << windowId;
917 tdeApp->dcopClient()->send( "kded", "kded",
918 "unregisterWindowId(long int)", params );
919 }
920}
921
922Scheduler* Scheduler::self() {
923 if ( !instance ) {
924 instance = new Scheduler;
925 }
926 return instance;
927}
928
929void Scheduler::virtual_hook( int id, void* data )
930{ DCOPObject::virtual_hook( id, data ); }
931
932
933
934#include "scheduler.moc"
KProtocolInfo::maxSlaves
static int maxSlaves(const TQString &protocol)
Returns the soft limit on the number of slaves for this protocol.
KProtocolManager::slaveProtocol
static TQString slaveProtocol(const KURL &url, TQString &proxy)
Return the protocol to use in order to handle the given url It's usually the same,...
Definition: tdeprotocolmanager.cpp:329
KProtocolManager::reparseConfiguration
static void reparseConfiguration()
Force a reload of the general config file of io-slaves ( tdeioslaverc).
Definition: tdeprotocolmanager.cpp:78
TDEIO::Connection::close
void close()
Closes the connection.
Definition: connection.cpp:86
TDEIO::Job
The base class for all jobs.
Definition: jobclasses.h:67
TDEIO::Job::kill
virtual void kill(bool quietly=true)
Abort this job.
Definition: job.cpp:260
TDEIO::MetaData
MetaData is a simple map of key/value strings.
Definition: global.h:516
TDEIO::NetRC::lookup
bool lookup(const KURL &url, AutoLogin &login, bool userealnetrc=false, TQString type=TQString::null, int mode=(exactOnly|defaultOnly))
Looks up the login information for the given url.
Definition: authinfo.cpp:122
TDEIO::NetRC::reload
void reload()
Reloads the auto login information.
Definition: authinfo.h:297
TDEIO::NetRC::self
static NetRC * self()
A reference to the instance of the class.
Definition: authinfo.cpp:115
TDEIO::Scheduler
The TDEIO::Scheduler manages io-slaves for the application.
Definition: scheduler.h:110
TDEIO::Scheduler::connect
static bool connect(const char *signal, const TQObject *receiver, const char *member)
Function to connect signals emitted by the scheduler.
Definition: scheduler.h:258
TDEIO::Scheduler::slotUnregisterWindow
void slotUnregisterWindow(TQObject *)
Definition: scheduler.cpp:900
TDEIO::SimpleJob
A simple job (one url and one command).
Definition: jobclasses.h:527
TDEIO::SimpleJob::url
const KURL & url() const
Returns the SimpleJob's URL.
Definition: jobclasses.h:548
TDEIO::SimpleJob::kill
virtual void kill(bool quietly=true)
Abort job.
Definition: job.cpp:486
TDEIO::SlaveConfig::configData
MetaData configData(const TQString &protocol, const TQString &host)
Query slave configuration for slaves of type protocol when dealing with host.
Definition: slaveconfig.cpp:192
TDEIO::SlaveConfig::reset
void reset()
Undo any changes made by calls to setConfigData.
Definition: slaveconfig.cpp:216
TDEIO::Slave
Attention developers: If you change the implementation of TDEIO::Slave, do not use connection() or sl...
Definition: slave.h:44
TDEIO::Slave::passwd
TQString passwd()
Definition: slave.h:138
TDEIO::Slave::connection
TDE_DEPRECATED Connection * connection()
Definition: slave.h:207
TDEIO::Slave::createSlave
static Slave * createSlave(const TQString &protocol, const KURL &url, int &error, TQString &error_text)
Creates a new slave.
Definition: slave.cpp:355
TDEIO::Slave::slaveProtocol
TQString slaveProtocol()
The actual protocol used to handle the request.
Definition: slave.h:118
TDEIO::Slave::port
int port()
Definition: slave.h:128
TDEIO::Slave::suspend
void suspend()
Suspends the operation of the attached tdeioslave.
Definition: slave.cpp:254
TDEIO::Slave::user
TQString user()
Definition: slave.h:133
TDEIO::Slave::kill
void kill()
Force termination.
Definition: slave.cpp:317
TDEIO::Slave::idleTime
time_t idleTime()
Definition: slave.cpp:206
TDEIO::Slave::setIdle
void setIdle()
Marks this slave as idle.
Definition: slave.cpp:201
TDEIO::Slave::host
TQString host()
Definition: slave.h:123
TDEIO::Slave::protocol
TQString protocol()
The protocol this slave handles.
Definition: slave.h:103
TDEIO::Slave::setHost
void setHost(const TQString &host, int port, const TQString &user, const TQString &passwd)
Set host for url.
Definition: slave.cpp:328
TDEIO::Slave::isAlive
bool isAlive()
Definition: slave.h:76
TDEIO::Slave::hold
void hold(const KURL &url)
Puts the tdeioslave associated with url at halt.
Definition: slave.cpp:216
TDEIO::Slave::send
void send(int cmd, const TQByteArray &data=TQByteArray())
Sends the given command to the tdeioslave.
Definition: slave.cpp:285
TDEIO::Slave::resetHost
void resetHost()
Clear host info.
Definition: slave.cpp:342
TDEIO::Slave::setConfig
void setConfig(const MetaData &config)
Configure slave.
Definition: slave.cpp:347
TDEIO::TransferJob
The transfer job pumps data into and/or out of a Slave.
Definition: jobclasses.h:874
TDEIO
A namespace for TDEIO globals.
Definition: authinfo.h:29
TDEIO::get
TDEIO_EXPORT TransferJob * get(const KURL &url, bool reload=false, bool showProgressInfo=true)
Get (a.k.a.
Definition: job.cpp:1284
TDEIO::NetRC::AutoLogin
Contains auto login information.
Definition: authinfo.h:266

tdeio/tdeio

Skip menu "tdeio/tdeio"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

tdeio/tdeio

Skip menu "tdeio/tdeio"
  • arts
  • dcop
  • dnssd
  • interfaces
  •   kspeech
  •     interface
  •     library
  •   tdetexteditor
  • kate
  • kded
  • kdoctools
  • kimgio
  • kjs
  • libtdemid
  • libtdescreensaver
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdeioslave
  •   http
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for tdeio/tdeio by doxygen 1.9.4
This website is maintained by Timothy Pearson.