diff options
Diffstat (limited to 'kmrml/kmrml/server')
-rw-r--r-- | kmrml/kmrml/server/Makefile.am | 12 | ||||
-rw-r--r-- | kmrml/kmrml/server/daemonwatcher.desktop | 103 | ||||
-rw-r--r-- | kmrml/kmrml/server/watcher.cpp | 280 | ||||
-rw-r--r-- | kmrml/kmrml/server/watcher.h | 107 |
4 files changed, 502 insertions, 0 deletions
diff --git a/kmrml/kmrml/server/Makefile.am b/kmrml/kmrml/server/Makefile.am new file mode 100644 index 00000000..875684b0 --- /dev/null +++ b/kmrml/kmrml/server/Makefile.am @@ -0,0 +1,12 @@ +kde_module_LTLIBRARIES = kded_daemonwatcher.la + +INCLUDES = $(all_includes) +kded_daemonwatcher_la_SOURCES = watcher.cpp watcher.skel +# watcher.stub +kded_daemonwatcher_la_LDFLAGS = $(all_libraries) -module -avoid-version +kded_daemonwatcher_la_LIBADD = $(LIB_KSYCOCA) $(LIB_KDEUI) + +METASOURCES = AUTO + +servicesdir = $(kde_servicesdir)/kded +services_DATA = daemonwatcher.desktop diff --git a/kmrml/kmrml/server/daemonwatcher.desktop b/kmrml/kmrml/server/daemonwatcher.desktop new file mode 100644 index 00000000..c29495b4 --- /dev/null +++ b/kmrml/kmrml/server/daemonwatcher.desktop @@ -0,0 +1,103 @@ +[Desktop Entry] +Type=Service +Name=KDED KMRML Daemon Watcher +Name[ar]=مراقب KDED KMRML Daemon +Name[bs]=KDED KMRML nadzor demona +Name[ca]=Dimoni vigilant KDED KMRL +Name[cs]=Sledovač KMRML démonů +Name[cy]=Gwyliwr Ellyll KMRML KDED +Name[da]=KDED KMRML-dæmon-overvåger +Name[de]=Überwachung der KDE-Bildersuche +Name[el]=Επόπτης δαίμονα KMRML KDED +Name[es]=Guardián del demonio KDED KMRML +Name[et]=KDED KMRML deemoni jälgija +Name[eu]=KDED KMRML deabru behatzailea +Name[fa]=پایشگر شبح KDED KMRML +Name[fi]=KDED KMRML-palvelimen tarkkailija +Name[fr]=Observateur KDE du démon KMRML +Name[gl]=Vixiante do daemon de KDED KMRML +Name[he]=צופה תהליכי הרקע של KDED KMRML +Name[hi]=KDED KMRML डेमन वाचर +Name[hu]=KDED KMRML szolgáltatásfigyelő +Name[is]=Eftirlit með KDED KMRML þjóninum +Name[it]=Controllo del demone KDED KMRML +Name[ja]=KDED KMRML デーモンウォッチャー +Name[kk]=KDED KMRML қызметі +Name[km]=កម្មវិធីឃ្លាំមើលដេមិន KDED KMRML +Name[lt]=KDED KMRML tarnybos stebėtojas +Name[ms]=Pemerhati Daemon KDED KMRML +Name[nb]=KDED KMRML nisseovervåker +Name[nds]=KMRML-Luerdämoon för KDED +Name[ne]=KDED KMRML डेइमन दर्शक +Name[nl]=KDED KMRML-daemonbeheer +Name[nn]=KDED KMRML-nisseovervaking +Name[pl]=Monitor usług KMRML +Name[pt]=Monitor KMRML de Servidores KDED +Name[pt_BR]=Sentinela de Serviços KDED +Name[ro]=Demon KDED pentru MRML +Name[ru]=Служба MRML +Name[se]=KDED KMRML-duogášprográmmagoziheaddji +Name[sk]=Sledovanie démona KDED KMRML +Name[sl]=Opazovalnik demona KMRML za KDED +Name[sr]=KDED KMRML демон за праћење +Name[sr@Latn]=KDED KMRML demon za praćenje +Name[sv]=KDED KMRML-demonbevakare +Name[ta]=KDED டிமென் வாட்சர் +Name[tg]=Мудири демони KDED KMRML +Name[th]=ตัวเฝ้าดูแดมอน KDED KMRML +Name[tr]=KDED KMRML Aracı İzleyici +Name[uk]=Спостерігач демону KDED KMRML +Name[zh_CN]=KDED KMRML 守护程序监视器 +Name[zh_HK]=KDED KMRML 系統程式監察器 +Name[zh_TW]=KDED KMRML 伺服程式監看器 +Comment=Starts daemons on demand and restarts them on failure +Comment[bg]=Стартиране на демоните при заявка и рестартиране на демони при грешка +Comment[bs]=Pokreće demone po potrebi i restartuje ih ako se sruše +Comment[ca]=Engega els dimonis sota petició i els torna a engegar si fallen +Comment[cs]=Spouští démony na požádání a restartuje je při selhání +Comment[da]=Starter dæmoner ved forespørgsel og genstarter dem ved fejl +Comment[de]=Startet KMRML-Dienste bei Bedarf und im Fehlerfall neu +Comment[el]=Εκκινεί δαίμονες όταν ζητηθεί και τους επανεκκινεί κατά την αποτυχία +Comment[es]=Inicia los demonios bajo demanda y los reinicia si fallan +Comment[et]=Käivitab nõudmisel deemoneid ja taaskäivitab neid ebaõnnestumise korral +Comment[eu]=Demonioak hasi eta bukau egiten ditu eskatzen zaionean +Comment[fa]=شبحها را بر اساس نیاز آغاز میکند و هنگام خرابی آنها را بازآغازی میکند +Comment[fi]=Käynnistää palvelimia tarpeen mukaan ja uudelleenkäynnistää ne virheen yhteydessä +Comment[fr]=Lance les démons à la demande et les redémarre en cas d'échec +Comment[gl]=Iniciar daemons cando sexa preciso e reinicialos se fallan. +Comment[he]=מפעיל תהליכי רקע לפי דרישה ומפעיל אותם מחדש במקרה של כשל +Comment[hu]=Szükség esetén elindítja, hiba esetén újraindítja a szolgáltatásokat +Comment[is]=Ræsir þjóna þegar þarf og endurræsir þá ef þeir bregðast +Comment[it]=Avvia i demoni su richiesta e li riavvia in caso di problemi +Comment[ja]=デーモンをオンデマンドで起動し、失敗したときは再起動します。 +Comment[kk]=Талап бойынша қызметті жегу, жаңылса қайта жегу +Comment[km]=ចាប់ផ្ដើមដេមិននៅពេលត្រូវការ ហើយចាប់ផ្ដើមពួកវាឡើងវិញនៅពេលបរាជ័យ +Comment[lt]=Paleidžia tarnybas pagal pareikalavimą ir paleidžia iš naujo nesėkmės atveju +Comment[ms]=Mulakan daemons atas permintaan dan mula semula atas kegagalan +Comment[nb]=Starter nisser på forespørsler og starter dem igjen ved feil. +Comment[nds]=Start Achtergrundperzessen op Nafraag un bi Fehlers nieg +Comment[ne]=माग गरेको बेलामा डेइमन सुरु गर्दछ र अफफल भएमा फेरि सुरु गर्दछ +Comment[nl]=Start achtergrondprogramma's op en herstart deze indien nodig +Comment[nn]=Startar nissar når dei trengst og startar dei om att ved feil +Comment[pl]=Uruchamia usługi na żądanie i wznawia je po awarii +Comment[pt]=Inicia os servidores a pedido e reinicia-os em caso de falha +Comment[pt_BR]=Inicia serviços sob demanda e reinicia-os em caso de falha +Comment[ro]=Porneşte demonii la cerere şi îi reporneşte în caz de eroare +Comment[ru]=Поддержка протокола MRML +Comment[sk]=Spustí démonov podľa požiadaviek a pri zlyhaní ich reštartuje +Comment[sl]=Na zahtevo zažene demone in jih ob napaki znova zažene +Comment[sr]=На захтев покреће демоне и поново их покреће ако се сруше +Comment[sr@Latn]=Na zahtev pokreće demone i ponovo ih pokreće ako se sruše +Comment[sv]=Starta demoner vid behov och starta om dem vid fel +Comment[ta]=அவசிய நேரத்தில் டிமென்னை துவக்குகிறது. இயலாதபோது திரும்ப துவக்குகிறது +Comment[tg]=Оғози демон аз рӯи дархост ва ҳангоми нуқсони он аз сари нав оғоз намудан. +Comment[tr]=İstek halinde programı başlatır ve hata durumunda yeniden başlatır. +Comment[uk]=Запускає демони при потребі та перезапускає їх при аварії +Comment[zh_CN]=按需启动守护程序并在失败时重新启动 +Comment[zh_HK]=依要求啟動系統程式並在失敗時重新啟動它們。 +Comment[zh_TW]=需要時啟動守護程式,失敗的話重新啟動 +ServiceTypes=KDEDModule +X-KDE-ModuleType=Library +X-KDE-Library=daemonwatcher +X-KDE-FactoryName=daemonwatcher +X-KDE-Kded-load-on-demand=true diff --git a/kmrml/kmrml/server/watcher.cpp b/kmrml/kmrml/server/watcher.cpp new file mode 100644 index 00000000..e6137cc5 --- /dev/null +++ b/kmrml/kmrml/server/watcher.cpp @@ -0,0 +1,280 @@ +/* This file is part of the KDE project + Copyright (C) 2002 Carsten Pfeiffer <pfeiffer@kde.org> + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation, version 2. + + This program 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <dcopclient.h> + +#include <kapplication.h> +#include <kdebug.h> +#include <kdeversion.h> +#include <klocale.h> +#include <kmessagebox.h> + +#include "watcher.h" + +using namespace KMrml; + +Watcher::Watcher( const QCString& name ) + : KDEDModule( name ) +{ + m_daemons.setAutoDelete( true ); + + // safety, for clients that die without unregistering + KApplication::dcopClient()->setNotifications( true ); + connect( KApplication::dcopClient(), + SIGNAL( applicationRemoved( const QCString& )), + SLOT( slotAppUnregistered( const QCString& ))); +} + +Watcher::~Watcher() +{ + KApplication::dcopClient()->setNotifications( false ); +} + +bool Watcher::requireDaemon( const QCString& clientAppId, + const QString& daemonKey, + const QString& commandline, + uint timeout /* seconds */, + int restartOnFailure ) +{ + if ( !KApplication::dcopClient()->isApplicationRegistered( clientAppId ) ) + kdWarning() << "Watcher::requireDaemon: " << daemonKey + << ": Client AppID is not registered with DCOP: " + << clientAppId << endl; + + DaemonData *daemon = m_daemons.find( daemonKey ); + + if ( daemon ) + { + if ( !daemon->apps.find( clientAppId ) ) + daemon->apps.append( clientAppId ); + + // timeout, commandline and restart values are: first come, first serve + return true; // process already running, all fine + } + + else // start daemon + { + daemon = new DaemonData( daemonKey, commandline, + timeout, restartOnFailure ); + m_daemons.insert( daemonKey, daemon ); + daemon->apps.append( clientAppId ); + +#if KDE_VERSION >= 306 + daemon->process = new KProcess(); + daemon->process->setUseShell( true ); +#else + daemon->process = new KShellProcess(); +#endif + daemon->process->setEnvironment( "LC_ALL", "C" ); + daemon->process->setEnvironment( "LANG", "C" ); + daemon->process->setEnvironment( "LANGUAGE", "C" ); + *daemon->process << commandline; + connect( daemon->process, SIGNAL( processExited( KProcess * ) ), + SLOT( slotProcExited( KProcess * ))); + return startDaemon( daemon ); + } +} + +void Watcher::unrequireDaemon( const QCString& clientAppId, + const QString& daemonKey ) +{ + unrequireDaemon( m_daemons.find( daemonKey ), clientAppId ); +} + +void Watcher::unrequireDaemon( DaemonData *daemon, + const QCString& clientAppId ) +{ + if ( daemon ) + { + daemon->apps.remove( clientAppId ); + if ( daemon->apps.isEmpty() ) + { + if ( !daemon->timer ) + { + daemon->timer = new QTimer(); + connect( daemon->timer, SIGNAL( timeout() ), + SLOT( slotTimeout() )); + } + daemon->timer->start( daemon->timeout * 1000, true ); + } + } + else + kdWarning() << "Watcher::unrequireDaemon: daemon unknown. client: " + << clientAppId << endl; +} + +QStringList Watcher::runningDaemons() const +{ + QStringList result; + QDictIterator<DaemonData> it( m_daemons ); + for ( ; it.current(); ++it ) + result.append( it.current()->commandline ); + + return result; +} + +void Watcher::slotProcExited( KProcess *proc ) +{ + DaemonData *daemon = findDaemonFromProcess( proc ); + + if ( proc->normalExit() ) + { + emitExited( daemon ); + return; + } + + if ( daemon ) + { + if ( --daemon->restartOnFailure <= 0 ) + { + if ( KMessageBox::questionYesNo( 0L, + i18n("<qt>The server with the command line" + "<br>%1<br>" + "is not available anymore. Do you want to " + "restart it?" ).arg( daemon->commandline ), + i18n("Service Failure"), i18n("Restart Server"), i18n("Do Not Restart") ) + == KMessageBox::Yes ) + { + daemon->restartOnFailure = 1; + } + } + + if ( daemon->restartOnFailure > 0 ) + { + startDaemon( daemon ); + return; + } + } + + emitFailure( daemon ); +} + +bool Watcher::startDaemon( DaemonData *daemon ) +{ + if ( daemon->process->start( KProcess::NotifyOnExit ) ) + return true; + + else + { + if ( KMessageBox::questionYesNo( 0L, + i18n("Unable to start the server with the " + "command line" + "<br>%1<br>" + "Try again?").arg( daemon->commandline ), + i18n("Service Failure"), i18n("Try Again"), i18n("Do Not Try") ) + == KMessageBox::Yes ) + { + return startDaemon( daemon ); + } + } + + return false; +} + +void Watcher::slotTimeout() +{ + QTimer *timer = static_cast<QTimer*>( const_cast<QObject *>( sender() ) ); + DaemonData *daemon = findDaemonFromTimer( timer ); + if ( daemon ) + { + if ( daemon->apps.isEmpty() ) + { + // the daemon and KProcess might get deleted by killing the + // KProcess (through slotProcExited()), so don't dereference + // daemon after proc->kill() + QString key = daemon->daemonKey; + + // noone registered during the timeout, so kill the daemon + if ( !daemon->process->kill() ) + daemon->process->kill( SIGKILL ); + + m_daemons.remove( key ); + } + } +} + +DaemonData * Watcher::findDaemonFromProcess( KProcess *proc ) +{ + DaemonData *daemon; + QDictIterator<DaemonData> it( m_daemons ); + for ( ; (daemon = it.current()); ++it ) + { + if ( daemon->process == proc ) + return daemon; + } + + return 0L; +} + +DaemonData * Watcher::findDaemonFromTimer( QTimer *timer ) +{ + DaemonData *daemon; + QDictIterator<DaemonData> it( m_daemons ); + for ( ; (daemon = it.current()); ++it ) + { + if ( daemon->timer == timer ) + return daemon; + } + + return 0L; +} + +void Watcher::slotAppUnregistered( const QCString& appId ) +{ + if ( m_daemons.isEmpty() ) + return; + + DaemonData *daemon; + QDictIterator<DaemonData> it( m_daemons ); + for ( ; (daemon = it.current()); ++it ) + { + if ( daemon->apps.find( appId ) != -1 ) + unrequireDaemon( daemon, appId ); + } +} + +void Watcher::emitExited( DaemonData *daemon ) +{ + if ( daemon ) + { + daemonExited( daemon->daemonKey, + daemon->process->pid(), + daemon->process->exitStatus() ); + + m_daemons.remove( daemon->daemonKey ); + } +} + +void Watcher::emitFailure( DaemonData *daemon ) +{ + if ( daemon ) + { + daemonDied( daemon->daemonKey, daemon->process->pid() ); + m_daemons.remove( daemon->daemonKey ); // deletes daemon + KProcess + } +} + +extern "C" { + KDE_EXPORT KDEDModule *create_daemonwatcher(const QCString & obj ) + { + return new Watcher( obj ); + } +} + + +#include "watcher.moc" diff --git a/kmrml/kmrml/server/watcher.h b/kmrml/kmrml/server/watcher.h new file mode 100644 index 00000000..67d9b5e1 --- /dev/null +++ b/kmrml/kmrml/server/watcher.h @@ -0,0 +1,107 @@ +/* This file is part of the KDE project + Copyright (C) 2002 Carsten Pfeiffer <pfeiffer@kde.org> + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation, version 2. + + This program 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef LAUNCHER_H +#define LAUNCHER_H + +#include <qdict.h> +#include <qmap.h> +#include <qstrlist.h> +#include <qstringlist.h> +#include <qtimer.h> + +#include <kdedmodule.h> +#include <kprocess.h> + +namespace KMrml +{ + class DaemonData + { + public: + DaemonData( const QString& key, const QString& cmd, + uint time, int numRestarts ) + : daemonKey( key ), + commandline( cmd ), + timeout( time ), + apps( true ), // deep copies + restartOnFailure( numRestarts ), + process( 0L ), + timer( 0L ) + { + } + ~DaemonData() + { + delete process; + delete timer; + } + QString daemonKey; + QString commandline; + uint timeout; + QStrList apps; + int restartOnFailure; + KProcess *process; + QTimer *timer; + }; + + class Watcher : public KDEDModule + { + Q_OBJECT + K_DCOP + + public: + Watcher( const QCString& name = "daemonwatcher" ); + ~Watcher(); + + k_dcop: + virtual bool requireDaemon( const QCString& clientAppId, + const QString& daemonKey, + const QString& commandline, + uint timeout = 60 /* seconds */, + int numRestarts = 5 ); + virtual void unrequireDaemon( const QCString& clientAppId, + const QString& daemonKey ); + virtual QStringList runningDaemons() const; + + k_dcop_signals: + void daemonExited(const QString& daemonKey, pid_t pid, int exitStatus); + void daemonDied( const QString& daemonKey, pid_t pid ); + + protected: + bool startDaemon( DaemonData *daemon ); + + protected slots: + virtual void slotTimeout(); + + private: + void unrequireDaemon( DaemonData *daemon, const QCString& clientAppId); + DaemonData *findDaemonFromProcess( KProcess *proc ); + DaemonData *findDaemonFromTimer( QTimer *timer ); + + void emitExited( DaemonData *daemon ); + void emitFailure( DaemonData *daemon ); + + private slots: + void slotProcExited( KProcess *proc ); + void slotAppUnregistered( const QCString& appId ); + + QDict<DaemonData> m_daemons; + }; + +} + +#endif // LAUNCHER_H |