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 <QFile>
#include <QFileInfo>
#include <stdlib.h>
using namespace BlackMisc;
using namespace BlackMisc::Network;
@@ -31,7 +32,8 @@ BlackCore::CApplication *sApp = nullptr; // set by constructor
namespace BlackCore
{
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(QCoreApplication::instance(), Q_FUNC_INFO, "no application object");
@@ -69,6 +71,7 @@ namespace BlackCore
// global setup
sApp = 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());
// notify when app goes down
@@ -86,7 +89,7 @@ namespace BlackCore
return QCoreApplication::instance()->applicationName() + " " + CProject::version();
}
bool CApplication::start()
bool CApplication::start(bool waitForStart)
{
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;
}
@@ -163,13 +186,28 @@ namespace BlackCore
return QCoreApplication::arguments();
}
void CApplication::useContexts(const CCoreFacadeConfig &coreConfig)
bool CApplication::useContexts(const CCoreFacadeConfig &coreConfig)
{
if (this->m_coreFacade.isNull())
{
this->m_coreFacade.reset(new CCoreFacade(coreConfig));
this->coreFacadeStarted();
}
Q_ASSERT_X(this->m_parsed, Q_FUNC_INFO, "Call this after parsing");
this->m_useContexts = true;
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()
@@ -236,6 +274,29 @@ namespace BlackCore
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()
{
return sApp;

View File

@@ -54,6 +54,9 @@ namespace BlackCore
//! Similar to \sa QCoreApplication::instance() returns the single instance
static CApplication *instance();
//! Own log categories
static const BlackMisc::CLogCategoryList &getLogCategories();
//! Constructor
CApplication(const QString &applicationName = executable());
@@ -64,7 +67,10 @@ namespace BlackCore
QString getApplicationNameAndVersion() const;
//! 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
QNetworkReply *requestNetworkResource(const QNetworkRequest &request,
@@ -130,7 +136,7 @@ namespace BlackCore
//! Init the contexts part and start core facade
//! \sa coreFacadeStarted
void useContexts(const CCoreFacadeConfig &coreConfig);
bool useContexts(const CCoreFacadeConfig &coreConfig);
//! Get the facade
CCoreFacade *getCoreFacade() { return m_coreFacade.data(); }
@@ -161,16 +167,14 @@ namespace BlackCore
//! Facade started
void coreFacadeStarted();
protected slots:
//! Setup read/syncronized
void ps_setupSyncronized(bool success);
protected:
//! Constructor
CApplication(const QString &applicationName, QCoreApplication *app);
//! executable name
static const QString &executable();
//! Own log categories
static const BlackMisc::CLogCategoryList &cats();
//! Display help message
virtual void helpMessage();
@@ -183,13 +187,26 @@ namespace BlackCore
//! Can be used to start special services
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
QCommandLineParser m_parser; //!< cmd parser
QCommandLineOption m_cmdHelp {"help"}; //!< help option
QCommandLineOption m_cmdVersion { "version" }; //!< version option
QCommandLineOption m_cmdDBusAddress {"empty"}; //!< DBus address
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
private:
@@ -207,7 +224,9 @@ namespace BlackCore
QScopedPointer<BlackMisc::CFileLogger> m_fileLogger; //!< file logger
QNetworkAccessManager m_accessManager { this }; //!< single network access manager
QString m_applicationName; //!< application name
CCoreFacadeConfig m_coreFacadeConfig; //!< Core facade config if any
bool m_shutdown = false; //!< is being shut down
bool m_useContexts = false; //!< use contexts
};
} // namespace