Files
pilotclient/src/blackcore/setupreader.h
Klaus Basan 3c20590293 Allow a forced update of the setup reader
When the network is down it can happen the bootstrap file request is not yet timed out but we use our own time out.
In that case we check the cached data upfront by faking a failed web read.
2018-12-05 04:03:43 +01:00

229 lines
8.7 KiB
C++

/* Copyright (C) 2015
* swift project Community / Contributors
*
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
* including this file, may be copied, modified, propagated, or distributed except according to the terms
* contained in the LICENSE file.
*/
//! \file
#ifndef BLACKCORE_SETUPREADER_H
#define BLACKCORE_SETUPREADER_H
#include "blackcore/blackcoreexport.h"
#include "blackcore/data/globalsetup.h"
#include "blackmisc/db/updateinfo.h"
#include "blackmisc/datacache.h"
#include "blackmisc/network/urllist.h"
#include "blackmisc/statusmessagelist.h"
#include <QCommandLineOption>
#include <QCoreApplication>
#include <QJsonObject>
#include <QList>
#include <QObject>
#include <QString>
#include <atomic>
class QNetworkReply;
namespace BlackMisc { class CLogCategoryList; }
namespace BlackCoreTest { class CTestConnectivity; }
namespace BlackCore
{
//! Read the central URLs / locations of our data, setup and versions.
//!
//! \details This class should be only used in BlackCore::CApplication.
//! It will also trigger reading update information.
//!
//! \note This class is no(!) BlackCore::CThreadedReader as it will be loaded once during startup
//! and reading setup data is fast. The read file is also called "bootstrap" file as it tells
//! swift which data and versions are located where. Without that file we cannot start.
//! Once the file is in place (i.e. in the cache) it can be automatically updated.
//!
//! \sa BlackCore::Data::TGlobalSetup
//! \sa BlackMisc::Db::TUpdateInfo
class BLACKCORE_EXPORT CSetupReader : public QObject
{
Q_OBJECT
friend class CApplication; //!< only using class
friend class BlackCoreTest::CTestConnectivity;
public:
//! Categories
static const BlackMisc::CLogCategoryList &getLogCategories();
//! Has a given cmd line argument for bootstrap URL?
bool hasCmdLineBootstrapUrl() const;
//! CMD line argument for bootstrap URL
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)
//! \remarks aka "bootstrap file"
//! \threadsafe
Data::CGlobalSetup getSetup() const;
//! Has cached setup ("bootstrap") data?
//! \threadsafe
bool hasCachedSetup() const;
//! Get setup cache timestamp
//! \threadsafe
QDateTime getSetupCacheTimestamp() const;
//! Load the cache file local bootstrap file
//! \remark can be used during installation as failover
//! \threadsafe
bool prefillCacheWithLocalResourceBootstrapFile();
//! Last distribution URL successfully read
//! \threadsafe
QString getLastSuccessfulSetupUrl() const;
//! Update info (artifacts and distributions)
//! \threadsafe
BlackMisc::Db::CUpdateInfo getUpdateInfo() const;
//! Has cached distribution info?
//! \threadsafe
bool hasCachedUpdateInfo() const;
//! Update info cache timestamp
//! \threadsafe
QDateTime getUpdateInfoCacheTimestamp() const;
//! Last update info URL successfully read
//! \threadsafe
QString getLastSuccessfulUpdateInfoUrl() const;
//! Synchronize the caches
void synchronize();
//! Last setup parsing error messages (if any)
BlackMisc::CStatusMessageList getLastSetupReadErrorMessages() const;
//! Get bootstrap URL, either m_bootstrapUrlFileValue or m_localSetupFileValue
const QString &getBootstrapUrlFile() const;
//! Mode as string
QString getBootstrapModeAsString() const;
signals:
//! Setup fetched or failed (from web, cache, or local file)?
void setupHandlingCompleted(bool available);
//! Update info available (from web, cache)?
void updateInfoAvailable(bool available);
//! A shared URL was successfully read
void successfullyReadSharedUrl(const BlackMisc::Network::CUrl &sharedUrl);
protected:
//! Constructor
explicit CSetupReader(QObject *parent);
//! Load the data
BlackMisc::CStatusMessageList asyncLoad();
//! Parse cmd line arguments
bool parseCmdLineArguments();
//! Add cmd line arguments to BlackCore::CApplication
QList<QCommandLineOption> getCmdLineOptions() const;
//! Terminate
void gracefulShutdown();
//! Setup available?
//! \threadsafe
bool isSetupAvailable() const { return m_setupAvailable; }
//! Force an availability update
//! \remark check for cached setup if the read check never got triggered
void forceAvailabilityUpdate();
//! Version info available?
//! \threadsafe
bool isUpdateInfoAvailable() const { return m_updateInfoAvailable; }
private:
//! Bootstrap mode
enum BootstrapMode
{
Implicit,
Explicit,
CacheOnly
};
std::atomic<bool> m_shutdown { false }; //!< shutdown in progress
std::atomic<bool> m_setupAvailable { false }; //!< setup available?
std::atomic<bool> m_updateInfoAvailable { false }; //!< update info available
std::atomic<bool> m_ignoreCmdBootstrapUrl { false }; //!< ignore the explicitly set bootstrap URL
std::atomic<bool> m_checkCmdBootstrapUrl { true }; //!< check connection on CMD bootstrap URL
std::atomic_int m_bootstrapReadErrors { 0 }; //!< failed bootstrap reads
std::atomic_int m_updateInfoReadErrors { 0 }; //!< failed version info reads
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::CUrlList m_bootstrapUrls; //!< location of setup files
BlackMisc::Network::CUrlList m_updateInfoUrls; //!< location of info files
QCommandLineOption m_cmdBootstrapUrl; //!< bootstrap URL
QCommandLineOption m_cmdBootstrapMode; //!< bootstrap mode
mutable QReadWriteLock m_lockSetup; //!< lock for setup
mutable QReadWriteLock m_lockUpdateInfo; //!< lock for update info
QString m_lastSuccessfulSetupUrl; //!< last successful read setup URL
QString m_lastSuccessfulUpdateInfoUrl; //!< last successful read update info URL
BlackMisc::CStatusMessageList m_setupReadErrorMsgs; //!< last parsing error messages
BlackMisc::CData<Data::TGlobalSetup> m_setup { this }; //!< data cache setup
BlackMisc::CData<BlackMisc::Db::TUpdateInfo> m_updateInfo { this }; //!< data cache distributions
//! Setup has been read (aka bootstrap file)
void parseBootstrapFile(QNetworkReply *nwReplyPtr);
//! Update info has been read
void parseUpdateInfoFile(QNetworkReply *nwReplyPtr);
//! Do reading
void readSetup();
//! Do reading of distributions
void readUpdateInfo();
//! Read by local individual file and update cache from that
BlackMisc::CStatusMessageList readLocalBootstrapFile(const QString &fileName);
//! Trigger reading
BlackMisc::CStatusMessageList triggerReadSetup();
//! Emit the availability signal and state and trigger follow up actions
//! \threadsafe
BlackMisc::CStatusMessageList manageSetupAvailability(bool webRead, bool localRead = false);
//! Emit the availability signal
//! \threadsafe
void manageUpdateInfoAvailability(bool webRead);
//! Set last setup parsing messages
void setLastSetupReadErrorMessages(const BlackMisc::CStatusMessageList &messages);
//! Convert string to bootstrap mode
static BootstrapMode stringToEnum(const QString &s);
//! Bootsrap URL used for unit tests
static const QString &unitTestBootstrapUrl();
};
} // ns
#endif // guard