mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-04-12 23:35:33 +08:00
* changed signals in setup reader * explicit mode is default * detailed information what is loaded * new log pattern * allow to add message list to log component * allow to clear cache by cmd line arg * consolidated cmd names
This commit is contained in:
@@ -41,10 +41,9 @@ BlackCore::CApplication *sApp = nullptr; // set by constructor
|
||||
|
||||
namespace BlackCore
|
||||
{
|
||||
CApplication::CApplication(const QString &applicationName, bool init) :
|
||||
m_cookieManager( {}, this),
|
||||
m_applicationName(applicationName),
|
||||
m_coreFacadeConfig(CCoreFacadeConfig::allEmpty())
|
||||
CApplication::CApplication(
|
||||
const QString &applicationName, bool init) :
|
||||
m_cookieManager( {}, this), 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");
|
||||
@@ -67,25 +66,26 @@ namespace BlackCore
|
||||
this->initParser();
|
||||
this->initLogging();
|
||||
|
||||
//
|
||||
// cmd line arguments not yet parsed here
|
||||
//
|
||||
|
||||
// Translations
|
||||
QFile file(":blackmisc/translations/blackmisc_i18n_de.qm");
|
||||
CLogMessage(this).debug() << (file.exists() ? "Found translations in resources" : "No translations in resources");
|
||||
QTranslator translator;
|
||||
if (translator.load("blackmisc_i18n_de", ":blackmisc/translations/"))
|
||||
{
|
||||
CLogMessage(this).debug() << "Translator loaded";
|
||||
}
|
||||
if (translator.load("blackmisc_i18n_de", ":blackmisc/translations/")) { CLogMessage(this).debug() << "Translator loaded"; }
|
||||
QCoreApplication::instance()->installTranslator(&translator);
|
||||
|
||||
// Global setup / bootstraping
|
||||
// Init network
|
||||
this->m_cookieManager.setParent(&this->m_accessManager);
|
||||
this->m_accessManager.setCookieJar(&this->m_cookieManager);
|
||||
|
||||
// global setup
|
||||
sApp = this;
|
||||
this->m_setupReader.reset(new CSetupReader(this));
|
||||
connect(this->m_setupReader.data(), &CSetupReader::setupSynchronized, this, &CApplication::ps_setupSyncronized);
|
||||
connect(this->m_setupReader.data(), &CSetupReader::updateInfoSynchronized, this, &CApplication::updateInfoSynchronized);
|
||||
connect(this->m_setupReader.data(), &CSetupReader::setupAvailable, this, &CApplication::ps_setupAvailable);
|
||||
connect(this->m_setupReader.data(), &CSetupReader::updateInfoAvailable, this, &CApplication::updateInfoAvailable);
|
||||
|
||||
this->m_parser.addOptions(this->m_setupReader->getCmdLineOptions());
|
||||
|
||||
@@ -97,7 +97,6 @@ namespace BlackCore
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
CApplication::~CApplication()
|
||||
{
|
||||
this->gracefulShutdown();
|
||||
@@ -137,13 +136,21 @@ namespace BlackCore
|
||||
if (!s) { return false; }
|
||||
}
|
||||
|
||||
// parsing itself is done
|
||||
if (this->m_startSetupReader && !this->m_setupReader->isSetupSyncronized())
|
||||
// clear cache?
|
||||
if (this->isSetOrTrue(this->m_cmdClearCache))
|
||||
{
|
||||
CStatusMessage m(this->requestReloadOfSetupAndVersion());
|
||||
if (m.isWarningOrAbove())
|
||||
QStringList files(CApplication::clearCaches());
|
||||
CLogMessage(this).debug() << "Cleared cache, " << files.size() << " files";
|
||||
}
|
||||
|
||||
// parsing itself is done
|
||||
if (this->m_startSetupReader && !this->m_setupReader->isSetupAvailable())
|
||||
{
|
||||
const CStatusMessageList msgs(this->requestReloadOfSetupAndVersion());
|
||||
CLogMessage::preformatted(msgs);
|
||||
if (msgs.isFailure())
|
||||
{
|
||||
this->cmdLineErrorMessage(m.getMessage());
|
||||
this->cmdLineErrorMessage(msgs.getWarningAndErrorMessages().toSingleMessage().getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -188,13 +195,13 @@ namespace BlackCore
|
||||
return this->m_started;
|
||||
}
|
||||
|
||||
bool CApplication::isSetupSyncronized() const
|
||||
bool CApplication::isSetupAvailable() const
|
||||
{
|
||||
if (this->m_shutdown || !this->m_setupReader) { return false; }
|
||||
return this->m_setupReader->isSetupSyncronized();
|
||||
return this->m_setupReader->isSetupAvailable();
|
||||
}
|
||||
|
||||
CStatusMessage CApplication::requestReloadOfSetupAndVersion()
|
||||
CStatusMessageList CApplication::requestReloadOfSetupAndVersion()
|
||||
{
|
||||
if (!this->m_shutdown)
|
||||
{
|
||||
@@ -256,16 +263,14 @@ namespace BlackCore
|
||||
return a.constData();
|
||||
}
|
||||
|
||||
bool CApplication::isRunningInDeveloperEnvironment() const
|
||||
bool CApplication::initIsRunningInDeveloperEnvironment() const
|
||||
{
|
||||
if (!CBuildConfig::canRunInDeveloperEnvironment()) { return false; }
|
||||
if (!this->m_parser.value(this->m_cmdDevelopment).isEmpty())
|
||||
if (this->m_parser.isSet(this->m_cmdDevelopment))
|
||||
{
|
||||
// explicit value
|
||||
const QString v(this->m_parser.value(this->m_cmdDevelopment));
|
||||
return stringToBool(v);
|
||||
return this->isSetOrTrue(this->m_cmdDevelopment);
|
||||
}
|
||||
else if (this->isSetupSyncronized())
|
||||
else if (this->isSetupAvailable())
|
||||
{
|
||||
// assume value from setup
|
||||
return this->getGlobalSetup().isDevelopment();
|
||||
@@ -442,7 +447,7 @@ namespace BlackCore
|
||||
{
|
||||
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; }
|
||||
if (!this->m_setupReader || !this->m_setupReader->isSetupAvailable()) { 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");
|
||||
@@ -460,7 +465,7 @@ namespace BlackCore
|
||||
{
|
||||
if (!this->m_useWebData) { return true; }
|
||||
if (!this->m_parsed) { return false; }
|
||||
if (!this->m_setupReader || !this->m_setupReader->isSetupSyncronized()) { return false; }
|
||||
if (!this->m_setupReader || !this->m_setupReader->isSetupAvailable()) { return false; }
|
||||
|
||||
Q_ASSERT_X(this->m_setupReader, Q_FUNC_INFO, "No web data services without setup possible");
|
||||
if (!this->m_webDataServices)
|
||||
@@ -490,7 +495,7 @@ namespace BlackCore
|
||||
this->m_cmdHelp = this->m_parser.addHelpOption();
|
||||
this->m_cmdVersion = this->m_parser.addVersionOption();
|
||||
|
||||
this->m_cmdDevelopment = QCommandLineOption({ "dev", "developemnt" },
|
||||
this->m_cmdDevelopment = QCommandLineOption({ "dev", "development" },
|
||||
QCoreApplication::translate("application", "Dev.system feature?"),
|
||||
"development");
|
||||
this->addParserOption(this->m_cmdDevelopment);
|
||||
@@ -499,6 +504,22 @@ namespace BlackCore
|
||||
QCoreApplication::translate("application", "Local shared directory."),
|
||||
"shared");
|
||||
this->addParserOption(this->m_cmdSharedDir);
|
||||
|
||||
this->m_cmdClearCache = QCommandLineOption({ "ccache", "clearcache" },
|
||||
QCoreApplication::translate("application", "Clear (reset) the caches."),
|
||||
"clearcache");
|
||||
this->addParserOption(this->m_cmdClearCache);
|
||||
}
|
||||
|
||||
bool CApplication::isSetOrTrue(const QCommandLineOption &option) const
|
||||
{
|
||||
if (!this->m_parser.isSet(option)) { return false; }
|
||||
|
||||
// explicit value
|
||||
const QString v(this->m_parser.value(option).trimmed());
|
||||
if (v.isEmpty()) { return true; } // just flag
|
||||
if (v.startsWith("-")) { return true; } // just flag, because value is already next parameter
|
||||
return stringToBool(v);
|
||||
}
|
||||
|
||||
void CApplication::registerMetadata()
|
||||
@@ -507,6 +528,13 @@ namespace BlackCore
|
||||
BlackCore::registerMetadata();
|
||||
}
|
||||
|
||||
QStringList CApplication::clearCaches()
|
||||
{
|
||||
const QStringList files(CDataCache::instance()->enumerateStore());
|
||||
CDataCache::instance()->clearAllValues();
|
||||
return files;
|
||||
}
|
||||
|
||||
void CApplication::gracefulShutdown()
|
||||
{
|
||||
if (this->m_shutdown) { return; }
|
||||
@@ -553,14 +581,15 @@ namespace BlackCore
|
||||
this->m_fileLogger->close();
|
||||
}
|
||||
|
||||
void CApplication::ps_setupSyncronized(bool success)
|
||||
void CApplication::ps_setupAvailable(bool available)
|
||||
{
|
||||
if (success)
|
||||
if (available)
|
||||
{
|
||||
emit setupSyncronized(success);
|
||||
this->m_started = this->asyncWebAndContextStart();
|
||||
}
|
||||
this->m_startUpCompleted = true;
|
||||
emit setupAvailable(available);
|
||||
|
||||
if (this->m_signalStartup)
|
||||
{
|
||||
emit this->startUpCompleted(this->m_started);
|
||||
@@ -624,7 +653,7 @@ namespace BlackCore
|
||||
|
||||
void CApplication::addDBusAddressOption()
|
||||
{
|
||||
this->m_cmdDBusAddress = QCommandLineOption({ "dbus", "dbus-address", "dbusaddress" },
|
||||
this->m_cmdDBusAddress = QCommandLineOption({ "dbus", "dbusaddress" },
|
||||
QCoreApplication::translate("application", "DBus address."),
|
||||
"dbusaddress");
|
||||
this->addParserOption(this->m_cmdDBusAddress);
|
||||
@@ -704,6 +733,9 @@ namespace BlackCore
|
||||
return true;
|
||||
}
|
||||
|
||||
// dev.
|
||||
this->m_devEnv = this->initIsRunningInDeveloperEnvironment();
|
||||
|
||||
// Hookin, other parsing
|
||||
if (!this->parsingHookIn()) { return false; }
|
||||
|
||||
|
||||
@@ -90,10 +90,10 @@ namespace BlackCore
|
||||
void deleteAllCookies();
|
||||
|
||||
//! Setup already syncronized
|
||||
bool isSetupSyncronized() const;
|
||||
bool isSetupAvailable() const;
|
||||
|
||||
//! Reload setup and version
|
||||
BlackMisc::CStatusMessage requestReloadOfSetupAndVersion();
|
||||
BlackMisc::CStatusMessageList requestReloadOfSetupAndVersion();
|
||||
|
||||
//! Web data services available?
|
||||
bool hasWebDataServices() const;
|
||||
@@ -114,7 +114,7 @@ namespace BlackCore
|
||||
const char *swiftVersionChar();
|
||||
|
||||
//! Running in dev.environment?
|
||||
bool isRunningInDeveloperEnvironment() const;
|
||||
bool isRunningInDeveloperEnvironment() const { return this->m_devEnv; }
|
||||
|
||||
//! Signal startup automatically or individually
|
||||
void signalStartupAutomatically(bool signal = false);
|
||||
@@ -137,6 +137,9 @@ namespace BlackCore
|
||||
//! Process all events for some time
|
||||
static void processEventsFor(int milliseconds);
|
||||
|
||||
//! Clear the caches
|
||||
static QStringList clearCaches();
|
||||
|
||||
// ----------------------- parsing ----------------------------------------
|
||||
|
||||
//! \name parsing of command line options
|
||||
@@ -259,11 +262,11 @@ namespace BlackCore
|
||||
const BlackMisc::CSlot<void(QNetworkReply *)> &callback);
|
||||
|
||||
signals:
|
||||
//! Setup syncronized
|
||||
void setupSyncronized(bool success);
|
||||
//! Setup available (cache, web load, ..)
|
||||
void setupAvailable(bool success);
|
||||
|
||||
//! Update info syncronized
|
||||
void updateInfoSynchronized(bool success);
|
||||
//! Update info available (cache, web load)
|
||||
void updateInfoAvailable(bool success);
|
||||
|
||||
//! Startup has been completed
|
||||
void startUpCompleted(bool success);
|
||||
@@ -276,7 +279,7 @@ namespace BlackCore
|
||||
|
||||
protected slots:
|
||||
//! Setup read/syncronized
|
||||
void ps_setupSyncronized(bool success);
|
||||
void ps_setupAvailable(bool available);
|
||||
|
||||
//! Startup completed
|
||||
virtual void ps_startupCompleted();
|
||||
@@ -297,6 +300,9 @@ namespace BlackCore
|
||||
//! Can be used to start special services
|
||||
virtual bool startHookIn() { return true; }
|
||||
|
||||
//! Flag set or explicitly set to true
|
||||
bool isSetOrTrue(const QCommandLineOption &option) const;
|
||||
|
||||
//! 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
|
||||
@@ -317,17 +323,17 @@ namespace BlackCore
|
||||
static void registerMetadata();
|
||||
|
||||
// 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
|
||||
QCommandLineOption m_cmdDevelopment {"dev"}; //!< Dev flag
|
||||
QCommandLineOption m_cmdSharedDir {"shared"}; //!< Dev flag
|
||||
|
||||
bool m_parsed = false; //!< Parsing accomplished?
|
||||
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
|
||||
QCommandLineParser m_parser; //!< cmd parser
|
||||
QCommandLineOption m_cmdHelp {"help"}; //!< help option
|
||||
QCommandLineOption m_cmdVersion {"version"}; //!< version option
|
||||
QCommandLineOption m_cmdDBusAddress {"empty"}; //!< DBus address
|
||||
QCommandLineOption m_cmdDevelopment {"dev"}; //!< Dev. flag
|
||||
QCommandLineOption m_cmdSharedDir {"shared"}; //!< Shared directory
|
||||
QCommandLineOption m_cmdClearCache {"clearcache"}; //!< Clear cache
|
||||
bool m_parsed = false; //!< Parsing accomplished?
|
||||
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:
|
||||
//! init logging system
|
||||
@@ -336,6 +342,9 @@ namespace BlackCore
|
||||
//! Init parser
|
||||
void initParser();
|
||||
|
||||
//! Dev.environment
|
||||
bool initIsRunningInDeveloperEnvironment() const;
|
||||
|
||||
//! Async. start when setup is loaded
|
||||
bool asyncWebAndContextStart();
|
||||
|
||||
@@ -354,6 +363,7 @@ namespace BlackCore
|
||||
bool m_useContexts = false; //!< use contexts
|
||||
bool m_useWebData = false; //!< use web data
|
||||
bool m_signalStartup = true; //!< signal startup automatically
|
||||
bool m_devEnv = false; //!< dev. environment
|
||||
};
|
||||
} // namespace
|
||||
|
||||
|
||||
@@ -82,14 +82,14 @@ namespace BlackCore
|
||||
|
||||
QString CGlobalSetup::buildBootstrapFileUrl(const QString &candidate)
|
||||
{
|
||||
static const QString vS(QString(versionString()).append("/"));
|
||||
static const QString version(QString(versionString()).append("/"));
|
||||
if (candidate.endsWith("bootstrap.json")) { return candidate; }
|
||||
CUrl url(candidate);
|
||||
if (candidate.contains("/bootstrap"))
|
||||
{
|
||||
url.appendPath("bootstrap.json");
|
||||
}
|
||||
else if (candidate.endsWith(versionString()) || candidate.endsWith(vS))
|
||||
else if (candidate.endsWith(versionString()) || candidate.endsWith(version))
|
||||
{
|
||||
url.appendPath("/bootstrap/bootstrap.json");
|
||||
}
|
||||
|
||||
@@ -30,10 +30,7 @@ namespace BlackCore
|
||||
{
|
||||
CSetupReader::CSetupReader(QObject *parent) :
|
||||
QObject(parent)
|
||||
{
|
||||
connect(this, &CSetupReader::setupSynchronized, this, &CSetupReader::ps_setupSyncronized);
|
||||
connect(this, &CSetupReader::updateInfoSynchronized, this, &CSetupReader::ps_versionInfoSyncronized);
|
||||
}
|
||||
{ }
|
||||
|
||||
QList<QCommandLineOption> CSetupReader::getCmdLineOptions() const
|
||||
{
|
||||
@@ -46,24 +43,33 @@ namespace BlackCore
|
||||
};
|
||||
}
|
||||
|
||||
CStatusMessage CSetupReader::asyncLoad()
|
||||
CStatusMessageList CSetupReader::asyncLoad()
|
||||
{
|
||||
CStatusMessageList msgs;
|
||||
if (this->readLocalBootstrapFile(this->m_localSetupFileValue))
|
||||
{
|
||||
// initialized by local file for testing
|
||||
emit this->setupSynchronized(true);
|
||||
return CStatusMessage(this, CStatusMessage::SeverityInfo, "Using local bootstrap file: " + this->m_localSetupFileValue);
|
||||
msgs.push_back(CStatusMessage(this, CStatusMessage::SeverityInfo, "Using local bootstrap file: " + this->m_localSetupFileValue));
|
||||
msgs.push_back(this->manageSetupAvailability(false, true));
|
||||
return msgs;
|
||||
}
|
||||
|
||||
m_setup.synchronize(); // make sure it is loaded
|
||||
CGlobalSetup cachedSetup = m_setup.getCopy();
|
||||
const bool cacheAvailable = cachedSetup.wasLoaded();
|
||||
msgs.push_back(cacheAvailable ?
|
||||
CStatusMessage(this, CStatusMessage::SeverityInfo , "Cached setup syncronized and contains data") :
|
||||
CStatusMessage(this, CStatusMessage::SeverityInfo , "Cached setup syncronized, but no data")
|
||||
);
|
||||
if (this->m_bootstrapMode == CacheOnly)
|
||||
{
|
||||
|
||||
CGlobalSetup currentSetup = m_setup.getCopy();
|
||||
this->m_updateInfoUrls = currentSetup.getUpdateInfoFileUrls();
|
||||
emit this->setupSynchronized(true);
|
||||
emit this->updateInfoSynchronized(true);
|
||||
return CStatusMessage(this, CStatusMessage::SeverityInfo, "Cache only setup, using it as it is");
|
||||
this->m_updateInfoUrls = cachedSetup.getUpdateInfoFileUrls();
|
||||
msgs.push_back(cacheAvailable ?
|
||||
CStatusMessage(this, CStatusMessage::SeverityInfo, "Cache only setup, using it as it is") :
|
||||
CStatusMessage(this, CStatusMessage::SeverityError, "Cache only setup, but cache is empty")
|
||||
);
|
||||
msgs.push_back(this->manageSetupAvailability(false, false));
|
||||
return msgs;
|
||||
}
|
||||
|
||||
this->m_bootstrapUrls.clear(); // clean up previous values
|
||||
@@ -76,37 +82,45 @@ namespace BlackCore
|
||||
}
|
||||
|
||||
// if ever loaded add those URLs
|
||||
const CGlobalSetup currentSetup = m_setup.getCopy();
|
||||
if (this->m_bootstrapMode != Explicit)
|
||||
if (cacheAvailable)
|
||||
{
|
||||
// also use previously cached URLs
|
||||
this->m_bootstrapUrls.push_back(currentSetup.getBootstrapFileUrls());
|
||||
|
||||
// fail over if still empty
|
||||
//! \todo do we want to keep this or use a cmd line flag to enable the behaviour. Risk here to use an undesired setup
|
||||
if (this->m_bootstrapUrls.isEmpty())
|
||||
if (this->m_bootstrapMode != Explicit)
|
||||
{
|
||||
// use file from disk delivered with swift
|
||||
// there is a potential risk here, if the URL passed via cmd args is actually adressing an entirely diffent scenario,
|
||||
// this would load a file for something else
|
||||
CGlobalSetup resourceSetup(CGlobalSetup::fromJsonFile(
|
||||
CBuildConfig::getBootstrapResourceFile()
|
||||
));
|
||||
this->m_bootstrapUrls.push_back(resourceSetup.getBootstrapFileUrls());
|
||||
// also use previously cached URLs
|
||||
const CUrlList bootstrapCacheUrls(cachedSetup.getBootstrapFileUrls());
|
||||
this->m_bootstrapUrls.push_back(bootstrapCacheUrls);
|
||||
msgs.push_back(bootstrapCacheUrls.isEmpty() ?
|
||||
CStatusMessage(this, CStatusMessage::SeverityWarning, "No bootsrap URLs in cache") :
|
||||
CStatusMessage(this, CStatusMessage::SeverityInfo, "Adding " + QString::number(bootstrapCacheUrls.size()) + " bootstrap URLs from cache"));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
msgs.push_back(CStatusMessage(this, CStatusMessage::SeverityInfo, "Empty cache, will not add URLs"));
|
||||
}
|
||||
|
||||
this->m_bootstrapUrls.removeDuplicates(); // clean up
|
||||
if (this->m_bootstrapUrls.isEmpty())
|
||||
{
|
||||
// after all still empty
|
||||
return CStatusMessage(this, CStatusMessage::SeverityError, "No bootstrap URLs, cannot load setup");
|
||||
msgs.push_back(CStatusMessage(this, CStatusMessage::SeverityError, "No bootstrap URLs, cannot load setup"));
|
||||
}
|
||||
else
|
||||
{
|
||||
this->ps_readSetup(); // start reading
|
||||
return CStatusMessage(this, CStatusMessage::SeverityInfo, "Will start loading setup");
|
||||
CStatusMessageList readMsgs = triggerReadSetup();
|
||||
if (cacheAvailable && readMsgs.isFailure())
|
||||
{
|
||||
// error but cache is available, we can continue
|
||||
readMsgs.clipSeverity(CStatusMessage::SeverityWarning);
|
||||
msgs.push_back(CStatusMessage(this, CStatusMessage::SeverityWarning, "Loading setup failed, but cache is available, will continue"));
|
||||
msgs.push_back(readMsgs);
|
||||
}
|
||||
else
|
||||
{
|
||||
msgs.push_back(readMsgs);
|
||||
}
|
||||
}
|
||||
return msgs;
|
||||
}
|
||||
|
||||
bool CSetupReader::parseCmdLineArguments()
|
||||
@@ -114,8 +128,13 @@ namespace BlackCore
|
||||
this->m_bootstrapUrlFileValue = CGlobalSetup::buildBootstrapFileUrl(
|
||||
sApp->getParserValue(this->m_cmdBootstrapUrl)
|
||||
);
|
||||
this->m_bootstrapMode = stringToEnum(sApp->getParserValue(this->m_cmdBootstrapMode));
|
||||
QUrl url(this->m_bootstrapUrlFileValue);
|
||||
const QString urlString(url.toString());
|
||||
this->m_bootstrapMode = stringToEnum(sApp->getParserValue(this->m_cmdBootstrapMode));
|
||||
if (urlString.isEmpty() && this->m_bootstrapMode == Explicit)
|
||||
{
|
||||
this->m_bootstrapMode = Implicit; // no URL, we use implicit mode
|
||||
}
|
||||
|
||||
// check on local file
|
||||
if (url.isLocalFile())
|
||||
@@ -136,7 +155,7 @@ namespace BlackCore
|
||||
{
|
||||
if (!CNetworkUtils::canConnect(url))
|
||||
{
|
||||
sApp->cmdLineErrorMessage("URL " + url.toString() + " not reachable");
|
||||
sApp->cmdLineErrorMessage("URL " + urlString + " not reachable");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -151,17 +170,29 @@ namespace BlackCore
|
||||
|
||||
void CSetupReader::ps_readSetup()
|
||||
{
|
||||
const CStatusMessageList msgs(this->triggerReadSetup());
|
||||
if (!msgs.isSuccess())
|
||||
{
|
||||
CLogMessage::preformatted(msgs);
|
||||
}
|
||||
}
|
||||
|
||||
CStatusMessageList CSetupReader::triggerReadSetup()
|
||||
{
|
||||
if (m_shutdown) { return CStatusMessage(this, CStatusMessage::SeverityError, "shutdown"); }
|
||||
const CUrl url(this->m_bootstrapUrls.obtainNextWorkingUrl());
|
||||
if (url.isEmpty())
|
||||
{
|
||||
CLogMessage(this).warning("Cannot read setup, URLs: %1, failed URLs: %2")
|
||||
<< this->m_bootstrapUrls
|
||||
<< this->m_bootstrapUrls.getFailedUrls();
|
||||
emit setupSynchronized(false);
|
||||
return;
|
||||
const CStatusMessage m(this, CStatusMessage::SeverityError,
|
||||
"Cannot read setup, URLs: " + this->m_bootstrapUrls.toQString() +
|
||||
" failed URLs: " + this->m_bootstrapUrls.getFailedUrls().toQString());
|
||||
CStatusMessageList msgs(m);
|
||||
msgs.push_back(this->manageSetupAvailability(false, false));
|
||||
return msgs;
|
||||
}
|
||||
if (m_shutdown) { return; }
|
||||
const CStatusMessage m(this, CStatusMessage::SeverityInfo, "Start reading URL: " + url.toQString());
|
||||
sApp->getFromNetwork(url.toNetworkRequest(), { this, &CSetupReader::ps_parseSetupFile });
|
||||
return m;
|
||||
}
|
||||
|
||||
void CSetupReader::ps_readUpdateInfo()
|
||||
@@ -172,33 +203,13 @@ namespace BlackCore
|
||||
CLogMessage(this).warning("Cannot read update info, URLs: %1, failed URLs: %2")
|
||||
<< this->m_updateInfoUrls
|
||||
<< this->m_updateInfoUrls.getFailedUrls();
|
||||
emit updateInfoSynchronized(false);
|
||||
this->manageUpdateAvailability(false);
|
||||
return;
|
||||
}
|
||||
if (m_shutdown) { return; }
|
||||
sApp->getFromNetwork(url.toNetworkRequest(), { this, &CSetupReader::ps_parseUpdateInfoFile});
|
||||
}
|
||||
|
||||
void CSetupReader::ps_setupSyncronized(bool success)
|
||||
{
|
||||
// trigger consecutive read
|
||||
this->m_setupSyncronized = success;
|
||||
if (success)
|
||||
{
|
||||
CLogMessage(this).info("Setup synchronized, will trigger read of update information");
|
||||
QTimer::singleShot(500, this, &CSetupReader::ps_readUpdateInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
CLogMessage(this).error("Setup reading failed, hence version info will not be loaded");
|
||||
}
|
||||
}
|
||||
|
||||
void CSetupReader::ps_versionInfoSyncronized(bool success)
|
||||
{
|
||||
this->m_updateInfoSyncronized = success;
|
||||
}
|
||||
|
||||
void CSetupReader::ps_setupChanged()
|
||||
{
|
||||
// settings have changed on disk
|
||||
@@ -209,7 +220,7 @@ namespace BlackCore
|
||||
const QString bsm(s.toLower().trimmed());
|
||||
if (bsm.startsWith("expl")) return Explicit;
|
||||
if (bsm.startsWith("cache")) return CacheOnly;
|
||||
return Default;
|
||||
return Implicit;
|
||||
}
|
||||
|
||||
bool CSetupReader::readLocalBootstrapFile(QString &fileName)
|
||||
@@ -273,7 +284,7 @@ namespace BlackCore
|
||||
{
|
||||
this->m_updateInfoUrls = currentSetup.getUpdateInfoFileUrls(); // defaults
|
||||
CLogMessage(this).info("Same setup version loaded from %1 as already in data cache %2") << urlString << m_setup.getFilename();
|
||||
emit setupSynchronized(true);
|
||||
CLogMessage::preformatted(this->manageSetupAvailability(true));
|
||||
return; // success
|
||||
}
|
||||
|
||||
@@ -284,14 +295,14 @@ namespace BlackCore
|
||||
{
|
||||
m.setCategories(getLogCategories());
|
||||
CLogMessage::preformatted(m);
|
||||
emit setupSynchronized(false);
|
||||
CLogMessage::preformatted(this->manageSetupAvailability(false));
|
||||
return; // issue with cache
|
||||
}
|
||||
else
|
||||
{
|
||||
this->m_updateInfoUrls = loadedSetup.getUpdateInfoFileUrls();
|
||||
CLogMessage(this).info("Setup: Updated data cache in %1") << this->m_setup.getFilename();
|
||||
emit setupSynchronized(true);
|
||||
CLogMessage::preformatted(this->manageSetupAvailability(true));
|
||||
return; // success
|
||||
} // cache
|
||||
|
||||
@@ -311,7 +322,7 @@ namespace BlackCore
|
||||
}
|
||||
else
|
||||
{
|
||||
emit setupSynchronized(false);
|
||||
CLogMessage::preformatted(manageSetupAvailability(false));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -346,7 +357,7 @@ namespace BlackCore
|
||||
if (sameVersionLoaded)
|
||||
{
|
||||
CLogMessage(this).info("Same update info version loaded from %1 as already in data cache %2") << urlString << m_setup.getFilename();
|
||||
emit updateInfoSynchronized(true);
|
||||
this->manageUpdateAvailability(true);
|
||||
return; // success
|
||||
}
|
||||
|
||||
@@ -355,13 +366,13 @@ namespace BlackCore
|
||||
{
|
||||
m.setCategories(getLogCategories());
|
||||
CLogMessage::preformatted(m);
|
||||
emit updateInfoSynchronized(false);
|
||||
this->manageUpdateAvailability(false);
|
||||
return; // issue with cache
|
||||
}
|
||||
else
|
||||
{
|
||||
CLogMessage(this).info("Update info: Updated data cache in %1") << m_updateInfo.getFilename();
|
||||
emit updateInfoSynchronized(true);
|
||||
this->manageUpdateAvailability(true);
|
||||
return; // success
|
||||
} // cache
|
||||
} // json empty
|
||||
@@ -380,13 +391,13 @@ namespace BlackCore
|
||||
}
|
||||
else
|
||||
{
|
||||
emit updateInfoSynchronized(false);
|
||||
this->manageUpdateAvailability(false);
|
||||
}
|
||||
} // function
|
||||
|
||||
const CLogCategoryList &CSetupReader::getLogCategories()
|
||||
{
|
||||
static const CLogCategoryList cats({ CLogCategory("swift.setupreader"), CLogCategory::webservice()});
|
||||
static const CLogCategoryList cats({ CLogCategory("swift.setupreader"), CLogCategory::webservice(), CLogCategory::startup()});
|
||||
return cats;
|
||||
}
|
||||
|
||||
@@ -399,4 +410,65 @@ namespace BlackCore
|
||||
{
|
||||
return m_updateInfo.getCopy();
|
||||
}
|
||||
|
||||
CStatusMessageList CSetupReader::manageSetupAvailability(bool webRead, bool localRead)
|
||||
{
|
||||
Q_ASSERT_X(!(webRead && localRead), Q_FUNC_INFO, "Local and web read together seems to be wrong");
|
||||
CStatusMessageList msgs;
|
||||
if (webRead)
|
||||
{
|
||||
msgs.push_back(CLogMessage(this).info("Setup loaded from web, will trigger read of update information"));
|
||||
QTimer::singleShot(500, this, &CSetupReader::ps_readUpdateInfo);
|
||||
}
|
||||
if (localRead)
|
||||
{
|
||||
msgs.push_back(CLogMessage(this).info("Setup loaded locally, will trigger read of update information"));
|
||||
QTimer::singleShot(500, this, &CSetupReader::ps_readUpdateInfo);
|
||||
}
|
||||
|
||||
bool available = false;
|
||||
if (webRead || localRead)
|
||||
{
|
||||
available = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
bool cacheAvailable = this->m_setup.get().wasLoaded();
|
||||
available = cacheAvailable && this->m_bootstrapMode != Explicit;
|
||||
}
|
||||
|
||||
if (available && !webRead && !localRead)
|
||||
{
|
||||
msgs.push_back(CStatusMessage(this, CStatusMessage::SeverityInfo, "Setup available, but not updated this time"));
|
||||
}
|
||||
else if (!available)
|
||||
{
|
||||
msgs.push_back(CStatusMessage(this, CStatusMessage::SeverityError, "Setup not available"));
|
||||
}
|
||||
|
||||
this->m_setupAvailable = available;
|
||||
emit setupAvailable(available);
|
||||
|
||||
if (!webRead && !localRead)
|
||||
{
|
||||
msgs.push_back(CStatusMessage(this).warning("Since setup was not updated this time, will not start loading of update information"));
|
||||
this->manageUpdateAvailability(false);
|
||||
}
|
||||
return msgs;
|
||||
}
|
||||
|
||||
void CSetupReader::manageUpdateAvailability(bool webRead)
|
||||
{
|
||||
if (webRead)
|
||||
{
|
||||
this->m_updateInfoAvailable = true;
|
||||
emit updateInfoAvailable(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
bool cached = this->m_updateInfo.isSaved();
|
||||
this->m_updateInfoAvailable = cached;
|
||||
emit updateInfoAvailable(cached);
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
@@ -52,18 +52,18 @@ namespace BlackCore
|
||||
BlackCore::Data::CUpdateInfo getUpdateInfo() const;
|
||||
|
||||
signals:
|
||||
//! Setup has been read
|
||||
void setupSynchronized(bool success);
|
||||
//! Setup avialable (from web, cache, or local file)
|
||||
void setupAvailable(bool available);
|
||||
|
||||
//! Version bas been read
|
||||
void updateInfoSynchronized(bool success);
|
||||
//! Setup avialable (from web, cache
|
||||
void updateInfoAvailable(bool available);
|
||||
|
||||
protected:
|
||||
//! Constructor
|
||||
explicit CSetupReader(QObject *parent);
|
||||
|
||||
//! Load the data
|
||||
BlackMisc::CStatusMessage asyncLoad();
|
||||
BlackMisc::CStatusMessageList asyncLoad();
|
||||
|
||||
//! Parse cmd line arguments
|
||||
bool parseCmdLineArguments();
|
||||
@@ -74,13 +74,13 @@ namespace BlackCore
|
||||
//! Terminate
|
||||
void gracefulShutdown();
|
||||
|
||||
//! Setup loaded?
|
||||
//! Setup available?
|
||||
//! \threadsafe
|
||||
bool isSetupSyncronized() const { return m_setupSyncronized; }
|
||||
bool isSetupAvailable() const { return m_setupAvailable; }
|
||||
|
||||
//! Version info loaded?
|
||||
//! Version info available?
|
||||
//! \threadsafe
|
||||
bool isUpdateSyncronized() const { return m_updateInfoSyncronized; }
|
||||
bool isUpdateInfoAvailable() const { return m_updateInfoAvailable; }
|
||||
|
||||
private slots:
|
||||
//! Setup has been read
|
||||
@@ -95,12 +95,6 @@ namespace BlackCore
|
||||
//! Do reading
|
||||
void ps_readUpdateInfo();
|
||||
|
||||
//! Setup has beem syncronized
|
||||
void ps_setupSyncronized(bool success);
|
||||
|
||||
//! Version info has beem syncronized
|
||||
void ps_versionInfoSyncronized(bool success);
|
||||
|
||||
//! Setup has been changed
|
||||
void ps_setupChanged();
|
||||
|
||||
@@ -108,17 +102,17 @@ namespace BlackCore
|
||||
//! Bootstrap mode
|
||||
enum BootstrapMode
|
||||
{
|
||||
Default,
|
||||
Implicit,
|
||||
Explicit,
|
||||
CacheOnly
|
||||
};
|
||||
|
||||
bool m_shutdown = false;
|
||||
std::atomic<bool> m_setupSyncronized { false };
|
||||
std::atomic<bool> m_updateInfoSyncronized { false };
|
||||
std::atomic<bool> m_setupAvailable { false };
|
||||
std::atomic<bool> m_updateInfoAvailable { false };
|
||||
QString m_localSetupFileValue; //! Local file for setup, passed by cmd line arguments
|
||||
QString m_bootstrapUrlFileValue; //! Bootstrap URL if not local
|
||||
BootstrapMode m_bootstrapMode; //! How to bootstrap
|
||||
BootstrapMode m_bootstrapMode = Explicit; //! How to bootstrap
|
||||
BlackMisc::Network::CFailoverUrlList m_bootstrapUrls; //!< location of setup files
|
||||
BlackMisc::Network::CFailoverUrlList m_updateInfoUrls; //!< location of info files
|
||||
BlackMisc::CData<BlackCore::Data::GlobalSetup> m_setup {this, &CSetupReader::ps_setupChanged}; //!< data cache setup
|
||||
@@ -126,20 +120,31 @@ namespace BlackCore
|
||||
|
||||
QCommandLineOption m_cmdBootstrapUrl
|
||||
{
|
||||
{ "url", "bootstrap-url", "bootstrapurl" },
|
||||
{ "url", "bootstrapurl" },
|
||||
QCoreApplication::translate("application", "bootstrap URL, e.g. datastore.swift-project.org"),
|
||||
"bootstrapurl"
|
||||
}; //!< bootstrap URL
|
||||
}; //!< bootstrap URL
|
||||
QCommandLineOption m_cmdBootstrapMode
|
||||
{
|
||||
{ "bmode", "bootstrap-mode", "bootstrapmode" },
|
||||
QCoreApplication::translate("application", "bootstrap mode: (e)xplicit, d(default), (c)ache-only"),
|
||||
"bootstrapmode", "default"
|
||||
}; //!< bootstrap mode
|
||||
{ "bmode", "bootstrapmode" },
|
||||
QCoreApplication::translate("application", "bootstrap mode: explicit, implicit, cache(-only)"),
|
||||
"bootstrapmode", "explicit"
|
||||
}; //!< bootstrap mode
|
||||
|
||||
//! Read by local individual file
|
||||
//! Read by local individual file and update cache from that
|
||||
bool readLocalBootstrapFile(QString &fileName);
|
||||
|
||||
//! Trigger reading
|
||||
BlackMisc::CStatusMessageList triggerReadSetup();
|
||||
|
||||
//! Emit the availability signal and state
|
||||
//! \threadsafe
|
||||
BlackMisc::CStatusMessageList manageSetupAvailability(bool webRead, bool localRead = false);
|
||||
|
||||
//! Emit the available signal
|
||||
//! \threadsafe
|
||||
void manageUpdateAvailability(bool webRead);
|
||||
|
||||
//! Convert string to mode
|
||||
static BootstrapMode stringToEnum(const QString &s);
|
||||
};
|
||||
|
||||
@@ -43,7 +43,7 @@ namespace BlackCore
|
||||
if (!sApp) { return; } // shutting down
|
||||
|
||||
Q_ASSERT_X(QSslSocket::supportsSsl(), Q_FUNC_INFO, "missing SSL support");
|
||||
Q_ASSERT_X(sApp->isSetupSyncronized(), Q_FUNC_INFO, "Setup not syncronized");
|
||||
Q_ASSERT_X(sApp->isSetupAvailable(), Q_FUNC_INFO, "Setup not syncronized");
|
||||
this->setObjectName("CWebDataReader");
|
||||
this->initReaders(readerFlags);
|
||||
this->initWriters();
|
||||
|
||||
Reference in New Issue
Block a user