refs #642, fixed setup loading, in same step refs #636 clear cache

* 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:
Klaus Basan
2016-04-14 02:27:23 +02:00
parent bd9de9308c
commit d0daad7d34
17 changed files with 372 additions and 159 deletions

View File

@@ -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; }

View File

@@ -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

View File

@@ -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");
}

View File

@@ -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

View File

@@ -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);
};

View File

@@ -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();