• Skip to content
  • Skip to link menu
KDE 4.1 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

NepomukDaemons

servicecontroller.cpp

Go to the documentation of this file.
00001 /* This file is part of the KDE Project
00002    Copyright (c) 2008 Sebastian Trueg <trueg@kde.org>
00003 
00004    This library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Library General Public
00006    License version 2 as published by the Free Software Foundation.
00007 
00008    This library is distributed in the hope that it will be useful,
00009    but WITHOUT ANY WARRANTY; without even the implied warranty of
00010    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00011    Library General Public License for more details.
00012 
00013    You should have received a copy of the GNU Library General Public License
00014    along with this library; see the file COPYING.LIB.  If not, write to
00015    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00016    Boston, MA 02110-1301, USA.
00017 */
00018 
00019 #include "servicecontroller.h"
00020 #include "processcontrol.h"
00021 #include "servicecontrolinterface.h"
00022 #include "nepomukserver.h"
00023 
00024 #include <QtCore/QEventLoop>
00025 #include <QtCore/QTimer>
00026 
00027 #include <KStandardDirs>
00028 #include <KConfigGroup>
00029 #include <KDebug>
00030 
00031 
00032 namespace {
00033     QString dbusServiceName( const QString& serviceName ) {
00034         return QString("org.kde.nepomuk.services.%1").arg(serviceName);
00035     }
00036 }
00037 
00038 
00039 class Nepomuk::ServiceController::Private
00040 {
00041 public:
00042     Private()
00043         : processControl( 0 ),
00044           serviceControlInterface( 0 ),
00045           attached(false),
00046           initialized( false ) {
00047     }
00048 
00049     KService::Ptr service;
00050     bool autostart;
00051     bool startOnDemand;
00052     bool runOnce;
00053 
00054     ProcessControl* processControl;
00055     OrgKdeNepomukServiceControlInterface* serviceControlInterface;
00056 
00057     // true if we attached to an already running instance instead of
00058     // starting our own (in that case processControl will be 0)
00059     bool attached;
00060 
00061     bool initialized;
00062 
00063     // list of loops waiting for the service to become initialized
00064     QList<QEventLoop*> loops;
00065 
00066     void init( KService::Ptr service );
00067 };
00068 
00069 
00070 void Nepomuk::ServiceController::Private::init( KService::Ptr s )
00071 {
00072     service = s;
00073     autostart = service->property( "X-KDE-Nepomuk-autostart", QVariant::Bool ).toBool();
00074     KConfigGroup cg( Server::self()->config(), QString("Service-%1").arg(service->desktopEntryName()) );
00075     autostart = cg.readEntry( "autostart", autostart );
00076 
00077     QVariant p = service->property( "X-KDE-Nepomuk-start-on-demand", QVariant::Bool );
00078     startOnDemand = ( p.isValid() ? p.toBool() : false );
00079 
00080     p = service->property( "X-KDE-Nepomuk-run-once", QVariant::Bool );
00081     runOnce = ( p.isValid() ? p.toBool() : false );
00082 
00083     initialized = false;
00084 }
00085 
00086 
00087 Nepomuk::ServiceController::ServiceController( KService::Ptr service, QObject* parent )
00088     : QObject( parent ),
00089       d(new Private())
00090 {
00091     d->init( service );
00092 }
00093 
00094 
00095 Nepomuk::ServiceController::~ServiceController()
00096 {
00097     stop();
00098     delete d;
00099 }
00100 
00101 
00102 KService::Ptr Nepomuk::ServiceController::service() const
00103 {
00104     return d->service;
00105 }
00106 
00107 
00108 QString Nepomuk::ServiceController::name() const
00109 {
00110     return d->service->desktopEntryName();
00111 }
00112 
00113 
00114 QStringList Nepomuk::ServiceController::dependencies() const
00115 {
00116     QStringList deps = d->service->property( "X-KDE-Nepomuk-dependencies", QVariant::StringList ).toStringList();
00117     if ( deps.isEmpty() ) {
00118         deps.append( "nepomukstorage" );
00119     }
00120     deps.removeAll( name() );
00121     return deps;
00122 }
00123 
00124 
00125 void Nepomuk::ServiceController::setAutostart( bool enable )
00126 {
00127     KConfigGroup cg( Server::self()->config(), QString("Service-%1").arg(name()) );
00128     cg.writeEntry( "autostart", enable );
00129 }
00130 
00131 
00132 bool Nepomuk::ServiceController::autostart() const
00133 {
00134     return d->autostart;
00135 }
00136 
00137 
00138 bool Nepomuk::ServiceController::startOnDemand() const
00139 {
00140     return d->startOnDemand;
00141 }
00142 
00143 
00144 bool Nepomuk::ServiceController::runOnce() const
00145 {
00146     return d->runOnce;
00147 }
00148 
00149 
00150 bool Nepomuk::ServiceController::start()
00151 {
00152     if( isRunning() ) {
00153         return true;
00154     }
00155 
00156     d->initialized = false;
00157 
00158     // check if the service is already running, ie. has been started by someone else or by a crashed instance of the server
00159     // we cannot rely on the auto-restart feature of ProcessControl here. So we handle that completely in slotServiceOwnerChanged
00160     if( QDBusConnection::sessionBus().interface()->isServiceRegistered( dbusServiceName( name() ) ) ) {
00161         kDebug() << "Attaching to already running service" << name();
00162         d->attached = true;
00163         createServiceControlInterface();
00164         return true;
00165     }
00166     else {
00167         kDebug(300002) << "Starting" << name();
00168 
00169         if( !d->processControl ) {
00170             d->processControl = new ProcessControl( this );
00171             connect( d->processControl, SIGNAL( finished( bool ) ),
00172                      this, SLOT( slotProcessFinished( bool ) ) );
00173         }
00174 
00175         connect( QDBusConnection::sessionBus().interface(),
00176                  SIGNAL( serviceOwnerChanged( const QString&, const QString&, const QString& ) ),
00177                  this,
00178                  SLOT( slotServiceOwnerChanged( const QString&, const QString&, const QString& ) ) );
00179 
00180         d->processControl->setCrashPolicy( ProcessControl::RestartOnCrash );
00181         return d->processControl->start( KGlobal::dirs()->locate( "exe", "nepomukservicestub" ),
00182                                          QStringList() << name() );
00183     }
00184 }
00185 
00186 
00187 void Nepomuk::ServiceController::stop()
00188 {
00189     if( isRunning() ) {
00190         kDebug(300002) << "Stopping" << name();
00191 
00192         d->attached = false;
00193 
00194         if( d->processControl ) {
00195             d->processControl->setCrashPolicy( ProcessControl::StopOnCrash );
00196         }
00197 
00198         if ( waitForInitialized( 2000 ) ) {
00199             d->serviceControlInterface->shutdown();
00200         }
00201 
00202         if( d->processControl ) {
00203             d->processControl->stop();
00204         }
00205     }
00206 }
00207 
00208 
00209 bool Nepomuk::ServiceController::isRunning() const
00210 {
00211     return( d->attached || ( d->processControl ? d->processControl->isRunning() : false ) );
00212 }
00213 
00214 
00215 bool Nepomuk::ServiceController::isInitialized() const
00216 {
00217     return d->initialized;
00218 }
00219 
00220 
00221 bool Nepomuk::ServiceController::waitForInitialized( int timeout )
00222 {
00223     if( !isRunning() ) {
00224         return false;
00225     }
00226 
00227     if( !d->initialized ) {
00228         QEventLoop loop;
00229         d->loops.append( &loop );
00230         if ( timeout > 0 ) {
00231             QTimer::singleShot( timeout, &loop, SLOT(quit()) );
00232         }
00233         loop.exec();
00234         d->loops.removeAll( &loop );
00235     }
00236 
00237     return d->initialized;
00238 }
00239 
00240 
00241 void Nepomuk::ServiceController::slotProcessFinished( bool /*clean*/ )
00242 {
00243     kDebug() << "Service" << name() << "went down";
00244     d->initialized = false;
00245     d->attached = false;
00246     disconnect( QDBusConnection::sessionBus().interface() );
00247     delete d->serviceControlInterface;
00248     d->serviceControlInterface = 0;
00249     foreach( QEventLoop* loop, d->loops ) {
00250         loop->exit();
00251     }
00252 }
00253 
00254 
00255 void Nepomuk::ServiceController::slotServiceOwnerChanged( const QString& serviceName,
00256                                                           const QString& oldOwner,
00257                                                           const QString& newOwner )
00258 {
00259     if( !newOwner.isEmpty() && serviceName == dbusServiceName( name() ) ) {
00260         createServiceControlInterface();
00261     }
00262 
00263     // an attached service was not started through ProcessControl. Thus, we cannot rely
00264     // on its restart-on-crash feature and have to do it manually. Afterwards it is back
00265     // to normals
00266     else if( d->attached &&
00267              oldOwner == dbusServiceName( name() ) ) {
00268         kDebug() << "Attached service" << name() << "went down. Restarting ourselves.";
00269         d->attached = false;
00270         start();
00271     }
00272 }
00273 
00274 
00275 void Nepomuk::ServiceController::createServiceControlInterface()
00276 {
00277     delete d->serviceControlInterface;
00278 
00279     d->serviceControlInterface = new OrgKdeNepomukServiceControlInterface( dbusServiceName( name() ),
00280                                                                            "/servicecontrol",
00281                                                                            QDBusConnection::sessionBus(),
00282                                                                            this );
00283     connect( d->serviceControlInterface, SIGNAL( serviceInitialized( bool ) ),
00284              this, SLOT( slotServiceInitialized( bool ) ) );
00285 
00286     if ( d->serviceControlInterface->isInitialized() ) {
00287         slotServiceInitialized( true );
00288     }
00289 }
00290 
00291 
00292 void Nepomuk::ServiceController::slotServiceInitialized( bool success )
00293 {
00294     if ( !d->initialized ) {
00295         kDebug() << "Service" << name() << "initialized:" << success;
00296         d->initialized = true;
00297         emit serviceInitialized( this );
00298 
00299         if ( runOnce() ) {
00300             // we have been run once. Do not autostart next time
00301             KConfigGroup cg( Server::self()->config(), QString("Service-%1").arg(name()) );
00302             cg.writeEntry( "autostart", false );
00303         }
00304     }
00305 
00306     foreach( QEventLoop* loop, d->loops ) {
00307         loop->exit();
00308     }
00309 }

NepomukDaemons

Skip menu "NepomukDaemons"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

API Reference

Skip menu "API Reference"
  • KCMShell
  • KNotify
  • KStyles
  • Nepomuk Daemons
Generated for API Reference by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal