From 6b7e05077c9ae9fdf736a275eaef9870a9030406 Mon Sep 17 00:00:00 2001 From: Klaus Basan Date: Tue, 24 May 2016 00:29:51 +0200 Subject: [PATCH] refs #656, info data reader (load DB metadata) --- src/blackcore/db/infodatareader.cpp | 147 ++++++++++++++++++++++++++++ src/blackcore/db/infodatareader.h | 84 ++++++++++++++++ 2 files changed, 231 insertions(+) create mode 100644 src/blackcore/db/infodatareader.cpp create mode 100644 src/blackcore/db/infodatareader.h diff --git a/src/blackcore/db/infodatareader.cpp b/src/blackcore/db/infodatareader.cpp new file mode 100644 index 000000000..8f39382f4 --- /dev/null +++ b/src/blackcore/db/infodatareader.cpp @@ -0,0 +1,147 @@ +/* Copyright (C) 2016 + * 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. + */ + +#include "blackcore/application.h" +#include "blackmisc/sequence.h" +#include "blackmisc/logmessage.h" +#include "blackmisc/network/networkutils.h" +#include "infodatareader.h" + +#include +#include +#include +#include + +using namespace BlackMisc; +using namespace BlackMisc::Network; +using namespace BlackMisc::Db; +using namespace BlackCore::Data; + +namespace BlackCore +{ + namespace Db + { + CInfoDataReader::CInfoDataReader(QObject *owner, const CDatabaseReaderConfigList &config) : + CDatabaseReader(owner, config, "CInfoDataReader") + { + // void + } + + CDbInfoList CInfoDataReader::getDbInfoObjects() const + { + QReadLocker l(&m_lockInfoObjects); + return m_infoObjects; + } + + int CInfoDataReader::getDbInfoObjectCount() const + { + QReadLocker l(&m_lockInfoObjects); + return m_infoObjects.size(); + } + + bool CInfoDataReader::areAllDataRead() const + { + return getDbInfoObjectCount() > 0; + } + + void CInfoDataReader::syncronizeCaches(CEntityFlags::Entity entities) + { + // no caching used here + Q_UNUSED(entities); + } + + void CInfoDataReader::invalidateCaches(CEntityFlags::Entity entities) + { + // no caching used here + Q_UNUSED(entities); + } + + QDateTime CInfoDataReader::getCacheTimestamp(CEntityFlags::Entity entity) + { + // no caching used here + Q_UNUSED(entity); + return QDateTime(); + } + + void CInfoDataReader::read(CEntityFlags::Entity entities, const QDateTime &newerThan) + { + this->ps_read(entities, newerThan); + } + + void CInfoDataReader::ps_read(CEntityFlags::Entity entities, const QDateTime &newerThan) + { + CEntityFlags::Entity triggeredRead = CEntityFlags::NoEntity; + CUrl url(getInfoObjectsUrl()); + if (entities.testFlag(CEntityFlags::InfoObjectEntity)) + { + if (!url.isEmpty()) + { + if (!newerThan.isNull()) + { + const QString tss(newerThan.toString(Qt::ISODate)); + url.appendQuery(QString(parameterLatestTimestamp() + "=" + tss)); + } + sApp->getFromNetwork(url, { this, &CInfoDataReader::ps_parseInfoObjectsData}); + triggeredRead |= CEntityFlags::InfoObjectEntity; + } + else + { + CLogMessage(this).error("No URL for %1") << CEntityFlags::flagToString(CEntityFlags::InfoObjectEntity); + } + } + + if (triggeredRead != CEntityFlags::NoEntity) + { + emit dataRead(triggeredRead, CEntityFlags::StartRead, 0); + } + } + + void CInfoDataReader::ps_parseInfoObjectsData(QNetworkReply *nwReplyPtr) + { + // wrap pointer, make sure any exit cleans up reply + // required to use delete later as object is created in a different thread + QScopedPointer nwReply(nwReplyPtr); + QString urlString(nwReply->url().toString()); + CDatabaseReader::JsonDatastoreResponse res = this->setStatusAndTransformReplyIntoDatastoreResponse(nwReply.data()); + if (res.hasErrorMessage()) + { + CLogMessage::preformatted(res.lastWarningOrAbove()); + emit dataRead(CEntityFlags::InfoObjectEntity, CEntityFlags::ReadFailed, 0); + return; + } + + // get all or incremental set of distributor + CDbInfoList infoObjects = CDbInfoList::fromDatabaseJson(res.getJsonArray()); + + // this part needs to be synchronized + int n = infoObjects.size(); + { + QWriteLocker wl(&this->m_lockInfoObjects); + this->m_infoObjects = infoObjects; + } + + // never emit when lock is held -> deadlock + emit dataRead(CEntityFlags::InfoObjectEntity, + res.isRestricted() ? CEntityFlags::ReadFinishedRestricted : CEntityFlags::ReadFinished, n); + CLogMessage(this).info("Read %1 %2 from %3") << n << CEntityFlags::flagToString(CEntityFlags::InfoObjectEntity) << urlString; + } + + CUrl CInfoDataReader::getBaseUrl() const + { + const CUrl baseUrl(sApp->getGlobalSetup().getDbInfoReaderUrl()); + return baseUrl; + } + + CUrl CInfoDataReader::getInfoObjectsUrl() const + { + return getBaseUrl().withAppendedPath("service/jsondbinfo.php"); + } + + } // namespace +} // namespace diff --git a/src/blackcore/db/infodatareader.h b/src/blackcore/db/infodatareader.h new file mode 100644 index 000000000..b36d79198 --- /dev/null +++ b/src/blackcore/db/infodatareader.h @@ -0,0 +1,84 @@ +/* Copyright (C) 2016 + * 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_DB_INFODATAREADER_H +#define BLACKCORE_DB_INFODATAREADER_H + +#include "blackcore/blackcoreexport.h" +#include "blackcore/db/databasereader.h" +#include "blackmisc/db/dbinfolist.h" + +#include +#include +#include + +namespace BlackCore +{ + namespace Db + { + //! Read information about data from Database + class BLACKCORE_EXPORT CInfoDataReader : public CDatabaseReader + { + Q_OBJECT + + public: + //! Constructor + explicit CInfoDataReader(QObject *owner, const CDatabaseReaderConfigList &config); + + //! Get info list + //! \threadsafe + BlackMisc::Db::CDbInfoList getDbInfoObjects() const; + + //! Get info list size + //! \threadsafe + int getDbInfoObjectCount() const; + + //! All data read? + //! \threadsafe + bool areAllDataRead() const; + + //! URL info objects web service + BlackMisc::Network::CUrl getInfoObjectsUrl() const; + + public slots: + //! Allow to call CInfoDataReader::ps_read directly, special for info objects + void read(BlackMisc::Network::CEntityFlags::Entity entities = BlackMisc::Network::CEntityFlags::InfoObjectEntity, const QDateTime &newerThan = QDateTime()); + + signals: + //! Combined read signal + void dataRead(BlackMisc::Network::CEntityFlags::Entity entity, BlackMisc::Network::CEntityFlags::ReadState state, int number); + + protected: + //! \name cache handling for base class + //! @{ + virtual void syncronizeCaches(BlackMisc::Network::CEntityFlags::Entity entities) override; + virtual void invalidateCaches(BlackMisc::Network::CEntityFlags::Entity entities) override; + virtual QDateTime getCacheTimestamp(BlackMisc::Network::CEntityFlags::Entity entity) override; + //! @} + + private slots: + //! Info objects have been read + void ps_parseInfoObjectsData(QNetworkReply *nwReply); + + //! Read / re-read data file + void ps_read(BlackMisc::Network::CEntityFlags::Entity entities = BlackMisc::Network::CEntityFlags::InfoObjectEntity, const QDateTime &newerThan = QDateTime()); + + private: + BlackMisc::Db::CDbInfoList m_infoObjects; + BlackMisc::Network::CUrl m_urlInfoObjects; + mutable QReadWriteLock m_lockInfoObjects; + + //! Base URL + BlackMisc::Network::CUrl getBaseUrl() const; + }; + } // ns +} // ns +#endif // guard