Ref T156, setup reader adjusted

* link with watchdog Ref T150
* allow to disable URL connect checks if setup dialog is used
* refactoring of CSetupReader::parseCmdLineArguments so reparsing is possible
This commit is contained in:
Klaus Basan
2017-09-14 02:52:22 +02:00
committed by Mathew Sutcliffe
parent 5d2531080b
commit 428ba0975c
2 changed files with 104 additions and 44 deletions

View File

@@ -81,7 +81,7 @@ namespace BlackCore
); );
if (this->m_bootstrapMode == CacheOnly) if (this->m_bootstrapMode == CacheOnly)
{ {
this->m_distributionUrls = cachedSetup.getDistributionUrls(); this->m_distributionUrls = cachedSetup.getSwiftDistributionFileUrls();
msgs.push_back(cacheAvailable ? msgs.push_back(cacheAvailable ?
CStatusMessage(this, CStatusMessage::SeverityInfo, "Cache only setup, using it as it is") : CStatusMessage(this, CStatusMessage::SeverityInfo, "Cache only setup, using it as it is") :
CStatusMessage(this, CStatusMessage::SeverityError, "Cache only setup, but cache is empty") CStatusMessage(this, CStatusMessage::SeverityError, "Cache only setup, but cache is empty")
@@ -105,7 +105,7 @@ namespace BlackCore
if (this->m_bootstrapMode != Explicit) if (this->m_bootstrapMode != Explicit)
{ {
// also use previously cached URLs // also use previously cached URLs
const CUrlList bootstrapCacheUrls(cachedSetup.getBootstrapFileUrls()); const CUrlList bootstrapCacheUrls(cachedSetup.getSwiftBootstrapFileUrls());
this->m_bootstrapUrls.push_back(bootstrapCacheUrls); this->m_bootstrapUrls.push_back(bootstrapCacheUrls);
msgs.push_back(bootstrapCacheUrls.isEmpty() ? msgs.push_back(bootstrapCacheUrls.isEmpty() ?
CStatusMessage(this, CStatusMessage::SeverityWarning, "No bootstrap URLs in cache") : CStatusMessage(this, CStatusMessage::SeverityWarning, "No bootstrap URLs in cache") :
@@ -144,50 +144,63 @@ namespace BlackCore
bool CSetupReader::parseCmdLineArguments() bool CSetupReader::parseCmdLineArguments()
{ {
// bootstrap file URL where we can download the bootstrap file // copy vars at beginning to simplify a threadsafe version in the future
const QString parserValueUrl = sApp->getParserValue(this->m_cmdBootstrapUrl); const QString cmdLineBootstrapUrl = this->getCmdLineBootstrapUrl();
this->m_bootstrapUrlFileValue = CGlobalSetup::buildBootstrapFileUrl(parserValueUrl); BootstrapMode bootstrapMode = stringToEnum(sApp->getParserValue(this->m_cmdBootstrapMode));
const QUrl url(this->m_bootstrapUrlFileValue); const bool ignoreCmdBootstrapUrl = m_ignoreCmdBootstrapUrl;
const bool checkCmdBootstrapUrl = m_checkCmdBootstrapUrl;
const QString bootstrapUrlFileValue = CGlobalSetup::buildBootstrapFileUrl(cmdLineBootstrapUrl);
QString localSetupFileValue;
const QUrl url(bootstrapUrlFileValue);
const QString urlString(url.toString()); const QString urlString(url.toString());
this->m_bootstrapMode = stringToEnum(sApp->getParserValue(this->m_cmdBootstrapMode)); bool ok = false;
if (urlString.isEmpty() && this->m_bootstrapMode == Explicit)
if (urlString.isEmpty() && bootstrapMode == Explicit)
{ {
this->m_bootstrapMode = Implicit; // no URL, we use implicit mode bootstrapMode = Implicit; // no URL, we use implicit mode
} }
// check on local file do
if (url.isLocalFile())
{ {
this->m_localSetupFileValue = url.toLocalFile(); // check on local file
const QFile f(this->m_localSetupFileValue); if (url.isLocalFile())
if (!f.exists())
{ {
sApp->cmdLineErrorMessage(QString("File '%1' does not exist)").arg(this->m_localSetupFileValue)); localSetupFileValue = url.toLocalFile();
return false; const QFile f(localSetupFileValue);
} if (!f.exists())
}
// check on explicit URL
if (this->m_bootstrapMode == Explicit)
{
if (!url.isLocalFile())
{
bool retry = false;
bool ok = false;
do
{ {
if (CNetworkUtils::canConnect(url, CNetworkUtils::getLongTimeoutMs())) sApp->cmdLineErrorMessage(QString("File '%1' does not exist)").arg(localSetupFileValue));
{ break;
ok = true; }
break; }
}
retry = sApp->cmdLineErrorMessage(QString("URL '%1' not reachable").arg(urlString), true); // check on explicit URL
if (bootstrapMode == Explicit)
{
if (!url.isLocalFile())
{
bool retry = false;
// "retry" possible in some cases
do
{
if (ignoreCmdBootstrapUrl || !checkCmdBootstrapUrl || CNetworkUtils::canConnect(url, CNetworkUtils::getLongTimeoutMs()))
{
ok = true;
break;
}
retry = sApp->cmdLineErrorMessage(QString("URL '%1' not reachable").arg(urlString), true);
}
while (retry);
} }
while (retry);
if (!ok) { return false; }
} }
} }
return true; while (false);
m_localSetupFileValue = localSetupFileValue;
m_bootstrapUrlFileValue = bootstrapUrlFileValue;
m_bootstrapMode = bootstrapMode;
return ok;
} }
void CSetupReader::gracefulShutdown() void CSetupReader::gracefulShutdown()
@@ -332,11 +345,14 @@ namespace BlackCore
CGlobalSetup loadedSetup; CGlobalSetup loadedSetup;
loadedSetup.convertFromJson(setupJson); loadedSetup.convertFromJson(setupJson);
loadedSetup.markAsLoaded(true); loadedSetup.markAsLoaded(true);
const CUrl sharedUrl(loadedSetup.getCorrespondingSharedUrl(url));
if (!sharedUrl.isEmpty()) { emit this->successfullyReadSharedUrl(sharedUrl); }
if (lastModified > 0 && lastModified > loadedSetup.getMSecsSinceEpoch()) { loadedSetup.setMSecsSinceEpoch(lastModified); } if (lastModified > 0 && lastModified > loadedSetup.getMSecsSinceEpoch()) { loadedSetup.setMSecsSinceEpoch(lastModified); }
bool sameVersionLoaded = (loadedSetup == currentSetup); bool sameVersionLoaded = (loadedSetup == currentSetup);
if (sameVersionLoaded) if (sameVersionLoaded)
{ {
this->m_distributionUrls = currentSetup.getDistributionUrls(); // defaults this->m_distributionUrls = currentSetup.getSwiftDistributionFileUrls(); // defaults
CLogMessage(this).info("Same setup version loaded from '%1' as already in data cache '%2'") << urlString << m_setup.getFilename(); CLogMessage(this).info("Same setup version loaded from '%1' as already in data cache '%2'") << urlString << m_setup.getFilename();
CLogMessage::preformatted(this->manageSetupAvailability(true)); CLogMessage::preformatted(this->manageSetupAvailability(true));
return; // success return; // success
@@ -349,7 +365,7 @@ namespace BlackCore
if (m.isSeverityInfoOrLess()) if (m.isSeverityInfoOrLess())
{ {
// no issue with cache // no issue with cache
this->m_distributionUrls = loadedSetup.getDistributionUrls(); this->m_distributionUrls = loadedSetup.getSwiftDistributionFileUrls();
CLogMessage(this).info("Loaded setup from '%1'") << urlString; CLogMessage(this).info("Loaded setup from '%1'") << urlString;
CLogMessage(this).info("Setup: Updated data cache in '%1'") << this->m_setup.getFilename(); CLogMessage(this).info("Setup: Updated data cache in '%1'") << this->m_setup.getFilename();
{ {
@@ -490,14 +506,21 @@ namespace BlackCore
bool CSetupReader::hasCmdLineBootstrapUrl() const bool CSetupReader::hasCmdLineBootstrapUrl() const
{ {
return !sApp->getParserValue(this->m_cmdBootstrapUrl).isEmpty(); return !this->getCmdLineBootstrapUrl().isEmpty();
} }
QString CSetupReader::getCmdLineBootstrapUrl() const QString CSetupReader::getCmdLineBootstrapUrl() const
{ {
if (m_ignoreCmdBootstrapUrl) return "";
return sApp->getParserValue(this->m_cmdBootstrapUrl); return sApp->getParserValue(this->m_cmdBootstrapUrl);
} }
void CSetupReader::setIgnoreCmdLineBootstrapUrl(bool ignore)
{
m_ignoreCmdBootstrapUrl = ignore;
this->parseCmdLineArguments(); // T156 this part not threadsafe, currently not a real problem as setup reader runs in main thread
}
CGlobalSetup CSetupReader::getSetup() const CGlobalSetup CSetupReader::getSetup() const
{ {
return m_setup.get(); return m_setup.get();
@@ -511,7 +534,7 @@ namespace BlackCore
const bool cacheAvailable = cachedSetup.wasLoaded(); const bool cacheAvailable = cachedSetup.wasLoaded();
if (cacheAvailable) if (cacheAvailable)
{ {
CLogMessage(this).info("Setup (bootstrap already cached, no prefill needed"); CLogMessage(this).info("Setup cache prefill (bootstrap already cached, no prefill needed");
return false; return false;
} }
const QString fn = CDirectoryUtils::bootstrapResourceFilePath(); const QString fn = CDirectoryUtils::bootstrapResourceFilePath();
@@ -543,6 +566,24 @@ namespace BlackCore
return this->m_setupReadErrorMsgs; return this->m_setupReadErrorMsgs;
} }
const QString &CSetupReader::getBootstrapUrlFile() const
{
if (!m_localSetupFileValue.isEmpty()) { return m_localSetupFileValue; }
return m_bootstrapUrlFileValue;
}
QString CSetupReader::getBootstrapModeAsString() const
{
switch (m_bootstrapMode)
{
case CacheOnly: return "cache only";
case Explicit: return "explicit";
case Implicit: return "implicit";
default: break;
}
return "";
}
void CSetupReader::setLastSetupReadErrorMessages(const CStatusMessageList &messages) void CSetupReader::setLastSetupReadErrorMessages(const CStatusMessageList &messages)
{ {
QWriteLocker l(&m_lockSetup); QWriteLocker l(&m_lockSetup);

View File

@@ -59,12 +59,20 @@ namespace BlackCore
//! CMD line argument for bootstrap URL //! CMD line argument for bootstrap URL
QString getCmdLineBootstrapUrl() const; QString getCmdLineBootstrapUrl() const;
//! Ignore the bootstrap URL
//! \threadsafe
void setIgnoreCmdLineBootstrapUrl(bool ignore);
//! Check connection of the bootstrap URL
//! \threadsafe
void setCheckCmdLineBootstrapUrl(bool check) { m_checkCmdBootstrapUrl = check; }
//! Current setup (reader URLs, DB location, crash server) //! Current setup (reader URLs, DB location, crash server)
//! \remarks aka "bootstrap file" //! \remarks aka "bootstrap file"
//! \threadsafe //! \threadsafe
BlackCore::Data::CGlobalSetup getSetup() const; BlackCore::Data::CGlobalSetup getSetup() const;
//! Load the cache file local boostrap file //! Load the cache file local bootstrap file
//! \remark can be used during installation as failover //! \remark can be used during installation as failover
//! \threadsafe //! \threadsafe
bool prefillCacheWithLocalResourceBootstrapFile(); bool prefillCacheWithLocalResourceBootstrapFile();
@@ -84,6 +92,12 @@ namespace BlackCore
//! Last setup parsing error messages (if any) //! Last setup parsing error messages (if any)
BlackMisc::CStatusMessageList getLastSetupReadErrorMessages() const; BlackMisc::CStatusMessageList getLastSetupReadErrorMessages() const;
//! Get bootstrap URL, either m_bootstrapUrlFileValue or m_localSetupFileValue
const QString &getBootstrapUrlFile() const;
//! Mode as string
QString getBootstrapModeAsString() const;
signals: signals:
//! Setup fetched or failed (from web, cache, or local file) //! Setup fetched or failed (from web, cache, or local file)
void setupHandlingCompleted(bool available); void setupHandlingCompleted(bool available);
@@ -91,6 +105,9 @@ namespace BlackCore
//! Setup avialable (from web, cache //! Setup avialable (from web, cache
void distributionInfoAvailable(bool available); void distributionInfoAvailable(bool available);
//! A shared URL was successfully read
void successfullyReadSharedUrl(const BlackMisc::Network::CUrl &sharedUrl);
protected: protected:
//! Constructor //! Constructor
explicit CSetupReader(QObject *parent); explicit CSetupReader(QObject *parent);
@@ -143,9 +160,11 @@ namespace BlackCore
std::atomic<bool> m_shutdown { false }; std::atomic<bool> m_shutdown { false };
std::atomic<bool> m_setupAvailable { false }; std::atomic<bool> m_setupAvailable { false };
std::atomic<bool> m_distributionInfoAvailable { false }; std::atomic<bool> m_distributionInfoAvailable { false };
QString m_localSetupFileValue; //! Local file for setup, passed by cmd line arguments std::atomic<bool> m_ignoreCmdBootstrapUrl { false }; //!< ignore the explicitly set bootstrap URL
QString m_bootstrapUrlFileValue; //! Bootstrap URL if not local std::atomic<bool> m_checkCmdBootstrapUrl { true }; //!< check connection on CMD bootstrap URL
BootstrapMode m_bootstrapMode = Explicit; //! How to bootstrap QString m_localSetupFileValue; //!< Local file for setup, passed by cmd line arguments
QString m_bootstrapUrlFileValue; //!< Bootstrap URL if not local
BootstrapMode m_bootstrapMode = Explicit; //!< How to bootstrap
BlackMisc::Network::CFailoverUrlList m_bootstrapUrls; //!< location of setup files BlackMisc::Network::CFailoverUrlList m_bootstrapUrls; //!< location of setup files
BlackMisc::Network::CFailoverUrlList m_distributionUrls; //!< location of info files BlackMisc::Network::CFailoverUrlList m_distributionUrls; //!< location of info files
QCommandLineOption m_cmdBootstrapUrl; //!< bootstrap URL QCommandLineOption m_cmdBootstrapUrl; //!< bootstrap URL