• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdelibs API Reference
  • KDE Home
  • Contact Us
 

Nepomuk-Core

  • sources
  • kde-4.12
  • kdelibs
  • nepomuk-core
  • server
servicecontroller.cpp
Go to the documentation of this file.
1 /* This file is part of the KDE Project
2  Copyright (c) 2008 Sebastian Trueg <trueg@kde.org>
3 
4  This library is free software; you can redistribute it and/or
5  modify it under the terms of the GNU Library General Public
6  License version 2 as published by the Free Software Foundation.
7 
8  This library is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11  Library General Public License for more details.
12 
13  You should have received a copy of the GNU Library General Public License
14  along with this library; see the file COPYING.LIB. If not, write to
15  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
16  Boston, MA 02110-1301, USA.
17 */
18 
19 #include "servicecontroller.h"
20 #include "processcontrol.h"
21 #include "servicecontrolinterface.h"
22 #include "nepomukserver.h"
23 
24 #include <QtCore/QTimer>
25 
26 #include <QtDBus/QDBusServiceWatcher>
27 #include <QtDBus/QDBusPendingReply>
28 #include <QtDBus/QDBusPendingCallWatcher>
29 
30 #include <KStandardDirs>
31 #include <KConfigGroup>
32 #include <KDebug>
33 
34 
35 namespace {
36  inline QString dbusServiceName( const QString& serviceName ) {
37  return QString("org.kde.nepomuk.services.%1").arg(serviceName);
38  }
39 }
40 
41 
42 class Nepomuk2::ServiceController::Private
43 {
44 public:
45  Private()
46  : processControl( 0 ),
47  serviceControlInterface( 0 ),
48  dbusServiceWatcher( 0 ),
49  attached( false ),
50  started( false ),
51  initialized( false ),
52  failedToInitialize( false ),
53  currentState(ServiceController::StateStopped) {
54  }
55 
56  KService::Ptr service;
57  bool autostart;
58  bool startOnDemand;
59  bool runOnce;
60 
61  ProcessControl* processControl;
62  OrgKdeNepomukServiceControlInterface* serviceControlInterface;
63  QDBusServiceWatcher* dbusServiceWatcher;
64 
65  // true if we attached to an already running instance instead of
66  // starting our own (in that case processControl will be 0)
67  bool attached;
68 
69  // true if we were asked to start the service
70  bool started;
71 
72  bool initialized;
73  bool failedToInitialize;
74  ServiceController::State currentState;
75 
76  void init( KService::Ptr service );
77  void reset();
78 };
79 
80 
81 void Nepomuk2::ServiceController::Private::init( KService::Ptr s )
82 {
83  service = s;
84  autostart = service->property( "X-KDE-Nepomuk-autostart", QVariant::Bool ).toBool();
85  KConfigGroup cg( Server::self()->config(), QString("Service-%1").arg(service->desktopEntryName()) );
86  autostart = cg.readEntry( "autostart", autostart );
87 
88  QVariant p = service->property( "X-KDE-Nepomuk-start-on-demand", QVariant::Bool );
89  startOnDemand = ( p.isValid() ? p.toBool() : false );
90 
91  p = service->property( "X-KDE-Nepomuk-run-once", QVariant::Bool );
92  runOnce = ( p.isValid() ? p.toBool() : false );
93 
94  initialized = false;
95 }
96 
97 
98 void Nepomuk2::ServiceController::Private::reset()
99 {
100  initialized = false;
101  attached = false;
102  started = false;
103  currentState = ServiceController::StateStopped;
104  failedToInitialize = false;
105  delete serviceControlInterface;
106  serviceControlInterface = 0;
107 }
108 
109 
110 Nepomuk2::ServiceController::ServiceController( KService::Ptr service, QObject* parent )
111  : QObject( parent ),
112  d(new Private())
113 {
114  d->init( service );
115 
116  d->dbusServiceWatcher = new QDBusServiceWatcher( dbusServiceName(name()),
117  QDBusConnection::sessionBus(),
118  QDBusServiceWatcher::WatchForRegistration | QDBusServiceWatcher::WatchForUnregistration,
119  this );
120  connect( d->dbusServiceWatcher, SIGNAL( serviceRegistered( QString ) ),
121  this, SLOT( slotServiceRegistered( QString ) ) );
122  connect( d->dbusServiceWatcher, SIGNAL( serviceUnregistered( QString ) ),
123  this, SLOT( slotServiceUnregistered( QString ) ) );
124 }
125 
126 
127 Nepomuk2::ServiceController::~ServiceController()
128 {
129  delete d;
130 }
131 
132 
133 KService::Ptr Nepomuk2::ServiceController::service() const
134 {
135  return d->service;
136 }
137 
138 
139 QString Nepomuk2::ServiceController::name() const
140 {
141  return d->service->desktopEntryName();
142 }
143 
144 
145 QStringList Nepomuk2::ServiceController::dependencies() const
146 {
147  QStringList deps = d->service->property( "X-KDE-Nepomuk-dependencies", QVariant::StringList ).toStringList();
148  if ( deps.isEmpty() ) {
149  deps.append( "nepomukstorage" );
150  }
151  deps.removeAll( name() );
152  return deps;
153 }
154 
155 
156 void Nepomuk2::ServiceController::setAutostart( bool enable )
157 {
158  KConfigGroup cg( Server::self()->config(), QString("Service-%1").arg(name()) );
159  cg.writeEntry( "autostart", enable );
160 }
161 
162 
163 bool Nepomuk2::ServiceController::autostart() const
164 {
165  return d->autostart;
166 }
167 
168 
169 bool Nepomuk2::ServiceController::startOnDemand() const
170 {
171  return d->startOnDemand;
172 }
173 
174 
175 bool Nepomuk2::ServiceController::runOnce() const
176 {
177  return d->runOnce;
178 }
179 
180 
181 void Nepomuk2::ServiceController::start()
182 {
183  if( d->currentState == StateStopped ) {
184  d->reset();
185  d->started = true;
186 
187  // check if the service is already running, ie. has been started by someone else or by a crashed instance of the server
188  // we cannot rely on the auto-restart feature of ProcessControl here. So we handle that completely via DBus signals
189  if( QDBusConnection::sessionBus().interface()->isServiceRegistered( dbusServiceName( name() ) ) ) {
190  kDebug() << "Attaching to already running service" << name();
191  d->attached = true;
192  d->currentState = StateRunning;
193  createServiceControlInterface();
194  }
195  else {
196  kDebug() << "Starting" << name();
197 
198  d->currentState = StateStarting;
199 
200  if( !d->processControl ) {
201  d->processControl = new ProcessControl( this );
202  connect( d->processControl, SIGNAL( finished( bool ) ),
203  this, SLOT( slotProcessFinished( bool ) ) );
204  }
205 
206  // we wait for the service to be registered with DBus before creating the service interface
207  QString exec = d->service->exec();
208  if( exec.isEmpty() ) {
209  d->processControl->start( KStandardDirs::findExe( "nepomukservicestub" ),
210  QStringList() << name(),
211  ProcessControl::RestartOnCrash );
212  }
213  else {
214  d->processControl->start( KStandardDirs::findExe( exec ),
215  QStringList(),
216  ProcessControl::RestartOnCrash );
217  }
218  }
219  }
220 }
221 
222 
223 void Nepomuk2::ServiceController::stop()
224 {
225  if( d->currentState == StateRunning ||
226  d->currentState == StateStarting ) {
227  kDebug() << "Stopping" << name();
228 
229  d->attached = false;
230  d->started = false;
231  d->currentState = StateStopping;
232 
233  if ( d->serviceControlInterface ) {
234  d->serviceControlInterface->shutdown();
235  }
236  else if( d->processControl ) {
237  // make sure we do not stop a process which has not been started properly yet.
238  // that would result in crashes
239  d->processControl->waitForStarted();
240  d->processControl->setCrashPolicy( ProcessControl::StopOnCrash );
241  d->processControl->terminate();
242  }
243  else {
244  kDebug() << "Cannot shut down service process.";
245  }
246  }
247 }
248 
249 
250 bool Nepomuk2::ServiceController::isRunning() const
251 {
252  return( d->attached || ( d->processControl ? d->processControl->isRunning() : false ) );
253 }
254 
255 
256 bool Nepomuk2::ServiceController::isInitialized() const
257 {
258  return d->initialized;
259 }
260 
261 
262 void Nepomuk2::ServiceController::slotProcessFinished( bool /*clean*/ )
263 {
264  kDebug() << "Service" << name() << "went down";
265  d->reset();
266  emit serviceStopped( this );
267 }
268 
269 
270 void Nepomuk2::ServiceController::slotServiceRegistered( const QString& serviceName )
271 {
272  if( serviceName == dbusServiceName( name() ) ) {
273  d->currentState = StateRunning;
274  kDebug() << serviceName;
275  if( !d->processControl || !d->processControl->isRunning() ) {
276  d->attached = true;
277  }
278  createServiceControlInterface();
279  }
280 }
281 
282 void Nepomuk2::ServiceController::slotServiceUnregistered( const QString& serviceName )
283 {
284  // an attached service was not started through ProcessControl. Thus, we cannot rely
285  // on its restart-on-crash feature and have to do it manually. Afterwards it is back
286  // to normal
287  if( serviceName == dbusServiceName( name() ) ) {
288  if( d->attached ) {
289  emit serviceStopped( this );
290  if( d->started ) {
291  kDebug() << "Attached service" << name() << "went down. Restarting ourselves.";
292  start();
293  }
294  else {
295  d->reset();
296  }
297  }
298  }
299 }
300 
301 
302 void Nepomuk2::ServiceController::createServiceControlInterface()
303 {
304  if(!d->attached && !d->started)
305  return;
306 
307  delete d->serviceControlInterface;
308  d->serviceControlInterface = new OrgKdeNepomukServiceControlInterface( dbusServiceName( name() ),
309  QLatin1String("/servicecontrol"),
310  QDBusConnection::sessionBus(),
311  this );
312  QDBusPendingCallWatcher* isInitializedWatcher = new QDBusPendingCallWatcher(d->serviceControlInterface->isInitialized(),
313  this);
314  connect(isInitializedWatcher, SIGNAL(finished(QDBusPendingCallWatcher*)),
315  this, SLOT(slotIsInitializedDBusCallFinished(QDBusPendingCallWatcher*)));
316 }
317 
318 
319 void Nepomuk2::ServiceController::slotServiceInitialized( bool success )
320 {
321  if ( !d->initialized ) {
322  if ( success ) {
323  kDebug() << "Service" << name() << "initialized";
324  d->initialized = true;
325  emit serviceInitialized( this );
326 
327  if ( runOnce() ) {
328  // we have been run once. Do not autostart next time
329  KConfigGroup cg( Server::self()->config(), QString("Service-%1").arg(name()) );
330  cg.writeEntry( "autostart", false );
331  }
332  }
333  else {
334  d->failedToInitialize = true;
335  kDebug() << "Failed to initialize service" << name();
336  // Do not stop because the storageservice now gets deinitialized when restoring a backup
337  // or migrating the data
338  //stop();
339  }
340  }
341 }
342 
343 Nepomuk2::ServiceController::State Nepomuk2::ServiceController::state() const
344 {
345  return d->currentState;
346 }
347 
348 void Nepomuk2::ServiceController::slotIsInitializedDBusCallFinished(QDBusPendingCallWatcher *watcher)
349 {
350  QDBusPendingReply<bool> isInitializedReply = *watcher;
351  if( isInitializedReply.isError() ) {
352  delete d->serviceControlInterface;
353  d->serviceControlInterface = 0;
354  kDebug() << "Failed to check service init state for" << name() << "Retrying.";
355  QMetaObject::invokeMethod( this, "createServiceControlInterface", Qt::QueuedConnection );
356  }
357  else {
358  if( isInitializedReply.value() ) {
359  slotServiceInitialized( true );
360  }
361  else {
362  kDebug() << "Service" << name() << "not initialized yet. Listening for signal.";
363  connect( d->serviceControlInterface, SIGNAL( serviceInitialized( bool ) ),
364  this, SLOT( slotServiceInitialized( bool ) ),
365  Qt::QueuedConnection );
366  }
367  }
368 
369  watcher->deleteLater();
370 }
371 
372 #include "servicecontroller.moc"
ProcessControl::StopOnCrash
Definition: processcontrol.h:46
Nepomuk2::ServiceController::~ServiceController
~ServiceController()
Definition: servicecontroller.cpp:127
Nepomuk2::ServiceController::dependencies
QStringList dependencies() const
All the service's direct dependencies.
Definition: servicecontroller.cpp:145
nepomukserver.h
Nepomuk2::ServiceController::setAutostart
void setAutostart(bool enable)
Definition: servicecontroller.cpp:156
QObject
servicecontroller.h
Nepomuk2::ServiceController::StateStopped
Definition: servicecontroller.h:66
Nepomuk2::ServiceController::State
State
Definition: servicecontroller.h:65
ProcessControl::RestartOnCrash
Definition: processcontrol.h:47
Nepomuk2::ServiceController::service
KService::Ptr service() const
Definition: servicecontroller.cpp:133
Nepomuk2::Server::self
static Server * self()
Definition: nepomukserver.cpp:177
Nepomuk2::ServiceController::startOnDemand
bool startOnDemand() const
Definition: servicecontroller.cpp:169
Nepomuk2::ServiceController::runOnce
bool runOnce() const
Definition: servicecontroller.cpp:175
Nepomuk2::ServiceController::isRunning
bool isRunning() const
Definition: servicecontroller.cpp:250
Nepomuk2::ServiceController::isInitialized
bool isInitialized() const
Definition: servicecontroller.cpp:256
Nepomuk2::ServiceController::name
QString name() const
The name of the service.
Definition: servicecontroller.cpp:139
Nepomuk2::ServiceController::stop
void stop()
Definition: servicecontroller.cpp:223
Nepomuk2::ServiceController::start
void start()
Make sure the service is running.
Definition: servicecontroller.cpp:181
Nepomuk2::ServiceController::ServiceController
ServiceController(KService::Ptr service, QObject *parent)
Definition: servicecontroller.cpp:110
ProcessControl
This class starts and observes a process.
Definition: processcontrol.h:32
start
void start()
Definition: ontologydownloadjob.cpp:13
Nepomuk2::ServiceController::state
State state() const
Definition: servicecontroller.cpp:343
processcontrol.h
Nepomuk2::ServiceController::autostart
bool autostart() const
Definition: servicecontroller.cpp:163
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:48:09 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

Nepomuk-Core

Skip menu "Nepomuk-Core"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Modules
  • Related Pages

kdelibs API Reference

Skip menu "kdelibs API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  • kjsembed
  •   WTF
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Nepomuk-Core
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal