File indexing completed on 2024-11-10 04:40:39

0001 /*
0002     SPDX-FileCopyrightText: 2007 Volker Krause <vkrause@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "control.h"
0008 #include "akonadicore_debug.h"
0009 #include "servermanager.h"
0010 
0011 #include <QCoreApplication>
0012 #include <QEventLoop>
0013 #include <QPointer>
0014 
0015 using namespace Akonadi;
0016 
0017 namespace Akonadi
0018 {
0019 namespace Internal
0020 {
0021 class StaticControl : public Control
0022 {
0023     Q_OBJECT
0024 };
0025 
0026 }
0027 
0028 Q_GLOBAL_STATIC(Internal::StaticControl, s_instance) // NOLINT(readability-redundant-member-init)
0029 
0030 /**
0031  * @internal
0032  */
0033 class ControlPrivate
0034 {
0035 public:
0036     explicit ControlPrivate(Control *parent)
0037         : mParent(parent)
0038     {
0039     }
0040 
0041     void cleanup()
0042     {
0043     }
0044 
0045     bool exec();
0046     void serverStateChanged(ServerManager::State state);
0047 
0048     QPointer<Control> mParent;
0049     QEventLoop *mEventLoop = nullptr;
0050     bool mSuccess = false;
0051 
0052     bool mStarting = false;
0053     bool mStopping = false;
0054 };
0055 
0056 bool ControlPrivate::exec()
0057 {
0058     qCDebug(AKONADICORE_LOG) << "Starting/Stopping Akonadi (using an event loop).";
0059     mEventLoop = new QEventLoop(mParent);
0060     mEventLoop->exec();
0061     mEventLoop->deleteLater();
0062     mEventLoop = nullptr;
0063 
0064     if (!mSuccess) {
0065         qCWarning(AKONADICORE_LOG) << "Could not start/stop Akonadi!";
0066     }
0067 
0068     mStarting = false;
0069     mStopping = false;
0070 
0071     const bool rv = mSuccess;
0072     mSuccess = false;
0073     return rv;
0074 }
0075 
0076 void ControlPrivate::serverStateChanged(ServerManager::State state)
0077 {
0078     qCDebug(AKONADICORE_LOG) << "Server state changed to" << state;
0079     if (mEventLoop && mEventLoop->isRunning()) {
0080         // ignore transient states going into the right direction
0081         if ((mStarting && (state == ServerManager::Starting || state == ServerManager::Upgrading)) || (mStopping && state == ServerManager::Stopping)) {
0082             return;
0083         }
0084         mEventLoop->quit();
0085         mSuccess = (mStarting && state == ServerManager::Running) || (mStopping && state == ServerManager::NotRunning);
0086     }
0087 }
0088 
0089 Control::Control()
0090     : d(new ControlPrivate(this))
0091 {
0092     connect(ServerManager::self(), &ServerManager::stateChanged, this, [this](Akonadi::ServerManager::State state) {
0093         d->serverStateChanged(state);
0094     });
0095     // mProgressIndicator is a widget, so it better be deleted before the QApplication is deleted
0096     // Otherwise we get a crash in QCursor code with Qt-4.5
0097     if (QCoreApplication::instance()) {
0098         connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit, this, [this]() {
0099             d->cleanup();
0100         });
0101     }
0102 }
0103 
0104 Control::~Control() = default;
0105 
0106 bool Control::start()
0107 {
0108     if (ServerManager::state() == ServerManager::Stopping) {
0109         qCDebug(AKONADICORE_LOG) << "Server is currently being stopped, won't try to start it now";
0110         return false;
0111     }
0112     if (ServerManager::isRunning() || s_instance->d->mEventLoop) {
0113         qCDebug(AKONADICORE_LOG) << "Server is already running";
0114         return true;
0115     }
0116     s_instance->d->mStarting = true;
0117     if (!ServerManager::start()) {
0118         qCDebug(AKONADICORE_LOG) << "ServerManager::start failed -> return false";
0119         return false;
0120     }
0121     return s_instance->d->exec();
0122 }
0123 
0124 bool Control::stop()
0125 {
0126     if (ServerManager::state() == ServerManager::Starting) {
0127         return false;
0128     }
0129     if (!ServerManager::isRunning() || s_instance->d->mEventLoop) {
0130         return true;
0131     }
0132     s_instance->d->mStopping = true;
0133     if (!ServerManager::stop()) {
0134         return false;
0135     }
0136     return s_instance->d->exec();
0137 }
0138 
0139 bool Control::restart()
0140 {
0141     if (ServerManager::isRunning()) {
0142         if (!stop()) {
0143             return false;
0144         }
0145     }
0146     return start();
0147 }
0148 
0149 } // namespace Akonadi
0150 
0151 #include "control.moc"
0152 
0153 #include "moc_control.cpp"