• Skip to content
  • Skip to link menu
KDE 4.5 API Reference
  • KDE API Reference
  • KDE-PIM Libraries
  • Sitemap
  • Contact Us
 

akonadi

servermanager.cpp

00001 /*
00002     Copyright (c) 2008 Volker Krause <vkrause@kde.org>
00003 
00004     This library is free software; you can redistribute it and/or modify it
00005     under the terms of the GNU Library General Public License as published by
00006     the Free Software Foundation; either version 2 of the License, or (at your
00007     option) any later version.
00008 
00009     This library is distributed in the hope that it will be useful, but WITHOUT
00010     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00011     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
00012     License for more details.
00013 
00014     You should have received a copy of the GNU Library General Public License
00015     along with this library; see the file COPYING.LIB.  If not, write to the
00016     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00017     02110-1301, USA.
00018 */
00019 
00020 #include "servermanager.h"
00021 #include "servermanager_p.h"
00022 
00023 #include "agenttype.h"
00024 #include "agentbase.h"
00025 #include "agentmanager.h"
00026 #include "selftestdialog_p.h"
00027 #include "session_p.h"
00028 #include "firstrun_p.h"
00029 
00030 #include <KDebug>
00031 #include <KGlobal>
00032 
00033 #include <QtDBus>
00034 #include <QTimer>
00035 
00036 #include <boost/scoped_ptr.hpp>
00037 
00038 #define AKONADI_CONTROL_SERVICE QLatin1String( "org.freedesktop.Akonadi.Control" )
00039 #define AKONADI_SERVER_SERVICE QLatin1String( "org.freedesktop.Akonadi" )
00040 
00041 using namespace Akonadi;
00042 
00043 class Akonadi::ServerManagerPrivate
00044 {
00045   public:
00046     ServerManagerPrivate() :
00047       instance( new ServerManager( this ) ),
00048       mState( ServerManager::NotRunning ),
00049       mSafetyTimer( new QTimer ),
00050       mFirstRunner( 0 )
00051     {
00052       mState = instance->state();
00053       mSafetyTimer->setSingleShot( true );
00054       mSafetyTimer->setInterval( 30000 );
00055       QObject::connect( mSafetyTimer.get(), SIGNAL( timeout() ), instance, SLOT( timeout() ) );
00056       KGlobal::locale()->insertCatalog( QString::fromLatin1( "libakonadi" ) );
00057       if ( mState == ServerManager::Running && Internal::clientType() == Internal::User )
00058         mFirstRunner = new Firstrun( instance );
00059     }
00060 
00061     ~ServerManagerPrivate()
00062     {
00063       delete instance;
00064     }
00065 
00066     void serviceOwnerChanged( const QString&, const QString&, const QString& )
00067     {
00068       serverProtocolVersion = -1,
00069       checkStatusChanged();
00070     }
00071 
00072     void checkStatusChanged()
00073     {
00074       setState( instance->state() );
00075     }
00076 
00077     void setState( ServerManager::State state )
00078     {
00079 
00080       if ( mState != state ) {
00081         mState = state;
00082         emit instance->stateChanged( state );
00083         if ( state == ServerManager::Running ) {
00084           emit instance->started();
00085           if ( !mFirstRunner && Internal::clientType() == Internal::User )
00086             mFirstRunner = new Firstrun( instance );
00087         } else if ( state == ServerManager::NotRunning || state == ServerManager::Broken ) {
00088           emit instance->stopped();
00089         }
00090 
00091         if ( state == ServerManager::Starting || state == ServerManager::Stopping )
00092           mSafetyTimer->start();
00093         else
00094           mSafetyTimer->stop();
00095       }
00096     }
00097 
00098     void timeout()
00099     {
00100       if ( mState == ServerManager::Starting || mState == ServerManager::Stopping )
00101         setState( ServerManager::Broken );
00102     }
00103 
00104     ServerManager *instance;
00105     static int serverProtocolVersion;
00106     ServerManager::State mState;
00107     boost::scoped_ptr<QTimer> mSafetyTimer;
00108     Firstrun *mFirstRunner;
00109     static Internal::ClientType clientType;
00110 };
00111 
00112 int ServerManagerPrivate::serverProtocolVersion = -1;
00113 Internal::ClientType ServerManagerPrivate::clientType = Internal::User;
00114 
00115 K_GLOBAL_STATIC( ServerManagerPrivate, sInstance )
00116 
00117 ServerManager::ServerManager(ServerManagerPrivate * dd ) :
00118     d( dd )
00119 {
00120   QDBusServiceWatcher *watcher = new QDBusServiceWatcher( AKONADI_SERVER_SERVICE,
00121                                                           QDBusConnection::sessionBus(),
00122                                                           QDBusServiceWatcher::WatchForOwnerChange, this );
00123   watcher->addWatchedService( AKONADI_CONTROL_SERVICE );
00124 
00125   connect( watcher, SIGNAL( serviceOwnerChanged( const QString&, const QString&, const QString& ) ),
00126            this, SLOT( serviceOwnerChanged( const QString&, const QString&, const QString& ) ) );
00127 
00128   // AgentManager is dangerous to use for agents themselves
00129   if ( Internal::clientType() != Internal::User )
00130     return;
00131   connect( AgentManager::self(), SIGNAL( typeAdded( const Akonadi::AgentType& ) ), SLOT( checkStatusChanged() ) );
00132   connect( AgentManager::self(), SIGNAL( typeRemoved( const Akonadi::AgentType& ) ), SLOT( checkStatusChanged() ) );
00133 }
00134 
00135 ServerManager * Akonadi::ServerManager::self()
00136 {
00137   return sInstance->instance;
00138 }
00139 
00140 bool ServerManager::start()
00141 {
00142   const bool controlRegistered = QDBusConnection::sessionBus().interface()->isServiceRegistered( AKONADI_CONTROL_SERVICE );
00143   const bool serverRegistered = QDBusConnection::sessionBus().interface()->isServiceRegistered( AKONADI_SERVER_SERVICE );
00144   if (  controlRegistered && serverRegistered )
00145     return true;
00146 
00147   // TODO: use AKONADI_CONTROL_SERVICE_LOCK instead once we depend on a recent enough Akonadi server
00148   const bool controlLockRegistered = QDBusConnection::sessionBus().interface()->isServiceRegistered( AKONADI_CONTROL_SERVICE + QLatin1String( ".lock" ) );
00149   if ( controlLockRegistered || controlRegistered ) {
00150     kDebug() << "Akonadi server is already starting up";
00151     sInstance->setState( Starting );
00152     return true;
00153   }
00154 
00155   kDebug() << "executing akonadi_control";
00156   const bool ok = QProcess::startDetached( QLatin1String( "akonadi_control" ) );
00157   if ( !ok ) {
00158     kWarning() << "Unable to execute akonadi_control, falling back to D-Bus auto-launch";
00159     QDBusReply<void> reply = QDBusConnection::sessionBus().interface()->startService( AKONADI_CONTROL_SERVICE );
00160     if ( !reply.isValid() ) {
00161       kDebug() << "Akonadi server could not be started via D-Bus either: "
00162                << reply.error().message();
00163       return false;
00164     }
00165   }
00166   sInstance->setState( Starting );
00167   return true;
00168 }
00169 
00170 bool ServerManager::stop()
00171 {
00172   QDBusInterface iface( AKONADI_CONTROL_SERVICE,
00173                         QString::fromLatin1( "/ControlManager" ),
00174                         QString::fromLatin1( "org.freedesktop.Akonadi.ControlManager" ) );
00175   if ( !iface.isValid() )
00176     return false;
00177   iface.call( QDBus::NoBlock, QString::fromLatin1( "shutdown" ) );
00178   sInstance->setState( Stopping );
00179   return true;
00180 }
00181 
00182 void ServerManager::showSelfTestDialog( QWidget *parent )
00183 {
00184   Akonadi::SelfTestDialog dlg( parent );
00185   dlg.hideIntroduction();
00186   dlg.exec();
00187 }
00188 
00189 bool ServerManager::isRunning()
00190 {
00191   return state() == Running;
00192 }
00193 
00194 ServerManager::State ServerManager::state()
00195 {
00196   ServerManager::State previousState = NotRunning;
00197   if ( sInstance.exists() ) // be careful, this is called from the ServerManager::Private ctor, so using sInstance unprotected can cause infinite recursion
00198     previousState = sInstance->mState;
00199 
00200   const bool controlRegistered = QDBusConnection::sessionBus().interface()->isServiceRegistered( AKONADI_CONTROL_SERVICE );
00201   const bool serverRegistered = QDBusConnection::sessionBus().interface()->isServiceRegistered( AKONADI_SERVER_SERVICE );
00202   if (  controlRegistered && serverRegistered ) {
00203     // check if the server protocol is recent enough
00204     if ( sInstance.exists() ) {
00205       if ( Internal::serverProtocolVersion() >= 0 &&
00206            Internal::serverProtocolVersion() < SessionPrivate::minimumProtocolVersion() )
00207         return Broken;
00208     }
00209 
00210     // AgentManager is dangerous to use for agents themselves
00211     if ( Internal::clientType() == Internal::User ) {
00212       // besides the running server processes we also need at least one resource to be operational
00213       AgentType::List agentTypes = AgentManager::self()->types();
00214       foreach ( const AgentType &type, agentTypes ) {
00215         if ( type.capabilities().contains( QLatin1String( "Resource" ) ) )
00216           return Running;
00217       }
00218       return Broken;
00219     } else {
00220       return Running;
00221     }
00222   }
00223 
00224   // TODO: use AKONADI_CONTROL_SERVICE_LOCK instead once we depend on a recent enough Akonadi server
00225   const bool controlLockRegistered = QDBusConnection::sessionBus().interface()->isServiceRegistered( AKONADI_CONTROL_SERVICE + QLatin1String( ".lock" ) );
00226   if ( controlLockRegistered || controlRegistered ) {
00227     kDebug() << "Akonadi server is already starting up";
00228     if ( previousState == Running )
00229       return NotRunning; // we don't know if it's starting or stopping, probably triggered by someone else
00230     return previousState;
00231   }
00232 
00233   if ( serverRegistered ) {
00234     kWarning() << "Akonadi server running without control process!";
00235     return Broken;
00236   }
00237 
00238   if ( previousState == Starting || previousState == Broken ) // valid cases where nothing might be running (yet)
00239     return previousState;
00240   return NotRunning;
00241 }
00242 
00243 int Internal::serverProtocolVersion()
00244 {
00245   return ServerManagerPrivate::serverProtocolVersion;
00246 }
00247 
00248 void Internal::setServerProtocolVersion( int version )
00249 {
00250   ServerManagerPrivate::serverProtocolVersion = version;
00251   if ( sInstance.exists() )
00252     sInstance->checkStatusChanged();
00253 }
00254 
00255 Internal::ClientType Internal::clientType()
00256 {
00257   return ServerManagerPrivate::clientType;
00258 }
00259 
00260 void Internal::setClientType( ClientType type )
00261 {
00262   ServerManagerPrivate::clientType = type;
00263 }
00264 
00265 #include "servermanager.moc"

akonadi

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

KDE-PIM Libraries

Skip menu "KDE-PIM Libraries"
  • akonadi
  •   contact
  •   kmime
  • kabc
  • kblog
  • kcal
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  •   richtextbuilders
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • microblog
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2
Generated for KDE-PIM Libraries by doxygen 1.7.1
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