22 #include <QtCore/QHash>
23 #include <QtDBus/QtDBus>
26 #include <KServiceTypeTrader>
35 class DependencyTree :
public QHash<QString, QStringList>
47 bool dependsOn(
const QString& service,
const QString& dependency );
53 void removeService(
const QString& service );
55 QStringList servicesDependingOn(
const QString& service );
58 void DependencyTree::cleanup()
63 it != tmpTree.constEnd(); ++it ) {
64 QString service = it.key();
65 QStringList dependencies = it.value();
67 foreach(
const QString &dep, dependencies ) {
69 if( !contains( dep ) ) {
70 kDebug() <<
"Found invalid dependency:" << service <<
"depends on non-existing service" << dep;
72 removeService( service );
78 else if( dependsOn( dep, service ) ) {
79 kDebug() <<
"Found dependency loop:" << service <<
"depends on" << dep <<
"and vice versa";
81 removeService( service );
88 bool DependencyTree::dependsOn(
const QString& service,
const QString& dependency )
90 foreach(
const QString &dep, value( service ) ) {
91 if( dep == dependency ||
92 dependsOn( dep, dependency ) ) {
100 void DependencyTree::removeService(
const QString& service )
102 if( contains( service ) ) {
108 it != tmpTree.constEnd(); ++it ) {
109 if( it.value().contains( service ) ) {
110 removeService( it.key() );
116 QStringList DependencyTree::servicesDependingOn(
const QString& service )
120 it != constEnd(); ++it ) {
121 if( it.value().contains( service ) ) {
122 sl.append( it.key() );
130 class Nepomuk2::ServiceManager::Private
134 : m_initialized(false),
142 DependencyTree dependencyTree;
148 QSet<ServiceController*> stoppedServices;
150 ServiceController* findService(
const QString& name );
151 void buildServiceMap();
168 void _k_serviceInitialized( ServiceController* );
174 void _k_serviceStopped( ServiceController* );
182 void Nepomuk2::ServiceManager::Private::buildServiceMap()
184 if( !m_initialized ) {
185 KService::List modules = KServiceTypeTrader::self()->query(
"NepomukService" );
186 for( KService::List::ConstIterator it = modules.constBegin(); it != modules.constEnd(); ++it ) {
187 KService::Ptr service = *it;
188 QStringList deps = service->property(
"X-KDE-Nepomuk-dependencies", QVariant::StringList ).toStringList();
189 if ( deps.isEmpty() ) {
190 deps.append(
"nepomukstorage" );
192 deps.removeAll( service->desktopEntryName() );
193 dependencyTree.insert( service->desktopEntryName(), deps );
199 const KService::List newModules = KServiceTypeTrader::self()->query(
"NepomukService2" );
200 for( KService::List::ConstIterator it = newModules.constBegin(); it != newModules.constEnd(); ++it ) {
201 KService::Ptr service = *it;
202 QStringList deps = service->property(
"X-KDE-Nepomuk-dependencies", QVariant::StringList ).toStringList();
203 if ( deps.isEmpty() ) {
204 deps.append(
"nepomukstorage" );
206 deps.removeAll( service->desktopEntryName() );
207 dependencyTree.insert( service->desktopEntryName(), deps );
210 dependencyTree.cleanup();
211 modules.append( newModules );
213 for( KService::List::ConstIterator it = modules.constBegin(); it != modules.constEnd(); ++it ) {
214 KService::Ptr service = *it;
215 if( dependencyTree.contains( service->desktopEntryName() ) ) {
216 ServiceController* sc =
new ServiceController( service, q );
217 connect( sc, SIGNAL(serviceInitialized(ServiceController*)),
218 q, SLOT(_k_serviceInitialized(ServiceController*)) );
219 connect( sc, SIGNAL(serviceStopped(ServiceController*)),
220 q, SLOT(_k_serviceStopped(ServiceController*)) );
221 services.insert( sc->name(), sc );
225 m_initialized =
true;
233 if( it != services.end() ) {
242 kDebug() << sc->name();
244 stoppedServices.remove(sc);
246 if( !sc->isRunning() ) {
248 bool needToQueue =
false;
249 foreach(
const QString &dependency, dependencyTree[sc->name()] ) {
250 ServiceController* depSc = findService( dependency );
251 if ( !needToQueue && !depSc->isInitialized() ) {
252 kDebug() <<
"Queueing" << sc->name() <<
"due to dependency" << dependency;
253 pendingServices.insert( sc );
257 if ( !depSc->isRunning() ) {
263 if ( !needToQueue ) {
272 pendingServices.remove(service);
274 if( service->isRunning() ) {
276 bool haveRunningRevDeps =
false;
277 foreach(
const QString& dep, dependencyTree.servicesDependingOn( service->name() )) {
278 ServiceController* sc = services[dep];
279 if( sc->isRunning() ) {
280 kDebug() <<
"Revdep still running:" << sc->name() <<
"Queuing to be stopped:" << service->name();
281 stoppedServices.insert( service );
282 haveRunningRevDeps =
true;
285 pendingServices.insert( sc );
290 if(!haveRunningRevDeps) {
291 stoppedServices.remove(service);
298 void Nepomuk2::ServiceManager::Private::_k_serviceInitialized( ServiceController* sc )
300 kDebug() <<
"Service initialized:" << sc->name();
304 QList<ServiceController*> sl = pendingServices.toList();
305 foreach( ServiceController* service, sl ) {
306 if ( service->dependencies().contains( sc->name() ) ) {
308 pendingServices.remove( service );
313 emit q->serviceInitialized( sc->name() );
317 void Nepomuk2::ServiceManager::Private::_k_serviceStopped( ServiceController* sc )
319 kDebug() <<
"Service stopped:" << sc->name();
321 emit q->serviceStopped( sc->name() );
326 QSet<ServiceController*> ss = stoppedServices;
327 foreach(ServiceController* sc, ss) {
328 stoppedServices.remove(sc);
338 foreach(
const QString &dep, dependencyTree.servicesDependingOn( sc->name() ) ) {
339 ServiceController* depsc = services[dep];
340 if( depsc->isRunning() ) {
341 kDebug() <<
"Stopping and queuing rev-dep" << depsc->name();
343 pendingServices.insert( depsc );
360 qDeleteAll(d->services);
367 d->buildServiceMap();
370 it != d->services.end(); ++it ) {
374 d->startService( serviceControl );
382 d->pendingServices.clear();
384 it != d->services.end(); ++it ) {
386 d->stopService( serviceControl );
394 d->startService( sc );
407 d->stopService( sc );
418 it != d->services.end(); ++it ) {
421 sl.append( serviceControl->
name() );
432 sl.append(sc->
name());
439 return d->services.keys();
446 return sc->isInitialized();
457 return sc->isRunning();
468 return sc->autostart();
479 sc->setAutostart( autostart );
511 #include "servicemanager.moc"
QStringList availableServices() const
All services that are available in the system.
bool isServiceRunning(const QString &servicename) const
void startAllServices()
Starts all autoload services.
bool stopService(const QString &name)
Stop a specific service.
void stopService(const KService::Ptr &ptr)
void startService(const KService::Ptr &ptr)
ServiceManager(QObject *parent=0)
void setServiceAutostarted(const QString &name, bool autostart)
Set the service indicated by name to be autostarted.
void stopAllServices()
Stops all services.
Manages all Nepomuk services.
QStringList pendingServices() const
The services that are scheduled to be started but are waiting for dependancies to get initialized...
QStringList runningServices() const
Even uninitialized services are running.
QString name() const
The name of the service.
bool isServiceAutostarted(const QString &name)
bool startService(const QString &name)
Start a specific service.
bool isServiceInitialized(const QString &servicename) const