diff options
Diffstat (limited to 'tdeio/tdeio/scheduler.h')
-rw-r--r-- | tdeio/tdeio/scheduler.h | 364 |
1 files changed, 364 insertions, 0 deletions
diff --git a/tdeio/tdeio/scheduler.h b/tdeio/tdeio/scheduler.h new file mode 100644 index 000000000..e55b2293c --- /dev/null +++ b/tdeio/tdeio/scheduler.h @@ -0,0 +1,364 @@ +// -*- c++ -*- +/* This file is part of the KDE libraries + Copyright (C) 2000 Stephan Kulow <coolo@kde.org> + Waldo Bastian <bastian@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef _kio_scheduler_h +#define _kio_scheduler_h + +#include "tdeio/job.h" +#include "tdeio/jobclasses.h" +#include <tqtimer.h> +#include <tqptrdict.h> +#include <tqmap.h> + +#include <dcopobject.h> + +namespace TDEIO { + + class Slave; + class SlaveList; + class SlaveConfig; + class SessionData; + + /** + * The TDEIO::Scheduler manages io-slaves for the application. + * It also queues jobs and assigns the job to a slave when one + * becomes available. + * + * There are 3 possible ways for a job to get a slave: + * + * <h3>1. Direct</h3> + * This is the default. When you create a job the + * TDEIO::Scheduler will be notified and will find either an existing + * slave that is idle or it will create a new slave for the job. + * + * Example: + * \code + * TransferJob *job = TDEIO::get(KURL("http://www.kde.org")); + * \endcode + * + * + * <h3>2. Scheduled</h3> + * If you create a lot of jobs, you might want not want to have a + * slave for each job. If you schedule a job, a maximum number + * of slaves will be created. When more jobs arrive, they will be + * queued. When a slave is finished with a job, it will be assigned + * a job from the queue. + * + * Example: + * \code + * TransferJob *job = TDEIO::get(KURL("http://www.kde.org")); + * TDEIO::Scheduler::scheduleJob(job); + * \endcode + * + * <h3>3. Connection Oriented</h3> + * For some operations it is important that multiple jobs use + * the same connection. This can only be ensured if all these jobs + * use the same slave. + * + * You can ask the scheduler to open a slave for connection oriented + * operations. You can then use the scheduler to assign jobs to this + * slave. The jobs will be queued and the slave will handle these jobs + * one after the other. + * + * Example: + * \code + * Slave *slave = TDEIO::Scheduler::getConnectedSlave( + * KURL("pop3://bastian:password@mail.kde.org")); + * TransferJob *job1 = TDEIO::get( + * KURL("pop3://bastian:password@mail.kde.org/msg1")); + * TDEIO::Scheduler::assignJobToSlave(slave, job1); + * TransferJob *job2 = TDEIO::get( + * KURL("pop3://bastian:password@mail.kde.org/msg2")); + * TDEIO::Scheduler::assignJobToSlave(slave, job2); + * TransferJob *job3 = TDEIO::get( + * KURL("pop3://bastian:password@mail.kde.org/msg3")); + * TDEIO::Scheduler::assignJobToSlave(slave, job3); + * + * // ... Wait for jobs to finish... + * + * TDEIO::Scheduler::disconnectSlave(slave); + * \endcode + * + * Note that you need to explicitly disconnect the slave when the + * connection goes down, so your error handler should contain: + * \code + * if (error == TDEIO::ERR_CONNECTION_BROKEN) + * TDEIO::Scheduler::disconnectSlave(slave); + * \endcode + * + * @see TDEIO::Slave + * @see TDEIO::Job + **/ + + class TDEIO_EXPORT Scheduler : public TQObject, virtual public DCOPObject { + Q_OBJECT + + public: + typedef TQPtrList<SimpleJob> JobList; + + // InfoDict needs Info, so we can't declare it private + class ProtocolInfo; + class JobData; + + ~Scheduler(); + + /** + * Register @p job with the scheduler. + * The default is to create a new slave for the job if no slave + * is available. This can be changed by calling scheduleJob. + * @param job the job to register + */ + static void doJob(SimpleJob *job) + { self()->_doJob(job); } + + /** + * Calling ths function makes that @p job gets scheduled for later + * execution, if multiple jobs are registered it might wait for + * other jobs to finish. + * @param job the job to schedule + */ + static void scheduleJob(SimpleJob *job) + { self()->_scheduleJob(job); } + + /** + * Stop the execution of a job. + * @param job the job to cancel + */ + static void cancelJob(SimpleJob *job) + { self()->_cancelJob(job); } + + /** + * Called when a job is done. + * @param job the finished job + * @param slave the slave that executed the @p job + */ + static void jobFinished(TDEIO::SimpleJob *job, TDEIO::Slave *slave) + { self()->_jobFinished(job, slave); } + + /** + * Puts a slave on notice. A next job may reuse this slave if it + * requests the same URL. + * + * A job can be put on hold after it has emit'ed its mimetype. + * Based on the mimetype, the program can give control to another + * component in the same process which can then resume the job + * by simply asking for the same URL again. + * @param job the job that should be stopped + * @param url the URL that is handled by the @p url + */ + static void putSlaveOnHold(TDEIO::SimpleJob *job, const KURL &url) + { self()->_putSlaveOnHold(job, url); } + + /** + * Removes any slave that might have been put on hold. If a slave + * was put on hold it will be killed. + */ + static void removeSlaveOnHold() + { self()->_removeSlaveOnHold(); } + + /** + * Send the slave that was put on hold back to KLauncher. This + * allows another process to take over the slave and resume the job + * that was started. + */ + static void publishSlaveOnHold() + { self()->_publishSlaveOnHold(); } + + /** + * Requests a slave for use in connection-oriented mode. + * + * @param url This defines the username,password,host & port to + * connect with. + * @param config Configuration data for the slave. + * + * @return A pointer to a connected slave or 0 if an error occurred. + * @see assignJobToSlave() + * @see disconnectSlave() + */ + static TDEIO::Slave *getConnectedSlave(const KURL &url, const TDEIO::MetaData &config = MetaData() ) + { return self()->_getConnectedSlave(url, config); } + + /* + * Uses @p slave to do @p job. + * This function should be called immediately after creating a Job. + * + * @param slave The slave to use. The slave must have been obtained + * with a call to getConnectedSlave and must not + * be currently assigned to any other job. + * @param job The job to do. + * + * @return true is successful, false otherwise. + * + * @see getConnectedSlave() + * @see disconnectSlave() + * @see slaveConnected() + * @see slaveError() + */ + static bool assignJobToSlave(TDEIO::Slave *slave, TDEIO::SimpleJob *job) + { return self()->_assignJobToSlave(slave, job); } + + /* + * Disconnects @p slave. + * + * @param slave The slave to disconnect. The slave must have been + * obtained with a call to getConnectedSlave + * and must not be assigned to any job. + * + * @return true is successful, false otherwise. + * + * @see getConnectedSlave + * @see assignJobToSlave + */ + static bool disconnectSlave(TDEIO::Slave *slave) + { return self()->_disconnectSlave(slave); } + + /** + * Send the slave that was put on hold back to KLauncher. This + * allows another process to take over the slave and resume the job + * the that was started. + * Register the mainwindow @p wid with the KIO subsystem + * Do not call this, it is called automatically from + * void TDEIO::Job::setWindow(TQWidget*). + * @param wid the window to register + * @since 3.1 + */ + static void registerWindow(TQWidget *wid) + { self()->_registerWindow(wid); } + + /** + * @internal + * Unregisters the window registered by registerWindow(). + */ + static void unregisterWindow(TQObject *wid) + { self()->slotUnregisterWindow(wid); } + + /** + * Function to connect signals emitted by the scheduler. + * + * @see slaveConnected() + * @see slaveError() + */ + static bool connect( const char *signal, const TQObject *receiver, + const char *member) + { return TQObject::connect(self(), signal, receiver, member); } + + static bool connect( const TQObject* sender, const char* signal, + const TQObject* receiver, const char* member ) + { return TQObject::connect(sender, signal, receiver, member); } + + static bool disconnect( const TQObject* sender, const char* signal, + const TQObject* receiver, const char* member ) + { return TQObject::disconnect(sender, signal, receiver, member); } + + bool connect( const TQObject *sender, const char *signal, + const char *member ) + { return TQObject::connect(sender, signal, member); } + + /** + * When true, the next job will check whether KLauncher has a slave + * on hold that is suitable for the job. + * @param b true when KLauncher has a job on hold + */ + static void checkSlaveOnHold(bool b) { self()->_checkSlaveOnHold(b); } + + void debug_info(); + + virtual bool process(const TQCString &fun, const TQByteArray &data, + TQCString& replyType, TQByteArray &replyData); + + virtual QCStringList functions(); + + public slots: + void slotSlaveDied(TDEIO::Slave *slave); + void slotSlaveStatus(pid_t pid, const TQCString &protocol, + const TQString &host, bool connected); + signals: + void slaveConnected(TDEIO::Slave *slave); + void slaveError(TDEIO::Slave *slave, int error, const TQString &errorMsg); + + protected: + void setupSlave(TDEIO::Slave *slave, const KURL &url, const TQString &protocol, const TQString &proxy , bool newSlave, const TDEIO::MetaData *config=0); + bool startJobScheduled(ProtocolInfo *protInfo); + bool startJobDirect(); + Scheduler(); + + protected slots: + void startStep(); + void slotCleanIdleSlaves(); + void slotSlaveConnected(); + void slotSlaveError(int error, const TQString &errorMsg); + void slotScheduleCoSlave(); + /// @since 3.1 + void slotUnregisterWindow(TQObject *); + + private: + class ProtocolInfoDict; + class ExtraJobData; + + Scheduler(const Scheduler&); + static Scheduler *self(); + static Scheduler *instance; + void _doJob(SimpleJob *job); + void _scheduleJob(SimpleJob *job); + void _cancelJob(SimpleJob *job); + void _jobFinished(TDEIO::SimpleJob *job, TDEIO::Slave *slave); + void _scheduleCleanup(); + void _putSlaveOnHold(TDEIO::SimpleJob *job, const KURL &url); + void _removeSlaveOnHold(); + Slave *_getConnectedSlave(const KURL &url, const TDEIO::MetaData &metaData ); + bool _assignJobToSlave(TDEIO::Slave *slave, TDEIO::SimpleJob *job); + bool _disconnectSlave(TDEIO::Slave *slave); + void _checkSlaveOnHold(bool b); + void _publishSlaveOnHold(); + void _registerWindow(TQWidget *wid); + + Slave *findIdleSlave(ProtocolInfo *protInfo, SimpleJob *job, bool &exact); + Slave *createSlave(ProtocolInfo *protInfo, SimpleJob *job, const KURL &url); + + + TQTimer slaveTimer; + TQTimer coSlaveTimer; + TQTimer cleanupTimer; + bool busy; + + SlaveList *slaveList; + SlaveList *idleSlaves; + SlaveList *coIdleSlaves; + + ProtocolInfoDict *protInfoDict; + Slave *slaveOnHold; + KURL urlOnHold; + JobList newJobs; + + TQPtrDict<JobList> coSlaves; + ExtraJobData *extraJobData; + SlaveConfig *slaveConfig; + SessionData *sessionData; + bool checkOnHold; + TQMap<TQObject *,WId> m_windowList; + protected: + virtual void virtual_hook( int id, void* data ); + private: + class SchedulerPrivate* d; +}; + +} +#endif |