refs #846, setup reader

* save last error message
* renamed to setupHandlingCompleted
* docu
This commit is contained in:
Klaus Basan
2016-12-29 00:43:11 +01:00
committed by Mathew Sutcliffe
parent 1e85842c71
commit 62f2593486
2 changed files with 81 additions and 43 deletions

View File

@@ -71,8 +71,8 @@ namespace BlackCore
return msgs; return msgs;
} }
m_setup.synchronize(); // make sure it is loaded this->m_setup.synchronize(); // make sure it is loaded
CGlobalSetup cachedSetup = m_setup.get(); const CGlobalSetup cachedSetup = m_setup.get();
const bool cacheAvailable = cachedSetup.wasLoaded(); const bool cacheAvailable = cachedSetup.wasLoaded();
msgs.push_back(cacheAvailable ? msgs.push_back(cacheAvailable ?
CStatusMessage(this, CStatusMessage::SeverityInfo , "Cached setup synchronized and contains data") : CStatusMessage(this, CStatusMessage::SeverityInfo , "Cached setup synchronized and contains data") :
@@ -107,7 +107,7 @@ namespace BlackCore
const CUrlList bootstrapCacheUrls(cachedSetup.getBootstrapFileUrls()); const CUrlList bootstrapCacheUrls(cachedSetup.getBootstrapFileUrls());
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 bootsrap URLs in cache") : CStatusMessage(this, CStatusMessage::SeverityWarning, "No bootstrap URLs in cache") :
CStatusMessage(this, CStatusMessage::SeverityInfo, "Adding " + QString::number(bootstrapCacheUrls.size()) + " bootstrap URLs from cache")); CStatusMessage(this, CStatusMessage::SeverityInfo, "Adding " + QString::number(bootstrapCacheUrls.size()) + " bootstrap URLs from cache"));
} }
} }
@@ -124,10 +124,10 @@ namespace BlackCore
} }
else else
{ {
CStatusMessageList readMsgs = triggerReadSetup(); CStatusMessageList readMsgs = this->triggerReadSetup(); // async loading
if (cacheAvailable && readMsgs.isFailure()) if (cacheAvailable && readMsgs.isFailure())
{ {
// error but cache is available, we can continue // error, but cache is available, we can continue
readMsgs.clampSeverity(CStatusMessage::SeverityWarning); readMsgs.clampSeverity(CStatusMessage::SeverityWarning);
msgs.push_back(CStatusMessage(this, CStatusMessage::SeverityWarning, "Loading setup failed, but cache is available, will continue")); msgs.push_back(CStatusMessage(this, CStatusMessage::SeverityWarning, "Loading setup failed, but cache is available, will continue"));
msgs.push_back(readMsgs); msgs.push_back(readMsgs);
@@ -145,7 +145,7 @@ namespace BlackCore
// bootstrap file URL where we can download the bootstrap file // bootstrap file URL where we can download the bootstrap file
const QString parserValueUrl = sApp->getParserValue(this->m_cmdBootstrapUrl); const QString parserValueUrl = sApp->getParserValue(this->m_cmdBootstrapUrl);
this->m_bootstrapUrlFileValue = CGlobalSetup::buildBootstrapFileUrl(parserValueUrl); this->m_bootstrapUrlFileValue = CGlobalSetup::buildBootstrapFileUrl(parserValueUrl);
QUrl url(this->m_bootstrapUrlFileValue); const QUrl url(this->m_bootstrapUrlFileValue);
const QString urlString(url.toString()); const QString urlString(url.toString());
this->m_bootstrapMode = stringToEnum(sApp->getParserValue(this->m_cmdBootstrapMode)); this->m_bootstrapMode = stringToEnum(sApp->getParserValue(this->m_cmdBootstrapMode));
if (urlString.isEmpty() && this->m_bootstrapMode == Explicit) if (urlString.isEmpty() && this->m_bootstrapMode == Explicit)
@@ -196,13 +196,14 @@ namespace BlackCore
CStatusMessageList CSetupReader::triggerReadSetup() CStatusMessageList CSetupReader::triggerReadSetup()
{ {
if (m_shutdown) { return CStatusMessage(this, CStatusMessage::SeverityError, "shutdown"); } if (this->m_shutdown) { return CStatusMessage(this, CStatusMessage::SeverityError, "shutdown"); }
if (!CNetworkUtils::hasConnectedInterface()) if (!CNetworkUtils::hasConnectedInterface())
{ {
const CStatusMessage m(this, CStatusMessage::SeverityError, const CStatusMessage m(this, CStatusMessage::SeverityError,
"No network, cancelled reading of setup"); "No network, cancelled reading of setup");
CStatusMessageList msgs(m); CStatusMessageList msgs(m);
msgs.push_back(this->manageSetupAvailability(false, false)); msgs.push_back(this->manageSetupAvailability(false, false));
this->setLastSetupReadErrorMessages(msgs);
return msgs; return msgs;
} }
@@ -214,10 +215,12 @@ namespace BlackCore
" failed URLs: " + this->m_bootstrapUrls.getFailedUrls().toQString()); " failed URLs: " + this->m_bootstrapUrls.getFailedUrls().toQString());
CStatusMessageList msgs(m); CStatusMessageList msgs(m);
msgs.push_back(this->manageSetupAvailability(false, false)); msgs.push_back(this->manageSetupAvailability(false, false));
this->setLastSetupReadErrorMessages(msgs);
return msgs; return msgs;
} }
const CStatusMessage m(this, CStatusMessage::SeverityInfo, "Start reading URL: " + url.toQString()); const CStatusMessage m(this, CStatusMessage::SeverityInfo, "Start reading URL: " + url.toQString());
sApp->getFromNetwork(url.toNetworkRequest(), { this, &CSetupReader::ps_parseSetupFile }); sApp->getFromNetwork(url.toNetworkRequest(), { this, &CSetupReader::ps_parseSetupFile });
this->setLastSetupReadErrorMessages(m); // clear errors
return m; return m;
} }
@@ -290,9 +293,9 @@ namespace BlackCore
QScopedPointer<QNetworkReply, QScopedPointerDeleteLater> nwReply(nwReplyPtr); QScopedPointer<QNetworkReply, QScopedPointerDeleteLater> nwReply(nwReplyPtr);
if (m_shutdown) { return; } if (m_shutdown) { return; }
QUrl url(nwReply->url()); const QUrl url(nwReply->url());
QString urlString(url.toString()); const QString urlString(url.toString());
QString replyMessage(nwReply->errorString()); const QString replyMessage(nwReply->errorString());
if (nwReply->error() == QNetworkReply::NoError) if (nwReply->error() == QNetworkReply::NoError)
{ {
@@ -320,31 +323,28 @@ namespace BlackCore
return; // success return; // success
} }
// in the past I used to do a timestamp comparison here and skipped further laoding // in the past I used to do a timestamp comparison here and skipped further setting
// with changed files from a different URL this was wrongly assuming outdated loaded files and was removed // with changed files from a different URL this was wrongly assuming outdated loaded files and was removed
CStatusMessage m = m_setup.set(loadedSetup, loadedSetup.getMSecsSinceEpoch()); const CStatusMessage m = m_setup.set(loadedSetup, loadedSetup.getMSecsSinceEpoch());
if (m.isWarningOrAbove()) CLogMessage::preformatted(m);
{ if (m.isSeverityInfoOrLess())
m.setCategories(getLogCategories());
CLogMessage::preformatted(m);
CLogMessage::preformatted(this->manageSetupAvailability(false));
return; // issue with cache
}
else
{ {
// no issue with cache
this->m_updateInfoUrls = loadedSetup.getUpdateInfoFileUrls(); this->m_updateInfoUrls = loadedSetup.getUpdateInfoFileUrls();
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();
CLogMessage::preformatted(this->manageSetupAvailability(true)); }
return; // success CLogMessage::preformatted(this->manageSetupAvailability(true));
} // cache return;
} // json empty } // json empty
} // no error } // no error
else else
{ {
// network error // network error, log as warning as we will read again if possible
CLogMessage(this).warning("Reading setup failed %1 %2") << replyMessage << urlString; // however, store as error because this will be a possible root cause if nothing else is
nwReply->abort(); nwReply->abort();
const CStatusMessage msg = CStatusMessage(this).error("Reading setup failed %1 %2 (can possibly be fixed by reading from another server afterwards)") << replyMessage << urlString;
CLogMessage::preformatted(msg);
this->setLastSetupReadErrorMessages(msg);
} }
// try next one if any // try next one if any
@@ -354,7 +354,8 @@ namespace BlackCore
} }
else else
{ {
CLogMessage::preformatted(manageSetupAvailability(false)); const CStatusMessageList msgs = this->manageSetupAvailability(false);
CLogMessage::preformatted(msgs);
} }
} }
@@ -365,9 +366,9 @@ namespace BlackCore
QScopedPointer<QNetworkReply, QScopedPointerDeleteLater> nwReply(nwReplyPtr); QScopedPointer<QNetworkReply, QScopedPointerDeleteLater> nwReply(nwReplyPtr);
if (m_shutdown) { return; } if (m_shutdown) { return; }
QUrl url(nwReply->url()); const QUrl url(nwReply->url());
QString urlString(url.toString()); const QString urlString(url.toString());
QString replyMessage(nwReply->errorString()); const QString replyMessage(nwReply->errorString());
if (nwReply->error() == QNetworkReply::NoError) if (nwReply->error() == QNetworkReply::NoError)
{ {
@@ -385,7 +386,7 @@ namespace BlackCore
CUpdateInfo loadedUpdateInfo; CUpdateInfo loadedUpdateInfo;
loadedUpdateInfo.convertFromJson(Json::jsonObjectFromString(setupJson)); loadedUpdateInfo.convertFromJson(Json::jsonObjectFromString(setupJson));
if (lastModified > 0 && lastModified > loadedUpdateInfo.getMSecsSinceEpoch()) { loadedUpdateInfo.setMSecsSinceEpoch(lastModified); } if (lastModified > 0 && lastModified > loadedUpdateInfo.getMSecsSinceEpoch()) { loadedUpdateInfo.setMSecsSinceEpoch(lastModified); }
bool sameVersionLoaded = (loadedUpdateInfo == currentUpdateInfo); const bool sameVersionLoaded = (loadedUpdateInfo == currentUpdateInfo);
if (sameVersionLoaded) if (sameVersionLoaded)
{ {
CLogMessage(this).info("Same update info version loaded from %1 as already in data cache %2") << urlString << m_setup.getFilename(); CLogMessage(this).info("Same update info version loaded from %1 as already in data cache %2") << urlString << m_setup.getFilename();
@@ -396,7 +397,7 @@ namespace BlackCore
CStatusMessage m = m_updateInfo.set(loadedUpdateInfo, loadedUpdateInfo.getMSecsSinceEpoch()); CStatusMessage m = m_updateInfo.set(loadedUpdateInfo, loadedUpdateInfo.getMSecsSinceEpoch());
if (!m.isEmpty()) if (!m.isEmpty())
{ {
m.setCategories(getLogCategories()); m.addCategories(getLogCategories());
CLogMessage::preformatted(m); CLogMessage::preformatted(m);
this->manageUpdateAvailability(false); this->manageUpdateAvailability(false);
return; // issue with cache return; // issue with cache
@@ -412,8 +413,8 @@ namespace BlackCore
else else
{ {
// network error // network error
CLogMessage(this).warning("Reading update info failed %1 %2") << replyMessage << urlString;
nwReply->abort(); nwReply->abort();
CLogMessage(this).error("Reading update info failed %1 %2 (can possibly be fixed by reading from another server afterwards)") << replyMessage << urlString;
} }
// try next one if any // try next one if any
@@ -423,7 +424,8 @@ namespace BlackCore
} }
else else
{ {
this->manageUpdateAvailability(false); const CStatusMessageList msgs = this->manageSetupAvailability(false);
CLogMessage::preformatted(msgs);
} }
} // function } // function
@@ -433,6 +435,16 @@ namespace BlackCore
return cats; return cats;
} }
bool CSetupReader::hasCmdLineBootstrapUrl() const
{
return !sApp->getParserValue(this->m_cmdBootstrapUrl).isEmpty();
}
QString CSetupReader::getCmdLineBootstrapUrl() const
{
return sApp->getParserValue(this->m_cmdBootstrapUrl);
}
CGlobalSetup CSetupReader::getSetup() const CGlobalSetup CSetupReader::getSetup() const
{ {
return m_setup.get(); return m_setup.get();
@@ -443,18 +455,30 @@ namespace BlackCore
return m_updateInfo.get(); return m_updateInfo.get();
} }
CStatusMessageList CSetupReader::getLastSetupReadErrorMessages() const
{
QReadLocker l(&m_lockSetup);
return this->m_setupReadErrorMsgs;
}
void CSetupReader::setLastSetupReadErrorMessages(const CStatusMessageList &messages)
{
QWriteLocker l(&m_lockSetup);
this->m_setupReadErrorMsgs = messages.getErrorMessages();
}
CStatusMessageList CSetupReader::manageSetupAvailability(bool webRead, bool localRead) CStatusMessageList CSetupReader::manageSetupAvailability(bool webRead, bool localRead)
{ {
Q_ASSERT_X(!(webRead && localRead), Q_FUNC_INFO, "Local and web read together seems to be wrong"); Q_ASSERT_X(!(webRead && localRead), Q_FUNC_INFO, "Local and web read together seems to be wrong");
CStatusMessageList msgs; CStatusMessageList msgs;
if (webRead) if (webRead)
{ {
msgs.push_back(CLogMessage(this).info("Setup loaded from web, will trigger read of update information")); msgs.push_back(CStatusMessage(this).info("Setup loaded from web, will trigger read of update information"));
QTimer::singleShot(500, this, &CSetupReader::ps_readUpdateInfo); QTimer::singleShot(500, this, &CSetupReader::ps_readUpdateInfo);
} }
if (localRead) if (localRead)
{ {
msgs.push_back(CLogMessage(this).info("Setup loaded locally, will trigger read of update information")); msgs.push_back(CStatusMessage(this).info("Setup loaded locally, will trigger read of update information"));
QTimer::singleShot(500, this, &CSetupReader::ps_readUpdateInfo); QTimer::singleShot(500, this, &CSetupReader::ps_readUpdateInfo);
} }
@@ -475,7 +499,6 @@ namespace BlackCore
} }
else if (!available) else if (!available)
{ {
msgs.push_back(CStatusMessage(this, CStatusMessage::SeverityError, "Setup not available")); msgs.push_back(CStatusMessage(this, CStatusMessage::SeverityError, "Setup not available"));
if (this->m_bootstrapMode == Explicit) if (this->m_bootstrapMode == Explicit)
{ {
@@ -483,7 +506,7 @@ namespace BlackCore
} }
} }
this->m_setupAvailable = available; this->m_setupAvailable = available;
emit setupAvailable(available); emit this->setupHandlingCompleted(available);
if (!webRead && !localRead) if (!webRead && !localRead)
{ {

View File

@@ -53,17 +53,27 @@ namespace BlackCore
//! Categories //! Categories
static const BlackMisc::CLogCategoryList &getLogCategories(); static const BlackMisc::CLogCategoryList &getLogCategories();
//! Current setup //! Has a given cmd line argument for bootstrap URL
bool hasCmdLineBootstrapUrl() const;
//! CMD line argument for bootstrap URL
QString getCmdLineBootstrapUrl() const;
//! Current setup (reader URLs, DB location, crash server)
//! \remarks aka "bootstrap file"
//! \threadsafe //! \threadsafe
BlackCore::Data::CGlobalSetup getSetup() const; BlackCore::Data::CGlobalSetup getSetup() const;
//! Update info //! Update info (version, updates, download URLs)
//! \threadsafe //! \threadsafe
BlackCore::Data::CUpdateInfo getUpdateInfo() const; BlackCore::Data::CUpdateInfo getUpdateInfo() const;
//! Last setup parsing error messages (if any)
BlackMisc::CStatusMessageList getLastSetupReadErrorMessages() const;
signals: signals:
//! Setup avialable (from web, cache, or local file) //! Setup fetched or failed (from web, cache, or local file)
void setupAvailable(bool available); void setupHandlingCompleted(bool available);
//! Setup avialable (from web, cache //! Setup avialable (from web, cache
void updateInfoAvailable(bool available); void updateInfoAvailable(bool available);
@@ -93,7 +103,7 @@ namespace BlackCore
bool isUpdateInfoAvailable() const { return m_updateInfoAvailable; } bool isUpdateInfoAvailable() const { return m_updateInfoAvailable; }
private slots: private slots:
//! Setup has been read //! Setup has been read (aka bootstrap file)
void ps_parseSetupFile(QNetworkReply *nwReply); void ps_parseSetupFile(QNetworkReply *nwReply);
//! Update info has been read //! Update info has been read
@@ -127,6 +137,8 @@ namespace BlackCore
BlackMisc::Network::CFailoverUrlList m_updateInfoUrls; //!< location of info files BlackMisc::Network::CFailoverUrlList m_updateInfoUrls; //!< location of info files
QCommandLineOption m_cmdBootstrapUrl; //!< bootstrap URL QCommandLineOption m_cmdBootstrapUrl; //!< bootstrap URL
QCommandLineOption m_cmdBootstrapMode; //!< bootstrap mode QCommandLineOption m_cmdBootstrapMode; //!< bootstrap mode
mutable QReadWriteLock m_lockSetup; //!< lock for setup
BlackMisc::CStatusMessageList m_setupReadErrorMsgs; //!< last parsing error messages
BlackMisc::CData<BlackCore::Data::TGlobalSetup> m_setup {this, &CSetupReader::ps_setupChanged}; //!< data cache setup BlackMisc::CData<BlackCore::Data::TGlobalSetup> m_setup {this, &CSetupReader::ps_setupChanged}; //!< data cache setup
BlackMisc::CData<BlackCore::Data::TUpdateInfo> m_updateInfo {this}; //!< data cache update info BlackMisc::CData<BlackCore::Data::TUpdateInfo> m_updateInfo {this}; //!< data cache update info
@@ -144,6 +156,9 @@ namespace BlackCore
//! \threadsafe //! \threadsafe
void manageUpdateAvailability(bool webRead); void manageUpdateAvailability(bool webRead);
//! Set last setup parsing messages
void setLastSetupReadErrorMessages(const BlackMisc::CStatusMessageList &messages);
//! Convert string to mode //! Convert string to mode
static BootstrapMode stringToEnum(const QString &s); static BootstrapMode stringToEnum(const QString &s);