• 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 
43 using namespace TDEIO;
44 
45 template class TQDict<TDEIO::Scheduler::ProtocolInfo>;
46 
47 Scheduler *Scheduler::instance = 0;
48 
49 class 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 
70 class TDEIO::Scheduler::JobData
71 {
72 public:
73  JobData() : checkOnHold(false) { }
74 
75 public:
76  TQString protocol;
77  TQString proxy;
78  bool checkOnHold;
79 };
80 
81 class TDEIO::Scheduler::ExtraJobData: public TQPtrDict<TDEIO::Scheduler::JobData>
82 {
83 public:
84  ExtraJobData() { setAutoDelete(true); }
85 };
86 
87 class TDEIO::Scheduler::ProtocolInfo
88 {
89 public:
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 
102 class TDEIO::Scheduler::ProtocolInfoDict : public TQDict<TDEIO::Scheduler::ProtocolInfo>
103 {
104  public:
105  ProtocolInfoDict() { }
106 
107  TDEIO::Scheduler::ProtocolInfo *get( const TQString &protocol);
108 };
109 
110 TDEIO::Scheduler::ProtocolInfo *
111 TDEIO::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 
126 Scheduler::Scheduler()
127  : DCOPObject( "TDEIO::Scheduler" ),
128  TQObject(kapp, "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, TQT_SIGNAL(timeout()), TQT_SLOT(startStep()));
143  connect(&coSlaveTimer, TQT_SIGNAL(timeout()), TQT_SLOT(slotScheduleCoSlave()));
144  connect(&cleanupTimer, TQT_SIGNAL(timeout()), TQT_SLOT(slotCleanIdleSlaves()));
145  busy = false;
146 }
147 
148 Scheduler::~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 
161 void
162 Scheduler::debug_info()
163 {
164 }
165 
166 bool 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 
193 QCStringList Scheduler::functions()
194 {
195  QCStringList funcs = DCOPObject::functions();
196  funcs << "void reparseSlaveConfiguration(TQString)";
197  return funcs;
198 }
199 
200 void 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 
218 void 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 
234 void 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 
269 void 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 
283 void 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 
331 bool 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 
413 bool 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 
450 static 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 
481 Slave *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 
535 Slave *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, TQT_SIGNAL(slaveDied(TDEIO::Slave *)),
545  TQT_SLOT(slotSlaveDied(TDEIO::Slave *)));
546  connect(slave, TQT_SIGNAL(slaveStatus(pid_t,const TQCString &,const TQString &, bool)),
547  TQT_SLOT(slotSlaveStatus(pid_t,const TQCString &, const TQString &, bool)));
548 
549  connect(slave,TQT_SIGNAL(authorizationKey(const TQCString&, const TQCString&, bool)),
550  sessionData,TQT_SLOT(slotAuthData(const TQCString&, const TQCString&, bool)));
551  connect(slave,TQT_SIGNAL(delAuthorization(const TQCString&)), sessionData,
552  TQT_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 
567 void Scheduler::slotSlaveStatus(pid_t, const TQCString &, const TQString &, bool)
568 {
569 }
570 
571 void 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 
610 void 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 
634 void 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 
656 void Scheduler::_scheduleCleanup()
657 {
658  if (idleSlaves->count())
659  {
660  if (!cleanupTimer.isActive())
661  cleanupTimer.start( MAX_SLAVE_IDLE*1000, true );
662  }
663 }
664 
665 void 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 
679 void Scheduler::_publishSlaveOnHold()
680 {
681  if (!slaveOnHold)
682  return;
683 
684  slaveOnHold->hold(urlOnHold);
685 }
686 
687 void Scheduler::_removeSlaveOnHold()
688 {
689  if (slaveOnHold)
690  {
691  slaveOnHold->kill();
692  }
693  slaveOnHold = 0;
694  urlOnHold = KURL();
695 }
696 
697 Slave *
698 Scheduler::_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, TQT_SIGNAL(connected()),
717  TQT_SLOT(slotSlaveConnected()));
718  connect(slave, TQT_SIGNAL(error(int, const TQString &)),
719  TQT_SLOT(slotSlaveError(int, const TQString &)));
720 
721  coSlaves.insert(slave, new TQPtrList<SimpleJob>());
722 // kdDebug(7006) << "_getConnectedSlave( " << slave << ")" << endl;
723  return slave;
724 }
725 
726 void
727 Scheduler::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 
769 void
770 Scheduler::slotSlaveConnected()
771 {
772  Slave *slave = (Slave *)sender();
773 // kdDebug(7006) << "slotSlaveConnected( " << slave << ")" << endl;
774  slave->setConnected(true);
775  disconnect(slave, TQT_SIGNAL(connected()),
776  this, TQT_SLOT(slotSlaveConnected()));
777  emit slaveConnected(slave);
778  assert(!coIdleSlaves->contains(slave));
779  coIdleSlaves->append(slave);
780  coSlaveTimer.start(0, true);
781 }
782 
783 void
784 Scheduler::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 
794 bool
795 Scheduler::_assignJobToSlave(TDEIO::Slave *slave, SimpleJob *job)
796 {
797 // kdDebug(7006) << "_assignJobToSlave( " << job << ", " << slave << ")" << endl;
798  TQString dummy;
799  if ((slave->slaveProtocol() != KProtocolManager::slaveProtocol( job->url(), dummy ))
800  ||
801  (!newJobs.removeRef(job)))
802  {
803  kdDebug(7006) << "_assignJobToSlave(): ERROR, nonmatching or unknown job." << endl;
804  job->kill();
805  return false;
806  }
807 
808  JobList *list = coSlaves.find(slave);
809  assert(list);
810  if (!list)
811  {
812  kdDebug(7006) << "_assignJobToSlave(): ERROR, unknown slave." << endl;
813  job->kill();
814  return false;
815  }
816 
817  assert(list->contains(job) == 0);
818  list->append(job);
819  coSlaveTimer.start(0, true); // Start job on timer event
820 
821  return true;
822 }
823 
824 bool
825 Scheduler::_disconnectSlave(TDEIO::Slave *slave)
826 {
827 // kdDebug(7006) << "_disconnectSlave( " << slave << ")" << endl;
828  JobList *list = coSlaves.take(slave);
829  assert(list);
830  if (!list)
831  return false;
832  // Kill jobs still in queue.
833  while(!list->isEmpty())
834  {
835  Job *job = list->take(0);
836  job->kill();
837  }
838  delete list;
839  coIdleSlaves->removeRef(slave);
840  assert(!coIdleSlaves->contains(slave));
841  disconnect(slave, TQT_SIGNAL(connected()),
842  this, TQT_SLOT(slotSlaveConnected()));
843  disconnect(slave, TQT_SIGNAL(error(int, const TQString &)),
844  this, TQT_SLOT(slotSlaveError(int, const TQString &)));
845  if (slave->isAlive())
846  {
847  idleSlaves->append(slave);
848  slave->send( CMD_DISCONNECT );
849  slave->setIdle();
850  slave->setConnected(false);
851  _scheduleCleanup();
852  }
853  return true;
854 }
855 
856 void
857 Scheduler::_checkSlaveOnHold(bool b)
858 {
859  checkOnHold = b;
860 }
861 
862 void
863 Scheduler::_registerWindow(TQWidget *wid)
864 {
865  if (!wid)
866  return;
867 
868  TQObject *obj = TQT_TQOBJECT(wid);
869  if (!m_windowList.contains(obj))
870  {
871  // We must store the window Id because by the time
872  // the destroyed signal is emitted we can no longer
873  // access TQWidget::winId() (already destructed)
874  WId windowId = wid->winId();
875  m_windowList.insert(obj, windowId);
876  connect(TQT_TQOBJECT(wid), TQT_SIGNAL(destroyed(TQObject *)),
877  this, TQT_SLOT(slotUnregisterWindow(TQObject*)));
878  TQByteArray params;
879  TQDataStream stream(params, IO_WriteOnly);
880  stream << windowId;
881  if( !kapp->dcopClient()->send( "kded", "kded",
882  "registerWindowId(long int)", params ) )
883  kdDebug(7006) << "Could not register window with kded!" << endl;
884  }
885 }
886 
887 void
888 Scheduler::slotUnregisterWindow(TQObject *obj)
889 {
890  if (!obj)
891  return;
892 
893  TQMap<TQObject *, WId>::Iterator it = m_windowList.find(obj);
894  if (it == m_windowList.end())
895  return;
896  WId windowId = it.data();
897  disconnect( it.key(), TQT_SIGNAL(destroyed(TQObject *)),
898  this, TQT_SLOT(slotUnregisterWindow(TQObject*)));
899  m_windowList.remove( it );
900  if (kapp)
901  {
902  TQByteArray params;
903  TQDataStream stream(params, IO_WriteOnly);
904  stream << windowId;
905  kapp->dcopClient()->send( "kded", "kded",
906  "unregisterWindowId(long int)", params );
907  }
908 }
909 
910 Scheduler* Scheduler::self() {
911  if ( !instance ) {
912  instance = new Scheduler;
913  }
914  return instance;
915 }
916 
917 void Scheduler::virtual_hook( int id, void* data )
918 { DCOPObject::virtual_hook( id, data ); }
919 
920 
921 
922 #include "scheduler.moc"
TDEIO::Slave::connection
KDE_DEPRECATED Connection * connection()
Definition: slave.h:207
TDEIO::Slave::isAlive
bool isAlive()
Definition: slave.h:76
TDEIO::Slave::resetHost
void resetHost()
Clear host info.
Definition: slave.cpp:342
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::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
KProtocolInfo::maxSlaves
static int maxSlaves(const TQString &protocol)
Returns the soft limit on the number of slaves for this protocol.
TDEIO::Slave::suspend
void suspend()
Suspends the operation of the attached tdeioslave.
Definition: slave.cpp:254
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::SimpleJob::url
const KURL & url() const
Returns the SimpleJob's URL.
Definition: jobclasses.h:548
TDEIO::Slave::slaveProtocol
TQString slaveProtocol()
The actual protocol used to handle the request.
Definition: slave.h:118
TDEIO::NetRC::AutoLogin
Contains auto login information.
Definition: authinfo.h:265
TDEIO::Slave::setIdle
void setIdle()
Marks this slave as idle.
Definition: slave.cpp:201
TDEIO
A namespace for TDEIO globals.
Definition: authinfo.h:29
TDEIO::Job
The base class for all jobs.
Definition: jobclasses.h:67
TDEIO::Slave::idleTime
time_t idleTime()
Definition: slave.cpp:206
TDEIO::SimpleJob::kill
virtual void kill(bool quietly=true)
Abort job.
Definition: job.cpp:457
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::Slave::user
TQString user()
Definition: slave.h:133
TDEIO::Job::kill
virtual void kill(bool quietly=true)
Abort this job.
Definition: job.cpp:239
TDEIO::Scheduler
The TDEIO::Scheduler manages io-slaves for the application.
Definition: scheduler.h:110
TDEIO::Slave::protocol
TQString protocol()
The protocol this slave handles.
Definition: slave.h:103
TDEIO::Slave::port
int port()
Definition: slave.h:128
TDEIO::NetRC::self
static NetRC * self()
A reference to the instance of the class.
Definition: authinfo.cpp:115
TDEIO::SimpleJob
A simple job (one url and one command).
Definition: jobclasses.h:527
TDEIO::SlaveConfig::reset
void reset()
Undo any changes made by calls to setConfigData.
Definition: slaveconfig.cpp:216
TDEIO::Slave::hold
void hold(const KURL &url)
Puts the tdeioslave associated with url at halt.
Definition: slave.cpp:216
TDEIO::Slave::kill
void kill()
Force termination.
Definition: slave.cpp:317
TDEIO::Slave
Attention developers: If you change the implementation of TDEIO::Slave, do not use connection() or sl...
Definition: slave.h:43
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, except that FTP, when handled by a proxy, needs an HTTP ioslave.
Definition: tdeprotocolmanager.cpp:329
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::setConfig
void setConfig(const MetaData &config)
Configure slave.
Definition: slave.cpp:347
TDEIO::Slave::passwd
TQString passwd()
Definition: slave.h:138
TDEIO::Slave::send
void send(int cmd, const TQByteArray &data=TQByteArray())
Sends the given command to the tdeioslave.
Definition: slave.cpp:285
TDEIO::TransferJob
The transfer job pumps data into and/or out of a Slave.
Definition: jobclasses.h:874
TDEIO::Slave::host
TQString host()
Definition: slave.h:123
TDEIO::Scheduler::slotUnregisterWindow
void slotUnregisterWindow(TQObject *)
Definition: scheduler.cpp:888
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::MetaData
MetaData is a simple map of key/value strings.
Definition: global.h:515

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
  •     tdecore
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  • tdeioslave
  •   http
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for tdeio/tdeio by doxygen 1.8.8
This website is maintained by Timothy Pearson.