/*************************************************************************** * Copyright (C) 2006 by Tobias Koenig * * Copyright (c) 2007 Volker Krause * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "agentmanager.h" #include "agentmanageradaptor.h" #include "agentmanagerinternaladaptor.h" #include "agentprocessinstance.h" #include "agentserverinterface.h" #include "agentthreadinstance.h" #include "akdebug.h" #include "libs/protocol_p.h" #include "libs/xdgbasedirs_p.h" #include "preprocessor_manager.h" #include "processcontrol.h" #include "resource_manager.h" #include "serverinterface.h" #include #include #include #include #include #include #ifndef QT_NO_DEBUG #include #endif #include #include #include #include using Akonadi::ProcessControl; #if defined(Q_WS_MAEMO_5) static bool enableAgentServerDefault = true; #else static bool enableAgentServerDefault = false; #endif AgentManager::AgentManager( QObject *parent ) : QObject( parent ) , mAgentServer( 0 ) #ifndef QT_NO_DEBUG , mAgentWatcher( new QFileSystemWatcher( this ) ) #endif { new AgentManagerAdaptor( this ); new AgentManagerInternalAdaptor( this ); QDBusConnection::sessionBus().registerObject( QLatin1String( "/AgentManager" ), this ); connect( QDBusConnection::sessionBus().interface(), SIGNAL(serviceOwnerChanged(QString,QString,QString)), this, SLOT(serviceOwnerChanged(QString,QString,QString)) ); if ( QDBusConnection::sessionBus().interface()->isServiceRegistered( AkDBus::serviceName( AkDBus::Server ) ) ) { akFatal() << "akonadiserver already running!"; } const QSettings settings( AkStandardDirs::agentConfigFile( Akonadi::XdgBaseDirs::ReadOnly ), QSettings::IniFormat ); mAgentServerEnabled = settings.value( QLatin1String( "AgentServer/Enabled" ), enableAgentServerDefault ).toBool(); QStringList serviceArgs; if ( AkApplication::hasInstanceIdentifier() ) { serviceArgs << QLatin1String( "--instance" ) << AkApplication::instanceIdentifier(); } mStorageController = new Akonadi::ProcessControl; mStorageController->setShutdownTimeout( 15 * 1000 ); // the server needs more time for shutdown if we are using an internal mysqld connect( mStorageController, SIGNAL(unableToStart()), SLOT(serverFailure()) ); mStorageController->start( QLatin1String( "akonadiserver" ), serviceArgs, Akonadi::ProcessControl::RestartOnCrash ); if ( mAgentServerEnabled ) { mAgentServer = new Akonadi::ProcessControl; connect( mAgentServer, SIGNAL(unableToStart()), SLOT(agentServerFailure()) ); mAgentServer->start( QLatin1String( "akonadi_agent_server" ), serviceArgs, Akonadi::ProcessControl::RestartOnCrash ); } #ifndef QT_NO_DEBUG connect( mAgentWatcher, SIGNAL(fileChanged(QString)), SLOT(agentExeChanged(QString)) ); #endif } void AgentManager::continueStartup() { // prevent multiple calls in case the server has to be restarted static bool first = true; if ( !first ) { return; } first = false; readPluginInfos(); Q_FOREACH ( const AgentType &info, mAgents ) { Q_EMIT agentTypeAdded( info.identifier ); } const QStringList pathList = pluginInfoPathList(); #ifndef QT_NO_DEBUG Q_FOREACH ( const QString &path, pathList ) { QFileSystemWatcher *watcher = new QFileSystemWatcher( this ); watcher->addPath( path ); connect( watcher, SIGNAL(directoryChanged(QString)), this, SLOT(updatePluginInfos()) ); } #endif load(); Q_FOREACH ( const AgentType &info, mAgents ) { ensureAutoStart( info ); } // register the real service name once everything is up an running if ( !QDBusConnection::sessionBus().registerService( AkDBus::serviceName( AkDBus::Control ) ) ) { // besides a race with an older Akonadi server I have no idea how we could possibly get here... akFatal() << "Unable to register service as" << AkDBus::serviceName( AkDBus::Control ) << "despite having the lock. Error was:" << QDBusConnection::sessionBus().lastError().message(); } akDebug() << "Akonadi server is now operational."; } AgentManager::~AgentManager() { cleanup(); } void AgentManager::cleanup() { Q_FOREACH ( const AgentInstance::Ptr &instance, mAgentInstances ) { instance->quit(); } mAgentInstances.clear(); mStorageController->setCrashPolicy( ProcessControl::StopOnCrash ); org::freedesktop::Akonadi::Server *serverIface = new org::freedesktop::Akonadi::Server( AkDBus::serviceName( AkDBus::Server ), QLatin1String( "/Server" ), QDBusConnection::sessionBus(), this ); serverIface->quit(); if ( mAgentServer ) { mAgentServer->setCrashPolicy( ProcessControl::StopOnCrash ); org::freedesktop::Akonadi::AgentServer *agentServerIface = new org::freedesktop::Akonadi::AgentServer( AkDBus::serviceName( AkDBus::AgentServer ), QLatin1String( "/AgentServer" ), QDBusConnection::sessionBus(), this ); agentServerIface->quit(); } delete mStorageController; mStorageController = 0; delete mAgentServer; mAgentServer = 0; } QStringList AgentManager::agentTypes() const { return mAgents.keys(); } QString AgentManager::agentName( const QString &identifier, const QString &language ) const { if ( !checkAgentExists( identifier ) ) { return QString(); } const QString name = mAgents.value( identifier ).name.value( language ); return name.isEmpty() ? mAgents.value( identifier ).name.value( QLatin1String( "en_US" ) ) : name; } QString AgentManager::agentComment( const QString &identifier, const QString &language ) const { if ( !checkAgentExists( identifier ) ) { return QString(); } const QString comment = mAgents.value( identifier ).comment.value( language ); return comment.isEmpty() ? mAgents.value( identifier ).comment.value( QLatin1String( "en_US" ) ) : comment; } QString AgentManager::agentIcon( const QString &identifier ) const { if ( !checkAgentExists( identifier ) ) { return QString(); } const AgentType info = mAgents.value( identifier ); if ( !info.icon.isEmpty() ) { return info.icon; } return QLatin1String( "application-x-executable" ); } QStringList AgentManager::agentMimeTypes( const QString &identifier ) const { if ( !checkAgentExists( identifier ) ) { return QStringList(); } return mAgents.value( identifier ).mimeTypes; } QStringList AgentManager::agentCapabilities( const QString &identifier ) const { if ( !checkAgentExists( identifier ) ) { return QStringList(); } return mAgents.value( identifier ).capabilities; } QVariantMap AgentManager::agentCustomProperties( const QString &identifier ) const { if ( !checkAgentExists( identifier ) ) { return QVariantMap(); } return mAgents.value( identifier ).custom; } AgentInstance::Ptr AgentManager::createAgentInstance( const AgentType &info ) { switch ( info.launchMethod ) { case AgentType::Server: return AgentInstance::Ptr( new Akonadi::AgentThreadInstance( this ) ); case AgentType::Launcher: // Fall through case AgentType::Process: return AgentInstance::Ptr( new Akonadi::AgentProcessInstance( this ) ); default: Q_ASSERT_X( false, "AgentManger::createAgentInstance", "Unhandled AgentType::LaunchMethod case" ); } return AgentInstance::Ptr(); } QString AgentManager::createAgentInstance( const QString &identifier ) { if ( !checkAgentExists( identifier ) ) { return QString(); } const AgentType agentInfo = mAgents.value( identifier ); mAgents[identifier].instanceCounter++; const AgentInstance::Ptr instance = createAgentInstance( agentInfo ); if ( agentInfo.capabilities.contains( AgentType::CapabilityUnique ) ) { instance->setIdentifier( identifier ); } else { instance->setIdentifier( QString::fromLatin1( "%1_%2" ).arg( identifier, QString::number( agentInfo.instanceCounter ) ) ); } if ( mAgentInstances.contains( instance->identifier() ) ) { akError() << Q_FUNC_INFO << "Cannot create another instance of agent" << identifier; return QString(); } // Return from this dbus call before we do the next. Otherwise dbus brakes for // this process. if ( calledFromDBus() ) { connection().send( message().createReply( instance->identifier() ) ); } if ( !instance->start( agentInfo ) ) { return QString(); } mAgentInstances.insert( instance->identifier(), instance ); registerAgentAtServer( instance->identifier(), agentInfo ); save(); return instance->identifier(); } void AgentManager::removeAgentInstance( const QString &identifier ) { if ( !mAgentInstances.contains( identifier ) ) { akError() << Q_FUNC_INFO << "Agent instance with identifier" << identifier << "does not exist"; return; } const AgentInstance::Ptr instance = mAgentInstances.value( identifier ); if ( instance->hasAgentInterface() ) { instance->cleanup(); } else { akError() << Q_FUNC_INFO << "Agent instance" << identifier << "has no interface!"; } mAgentInstances.remove( identifier ); save(); org::freedesktop::Akonadi::ResourceManager resmanager( AkDBus::serviceName( AkDBus::Server ), QLatin1String( "/ResourceManager" ), QDBusConnection::sessionBus(), this ); resmanager.removeResourceInstance( instance->identifier() ); // Kill the preprocessor instance, if any. org::freedesktop::Akonadi::PreprocessorManager preProcessorManager( AkDBus::serviceName( AkDBus::Server ), QLatin1String( "/PreprocessorManager" ), QDBusConnection::sessionBus(), this ); preProcessorManager.unregisterInstance( instance->identifier() ); if ( instance->hasAgentInterface() ) { akDebug() << "AgentManager::removeAgentInstance: calling instance->quit()"; instance->quit(); } else { akError() << Q_FUNC_INFO << "Agent instance" << identifier << "has no interface!"; } Q_EMIT agentInstanceRemoved( identifier ); } QString AgentManager::agentInstanceType( const QString &identifier ) { if ( !mAgentInstances.contains( identifier ) ) { akError() << Q_FUNC_INFO << "Agent instance with identifier" << identifier << "does not exist"; return QString(); } return mAgentInstances.value( identifier )->agentType(); } QStringList AgentManager::agentInstances() const { return mAgentInstances.keys(); } int AgentManager::agentInstanceStatus( const QString &identifier ) const { if ( !checkInstance( identifier ) ) { return 2; } return mAgentInstances.value( identifier )->status(); } QString AgentManager::agentInstanceStatusMessage( const QString &identifier ) const { if ( !checkInstance( identifier ) ) { return QString(); } return mAgentInstances.value( identifier )->statusMessage(); } uint AgentManager::agentInstanceProgress( const QString &identifier ) const { if ( !checkInstance( identifier ) ) { return 0; } return mAgentInstances.value( identifier )->progress(); } QString AgentManager::agentInstanceProgressMessage( const QString &identifier ) const { Q_UNUSED( identifier ); return QString(); } void AgentManager::agentInstanceConfigure( const QString &identifier, qlonglong windowId ) { if ( !checkAgentInterfaces( identifier, QLatin1String( "agentInstanceConfigure" ) ) ) { return; } mAgentInstances.value( identifier )->configure( windowId ); } bool AgentManager::agentInstanceOnline( const QString &identifier ) { if ( !checkInstance( identifier ) ) { return false; } return mAgentInstances.value( identifier )->isOnline(); } void AgentManager::setAgentInstanceOnline( const QString &identifier, bool state ) { if ( !checkAgentInterfaces( identifier, QLatin1String( "setAgentInstanceOnline" ) ) ) { return; } mAgentInstances.value( identifier )->statusInterface()->setOnline( state ); } // resource specific methods // void AgentManager::setAgentInstanceName( const QString &identifier, const QString &name ) { if ( !checkResourceInterface( identifier, QLatin1String( "setAgentInstanceName" ) ) ) { return; } mAgentInstances.value( identifier )->resourceInterface()->setName( name ); } QString AgentManager::agentInstanceName( const QString &identifier, const QString &language ) const { if ( !checkInstance( identifier ) ) { return QString(); } const AgentInstance::Ptr instance = mAgentInstances.value( identifier ); if ( !instance->resourceName().isEmpty() ) { return instance->resourceName(); } if ( !checkAgentExists( instance->agentType() ) ) { return QString(); } const QString name = mAgents.value( instance->agentType() ).name.value( language ); return name.isEmpty() ? mAgents.value( instance->agentType() ).name.value( QLatin1String( "en_US" ) ) : name; } void AgentManager::agentInstanceSynchronize( const QString &identifier ) { if ( !checkResourceInterface( identifier, QLatin1String( "agentInstanceSynchronize" ) ) ) { return; } mAgentInstances.value( identifier )->resourceInterface()->synchronize(); } void AgentManager::agentInstanceSynchronizeCollectionTree( const QString &identifier ) { if ( !checkResourceInterface( identifier, QLatin1String( "agentInstanceSynchronizeCollectionTree" ) ) ) { return; } mAgentInstances.value( identifier )->resourceInterface()->synchronizeCollectionTree(); } void AgentManager::agentInstanceSynchronizeCollection( const QString &identifier, qint64 collection ) { agentInstanceSynchronizeCollection( identifier, collection, false ); } void AgentManager::agentInstanceSynchronizeCollection( const QString &identifier, qint64 collection, bool recursive ) { if ( !checkResourceInterface( identifier, QLatin1String( "agentInstanceSynchronizeCollection" ) ) ) { return; } mAgentInstances.value( identifier )->resourceInterface()->synchronizeCollection( collection, recursive ); } void AgentManager::restartAgentInstance( const QString &identifier ) { if ( !checkInstance( identifier ) ) { return; } mAgentInstances.value( identifier )->restartWhenIdle(); } void AgentManager::updatePluginInfos() { const QHash oldInfos = mAgents; readPluginInfos(); Q_FOREACH ( const AgentType &oldInfo, oldInfos ) { if ( !mAgents.contains( oldInfo.identifier ) ) { Q_EMIT agentTypeRemoved( oldInfo.identifier ); } } Q_FOREACH ( const AgentType &newInfo, mAgents ) { if ( !oldInfos.contains( newInfo.identifier ) ) { Q_EMIT agentTypeAdded( newInfo.identifier ); ensureAutoStart( newInfo ); } } } void AgentManager::readPluginInfos() { #ifndef QT_NO_DEBUG if ( !mAgentWatcher->files().isEmpty() ) { mAgentWatcher->removePaths( mAgentWatcher->files() ); } #endif mAgents.clear(); const QStringList pathList = pluginInfoPathList(); Q_FOREACH ( const QString &path, pathList ) { const QDir directory( path, QLatin1String( "*.desktop" ) ); readPluginInfos( directory ); } } void AgentManager::readPluginInfos( const QDir &directory ) { const QStringList files = directory.entryList(); akDebug() << "PLUGINS: " << directory.canonicalPath(); akDebug() << "PLUGINS: " << files; for ( int i = 0; i < files.count(); ++i ) { const QString fileName = directory.absoluteFilePath( files[i] ); AgentType agentInfo; if ( agentInfo.load( fileName, this ) ) { if ( mAgents.contains( agentInfo.identifier ) ) { akError() << Q_FUNC_INFO << "Duplicated agent identifier" << agentInfo.identifier << "from file" << fileName; continue; } const QString disableAutostart = getEnv( "AKONADI_DISABLE_AGENT_AUTOSTART" ); if ( !disableAutostart.isEmpty() ) { akDebug() << "Autostarting of agents is disabled."; agentInfo.capabilities.removeOne( AgentType::CapabilityAutostart ); } if ( !mAgentServerEnabled && agentInfo.launchMethod == AgentType::Server ) { agentInfo.launchMethod = AgentType::Launcher; } if ( agentInfo.launchMethod == AgentType::Process ) { const QString executable = Akonadi::XdgBaseDirs::findExecutableFile( agentInfo.exec ); if ( executable.isEmpty() ) { akError() << "Executable" << agentInfo.exec << "for agent" << agentInfo.identifier << "could not be found!"; continue; } #ifndef QT_NO_DEBUG if ( !mAgentWatcher->files().contains( executable ) ) { mAgentWatcher->addPath( executable ); } #endif } akDebug() << "PLUGINS inserting: " << agentInfo.identifier << agentInfo.instanceCounter << agentInfo.capabilities; mAgents.insert( agentInfo.identifier, agentInfo ); } } } QStringList AgentManager::pluginInfoPathList() { return Akonadi::XdgBaseDirs::findAllResourceDirs( "data", QLatin1String( "akonadi/agents" ) ); } void AgentManager::load() { org::freedesktop::Akonadi::ResourceManager resmanager( AkDBus::serviceName( AkDBus::Server ), QLatin1String( "/ResourceManager" ), QDBusConnection::sessionBus(), this ); const QStringList knownResources = resmanager.resourceInstances(); QSettings file( AkStandardDirs::agentConfigFile( Akonadi::XdgBaseDirs::ReadOnly ), QSettings::IniFormat ); file.beginGroup( QLatin1String( "Instances" ) ); const QStringList entries = file.childGroups(); for ( int i = 0; i < entries.count(); ++i ) { const QString instanceIdentifier = entries[i]; if ( mAgentInstances.contains( instanceIdentifier ) ) { akError() << Q_FUNC_INFO << "Duplicated instance identifier" << instanceIdentifier << "found in agentsrc"; continue; } file.beginGroup( entries[i] ); const QString agentType = file.value( QLatin1String( "AgentType" ) ).toString(); if ( !mAgents.contains( agentType ) ) { akError() << Q_FUNC_INFO << "Reference to unknown agent type" << agentType << "in agentsrc"; file.endGroup(); continue; } const AgentType type = mAgents.value( agentType ); // recover if the db has been deleted in the meantime or got otherwise corrupted if ( !knownResources.contains( instanceIdentifier ) && type.capabilities.contains( AgentType::CapabilityResource ) ) { akDebug() << "Recovering instance" << instanceIdentifier << "after database loss"; registerAgentAtServer( instanceIdentifier, type ); } const AgentInstance::Ptr instance = createAgentInstance( type ); instance->setIdentifier( instanceIdentifier ); if ( instance->start( type ) ) { mAgentInstances.insert( instanceIdentifier, instance ); } file.endGroup(); } file.endGroup(); } void AgentManager::save() { QSettings file( AkStandardDirs::agentConfigFile( Akonadi::XdgBaseDirs::WriteOnly ), QSettings::IniFormat ); Q_FOREACH ( const AgentType &info, mAgents ) { info.save( &file ); } file.beginGroup( QLatin1String( "Instances" ) ); file.remove( QString() ); Q_FOREACH ( const AgentInstance::Ptr &instance, mAgentInstances ) { file.beginGroup( instance->identifier() ); file.setValue( QLatin1String( "AgentType" ), instance->agentType() ); file.endGroup(); } file.endGroup(); file.sync(); } void AgentManager::serviceOwnerChanged( const QString &name, const QString &oldOwner, const QString &newOwner ) { Q_UNUSED( oldOwner ); // This is called by the D-Bus server when a service comes up, goes down or changes ownership for some reason // and this is where we "hook up" our different Agent interfaces. //akDebug() << "Service " << name << " owner changed from " << oldOwner << " to " << newOwner; if ( ( name == AkDBus::serviceName( AkDBus::Server ) || name == AkDBus::serviceName( AkDBus::AgentServer ) ) && !newOwner.isEmpty() ) { if ( QDBusConnection::sessionBus().interface()->isServiceRegistered( AkDBus::serviceName( AkDBus::Server ) ) && ( !mAgentServer || QDBusConnection::sessionBus().interface()->isServiceRegistered( AkDBus::serviceName( AkDBus::AgentServer ) ) ) ) { // server is operational, start agents continueStartup(); } } AkDBus::AgentType agentType = AkDBus::Unknown; const QString agentIdentifier = AkDBus::parseAgentServiceName( name, agentType ); switch ( agentType ) { case AkDBus::Agent: { // An agent service went up or down if ( newOwner.isEmpty() ) { return; // It went down: we don't care here. } if ( !mAgentInstances.contains( agentIdentifier ) ) { return; } const AgentInstance::Ptr instance = mAgentInstances.value( agentIdentifier ); const bool restarting = instance->hasAgentInterface(); if ( !instance->obtainAgentInterface() ) { return; } if ( !restarting ) { Q_EMIT agentInstanceAdded( agentIdentifier ); } break; } case AkDBus::Resource: { // A resource service went up or down if ( newOwner.isEmpty() ) { return; // It went down: we don't care here. } if ( !mAgentInstances.contains( agentIdentifier ) ) { return; } mAgentInstances.value( agentIdentifier )->obtainResourceInterface(); break; } case AkDBus::Preprocessor: { // A preprocessor service went up or down // If the preprocessor is going up then the org.freedesktop.Akonadi.Agent.* interface // should be already up (as it's registered before the preprocessor one). // So if we don't know about the preprocessor as agent instance // then it's not our preprocessor. // If the preprocessor is going down then either the agent interface already // went down (and it has been already unregistered on the manager side) // or it's still registered as agent and WE have to unregister it. // The order of interface deletions depends on Qt but we handle both cases. // Check if we "know" about it. akDebug() << "Preprocessor " << agentIdentifier << " is going up or down..."; if ( !mAgentInstances.contains( agentIdentifier ) ) { akDebug() << "But it isn't registered as agent... not mine (anymore?)"; return; // not our agent (?) } org::freedesktop::Akonadi::PreprocessorManager preProcessorManager( AkDBus::serviceName( AkDBus::Server ), QLatin1String( "/PreprocessorManager" ), QDBusConnection::sessionBus(), this ); if ( !preProcessorManager.isValid() ) { akError() << Q_FUNC_INFO << "Could not connect to PreprocessorManager via D-Bus:" << preProcessorManager.lastError().message(); } else { if ( newOwner.isEmpty() ) { // The preprocessor went down. Unregister it on server side. preProcessorManager.unregisterInstance( agentIdentifier ); } else { // The preprocessor went up. Register it on server side. if ( !mAgentInstances.value( agentIdentifier )->obtainPreprocessorInterface() ) { // Hm.. couldn't hook up its preprocessor interface.. // Make sure we don't have it in the preprocessor chain qWarning() << "Couldn't obtain preprocessor interface for instance" << agentIdentifier; preProcessorManager.unregisterInstance( agentIdentifier ); return; } akDebug() << "Registering preprocessor instance" << agentIdentifier; // Add to the preprocessor chain preProcessorManager.registerInstance( agentIdentifier ); } } break; } default: break; } } bool AgentManager::checkInstance( const QString &identifier ) const { if ( !mAgentInstances.contains( identifier ) ) { qWarning() << "Agent instance with identifier " << identifier << " does not exist"; return false; } return true; } bool AgentManager::checkResourceInterface( const QString &identifier, const QString &method ) const { if ( !checkInstance( identifier ) ) { return false; } if ( !mAgents[mAgentInstances[identifier]->agentType()].capabilities.contains( QLatin1String( "Resource" ) ) ) { return false; } if ( !mAgentInstances[identifier]->hasResourceInterface() ) { qWarning() << QLatin1String( "AgentManager::" ) + method << " Agent instance " << identifier << " has no resource interface!"; return false; } return true; } bool AgentManager::checkAgentExists( const QString &identifier ) const { if ( !mAgents.contains( identifier ) ) { qWarning() << "Agent instance " << identifier << " does not exist."; return false; } return true; } bool AgentManager::checkAgentInterfaces( const QString &identifier, const QString &method ) const { if ( !checkInstance( identifier ) ) { return false; } if ( !mAgentInstances.value( identifier )->hasAgentInterface() ) { qWarning() << "Agent instance (" << method << ") " << identifier << " has no agent interface."; return false; } return true; } void AgentManager::ensureAutoStart( const AgentType &info ) { if ( !info.capabilities.contains( AgentType::CapabilityAutostart ) ) { return; // no an autostart agent } org::freedesktop::Akonadi::AgentServer agentServer( AkDBus::serviceName( AkDBus::AgentServer ), QLatin1String( "/AgentServer" ), QDBusConnection::sessionBus(), this ); if ( mAgentInstances.contains( info.identifier ) || ( agentServer.isValid() && agentServer.started( info.identifier ) ) ) { return; // already running } const AgentInstance::Ptr instance = createAgentInstance( info ); instance->setIdentifier( info.identifier ); if ( instance->start( info ) ) { mAgentInstances.insert( instance->identifier(), instance ); registerAgentAtServer( instance->identifier(), info ); save(); } } void AgentManager::agentExeChanged( const QString &fileName ) { if ( !QFile::exists( fileName ) ) { return; } Q_FOREACH ( const AgentType &type, mAgents ) { if ( fileName.endsWith( type.exec ) ) { Q_FOREACH ( const AgentInstance::Ptr &instance, mAgentInstances ) { if ( instance->agentType() == type.identifier ) { instance->restartWhenIdle(); } } } } } void AgentManager::registerAgentAtServer( const QString &agentIdentifier, const AgentType &type ) { if ( type.capabilities.contains( AgentType::CapabilityResource ) ) { boost::scoped_ptr resmanager( new org::freedesktop::Akonadi::ResourceManager( AkDBus::serviceName( AkDBus::Server ), QLatin1String( "/ResourceManager" ), QDBusConnection::sessionBus(), this ) ); resmanager->addResourceInstance( agentIdentifier, type.capabilities ); } } void AgentManager::addSearch( const QString &query, const QString &queryLanguage, qint64 resultCollectionId ) { akDebug() << "AgentManager::addSearch" << query << queryLanguage << resultCollectionId; Q_FOREACH ( const AgentInstance::Ptr &instance, mAgentInstances ) { const AgentType type = mAgents.value( instance->agentType() ); if ( type.capabilities.contains( AgentType::CapabilitySearch ) && instance->searchInterface() ) { instance->searchInterface()->addSearch( query, queryLanguage, resultCollectionId ); } } } void AgentManager::removeSearch( quint64 resultCollectionId ) { akDebug() << "AgentManager::removeSearch" << resultCollectionId; Q_FOREACH ( const AgentInstance::Ptr &instance, mAgentInstances ) { const AgentType type = mAgents.value( instance->agentType() ); if ( type.capabilities.contains( AgentType::CapabilitySearch ) && instance->searchInterface() ) { instance->searchInterface()->removeSearch( resultCollectionId ); } } } void AgentManager::agentServerFailure() { akError() << "Failed to start AgentServer!"; // if ( requiresAgentServer ) // QCoreApplication::instance()->exit( 255 ); } void AgentManager::serverFailure() { QCoreApplication::instance()->exit( 255 ); }