NepomukDaemons
servicecontroller.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
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
00058
00059 bool attached;
00060
00061 bool initialized;
00062
00063
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
00159
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 )
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
00264
00265
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
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 }