refs #597, loading changed so that it is guaranteed setup is loaded before application is actually started

This commit is contained in:
Klaus Basan
2016-03-13 17:59:22 +00:00
committed by Mathew Sutcliffe
parent 488bdb3392
commit c649c1b7ed
2 changed files with 98 additions and 18 deletions

View File

@@ -21,6 +21,7 @@
#include <QStandardPaths> #include <QStandardPaths>
#include <QFile> #include <QFile>
#include <QFileInfo> #include <QFileInfo>
#include <stdlib.h>
using namespace BlackMisc; using namespace BlackMisc;
using namespace BlackMisc::Network; using namespace BlackMisc::Network;
@@ -31,7 +32,8 @@ BlackCore::CApplication *sApp = nullptr; // set by constructor
namespace BlackCore namespace BlackCore
{ {
CApplication::CApplication(const QString &applicationName) : CApplication::CApplication(const QString &applicationName) :
m_applicationName(applicationName) m_applicationName(applicationName),
m_coreFacadeConfig(CCoreFacadeConfig::allEmpty())
{ {
Q_ASSERT_X(!sApp, Q_FUNC_INFO, "already initialized"); Q_ASSERT_X(!sApp, Q_FUNC_INFO, "already initialized");
Q_ASSERT_X(QCoreApplication::instance(), Q_FUNC_INFO, "no application object"); Q_ASSERT_X(QCoreApplication::instance(), Q_FUNC_INFO, "no application object");
@@ -69,6 +71,7 @@ namespace BlackCore
// global setup // global setup
sApp = this; sApp = this;
this->m_setupReader.reset(new CSetupReader(this)); this->m_setupReader.reset(new CSetupReader(this));
connect(this->m_setupReader.data(), &CSetupReader::setupSynchronized, this, &CApplication::ps_setupSyncronized);
this->m_parser.addOptions(this->m_setupReader->getCmdLineOptions()); this->m_parser.addOptions(this->m_setupReader->getCmdLineOptions());
// notify when app goes down // notify when app goes down
@@ -86,7 +89,7 @@ namespace BlackCore
return QCoreApplication::instance()->applicationName() + " " + CProject::version(); return QCoreApplication::instance()->applicationName() + " " + CProject::version();
} }
bool CApplication::start() bool CApplication::start(bool waitForStart)
{ {
if (!this->m_parsed) if (!this->m_parsed)
{ {
@@ -105,7 +108,27 @@ namespace BlackCore
} }
} }
this->m_started = this->startHookIn(); bool s = this->startHookIn();
if (waitForStart)
{
s = this->waitForStart();
}
this->m_started = s;
return s;
}
bool CApplication::waitForStart()
{
// process events return immediatley if nothing is to be processed
const QTime dieTime = QTime::currentTime().addMSecs(5000);
while (QTime::currentTime() < dieTime && !this->m_started && !this->m_startUpCompleted)
{
QCoreApplication::instance()->processEvents(QEventLoop::AllEvents, 250);
}
if (this->m_startUpCompleted)
{
CLogMessage(this).error("Waiting for startup timed out");
}
return this->m_started; return this->m_started;
} }
@@ -163,13 +186,28 @@ namespace BlackCore
return QCoreApplication::arguments(); return QCoreApplication::arguments();
} }
void CApplication::useContexts(const CCoreFacadeConfig &coreConfig) bool CApplication::useContexts(const CCoreFacadeConfig &coreConfig)
{ {
if (this->m_coreFacade.isNull()) Q_ASSERT_X(this->m_parsed, Q_FUNC_INFO, "Call this after parsing");
{
this->m_coreFacade.reset(new CCoreFacade(coreConfig)); this->m_useContexts = true;
this->coreFacadeStarted(); this->m_coreFacadeConfig = coreConfig;
} return this->startCoreFacade(); // will do nothing if setup is not yet loaded
}
bool CApplication::startCoreFacade()
{
if (!this->m_useContexts) { return true; } // we do not use context, so no need to startup
if (!this->m_parsed) { return false; }
if (!this->m_setupReader || !this->m_setupReader->isSetupSyncronized()) { return false; }
Q_ASSERT_X(this->m_coreFacade.isNull(), Q_FUNC_INFO, "Cannot alter facade");
Q_ASSERT_X(this->m_setupReader, Q_FUNC_INFO, "No facade without setup possible");
CLogMessage(this).info("Will start core facade now");
this->m_coreFacade.reset(new CCoreFacade(this->m_coreFacadeConfig));
emit this->coreFacadeStarted();
return true;
} }
void CApplication::initLogging() void CApplication::initLogging()
@@ -236,6 +274,29 @@ namespace BlackCore
this->m_fileLogger->close(); this->m_fileLogger->close();
} }
void CApplication::ps_setupSyncronized(bool success)
{
if (success)
{
if (!this->m_started)
{
// follow up startup
this->m_started = this->startCoreFacade();
}
}
this->m_startUpCompleted = true;
}
void CApplication::severeStartupProblem(const CStatusMessage &message)
{
CLogMessage(this).preformatted(message);
this->errorMessage(message.getMessage());
this->exit(EXIT_FAILURE);
// if I get here the event loop was not yet running
std::exit(EXIT_FAILURE);
}
CApplication *BlackCore::CApplication::instance() CApplication *BlackCore::CApplication::instance()
{ {
return sApp; return sApp;

View File

@@ -54,6 +54,9 @@ namespace BlackCore
//! Similar to \sa QCoreApplication::instance() returns the single instance //! Similar to \sa QCoreApplication::instance() returns the single instance
static CApplication *instance(); static CApplication *instance();
//! Own log categories
static const BlackMisc::CLogCategoryList &getLogCategories();
//! Constructor //! Constructor
CApplication(const QString &applicationName = executable()); CApplication(const QString &applicationName = executable());
@@ -64,7 +67,10 @@ namespace BlackCore
QString getApplicationNameAndVersion() const; QString getApplicationNameAndVersion() const;
//! Start services, if not yet parsed call CApplication::parse //! Start services, if not yet parsed call CApplication::parse
virtual bool start(); virtual bool start(bool waitForStart = true);
//! Wait for stert by calling the event loop and waiting until everything is ready
bool waitForStart();
//! Request to get network reply //! Request to get network reply
QNetworkReply *requestNetworkResource(const QNetworkRequest &request, QNetworkReply *requestNetworkResource(const QNetworkRequest &request,
@@ -130,7 +136,7 @@ namespace BlackCore
//! Init the contexts part and start core facade //! Init the contexts part and start core facade
//! \sa coreFacadeStarted //! \sa coreFacadeStarted
void useContexts(const CCoreFacadeConfig &coreConfig); bool useContexts(const CCoreFacadeConfig &coreConfig);
//! Get the facade //! Get the facade
CCoreFacade *getCoreFacade() { return m_coreFacade.data(); } CCoreFacade *getCoreFacade() { return m_coreFacade.data(); }
@@ -161,16 +167,14 @@ namespace BlackCore
//! Facade started //! Facade started
void coreFacadeStarted(); void coreFacadeStarted();
protected slots:
//! Setup read/syncronized
void ps_setupSyncronized(bool success);
protected: protected:
//! Constructor //! Constructor
CApplication(const QString &applicationName, QCoreApplication *app); CApplication(const QString &applicationName, QCoreApplication *app);
//! executable name
static const QString &executable();
//! Own log categories
static const BlackMisc::CLogCategoryList &cats();
//! Display help message //! Display help message
virtual void helpMessage(); virtual void helpMessage();
@@ -183,13 +187,26 @@ namespace BlackCore
//! Can be used to start special services //! Can be used to start special services
virtual bool startHookIn() { return true; } virtual bool startHookIn() { return true; }
//! Severe issue during startup, most likely it does not make sense to continue
//! \note call this here if the parsing stage is over and reaction to a runtime issue
//! is needed
void severeStartupProblem(const BlackMisc::CStatusMessage &message);
//! Start the core facade
//! \note does nothing when setup is not yet loaded
bool startCoreFacade();
//! executable name
static const QString &executable();
// cmd parsing // cmd parsing
QCommandLineParser m_parser; //!< cmd parser QCommandLineParser m_parser; //!< cmd parser
QCommandLineOption m_cmdHelp {"help"}; //!< help option QCommandLineOption m_cmdHelp {"help"}; //!< help option
QCommandLineOption m_cmdVersion { "version" }; //!< version option QCommandLineOption m_cmdVersion { "version" }; //!< version option
QCommandLineOption m_cmdDBusAddress {"empty"}; //!< DBus address QCommandLineOption m_cmdDBusAddress {"empty"}; //!< DBus address
bool m_parsed = false; //!< Parsing accomplished? bool m_parsed = false; //!< Parsing accomplished?
bool m_started = false; //!< started? bool m_started = false; //!< started with success?
bool m_startUpCompleted = false; //!< startup phase completed? Can mean startup failed
bool m_startSetupReader = false; //!< start the setup reader bool m_startSetupReader = false; //!< start the setup reader
private: private:
@@ -207,7 +224,9 @@ namespace BlackCore
QScopedPointer<BlackMisc::CFileLogger> m_fileLogger; //!< file logger QScopedPointer<BlackMisc::CFileLogger> m_fileLogger; //!< file logger
QNetworkAccessManager m_accessManager { this }; //!< single network access manager QNetworkAccessManager m_accessManager { this }; //!< single network access manager
QString m_applicationName; //!< application name QString m_applicationName; //!< application name
CCoreFacadeConfig m_coreFacadeConfig; //!< Core facade config if any
bool m_shutdown = false; //!< is being shut down bool m_shutdown = false; //!< is being shut down
bool m_useContexts = false; //!< use contexts
}; };
} // namespace } // namespace