From bb999376ca616140bdfce8c2dcf2e3e6296013b5 Mon Sep 17 00:00:00 2001 From: EndrII Date: Sun, 14 May 2023 12:23:37 +0200 Subject: [PATCH 01/17] added base methods for the control versions of the packages --- HeartTests/units/bigdatatest.cpp | 2 +- src/private/apiversion.cpp | 4 +-- src/private/apiversion.h | 7 +++-- src/private/versionisreceived.h | 2 ++ src/public/apiversionparser.cpp | 4 +-- src/public/packages/abstractdata.cpp | 16 ++++++++++- src/public/packages/abstractdata.h | 40 ++++++++++++++++++++++++--- src/public/packages/badrequest.h | 2 +- src/public/packages/bigdatabase.h | 2 +- src/public/packages/bigdataheader.h | 2 +- src/public/packages/bigdatapart.h | 2 +- src/public/packages/bigdatarequest.h | 2 +- src/public/packages/bigdatawraper.h | 2 +- src/public/packages/closeconnection.h | 2 +- src/public/packages/datapack.h | 2 +- src/public/packages/dbobject.h | 4 +-- src/public/packages/dbobjectset.h | 2 +- src/public/packages/deleteobject.h | 2 +- src/public/packages/getmaxintegerid.h | 2 +- src/public/packages/getsinglevalue.h | 2 +- src/public/packages/ping.h | 2 +- src/public/packages/setsinglevalue.h | 2 +- 22 files changed, 79 insertions(+), 28 deletions(-) diff --git a/HeartTests/units/bigdatatest.cpp b/HeartTests/units/bigdatatest.cpp index 7dadf62..2307cf2 100644 --- a/HeartTests/units/bigdatatest.cpp +++ b/HeartTests/units/bigdatatest.cpp @@ -12,7 +12,7 @@ #define LOCAL_TEST_PORT TEST_PORT + 4 class BigPackage: public QH::PKG::AbstractData { - QH_PACKAGE(BigPackage, "BigPackage") + QH_PACKAGE_AUTO(BigPackage) public: BigPackage(){ diff --git a/src/private/apiversion.cpp b/src/private/apiversion.cpp index f29c339..c36f05d 100644 --- a/src/private/apiversion.cpp +++ b/src/private/apiversion.cpp @@ -26,11 +26,11 @@ QDataStream &APIVersion::toStream(QDataStream &stream) const { return stream; } -const VersionData &APIVersion::version() const { +const VersionData &APIVersion::nodeVersion() const { return _version; } -void APIVersion::setVersion(const VersionData &newVersion) { +void APIVersion::setNodeVersion(const VersionData &newVersion) { _version = newVersion; } diff --git a/src/private/apiversion.h b/src/private/apiversion.h index dd43df0..532a8fe 100644 --- a/src/private/apiversion.h +++ b/src/private/apiversion.h @@ -27,13 +27,16 @@ class APIVersion: public QH::PKG::AbstractData APIVersion(); static unsigned short command(){return PROTOCKOL_VERSION_COMMAND;} + static unsigned short version(){return 0;} + static QString commandText(){return "PROTOCKOL_VERSION_COMMAND";} unsigned short cmd() const override {return APIVersion::command();} + unsigned short ver() const override {return APIVersion::version();} QString cmdString() const override {return APIVersion::commandText();} - const VersionData &version() const; - void setVersion(const VersionData &newVersion); + const VersionData &nodeVersion() const; + void setNodeVersion(const VersionData &newVersion); bool isValid() const override; diff --git a/src/private/versionisreceived.h b/src/private/versionisreceived.h index a2f58c8..0be6f32 100644 --- a/src/private/versionisreceived.h +++ b/src/private/versionisreceived.h @@ -22,11 +22,13 @@ class VersionIsReceived: public QH::PKG::AbstractData public: VersionIsReceived(); + static unsigned short version(){return 0;} static unsigned short command(){return PROTOCKOL_VERSION_RECEIVED_COMMAND;} static QString commandText(){return "PROTOCKOL_VERSION_RECEIVED_COMMAND";} unsigned short cmd() const override {return VersionIsReceived::command();} QString cmdString() const override {return VersionIsReceived::commandText();} + unsigned short ver() const override {return VersionIsReceived::version();} // StreamBase interface diff --git a/src/public/apiversionparser.cpp b/src/public/apiversionparser.cpp index 53200f7..b49003f 100644 --- a/src/public/apiversionparser.cpp +++ b/src/public/apiversionparser.cpp @@ -290,7 +290,7 @@ bool APIVersionParser::sendSupportedAPI(AbstractNodeInfo *dist) const { return false; PKG::APIVersion versionInformationPkg; - versionInformationPkg.setVersion(supportedAPIs); + versionInformationPkg.setNodeVersion(supportedAPIs); return sendData(&versionInformationPkg, dist); } @@ -299,7 +299,7 @@ bool APIVersionParser::processAppVersion(const QSharedPointer & QH::AbstractNodeInfo *sender, const QH::Header &) { - auto distVersion = message->version(); + auto distVersion = message->nodeVersion(); sender->setVersion(distVersion); auto parser = selectParser(distVersion); diff --git a/src/public/packages/abstractdata.cpp b/src/public/packages/abstractdata.cpp index 1609462..3565bd9 100644 --- a/src/public/packages/abstractdata.cpp +++ b/src/public/packages/abstractdata.cpp @@ -21,6 +21,7 @@ AbstractData::AbstractData() { } bool AbstractData::toPackage(Package &package, + unsigned short reqVersion, unsigned int triggerHash) const { if (!checkCmd()) { @@ -33,7 +34,11 @@ bool AbstractData::toPackage(Package &package, return false; } - package.data = toBytes(); + if (!toVersion(package.data, reqVersion)) { + QuasarAppUtils::Params::log("You try send not supported version of packge on the distanation node.", + QuasarAppUtils::Error); + return false; + } package.hdr.command = cmd(); package.hdr.triggerHash = triggerHash; @@ -67,6 +72,15 @@ void AbstractData::fromPakcage(const Package &pkg) { fromBytes(pkg.data); } +bool AbstractData::toVersion(QByteArray& out, unsigned short reqVersion) const { + if (reqVersion == ver()) { + out = toBytes(); + return true; + } + + return false; +} + AbstractData::~AbstractData() { } diff --git a/src/public/packages/abstractdata.h b/src/public/packages/abstractdata.h index 8271015..b31f24f 100644 --- a/src/public/packages/abstractdata.h +++ b/src/public/packages/abstractdata.h @@ -9,6 +9,7 @@ #define ABSTRACTDATA_H #include "humanreadableobject.h" #include "package.h" +#include #include #include @@ -26,22 +27,37 @@ * @brief QH_PACKAGE This macross prepare data to send and create a global id for package. For get global id use the cmd method. * For get quick access for global command use the ClassName::command() method. This method is static. */ -#define QH_PACKAGE(X, S) \ +#define QH_PACKAGE(X, S, V) \ public: \ static unsigned short command(){\ QByteArray ba = QString(S).toLocal8Bit();\ return qa_common::hash16(ba.data(), ba.size());\ } \ static QString commandText(){return S;} \ + static unsigned short version(){ return V; } \ unsigned short cmd() const override {return X::command();} \ + unsigned short ver() const override {return X::version();}; \ +\ QString cmdString() const override {return X::commandText();} \ protected: \ unsigned int localCode() const override {return typeid(X).hash_code();} \ \ private: +/** + * @brief QH_PACKAGE_AUTO This macross prepare data to send and create a global id for package. + * @arg X This is unique id of the pacakge. shold be some on all your network devices. + * @note auto pacakge create a 0 version of your package. +*/ +#define QH_PACKAGE_AUTO(X) QH_PACKAGE(X,#X, 0) -#define QH_PACKAGE_AUTO(X) QH_PACKAGE(X,#X) +/** + * @brief QH_PACKAGE_AUTO This macross prepare data to send and create a global id for package. + * @arg X This is unique id of the pacakge. shold be some on all your network devices. + * @arg V This is version of the yor pacakge. + * @note auto pacakge create a 0 version of your package. +*/ +#define QH_PACKAGE_AUTO_VER(X, V) QH_PACKAGE(X,#X, V) namespace QH { namespace PKG { @@ -54,6 +70,7 @@ namespace PKG { * \code{cpp} * class MyPackage: public QH::AbstractData { + QH_PACKAGE_AUTO_VER(MyPackage, 1) public: MyPackage(); @@ -92,6 +109,12 @@ class HEARTSHARED_EXPORT AbstractData : public StreamBase, public QuasarAppUtils */ virtual unsigned short cmd() const = 0; + /** + * @brief ver This method should be return number of the pacakge version. + * @return pcakge version. by default return - 0 (any version) + */ + virtual unsigned short ver() const = 0; + /** * @brief cmd - This is command string of this object, (for generate cmd use macross QH_PACKAGE) * @note Use the QH_PACKAGE macross for implement this method. @@ -103,11 +126,12 @@ class HEARTSHARED_EXPORT AbstractData : public StreamBase, public QuasarAppUtils /** * @brief toPackage This method convert this class object to the package. * For more info see Package class. - * @param package This is return value of Package class. + * @param package This is return value of Package class. + * @param reqVersion This is required version. This method create package of the needed version. * @param triggerHash This is hash of the package the current class is responding to. * @return True if convert to package finished successful. */ - bool toPackage(Package &package, unsigned int triggerHash = 0) const; + bool toPackage(Package &package, unsigned short reqVersion, unsigned int triggerHash = 0) const; /** * @brief isValid This method check current object to valid. @@ -152,6 +176,14 @@ class HEARTSHARED_EXPORT AbstractData : public StreamBase, public QuasarAppUtils */ static QString commandText(){return "NULL";}; + /** + * @brief toVersion This method should be convert package to rquired version. + * @param outputArray This is output byte array after convertation. + * @param version This is required version pacakge. + * @return true if convertation finished successful. + */ + virtual bool toVersion(QByteArray& outputArray, unsigned short version) const; + protected: /** * @brief AbstractData - Base constructor of this object. diff --git a/src/public/packages/badrequest.h b/src/public/packages/badrequest.h index 36ab523..07c622c 100644 --- a/src/public/packages/badrequest.h +++ b/src/public/packages/badrequest.h @@ -33,7 +33,7 @@ struct ErrorData { */ class HEARTSHARED_EXPORT BadRequest : public AbstractData { - QH_PACKAGE(BadRequest, "BadRequest") + QH_PACKAGE_AUTO(BadRequest) public: /** diff --git a/src/public/packages/bigdatabase.h b/src/public/packages/bigdatabase.h index 3f296cc..1cbf565 100644 --- a/src/public/packages/bigdatabase.h +++ b/src/public/packages/bigdatabase.h @@ -19,7 +19,7 @@ namespace PKG { */ class HEARTSHARED_EXPORT BigDataBase: public AbstractData { - QH_PACKAGE(BigDataBase, "BigDataBase") + QH_PACKAGE_AUTO(BigDataBase) public: BigDataBase(); diff --git a/src/public/packages/bigdataheader.h b/src/public/packages/bigdataheader.h index d3b5aca..af4f7a7 100644 --- a/src/public/packages/bigdataheader.h +++ b/src/public/packages/bigdataheader.h @@ -27,7 +27,7 @@ namespace PKG { */ class HEARTSHARED_EXPORT BigDataHeader : public BigDataBase { - QH_PACKAGE(BigDataHeader, "BigDataHeader") + QH_PACKAGE_AUTO(BigDataHeader) public: BigDataHeader(); diff --git a/src/public/packages/bigdatapart.h b/src/public/packages/bigdatapart.h index 5e46559..6f34777 100644 --- a/src/public/packages/bigdatapart.h +++ b/src/public/packages/bigdatapart.h @@ -20,7 +20,7 @@ namespace PKG { */ class HEARTSHARED_EXPORT BigDataPart : public BigDataBase { - QH_PACKAGE(BigDataPart, "BigDataPart") + QH_PACKAGE_AUTO(BigDataPart) public: BigDataPart(); diff --git a/src/public/packages/bigdatarequest.h b/src/public/packages/bigdatarequest.h index 633d12b..950566c 100644 --- a/src/public/packages/bigdatarequest.h +++ b/src/public/packages/bigdatarequest.h @@ -19,7 +19,7 @@ namespace PKG { */ class HEARTSHARED_EXPORT BigDataRequest: public BigDataBase { - QH_PACKAGE(BigDataRequest, "BigDataRequest") + QH_PACKAGE_AUTO(BigDataRequest) public: BigDataRequest(); diff --git a/src/public/packages/bigdatawraper.h b/src/public/packages/bigdatawraper.h index 685a567..4b3a583 100644 --- a/src/public/packages/bigdatawraper.h +++ b/src/public/packages/bigdatawraper.h @@ -19,7 +19,7 @@ namespace PKG { */ class BigDataWraper: public AbstractData { - QH_PACKAGE(BigDataWraper, "BigDataWraper") + QH_PACKAGE_AUTO(BigDataWraper) public: BigDataWraper() = default; diff --git a/src/public/packages/closeconnection.h b/src/public/packages/closeconnection.h index 79d33b0..efb51c1 100644 --- a/src/public/packages/closeconnection.h +++ b/src/public/packages/closeconnection.h @@ -27,7 +27,7 @@ namespace PKG { */ class HEARTSHARED_EXPORT CloseConnection: public AbstractData { - QH_PACKAGE(CloseConnection, "CloseConnection") + QH_PACKAGE_AUTO(CloseConnection) public: CloseConnection(); diff --git a/src/public/packages/datapack.h b/src/public/packages/datapack.h index d7a508b..7585eab 100644 --- a/src/public/packages/datapack.h +++ b/src/public/packages/datapack.h @@ -25,7 +25,7 @@ namespace PKG { template class DataPack final: public AbstractData { - QH_PACKAGE(DataPack, Package::commandText() + "Pack") + QH_PACKAGE(DataPack, Package::commandText() + "Pack", 0) public: diff --git a/src/public/packages/dbobject.h b/src/public/packages/dbobject.h index e4a2799..2fda2e7 100644 --- a/src/public/packages/dbobject.h +++ b/src/public/packages/dbobject.h @@ -21,7 +21,7 @@ namespace PKG { /** * The ONLY_DATABASE_PACKAGE macross is base macros for all database objects that do not use stream and network functions. */ -#define ONLY_DATABASE_PACKAGE QH_PACKAGE(DBObject, "DBObject") +#define ONLY_DATABASE_PACKAGE QH_PACKAGE(DBObject, "DBObject", 0) /** @@ -95,7 +95,7 @@ typedef QMap DBVariantMap; */ class HEARTSHARED_EXPORT DBObject : public AbstractData { - QH_PACKAGE(DBObject, "DBObject") + QH_PACKAGE_AUTO(DBObject) public: diff --git a/src/public/packages/dbobjectset.h b/src/public/packages/dbobjectset.h index 57b5328..3d42dc2 100644 --- a/src/public/packages/dbobjectset.h +++ b/src/public/packages/dbobjectset.h @@ -22,7 +22,7 @@ namespace PKG { */ class HEARTSHARED_EXPORT DBObjectSet: public DBObject { - QH_PACKAGE(DBObjectSet, "DBObjectSet") + QH_PACKAGE_AUTO(DBObjectSet) public: DBObjectSet(const QString table); diff --git a/src/public/packages/deleteobject.h b/src/public/packages/deleteobject.h index 9138e54..e99bd3b 100644 --- a/src/public/packages/deleteobject.h +++ b/src/public/packages/deleteobject.h @@ -25,7 +25,7 @@ namespace PKG { */ class HEARTSHARED_EXPORT DeleteObject: public DBObject, public IToken { - QH_PACKAGE(DeleteObject, "DeleteObject") + QH_PACKAGE_AUTO(DeleteObject) public: DeleteObject(); diff --git a/src/public/packages/getmaxintegerid.h b/src/public/packages/getmaxintegerid.h index c5a5c1f..0ab0de8 100644 --- a/src/public/packages/getmaxintegerid.h +++ b/src/public/packages/getmaxintegerid.h @@ -19,7 +19,7 @@ namespace PKG { */ class HEARTSHARED_EXPORT GetMaxIntegerId: public DBObject { - QH_PACKAGE(GetMaxIntegerId, "GetMaxIntegerId") + QH_PACKAGE_AUTO(GetMaxIntegerId) public: /** diff --git a/src/public/packages/getsinglevalue.h b/src/public/packages/getsinglevalue.h index f8e8c9f..3dafbb4 100644 --- a/src/public/packages/getsinglevalue.h +++ b/src/public/packages/getsinglevalue.h @@ -38,7 +38,7 @@ namespace PKG { */ class HEARTSHARED_EXPORT GetSingleValue final: public DBObject { - QH_PACKAGE(GetSingleValue, "GetSingleValue") + QH_PACKAGE_AUTO(GetSingleValue) public: /** diff --git a/src/public/packages/ping.h b/src/public/packages/ping.h index 8bac4e4..159734d 100644 --- a/src/public/packages/ping.h +++ b/src/public/packages/ping.h @@ -20,7 +20,7 @@ namespace PKG { */ class HEARTSHARED_EXPORT Ping: public AbstractData { - QH_PACKAGE(Ping, "Ping") + QH_PACKAGE_AUTO(Ping) public: Ping(); diff --git a/src/public/packages/setsinglevalue.h b/src/public/packages/setsinglevalue.h index 1e09219..213149a 100644 --- a/src/public/packages/setsinglevalue.h +++ b/src/public/packages/setsinglevalue.h @@ -32,7 +32,7 @@ namespace PKG { */ class HEARTSHARED_EXPORT SetSingleValue final: public DBObject { - QH_PACKAGE(SetSingleValue, "SetSingleValue") + QH_PACKAGE_AUTO(SetSingleValue) public: /** From 79ffb003e419bcffa97e3668ac1260887119e034 Mon Sep 17 00:00:00 2001 From: EndrII Date: Sun, 14 May 2023 18:41:54 +0200 Subject: [PATCH 02/17] fix build --- src/private/apiversion.cpp | 33 +++++++++++++++++++++------- src/private/apiversion.h | 16 ++++++++++---- src/public/abstractnode.cpp | 10 +++++++-- src/public/abstractnodeinfo.cpp | 8 +++++++ src/public/abstractnodeinfo.h | 16 ++++++++++++++ src/public/apiversionparser.cpp | 17 +++++++++++--- src/public/apiversionparser.h | 2 ++ src/public/distversion.cpp | 20 +++++++++++++++++ src/public/distversion.h | 20 +++++++++++++++++ src/public/iparser.cpp | 22 ++++++++++++------- src/public/iparser.h | 33 +++++++++++++++++++++++----- src/public/packages/abstractdata.cpp | 4 ++-- src/public/packages/abstractdata.h | 4 ++-- 13 files changed, 171 insertions(+), 34 deletions(-) diff --git a/src/private/apiversion.cpp b/src/private/apiversion.cpp index c36f05d..51ccfd1 100644 --- a/src/private/apiversion.cpp +++ b/src/private/apiversion.cpp @@ -17,28 +17,45 @@ APIVersion::APIVersion() { QDataStream &APIVersion::fromStream(QDataStream &stream) { - stream >> _version; + stream >> _apisVersions; + stream >> _packagesVersions; return stream; } QDataStream &APIVersion::toStream(QDataStream &stream) const { - stream << _version; + stream << _apisVersions; + stream << _packagesVersions; + return stream; } -const VersionData &APIVersion::nodeVersion() const { - return _version; +VersionData APIVersion::apisVersions() const { + return _apisVersions; +} + +void APIVersion::setApisVersions(const VersionData &newApisVersions) { + _apisVersions = newApisVersions; +} + +PackagesVersionData APIVersion::packagesVersions() const { + return _packagesVersions; } -void APIVersion::setNodeVersion(const VersionData &newVersion) { - _version = newVersion; +void APIVersion::setPackagesVersions(const PackagesVersionData &newPackagesVersions) { + _packagesVersions = newPackagesVersions; } bool APIVersion::isValid() const { - if (_version.isEmpty()) + if (_apisVersions.isEmpty()) return false; - for (const auto & version: _version) { + for (const auto & version: _apisVersions) { + if (version.max() < version.min()) { + return false; + } + } + + for (const auto & version: _packagesVersions) { if (version.max() < version.min()) { return false; } diff --git a/src/private/apiversion.h b/src/private/apiversion.h index 532a8fe..5e32e67 100644 --- a/src/private/apiversion.h +++ b/src/private/apiversion.h @@ -35,18 +35,26 @@ class APIVersion: public QH::PKG::AbstractData QString cmdString() const override {return APIVersion::commandText();} - const VersionData &nodeVersion() const; - void setNodeVersion(const VersionData &newVersion); - bool isValid() const override; + /** + * @brief packagesVersions This method return list of available multi-version packages on the node. + * @return + */ + PackagesVersionData packagesVersions() const; + void setPackagesVersions(const PackagesVersionData &newPackagesVersions); + + VersionData apisVersions() const; + void setApisVersions(const VersionData &newApisVersions); + protected: unsigned int localCode() const override {return typeid(APIVersion).hash_code();} QDataStream &fromStream(QDataStream &stream) override; QDataStream &toStream(QDataStream &stream) const override; private: - VersionData _version; + VersionData _apisVersions; + PackagesVersionData _packagesVersions; }; diff --git a/src/public/abstractnode.cpp b/src/public/abstractnode.cpp index f69d083..00dbc37 100644 --- a/src/public/abstractnode.cpp +++ b/src/public/abstractnode.cpp @@ -756,12 +756,18 @@ unsigned int AbstractNode::sendData(const PKG::AbstractData *resp, return 0; } + int version = node->multiVersionPackages().value(resp->cmd()). + getMaxСompatible(_apiVersionParser->multiVersionPackages().value(resp->cmd())); + if (version < 0) { + return 0; + } + Package pkg; bool convert = false; if (req && req->isValid()) { - convert = resp->toPackage(pkg, req->hash); + convert = resp->toPackage(pkg, version,req->hash); } else { - convert = resp->toPackage(pkg); + convert = resp->toPackage(pkg, version); } if (!convert) { diff --git a/src/public/abstractnodeinfo.cpp b/src/public/abstractnodeinfo.cpp index fda1eb3..70489c7 100644 --- a/src/public/abstractnodeinfo.cpp +++ b/src/public/abstractnodeinfo.cpp @@ -131,6 +131,14 @@ bool AbstractNodeInfo::confirmData() const { return _status != NodeCoonectionStatus::NotConnected && fVersionDelivered() && fVersionReceived(); } +const PackagesVersionData& AbstractNodeInfo::multiVersionPackages() const { + return _multiVersionPackages; +} + +void AbstractNodeInfo::setMultiVersionPackages(const PackagesVersionData &newMultiVersionPackages) { + _multiVersionPackages = newMultiVersionPackages; +} + bool AbstractNodeInfo::fVersionDelivered() const { return _fVersionDelivered; } diff --git a/src/public/abstractnodeinfo.h b/src/public/abstractnodeinfo.h index 015be85..c5b92a3 100644 --- a/src/public/abstractnodeinfo.h +++ b/src/public/abstractnodeinfo.h @@ -259,6 +259,18 @@ class HEARTSHARED_EXPORT AbstractNodeInfo: public QObject */ void addParser(QSharedPointer parser); + /** + * @brief multiVersionPackages This is list of packages of one api package tah support multiple versions. + * @return list of packages of one api package tah support multiple versions. + */ + const PackagesVersionData &multiVersionPackages() const; + + /** + * @brief setMultiVersionPackages This method sets new list of multi-version packages. + * @param newMultiVersionPackages This is new value of multi-version packages. + */ + void setMultiVersionPackages(const PackagesVersionData &newMultiVersionPackages); + public slots: /** * @brief removeSocket This method use for remove socket. @@ -335,6 +347,10 @@ public slots: QHash> _parsersKeysMap; QMutex _parsersListMutex; + /** + * @brief _multiVersionPackages contains packages list that has multiple versions on one api rest of this is universal packages with version 0. + */ + PackagesVersionData _multiVersionPackages; VersionData _version; bool _fVersionReceived = false; bool _fVersionDelivered = false; diff --git a/src/public/apiversionparser.cpp b/src/public/apiversionparser.cpp index b49003f..4399c13 100644 --- a/src/public/apiversionparser.cpp +++ b/src/public/apiversionparser.cpp @@ -232,7 +232,7 @@ QSharedPointer APIVersionParser::selectParser(const QString &parserKey, } QSharedPointer APIVersionParser::selectParserImpl(unsigned short cmd, - AbstractNodeInfo *sender) const{ + AbstractNodeInfo *sender) const { auto version = sender->version(); const auto availableParser = selectParser(version); for (const auto& parser: availableParser) { @@ -275,10 +275,18 @@ unsigned short APIVersionParser::minimumApiVersion(const QString &apiKey) const bool APIVersionParser::sendSupportedAPI(AbstractNodeInfo *dist) const { VersionData supportedAPIs; + PackagesVersionData multiVersionPackages; for (auto it = _apiParsers.begin(); it != _apiParsers.end(); ++it) { DistVersion supportVersions; + for (auto api = it->begin(); api != it->end(); ++api) { + const auto packages = api.value()->multiVersionPackages(); + for (auto pkg = packages.begin(); pkg != packages.end(); ++pkg) { + multiVersionPackages[pkg.key()] = pkg.value(); + } + } + supportVersions.setMax(it->lastKey()); supportVersions.setMin(it->firstKey()); @@ -290,7 +298,8 @@ bool APIVersionParser::sendSupportedAPI(AbstractNodeInfo *dist) const { return false; PKG::APIVersion versionInformationPkg; - versionInformationPkg.setNodeVersion(supportedAPIs); + versionInformationPkg.setApisVersions(supportedAPIs); + versionInformationPkg.setPackagesVersions(multiVersionPackages); return sendData(&versionInformationPkg, dist); } @@ -299,8 +308,10 @@ bool APIVersionParser::processAppVersion(const QSharedPointer & QH::AbstractNodeInfo *sender, const QH::Header &) { - auto distVersion = message->nodeVersion(); + auto distVersion = message->apisVersions(); sender->setVersion(distVersion); + sender->setMultiVersionPackages(message->packagesVersions()); + auto parser = selectParser(distVersion); for (auto parserKey = distVersion.keyBegin(); parserKey != distVersion.keyEnd(); ++parserKey) { diff --git a/src/public/apiversionparser.h b/src/public/apiversionparser.h index 3ff2012..b110350 100644 --- a/src/public/apiversionparser.h +++ b/src/public/apiversionparser.h @@ -129,6 +129,8 @@ class APIVersionParser: public iParser */ bool sendSupportedAPI(AbstractNodeInfo *dist) const; + unsigned short selectPackageVersion(const VersionData& local, const VersionData& dist); + signals: /** diff --git a/src/public/distversion.cpp b/src/public/distversion.cpp index 005d6f5..87b98c9 100644 --- a/src/public/distversion.cpp +++ b/src/public/distversion.cpp @@ -16,6 +16,26 @@ void DistVersion::setMax(unsigned short newMax) { _max = newMax; } +int DistVersion::getMaxСompatible(const DistVersion &distVersion) const { + unsigned short midMax = std::min(distVersion.max(), _max); + unsigned short midMin = std::max(distVersion.min(), _min); + + if (midMax < midMin) + return -1; + + return midMax; +} + +int DistVersion::getMinСompatible(const DistVersion &distVersion) const { + unsigned short midMax = std::min(distVersion.max(), _max); + unsigned short midMin = std::max(distVersion.min(), _min); + + if (midMax < midMin) + return -1; + + return midMin; +} + QDataStream &DistVersion::fromStream(QDataStream &stream) { stream >> _min; stream >> _max; diff --git a/src/public/distversion.h b/src/public/distversion.h index 1942933..6676564 100644 --- a/src/public/distversion.h +++ b/src/public/distversion.h @@ -26,6 +26,21 @@ class DistVersion: public StreamBase { unsigned short max() const; void setMax(unsigned short newMax); + /** + * @brief getMaxСompatible return maximum available on booth nodes version. + * @param distVersion this is dis version. + * @return return maximum version. if this version is not found retun -1 + */ + int getMaxСompatible(const DistVersion& distVersion) const; + + + /** + * @brief getMinСompatible return maximum available on booth nodes version. + * @param distVersion this is dis version. + * @return return minimum version. if this version is not found retun -1 + */ + int getMinСompatible(const DistVersion& distVersion) const; + protected: QDataStream &fromStream(QDataStream &stream) override; @@ -47,5 +62,10 @@ class DistVersion: public StreamBase { */ typedef QHash VersionData; +/** + * @brief PackagesVersionData This is some as VersionData but for int commands. + */ +typedef QHash PackagesVersionData; + } #endif // DISTVERSION_H diff --git a/src/public/iparser.cpp b/src/public/iparser.cpp index b9412c9..8094392 100644 --- a/src/public/iparser.cpp +++ b/src/public/iparser.cpp @@ -31,17 +31,17 @@ QString iParser::pareseResultToString(const ParserResult &parseResult) { } } -const QHash > & -iParser::registeredTypes() const { +const PacksMap &iParser::registeredTypes() const { return _registeredTypes; } -QSharedPointer iParser::genPackage(unsigned short cmd) const { - return QSharedPointer(_registeredTypes.value(cmd, [](){return nullptr;})()); +QSharedPointer iParser::genPackage(unsigned short cmd, unsigned short ver) const { + return QSharedPointer(_registeredTypes.value(cmd, {}).value(ver, [](){return nullptr;})()); } -bool iParser::checkCommand(unsigned short cmd) const { - return _registeredTypes.contains(cmd); +bool iParser::checkCommand(unsigned short cmd, unsigned short ver) const { + auto versions = _registeredTypes.value(cmd, {}); + return versions.contains(ver); } AbstractNode *iParser::node() const { @@ -58,7 +58,10 @@ unsigned int iParser::sendData(const PKG::AbstractData *resp, const AbstractNodeInfo *dist, const Header *req) const { return node()->sendData(resp, dist, req); +} +const PackagesVersionData &iParser::multiVersionPackages() const { + return _multiVersionPackages; } void iParser::initSupportedCommands() {} @@ -66,8 +69,11 @@ void iParser::initSupportedCommands() {} QString iParser::toString() const { QString message = parserId() + " supports next commands:\n"; - for (auto it = _registeredTypes.keyBegin(); it != _registeredTypes.keyEnd(); ++it) { - message += genPackage(*it)->cmdString() + " - " + QString::number(*it) + "\n"; + for (const auto& versionsMap: _registeredTypes) { + for (auto it = versionsMap.keyBegin(); it != versionsMap.keyEnd(); ++it) { + auto pkg = genPackage(*it); + message += pkg->cmdString() + ":v" + pkg->ver() + " - " + QString::number(*it) + "\n"; + } } return message; diff --git a/src/public/iparser.h b/src/public/iparser.h index b6ee64b..ef29eee 100644 --- a/src/public/iparser.h +++ b/src/public/iparser.h @@ -9,6 +9,7 @@ #ifndef IPARSER_H #define IPARSER_H +#include "distversion.h" #include "hostaddress.h" #include #include @@ -22,6 +23,11 @@ namespace PKG { class AbstractData; } +/** + * @brief PacksMap This is hash map with the package id - version of package and package factory function. + */ +using PacksMap = QHash>>; + /** * @brief The ParserResult enum. @@ -57,9 +63,15 @@ class HEARTSHARED_EXPORT iParser: public QObject, public QuasarAppUtils::iHRO * @see initSupportedCommands */ void registerPackageType() { - _registeredTypes[T::command()] = [](){ + _registeredTypes[T::command()][T::version()] = [](){ return new T(); }; + + auto multiVersionsList = _registeredTypes.value(T::command()); + if (multiVersionsList.size() > 1) { + _multiVersionPackages[T::command()].setMax(multiVersionsList.lastKey()); + _multiVersionPackages[T::command()].setMin(multiVersionsList.firstKey()); + } }; /** @@ -181,24 +193,25 @@ class HEARTSHARED_EXPORT iParser: public QObject, public QuasarAppUtils::iHRO * @return list of registered command. * @see iParser::registerPackageType */ - const QHash > ®isteredTypes() const; + const PacksMap ®isteredTypes() const; /** * @brief genPackage This is factory method that generate data pacakge objects by command. * All object should be registered before using this method. * @param cmd This is command of pacakge see Header::command. + * @param ver - This is version of the package - by default is 0 * @return shared pointer to new data object. * @see AbstractNode::registerPackageType * @see Header::command */ - QSharedPointer genPackage(unsigned short cmd) const; + QSharedPointer genPackage(unsigned short cmd, unsigned short ver = 0) const; /** * @brief checkCommand This method check command are if registered type or not. * @brief cmd This is command of a verifiable package. * @return True if the package is registered in a node. */ - bool checkCommand(unsigned short cmd) const; + bool checkCommand(unsigned short cmd, unsigned short ver = 0) const; /** * @brief parserId This is id of the parsers. All parser will be synced betwin nodes by ids. @@ -213,6 +226,13 @@ class HEARTSHARED_EXPORT iParser: public QObject, public QuasarAppUtils::iHRO virtual void initSupportedCommands(); QString toString() const override; + + /** + * @brief multiVersionPackages return list of the supported multiversions packages. + * @return list of the supported multiversions packages. + */ + const PackagesVersionData& multiVersionPackages() const; + protected: AbstractNode *node() const; @@ -239,7 +259,10 @@ class HEARTSHARED_EXPORT iParser: public QObject, public QuasarAppUtils::iHRO const Header *req = nullptr) const; private: - QHash> _registeredTypes; + // command - {version - factory} + PacksMap _registeredTypes; + PackagesVersionData _multiVersionPackages; + AbstractNode *_node; friend class BigDataParserOld; diff --git a/src/public/packages/abstractdata.cpp b/src/public/packages/abstractdata.cpp index 3565bd9..cb9e9f5 100644 --- a/src/public/packages/abstractdata.cpp +++ b/src/public/packages/abstractdata.cpp @@ -34,7 +34,7 @@ bool AbstractData::toPackage(Package &package, return false; } - if (!toVersion(package.data, reqVersion)) { + if (!toBytesAdaptiveWithVersion(package.data, reqVersion)) { QuasarAppUtils::Params::log("You try send not supported version of packge on the distanation node.", QuasarAppUtils::Error); return false; @@ -72,7 +72,7 @@ void AbstractData::fromPakcage(const Package &pkg) { fromBytes(pkg.data); } -bool AbstractData::toVersion(QByteArray& out, unsigned short reqVersion) const { +bool AbstractData::toBytesAdaptiveWithVersion(QByteArray& out, unsigned short reqVersion) const { if (reqVersion == ver()) { out = toBytes(); return true; diff --git a/src/public/packages/abstractdata.h b/src/public/packages/abstractdata.h index b31f24f..615e95a 100644 --- a/src/public/packages/abstractdata.h +++ b/src/public/packages/abstractdata.h @@ -177,12 +177,12 @@ class HEARTSHARED_EXPORT AbstractData : public StreamBase, public QuasarAppUtils static QString commandText(){return "NULL";}; /** - * @brief toVersion This method should be convert package to rquired version. + * @brief toBytesAdaptiveWithVersion This method should be convert package to rquired version. * @param outputArray This is output byte array after convertation. * @param version This is required version pacakge. * @return true if convertation finished successful. */ - virtual bool toVersion(QByteArray& outputArray, unsigned short version) const; + virtual bool toBytesAdaptiveWithVersion(QByteArray& outputArray, unsigned short version) const; protected: /** From 501cb0ccf9ba6d8e4bd4cf3dbc4081cb04d7abb7 Mon Sep 17 00:00:00 2001 From: EndrII Date: Sun, 21 May 2023 12:05:14 +0200 Subject: [PATCH 03/17] try fix bug with old gcc commpillers --- src/public/distversion.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/public/distversion.h b/src/public/distversion.h index 6676564..17bec3a 100644 --- a/src/public/distversion.h +++ b/src/public/distversion.h @@ -29,7 +29,7 @@ class DistVersion: public StreamBase { /** * @brief getMaxСompatible return maximum available on booth nodes version. * @param distVersion this is dis version. - * @return return maximum version. if this version is not found retun -1 + * @return return maximum version. if this version is not found retun "-1" */ int getMaxСompatible(const DistVersion& distVersion) const; @@ -37,7 +37,7 @@ class DistVersion: public StreamBase { /** * @brief getMinСompatible return maximum available on booth nodes version. * @param distVersion this is dis version. - * @return return minimum version. if this version is not found retun -1 + * @return return minimum version. if this version is not found retun "-1" */ int getMinСompatible(const DistVersion& distVersion) const; From abc1bf4ab5e3c9fddebefcca324980047113c3ed Mon Sep 17 00:00:00 2001 From: EndrII Date: Sun, 21 May 2023 12:09:30 +0200 Subject: [PATCH 04/17] try fix build on old gcc --- src/public/distversion.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/public/distversion.h b/src/public/distversion.h index 17bec3a..2ef954a 100644 --- a/src/public/distversion.h +++ b/src/public/distversion.h @@ -33,7 +33,6 @@ class DistVersion: public StreamBase { */ int getMaxСompatible(const DistVersion& distVersion) const; - /** * @brief getMinСompatible return maximum available on booth nodes version. * @param distVersion this is dis version. From 67fa5c59b07f163015d9a7fca20e0af1522245b8 Mon Sep 17 00:00:00 2001 From: EndrII Date: Sun, 21 May 2023 12:17:02 +0200 Subject: [PATCH 05/17] fix build (remove russean C char from the functions names ) --- src/public/abstractnode.cpp | 2 +- src/public/distversion.cpp | 4 ++-- src/public/distversion.h | 14 +++++++------- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/public/abstractnode.cpp b/src/public/abstractnode.cpp index 00dbc37..1407862 100644 --- a/src/public/abstractnode.cpp +++ b/src/public/abstractnode.cpp @@ -757,7 +757,7 @@ unsigned int AbstractNode::sendData(const PKG::AbstractData *resp, } int version = node->multiVersionPackages().value(resp->cmd()). - getMaxСompatible(_apiVersionParser->multiVersionPackages().value(resp->cmd())); + getMaxCompatible(_apiVersionParser->multiVersionPackages().value(resp->cmd())); if (version < 0) { return 0; } diff --git a/src/public/distversion.cpp b/src/public/distversion.cpp index 87b98c9..2862256 100644 --- a/src/public/distversion.cpp +++ b/src/public/distversion.cpp @@ -16,7 +16,7 @@ void DistVersion::setMax(unsigned short newMax) { _max = newMax; } -int DistVersion::getMaxСompatible(const DistVersion &distVersion) const { +int DistVersion::getMaxCompatible(const DistVersion &distVersion) const { unsigned short midMax = std::min(distVersion.max(), _max); unsigned short midMin = std::max(distVersion.min(), _min); @@ -26,7 +26,7 @@ int DistVersion::getMaxСompatible(const DistVersion &distVersion) const { return midMax; } -int DistVersion::getMinСompatible(const DistVersion &distVersion) const { +int DistVersion::getMinCompatible(const DistVersion &distVersion) const { unsigned short midMax = std::min(distVersion.max(), _max); unsigned short midMin = std::max(distVersion.min(), _min); diff --git a/src/public/distversion.h b/src/public/distversion.h index 2ef954a..6d45a34 100644 --- a/src/public/distversion.h +++ b/src/public/distversion.h @@ -15,7 +15,7 @@ namespace QH { /** - * @brief The DistVersion class This is infirmation of supported versions of the distanation api. + * @brief The DistVersion class This is information of supported versions of the destinations api. */ class DistVersion: public StreamBase { @@ -29,16 +29,16 @@ class DistVersion: public StreamBase { /** * @brief getMaxСompatible return maximum available on booth nodes version. * @param distVersion this is dis version. - * @return return maximum version. if this version is not found retun "-1" + * @return return maximum version. if this version is not found return "-1" */ - int getMaxСompatible(const DistVersion& distVersion) const; + int getMaxCompatible(const DistVersion& distVersion) const; /** * @brief getMinСompatible return maximum available on booth nodes version. * @param distVersion this is dis version. - * @return return minimum version. if this version is not found retun "-1" + * @return return minimum version. if this version is not found return "-1" */ - int getMinСompatible(const DistVersion& distVersion) const; + int getMinCompatible(const DistVersion& distVersion) const; protected: @@ -47,7 +47,7 @@ class DistVersion: public StreamBase { private: - /// This is monimum supported version. + /// This is minimum supported version. unsigned short _min = 0; /// This is maximum supported version. @@ -57,7 +57,7 @@ class DistVersion: public StreamBase { /** - * @brief VersionData This is array of all avalable apis and supported its versions. + * @brief VersionData This is array of all available apis and supported its versions. */ typedef QHash VersionData; From 88b1d5a6207c15d134e54765f0e1ef17bde0a851 Mon Sep 17 00:00:00 2001 From: EndrII Date: Sun, 21 May 2023 12:36:59 +0200 Subject: [PATCH 06/17] some fixes --- src/public/packages/abstractdata.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/public/packages/abstractdata.cpp b/src/public/packages/abstractdata.cpp index cb9e9f5..f49efa0 100644 --- a/src/public/packages/abstractdata.cpp +++ b/src/public/packages/abstractdata.cpp @@ -63,9 +63,11 @@ bool AbstractData::isValid() const { } QString AbstractData::toString() const { - return QString("Type: %0, command: %1"). + return QString("Type: %0 \n" + "Version: %2 \n" + "Command: %1 \n"). arg(cmdString()). - arg(cmd()); + arg(cmd()).arg(ver()); } void AbstractData::fromPakcage(const Package &pkg) { From 88f4e92ffdc00348ef1ace7b68e3be2a72518d2c Mon Sep 17 00:00:00 2001 From: EndrII Date: Sun, 21 May 2023 13:42:09 +0200 Subject: [PATCH 07/17] change macross system --- HeartTests/units/bigdatatest.cpp | 2 +- src/private/apiversion.h | 1 - src/private/versionisreceived.h | 1 - src/public/packages/abstractdata.cpp | 11 ------- src/public/packages/abstractdata.h | 45 +++++++++++---------------- src/public/packages/badrequest.h | 2 +- src/public/packages/bigdatabase.h | 2 +- src/public/packages/bigdataheader.h | 2 +- src/public/packages/bigdatapart.h | 2 +- src/public/packages/bigdatarequest.h | 2 +- src/public/packages/bigdatawraper.h | 2 +- src/public/packages/closeconnection.h | 2 +- src/public/packages/datapack.h | 14 +++++++-- src/public/packages/dbobject.h | 8 +---- src/public/packages/dbobjectset.h | 2 +- src/public/packages/deleteobject.h | 1 - src/public/packages/getmaxintegerid.h | 1 - src/public/packages/getsinglevalue.h | 1 - src/public/packages/ping.h | 2 +- src/public/packages/setsinglevalue.h | 2 -- 20 files changed, 40 insertions(+), 65 deletions(-) diff --git a/HeartTests/units/bigdatatest.cpp b/HeartTests/units/bigdatatest.cpp index 2307cf2..8a4fac8 100644 --- a/HeartTests/units/bigdatatest.cpp +++ b/HeartTests/units/bigdatatest.cpp @@ -12,7 +12,7 @@ #define LOCAL_TEST_PORT TEST_PORT + 4 class BigPackage: public QH::PKG::AbstractData { - QH_PACKAGE_AUTO(BigPackage) + QH_PACKAGE_AUTO("BigPackage") public: BigPackage(){ diff --git a/src/private/apiversion.h b/src/private/apiversion.h index 5e32e67..11ce64d 100644 --- a/src/private/apiversion.h +++ b/src/private/apiversion.h @@ -48,7 +48,6 @@ class APIVersion: public QH::PKG::AbstractData void setApisVersions(const VersionData &newApisVersions); protected: - unsigned int localCode() const override {return typeid(APIVersion).hash_code();} QDataStream &fromStream(QDataStream &stream) override; QDataStream &toStream(QDataStream &stream) const override; diff --git a/src/private/versionisreceived.h b/src/private/versionisreceived.h index 0be6f32..401a82a 100644 --- a/src/private/versionisreceived.h +++ b/src/private/versionisreceived.h @@ -33,7 +33,6 @@ class VersionIsReceived: public QH::PKG::AbstractData // StreamBase interface protected: - unsigned int localCode() const override {return typeid(VersionIsReceived).hash_code();} QDataStream &fromStream(QDataStream &stream) override; QDataStream &toStream(QDataStream &stream) const override; }; diff --git a/src/public/packages/abstractdata.cpp b/src/public/packages/abstractdata.cpp index f49efa0..0d4711c 100644 --- a/src/public/packages/abstractdata.cpp +++ b/src/public/packages/abstractdata.cpp @@ -24,12 +24,6 @@ bool AbstractData::toPackage(Package &package, unsigned short reqVersion, unsigned int triggerHash) const { - if (!checkCmd()) { - QuasarAppUtils::Params::log("You try send pacakge without QH_PACKAGE macross. Please add QH_PACKAGE macros to this class.", - QuasarAppUtils::Error); - return false; - } - if (!isValid()) { return false; } @@ -53,11 +47,6 @@ bool AbstractData::toPackage(Package &package, return package.isValid(); } -bool AbstractData::checkCmd() const { - unsigned int code = typeid (*this).hash_code(); - return code == localCode(); -} - bool AbstractData::isValid() const { return true; } diff --git a/src/public/packages/abstractdata.h b/src/public/packages/abstractdata.h index 615e95a..6a9611f 100644 --- a/src/public/packages/abstractdata.h +++ b/src/public/packages/abstractdata.h @@ -24,10 +24,14 @@ #define PROTOCKOL_VERSION_RECEIVED_COMMAND PROTOCKOL_VERSION_COMMAND - 1 /** - * @brief QH_PACKAGE This macross prepare data to send and create a global id for package. For get global id use the cmd method. + * @brief QH_PACKAGE This macross prepare data to send and create a global id for package. + * For get global id use the cmd method. * For get quick access for global command use the ClassName::command() method. This method is static. + * @arg S This is unique id of the pacakge. Shold be some on all your network devices. + * @arg V This is version of the package If you do not use multople versions use 0 or QH_PACKAGE_AUTO instand QH_PACKAGE. + */ -#define QH_PACKAGE(X, S, V) \ +#define QH_PACKAGE(S, V) \ public: \ static unsigned short command(){\ QByteArray ba = QString(S).toLocal8Bit();\ @@ -35,29 +39,28 @@ } \ static QString commandText(){return S;} \ static unsigned short version(){ return V; } \ - unsigned short cmd() const override {return X::command();} \ - unsigned short ver() const override {return X::version();}; \ + unsigned short cmd() const override {return command();} \ + unsigned short ver() const override {return V;} \ \ - QString cmdString() const override {return X::commandText();} \ - protected: \ - unsigned int localCode() const override {return typeid(X).hash_code();} \ - \ + QString cmdString() const override {return S;} \ private: /** * @brief QH_PACKAGE_AUTO This macross prepare data to send and create a global id for package. - * @arg X This is unique id of the pacakge. shold be some on all your network devices. + * @arg S This is unique id of the pacakge. shold be some on all your network devices. * @note auto pacakge create a 0 version of your package. */ -#define QH_PACKAGE_AUTO(X) QH_PACKAGE(X,#X, 0) +#define QH_PACKAGE_AUTO(S) QH_PACKAGE(S, 0) /** - * @brief QH_PACKAGE_AUTO This macross prepare data to send and create a global id for package. - * @arg X This is unique id of the pacakge. shold be some on all your network devices. - * @arg V This is version of the yor pacakge. - * @note auto pacakge create a 0 version of your package. + * @brief QH_PACKAGE_ONLY_VERSION This macross can be used only if parrent class alredy has QH_PACKAGE macros and int is some pacakge but with new version. + * @arg B This is new version of the package. */ -#define QH_PACKAGE_AUTO_VER(X, V) QH_PACKAGE(X,#X, V) +#define QH_PACKAGE_ONLY_VERSION(V) \ +public: \ + static unsigned short version(){ return V; } \ + unsigned short ver() const override {return V;} \ + private: \ namespace QH { namespace PKG { @@ -190,23 +193,11 @@ class HEARTSHARED_EXPORT AbstractData : public StreamBase, public QuasarAppUtils */ explicit AbstractData(); - /** - * @brief localCode This method return local code - * @return local command of this class. used for check QH_PACKAGE macro before send pacakge. - */ - virtual unsigned int localCode() const = 0; - /** * @brief isOldPackage This method mark package as a old, old pacakges use the Package::calcHashOld method for calculation hash sum of packages. * @return true if the pacakge is old. */ virtual bool isOldPackage() const; -private: - /** - * @brief checkCmd This method check QH_PACKAGE macross. - * @return true if the QH_PACKAGE macross is enabled else fal. - */ - bool checkCmd() const;; }; diff --git a/src/public/packages/badrequest.h b/src/public/packages/badrequest.h index 07c622c..51100f6 100644 --- a/src/public/packages/badrequest.h +++ b/src/public/packages/badrequest.h @@ -33,7 +33,7 @@ struct ErrorData { */ class HEARTSHARED_EXPORT BadRequest : public AbstractData { - QH_PACKAGE_AUTO(BadRequest) + QH_PACKAGE_AUTO("BadRequest") public: /** diff --git a/src/public/packages/bigdatabase.h b/src/public/packages/bigdatabase.h index 1cbf565..25d3bd5 100644 --- a/src/public/packages/bigdatabase.h +++ b/src/public/packages/bigdatabase.h @@ -19,7 +19,7 @@ namespace PKG { */ class HEARTSHARED_EXPORT BigDataBase: public AbstractData { - QH_PACKAGE_AUTO(BigDataBase) + QH_PACKAGE_AUTO("BigDataBase") public: BigDataBase(); diff --git a/src/public/packages/bigdataheader.h b/src/public/packages/bigdataheader.h index af4f7a7..0afce2c 100644 --- a/src/public/packages/bigdataheader.h +++ b/src/public/packages/bigdataheader.h @@ -27,7 +27,7 @@ namespace PKG { */ class HEARTSHARED_EXPORT BigDataHeader : public BigDataBase { - QH_PACKAGE_AUTO(BigDataHeader) + QH_PACKAGE_AUTO("BigDataHeader") public: BigDataHeader(); diff --git a/src/public/packages/bigdatapart.h b/src/public/packages/bigdatapart.h index 6f34777..2104059 100644 --- a/src/public/packages/bigdatapart.h +++ b/src/public/packages/bigdatapart.h @@ -20,7 +20,7 @@ namespace PKG { */ class HEARTSHARED_EXPORT BigDataPart : public BigDataBase { - QH_PACKAGE_AUTO(BigDataPart) + QH_PACKAGE_AUTO("BigDataPart") public: BigDataPart(); diff --git a/src/public/packages/bigdatarequest.h b/src/public/packages/bigdatarequest.h index 950566c..6c9fad7 100644 --- a/src/public/packages/bigdatarequest.h +++ b/src/public/packages/bigdatarequest.h @@ -19,7 +19,7 @@ namespace PKG { */ class HEARTSHARED_EXPORT BigDataRequest: public BigDataBase { - QH_PACKAGE_AUTO(BigDataRequest) + QH_PACKAGE_AUTO("BigDataRequest") public: BigDataRequest(); diff --git a/src/public/packages/bigdatawraper.h b/src/public/packages/bigdatawraper.h index 4b3a583..569a5bd 100644 --- a/src/public/packages/bigdatawraper.h +++ b/src/public/packages/bigdatawraper.h @@ -19,7 +19,7 @@ namespace PKG { */ class BigDataWraper: public AbstractData { - QH_PACKAGE_AUTO(BigDataWraper) + QH_PACKAGE_AUTO("BigDataWraper") public: BigDataWraper() = default; diff --git a/src/public/packages/closeconnection.h b/src/public/packages/closeconnection.h index efb51c1..8250d92 100644 --- a/src/public/packages/closeconnection.h +++ b/src/public/packages/closeconnection.h @@ -27,7 +27,7 @@ namespace PKG { */ class HEARTSHARED_EXPORT CloseConnection: public AbstractData { - QH_PACKAGE_AUTO(CloseConnection) + QH_PACKAGE_AUTO("CloseConnection") public: CloseConnection(); diff --git a/src/public/packages/datapack.h b/src/public/packages/datapack.h index 7585eab..b4a2abb 100644 --- a/src/public/packages/datapack.h +++ b/src/public/packages/datapack.h @@ -8,8 +8,7 @@ #ifndef DATAPACK_H #define DATAPACK_H -#include "universaldata.h" - +#include namespace QH { namespace PKG { @@ -25,7 +24,7 @@ namespace PKG { template class DataPack final: public AbstractData { - QH_PACKAGE(DataPack, Package::commandText() + "Pack", 0) + QH_PACKAGE(Package::commandText() + "Pack", Package::version()) public: @@ -114,6 +113,15 @@ class DataPack final: public AbstractData _data = newToken; } + bool toBytesAdaptiveWithVersion(QByteArray& outputArray, unsigned short version) const override { + if (AbstractData::toBytesAdaptiveWithVersion(outputArray, version)) { + return true; + } + + version == ??? + } + + protected: QDataStream &fromStream(QDataStream &stream) override { diff --git a/src/public/packages/dbobject.h b/src/public/packages/dbobject.h index 2fda2e7..5415425 100644 --- a/src/public/packages/dbobject.h +++ b/src/public/packages/dbobject.h @@ -18,12 +18,6 @@ class QSqlQuery; namespace QH { namespace PKG { -/** - * The ONLY_DATABASE_PACKAGE macross is base macros for all database objects that do not use stream and network functions. -*/ -#define ONLY_DATABASE_PACKAGE QH_PACKAGE(DBObject, "DBObject", 0) - - /** * @brief The PrepareResult enum is result of work prepare sql query of dbobjects. */ @@ -95,7 +89,7 @@ typedef QMap DBVariantMap; */ class HEARTSHARED_EXPORT DBObject : public AbstractData { - QH_PACKAGE_AUTO(DBObject) + QH_PACKAGE("DBObject", 0) public: diff --git a/src/public/packages/dbobjectset.h b/src/public/packages/dbobjectset.h index 3d42dc2..53d542f 100644 --- a/src/public/packages/dbobjectset.h +++ b/src/public/packages/dbobjectset.h @@ -22,7 +22,7 @@ namespace PKG { */ class HEARTSHARED_EXPORT DBObjectSet: public DBObject { - QH_PACKAGE_AUTO(DBObjectSet) + QH_PACKAGE_AUTO("DBObjectSet") public: DBObjectSet(const QString table); diff --git a/src/public/packages/deleteobject.h b/src/public/packages/deleteobject.h index e99bd3b..35e2931 100644 --- a/src/public/packages/deleteobject.h +++ b/src/public/packages/deleteobject.h @@ -25,7 +25,6 @@ namespace PKG { */ class HEARTSHARED_EXPORT DeleteObject: public DBObject, public IToken { - QH_PACKAGE_AUTO(DeleteObject) public: DeleteObject(); diff --git a/src/public/packages/getmaxintegerid.h b/src/public/packages/getmaxintegerid.h index 0ab0de8..5029411 100644 --- a/src/public/packages/getmaxintegerid.h +++ b/src/public/packages/getmaxintegerid.h @@ -19,7 +19,6 @@ namespace PKG { */ class HEARTSHARED_EXPORT GetMaxIntegerId: public DBObject { - QH_PACKAGE_AUTO(GetMaxIntegerId) public: /** diff --git a/src/public/packages/getsinglevalue.h b/src/public/packages/getsinglevalue.h index 3dafbb4..9ffc220 100644 --- a/src/public/packages/getsinglevalue.h +++ b/src/public/packages/getsinglevalue.h @@ -38,7 +38,6 @@ namespace PKG { */ class HEARTSHARED_EXPORT GetSingleValue final: public DBObject { - QH_PACKAGE_AUTO(GetSingleValue) public: /** diff --git a/src/public/packages/ping.h b/src/public/packages/ping.h index 159734d..2d07418 100644 --- a/src/public/packages/ping.h +++ b/src/public/packages/ping.h @@ -20,7 +20,7 @@ namespace PKG { */ class HEARTSHARED_EXPORT Ping: public AbstractData { - QH_PACKAGE_AUTO(Ping) + QH_PACKAGE_AUTO("Ping") public: Ping(); diff --git a/src/public/packages/setsinglevalue.h b/src/public/packages/setsinglevalue.h index 213149a..4047433 100644 --- a/src/public/packages/setsinglevalue.h +++ b/src/public/packages/setsinglevalue.h @@ -32,8 +32,6 @@ namespace PKG { */ class HEARTSHARED_EXPORT SetSingleValue final: public DBObject { - QH_PACKAGE_AUTO(SetSingleValue) - public: /** * @brief SetSingleValue This is default constructor of the update query generator. From c1ec94bd141e92ba66ba43ce1aecf858c36e402a Mon Sep 17 00:00:00 2001 From: EndrII Date: Mon, 22 May 2023 00:45:37 +0200 Subject: [PATCH 08/17] change mutiversion methods names --- src/public/packages/abstractdata.cpp | 26 +++++++++++++++----------- src/public/packages/abstractdata.h | 16 ++++++++++++---- src/public/packages/datapack.h | 24 +++++++++++++----------- 3 files changed, 40 insertions(+), 26 deletions(-) diff --git a/src/public/packages/abstractdata.cpp b/src/public/packages/abstractdata.cpp index 0d4711c..67750f1 100644 --- a/src/public/packages/abstractdata.cpp +++ b/src/public/packages/abstractdata.cpp @@ -28,12 +28,7 @@ bool AbstractData::toPackage(Package &package, return false; } - if (!toBytesAdaptiveWithVersion(package.data, reqVersion)) { - QuasarAppUtils::Params::log("You try send not supported version of packge on the distanation node.", - QuasarAppUtils::Error); - return false; - } - + package.data = toBytesOf(reqVersion); package.hdr.command = cmd(); package.hdr.triggerHash = triggerHash; package.hdr.size = package.data.size(); @@ -63,13 +58,22 @@ void AbstractData::fromPakcage(const Package &pkg) { fromBytes(pkg.data); } -bool AbstractData::toBytesAdaptiveWithVersion(QByteArray& out, unsigned short reqVersion) const { - if (reqVersion == ver()) { - out = toBytes(); - return true; +QByteArray AbstractData::toBytesOf(unsigned short reqVersion) const { + QByteArray res; + QDataStream stream(&res, QIODevice::WriteOnly); + + if (parsingVersion()) { + stream.setVersion(parsingVersion()); } - return false; + toStreamOf(stream, reqVersion); + return res; +} + +QDataStream &AbstractData::toStreamOf(QDataStream &stream, unsigned short version) const { + debug_assert(version == ver(), "from stream should be overload for the multi version packages."); + + return toStream(stream); } AbstractData::~AbstractData() { diff --git a/src/public/packages/abstractdata.h b/src/public/packages/abstractdata.h index 6a9611f..b4572f1 100644 --- a/src/public/packages/abstractdata.h +++ b/src/public/packages/abstractdata.h @@ -180,12 +180,20 @@ class HEARTSHARED_EXPORT AbstractData : public StreamBase, public QuasarAppUtils static QString commandText(){return "NULL";}; /** - * @brief toBytesAdaptiveWithVersion This method should be convert package to rquired version. - * @param outputArray This is output byte array after convertation. + * @brief toBytesOf This is overload method of StreamBase::toBytes for support multi versions of packages. * @param version This is required version pacakge. - * @return true if convertation finished successful. + * @return bytes array for package. + * @note This is just wrapper method for the AbstractData::toStream method. */ - virtual bool toBytesAdaptiveWithVersion(QByteArray& outputArray, unsigned short version) const; + QByteArray toBytesOf(unsigned short version) const; + + /** + * @brief toStreamOf This overrload of the base toStream method for support the multi version packages. + * @param stream this is stream object. + * @param version this is custom version of parsing function. + * @return stream object. + */ + virtual QDataStream& toStreamOf(QDataStream& stream, unsigned short version) const; protected: /** diff --git a/src/public/packages/datapack.h b/src/public/packages/datapack.h index b4a2abb..9adb6fa 100644 --- a/src/public/packages/datapack.h +++ b/src/public/packages/datapack.h @@ -113,15 +113,6 @@ class DataPack final: public AbstractData _data = newToken; } - bool toBytesAdaptiveWithVersion(QByteArray& outputArray, unsigned short version) const override { - if (AbstractData::toBytesAdaptiveWithVersion(outputArray, version)) { - return true; - } - - version == ??? - } - - protected: QDataStream &fromStream(QDataStream &stream) override { @@ -143,8 +134,8 @@ class DataPack final: public AbstractData QDataStream &toStream(QDataStream &stream) const override { stream << static_cast(_packData.size()); - for (const auto &ptr: qAsConst(_packData)) { - stream << *ptr; + for (const auto &data: qAsConst(_packData)) { + stream << *data; } stream << _data; @@ -152,6 +143,17 @@ class DataPack final: public AbstractData return stream; } + QDataStream &toStreamOf(QDataStream &stream, unsigned short version) const override { + stream << static_cast(_packData.size()); + + for (const auto &data: qAsConst(_packData)) { + data->toStreamOf(stream, version); + } + + stream << _data; + + return stream; + } private: QList> _packData; From 441fe98a0267582803c1f483ad8fd5b736f79220 Mon Sep 17 00:00:00 2001 From: EndrII Date: Tue, 23 May 2023 10:55:03 +0200 Subject: [PATCH 09/17] begin to integration new versions fields --- src/private/bigdataparser.cpp | 2 ++ src/public/abstractnode.cpp | 6 ++++-- src/public/abstractnode.h | 11 ++++++++++- src/public/apiversionparser.cpp | 3 ++- src/public/apiversionparser.h | 5 ++++- src/public/iparser.cpp | 10 ++++++---- src/public/packages/bigdataheader.cpp | 10 ++++++++++ src/public/packages/bigdataheader.h | 15 ++++++++++++++- 8 files changed, 52 insertions(+), 10 deletions(-) diff --git a/src/private/bigdataparser.cpp b/src/private/bigdataparser.cpp index 3a32c70..c02943b 100644 --- a/src/private/bigdataparser.cpp +++ b/src/private/bigdataparser.cpp @@ -135,6 +135,7 @@ bool BigDataParser::processPart(const QSharedPointer &part, } auto package = node()->genPackage(localPool.header->getCommand(), + localPool.header->pkgVersion(), sender); if (!package) return false; @@ -209,6 +210,7 @@ bool BigDataParser::sendBigDataPackage(const PKG::AbstractData *data, hdr->setPackagesCount(std::ceil(rawData.size() / static_cast(sizeLimit))); hdr->setPackageId(rand()); hdr->setCommand(data->cmd()); + hdr->setPkgVersion(data->ver()); insertNewBigData(hdr); diff --git a/src/public/abstractnode.cpp b/src/public/abstractnode.cpp index 1407862..0e31e95 100644 --- a/src/public/abstractnode.cpp +++ b/src/public/abstractnode.cpp @@ -710,9 +710,11 @@ ParserResult AbstractNode::parsePackage(const QSharedPointer &pkg, return _apiVersionParser->parsePackage(pkg, pkgHeader, sender); } -QSharedPointer AbstractNode::genPackage(unsigned short cmd, AbstractNodeInfo *sender) const { +QSharedPointer AbstractNode::genPackage(unsigned short cmd, + unsigned short ver, + AbstractNodeInfo *sender) const { if (_apiVersionParser) - return _apiVersionParser->searchPackage(cmd, sender); + return _apiVersionParser->searchPackage(cmd, ver, sender); return nullptr; } diff --git a/src/public/abstractnode.h b/src/public/abstractnode.h index 8e8f708..50dc463 100644 --- a/src/public/abstractnode.h +++ b/src/public/abstractnode.h @@ -762,8 +762,17 @@ private slots: const Header &pkgHeader, AbstractNodeInfo *sender); + /** + * @brief genPackage This method generate a package from the command and version + * @param cmd this is command of the package. + * @param ver this is version of the package + * @param sender This is sender that sent this requests. + * @return empty package object. + */ QSharedPointer - genPackage(unsigned short cmd, AbstractNodeInfo *sender) const; + genPackage(unsigned short cmd, + unsigned short ver, + AbstractNodeInfo *sender) const; /** @note just disaable listen method in the node objects. diff --git a/src/public/apiversionparser.cpp b/src/public/apiversionparser.cpp index 4399c13..a6d36cf 100644 --- a/src/public/apiversionparser.cpp +++ b/src/public/apiversionparser.cpp @@ -82,6 +82,7 @@ QString APIVersionParser::toString() const { QSharedPointer APIVersionParser::searchPackage(unsigned short cmd, + unsigned short ver, AbstractNodeInfo *sender) const { if (!sender) return nullptr; @@ -106,7 +107,7 @@ APIVersionParser::searchPackage(unsigned short cmd, continue; } - if (auto package = parser->genPackage(cmd)) + if (auto package = parser->genPackage(cmd, ver)) return package; } diff --git a/src/public/apiversionparser.h b/src/public/apiversionparser.h index b110350..93145be 100644 --- a/src/public/apiversionparser.h +++ b/src/public/apiversionparser.h @@ -44,11 +44,14 @@ class APIVersionParser: public iParser * @brief searchPackage This method search package recursive in all registered pararsers. Searching will be in compatibility versions. * Before search methd choose compatibly verson. * @param cmd This is command for that shold be create pacakge object. + * @param ver This is version for that shold be create pacakge object. * @param sender This is node that sent @a the cmd. * @return Package generated from cmd. */ QSharedPointer - searchPackage(unsigned short cmd, AbstractNodeInfo *sender) const; + searchPackage(unsigned short cmd, + unsigned short ver, + AbstractNodeInfo *sender) const; /** * @brief getSelectedApiParser This method return apiParser for selected node diff --git a/src/public/iparser.cpp b/src/public/iparser.cpp index 8094392..b7eff41 100644 --- a/src/public/iparser.cpp +++ b/src/public/iparser.cpp @@ -69,10 +69,12 @@ void iParser::initSupportedCommands() {} QString iParser::toString() const { QString message = parserId() + " supports next commands:\n"; - for (const auto& versionsMap: _registeredTypes) { - for (auto it = versionsMap.keyBegin(); it != versionsMap.keyEnd(); ++it) { - auto pkg = genPackage(*it); - message += pkg->cmdString() + ":v" + pkg->ver() + " - " + QString::number(*it) + "\n"; + for (auto versionsMap = _registeredTypes.begin(); versionsMap != _registeredTypes.end(); ++versionsMap) { + auto cmd = versionsMap.key(); + auto versions = versionsMap.value(); + for (auto it = versions.begin(); it != versions.end(); ++it) { + auto pkg = genPackage(cmd, it.key()); + message += pkg->cmdString() + "-" + QString::number(pkg->cmd()) + ":v" + QString::number(it.key()) + "\n"; } } diff --git a/src/public/packages/bigdataheader.cpp b/src/public/packages/bigdataheader.cpp index ac0c46b..5ea658f 100644 --- a/src/public/packages/bigdataheader.cpp +++ b/src/public/packages/bigdataheader.cpp @@ -39,6 +39,7 @@ QDataStream &BigDataHeader::fromStream(QDataStream &stream) { stream >> packagesCount; stream >> _command; + stream >> _version; return stream; } @@ -48,10 +49,19 @@ QDataStream &BigDataHeader::toStream(QDataStream &stream) const { stream << packagesCount; stream << _command; + stream << _version; return stream; } +unsigned short BigDataHeader::pkgVersion() const { + return _version; +} + +void BigDataHeader::setPkgVersion(unsigned short newVersion) { + _version = newVersion; +} + unsigned short BigDataHeader::getCommand() const { return _command; } diff --git a/src/public/packages/bigdataheader.h b/src/public/packages/bigdataheader.h index 0afce2c..bfe5f10 100644 --- a/src/public/packages/bigdataheader.h +++ b/src/public/packages/bigdataheader.h @@ -60,13 +60,26 @@ class HEARTSHARED_EXPORT BigDataHeader : public BigDataBase */ void setCommand(unsigned short newCommand); + /** + * @brief pkgVersion This is version of the moving big data package. + * @return version of the moving big data package. + */ + unsigned short pkgVersion() const; + + /** + * @brief setPkgVersion This method sets new version of bid data package. + * @param newVersion This is new version + */ + void setPkgVersion(unsigned short newVersion); + protected: QDataStream &fromStream(QDataStream &stream) override; QDataStream &toStream(QDataStream &stream) const override; private: int packagesCount; - unsigned short _command; + unsigned short _command = 0; + unsigned short _version = 0; }; } } From f2612d5e4204e88bc65c2856af4aa4c997e03515 Mon Sep 17 00:00:00 2001 From: EndrII Date: Tue, 23 May 2023 19:02:37 +0200 Subject: [PATCH 10/17] added new system for support network pacakges versions --- CMakeLists.txt | 2 +- src/CMakeLists.txt | 2 +- src/public/abstractnode.cpp | 2 +- src/public/header.cpp | 11 +++++++--- src/public/header.h | 30 ++++++++++++++++++++++------ src/public/package.cpp | 2 +- src/public/package.h | 3 +-- src/public/packages/abstractdata.cpp | 1 + 8 files changed, 38 insertions(+), 15 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4645f6f..53f7bd4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,7 +24,7 @@ if (DEFINED TARGET_PLATFORM_TOOLCHAIN) endif() updateGitVars() -set(HEART_VERSION 1.2.${GIT_COMMIT_COUNT}.${GIT_COMMIT_HASH}) +set(HEART_VERSION 1.3.${GIT_COMMIT_COUNT}.${GIT_COMMIT_HASH}) if (ANDROID OR IOS) option(HEART_TESTS "Enable or disable tests of the heart library" OFF) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6b3e7a3..8e8cd92 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -5,7 +5,7 @@ # of this license document, but changing it is not allowed. # -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.18) set(CMAKE_INCLUDE_CURRENT_DIR ON) diff --git a/src/public/abstractnode.cpp b/src/public/abstractnode.cpp index 0e31e95..856d47f 100644 --- a/src/public/abstractnode.cpp +++ b/src/public/abstractnode.cpp @@ -1126,7 +1126,7 @@ QSharedPointer AbstractNode::prepareData(const Package &pkg, AbstractNodeInfo *sender) const { - auto value = _apiVersionParser->searchPackage(pkg.hdr.command, sender); + auto value = _apiVersionParser->searchPackage(pkg.hdr.command, pkg.hdr.packageVersion, sender); if (!value) { QuasarAppUtils::Params::log("You try parse not registered package type." " Plese use the registerPackageType method befor parsing." diff --git a/src/public/header.cpp b/src/public/header.cpp index 7140c82..9199076 100644 --- a/src/public/header.cpp +++ b/src/public/header.cpp @@ -10,6 +10,7 @@ #include namespace QH { + Header::Header() { reset(); } @@ -18,7 +19,7 @@ bool Header::isValid() const { if (size > Package::maximumSize()) { return false; } - return command && hash; + return command && hash && headerVersion == 1 && unusedSpace1 == 0; } void Header::reset() { @@ -26,10 +27,14 @@ void Header::reset() { command = 0; triggerHash = 0; hash = 0; + packageVersion = 0; + unusedSpace1 = 0; + unusedSpace2 = 0; + } QString Header::toString() const { - return QString("Header description: Size - %0, Command - %1, hash - %2, triggerHash - %3"). - arg(size).arg(command).arg(QString::number(hash, 16), QString::number(triggerHash, 16)); + return QString("Header description: HeaderVersion - %0, PackageVersion - %1, Size - %2, Command - %3, hash - %4, triggerHash - %5"). + arg(headerVersion).arg(packageVersion).arg(size).arg(command).arg(QString::number(hash, 16), QString::number(triggerHash, 16)); } } diff --git a/src/public/header.h b/src/public/header.h index 4942737..efdfce5 100644 --- a/src/public/header.h +++ b/src/public/header.h @@ -13,31 +13,50 @@ namespace QH { /** - * @brief The Header struct 12 bytes. + * @brief The Header struct 32 bytes. */ #pragma pack(push, 1) struct HEARTSHARED_EXPORT Header { /** * @brief command of package for more information see the AbstractData::toPackage method. */ - unsigned short command; + unsigned short command = 0; //2 bytes + + /** + * @brief headerVersion This is version of the header struct + */ + const unsigned char headerVersion = 1; //3 bytes + + /** + * @brief packageVersion This is package's version + */ + unsigned short packageVersion = 0; //5 bytes /** * @brief size This is size of package data (exclude header size). */ - unsigned int size; + unsigned int size = 0; //9 bytes /** * @brief hash This is unique id of a package. id calc with CRC32 function for Qt implementation. */ - unsigned int hash; + unsigned int hash = 0; //13 bytes /** * @brief triggerHash This is hash of request package that package has been responded. * The server should write to which command it responds. */ - unsigned int triggerHash; + unsigned int triggerHash = 0; //17 bytes + /** + * @brief unusedSpace This is unused space for changes of the header struct in the future. + */ + unsigned long long unusedSpace1 = 0; //25 bytes + + /** + * @brief unusedSpace This is unused space for changes of the header struct in the future. + */ + unsigned long long unusedSpace2:7 ; //32 bytes /** * @brief Header default constructor */ @@ -63,7 +82,6 @@ struct HEARTSHARED_EXPORT Header { }; #pragma pack(pop) - } diff --git a/src/public/package.cpp b/src/public/package.cpp index 710ead3..24e503c 100644 --- a/src/public/package.cpp +++ b/src/public/package.cpp @@ -41,7 +41,7 @@ void Package::reset() { QString Package::toString() const { return QString("Pakcage description: %0." " Data description: Data size - %1, Data: %2"). - arg(hdr.toString()).arg(data.size()).arg(QString(data.toHex().toUpper())); + arg(hdr.toString()).arg(data.size()).arg(QString(data.toHex().toUpper())); } unsigned int Package::calcHash() const { diff --git a/src/public/package.h b/src/public/package.h index 3f8c8be..50daa6d 100644 --- a/src/public/package.h +++ b/src/public/package.h @@ -15,10 +15,9 @@ namespace QH { -class Abstract; /** * @brief The Package struct. This is base structure for transporting data by network between QH nodes. - * The Package contains a 12 bytes header and Package::data array. The size on the header should be equals size of Package::data array. + * The Package contains a 32 bytes header and Package::data array. The size on the header should be equals size of Package::data array. * */ class HEARTSHARED_EXPORT Package: public StreamBase { diff --git a/src/public/packages/abstractdata.cpp b/src/public/packages/abstractdata.cpp index 67750f1..c7456ee 100644 --- a/src/public/packages/abstractdata.cpp +++ b/src/public/packages/abstractdata.cpp @@ -30,6 +30,7 @@ bool AbstractData::toPackage(Package &package, package.data = toBytesOf(reqVersion); package.hdr.command = cmd(); + package.hdr.packageVersion = reqVersion; package.hdr.triggerHash = triggerHash; package.hdr.size = package.data.size(); From 9a97eccb8c7f880f9587cd86f0357fba327e077a Mon Sep 17 00:00:00 2001 From: EndrII Date: Wed, 24 May 2023 22:36:39 +0200 Subject: [PATCH 11/17] fix windows build --- src/public/distversion.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/public/distversion.h b/src/public/distversion.h index 6d45a34..16bbdee 100644 --- a/src/public/distversion.h +++ b/src/public/distversion.h @@ -17,7 +17,7 @@ namespace QH { /** * @brief The DistVersion class This is information of supported versions of the destinations api. */ -class DistVersion: public StreamBase { +class HEARTSHARED_EXPORT DistVersion: public StreamBase { public: From f560c7dd2b9fb451737f454e6ae07b03eae53259 Mon Sep 17 00:00:00 2001 From: EndrII Date: Thu, 25 May 2023 09:35:54 +0200 Subject: [PATCH 12/17] try fix tests --- HeartTests/tst_testprotockol.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/HeartTests/tst_testprotockol.cpp b/HeartTests/tst_testprotockol.cpp index 7e3820a..ac8afb5 100644 --- a/HeartTests/tst_testprotockol.cpp +++ b/HeartTests/tst_testprotockol.cpp @@ -67,7 +67,6 @@ testProtockol::testProtockol() { } testProtockol::~testProtockol() { - _app->exit(0); delete _app; } From d2333f8f5a3871aff7bd7ae6cfc510d1bb35673e Mon Sep 17 00:00:00 2001 From: EndrII Date: Thu, 25 May 2023 10:21:32 +0200 Subject: [PATCH 13/17] change times for the shedullertest --- HeartTests/units/shedullertest.cpp | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/HeartTests/units/shedullertest.cpp b/HeartTests/units/shedullertest.cpp index 2b2e58a..6e5203b 100644 --- a/HeartTests/units/shedullertest.cpp +++ b/HeartTests/units/shedullertest.cpp @@ -40,6 +40,14 @@ class TestTask: public QH::AbstractTask { }; +#ifdef Q_OS_WIN +const int stepTime = 5000; +const int measurementError = 2000; +#else +const int stepTime = 2000; +const int measurementError = 1000; +#endif + ShedullerTest::ShedullerTest() { } @@ -56,13 +64,13 @@ void ShedullerTest::testSingleMode() { auto task = QSharedPointer::create(); task->setMode(QH::ScheduleMode::SingleWork); - task->setTime(2000); + task->setTime(stepTime); quint64 ct = QDateTime::currentMSecsSinceEpoch(); node->sheduleTask(task); QVERIFY(wait([&node](){return node->executedTime;}, WAIT_TIME)); - int diff = std::abs(static_cast(node->executedTime - (ct + 2000))); - QVERIFY(diff < 1000); + int diff = std::abs(static_cast(node->executedTime - (ct + stepTime))); + QVERIFY(diff < measurementError); node->executedTime = 0; QVERIFY(node->sheduledTaskCount() == 0); @@ -73,24 +81,24 @@ void ShedullerTest::testSingleMode() { void ShedullerTest::testRepeatMode() { ShedullerestNode *node = new ShedullerestNode(); auto task = QSharedPointer::create(); - task->setTime(2000); + task->setTime(stepTime); task->setMode(QH::ScheduleMode::Repeat); quint64 ct = QDateTime::currentMSecsSinceEpoch(); node->sheduleTask(task); QVERIFY(wait([&node](){return node->executedTime;}, WAIT_TIME)); - int diff = std::abs(static_cast(node->executedTime - (ct + 2000))); + int diff = std::abs(static_cast(node->executedTime - (ct + stepTime))); - QVERIFY(diff < 1000); + QVERIFY(diff < measurementError); node->executedTime = 0; QVERIFY(node->sheduledTaskCount() == 1); QVERIFY(wait([&node](){return node->executedTime;}, WAIT_TIME)); - diff = std::abs(static_cast(node->executedTime - (ct + 4000))); + diff = std::abs(static_cast(node->executedTime - (ct + stepTime * 2))); - QVERIFY(diff < 1000); + QVERIFY(diff < measurementError); QVERIFY(node->sheduledTaskCount() == 1); node->removeTask(task->taskId()); @@ -114,7 +122,7 @@ void ShedullerTest::testTimePointMode() { QVERIFY(wait([&node](){return node->executedTime;}, WAIT_TIME)); int diff = std::abs(static_cast(node->executedTime - requestTime)); - QVERIFY(diff < 1000); + QVERIFY(diff < measurementError); QVERIFY(node->sheduledTaskCount() == 0); node->softDelete(); From ea9725b920c88f080c961ac9c7edd163cdf89654 Mon Sep 17 00:00:00 2001 From: EndrII Date: Thu, 25 May 2023 23:24:48 +0200 Subject: [PATCH 14/17] refactoring multiversions sustem --- HeartTests/units/bigdatatest.cpp | 10 +++- HeartTests/units/multiversiontest.cpp | 58 +++++++++++++++++++ HeartTests/units/multiversiontest.h | 29 ++++++++++ src/private/apiversion.cpp | 1 + src/private/apiversion.h | 1 - src/private/bigdataparser.cpp | 2 - src/private/versionisreceived.h | 1 - src/public/abstractnode.cpp | 5 +- src/public/abstractnode.h | 2 - src/public/accesstoken.cpp | 1 + src/public/apiversionparser.cpp | 3 +- src/public/apiversionparser.h | 1 - src/public/distversion.cpp | 13 +++++ src/public/distversion.h | 15 ++++- src/public/header.cpp | 8 +-- src/public/header.h | 19 ++---- src/public/iparser.cpp | 18 ++---- src/public/iparser.h | 25 ++++---- src/public/package.cpp | 9 +-- src/public/package.h | 7 --- src/public/packages/abstractdata.cpp | 34 ++++++----- src/public/packages/abstractdata.h | 51 ++++++----------- src/public/packages/badrequest.cpp | 1 + src/public/packages/badrequest.h | 2 +- src/public/packages/bigdatabase.cpp | 2 + src/public/packages/bigdatabase.h | 2 +- src/public/packages/bigdataheader.cpp | 10 ---- src/public/packages/bigdataheader.h | 15 +---- src/public/packages/bigdatapart.h | 2 +- src/public/packages/bigdatarequest.h | 2 +- src/public/packages/bigdatawraper.h | 2 +- src/public/packages/closeconnection.h | 2 +- src/public/packages/dbobject.h | 2 +- src/public/packages/dbobjectset.h | 2 +- src/public/packages/deleteobject.cpp | 1 + src/public/packages/multiversiondata.cpp | 34 +++++++++++ src/public/packages/multiversiondata.h | 73 ++++++++++++++++++++++++ src/public/packages/ping.cpp | 2 + src/public/packages/ping.h | 2 +- src/public/packages/universaldata.cpp | 2 + src/public/packages/universaldata.h | 2 +- 41 files changed, 321 insertions(+), 152 deletions(-) create mode 100644 HeartTests/units/multiversiontest.cpp create mode 100644 HeartTests/units/multiversiontest.h create mode 100644 src/public/packages/multiversiondata.cpp create mode 100644 src/public/packages/multiversiondata.h diff --git a/HeartTests/units/bigdatatest.cpp b/HeartTests/units/bigdatatest.cpp index 8a4fac8..bc59620 100644 --- a/HeartTests/units/bigdatatest.cpp +++ b/HeartTests/units/bigdatatest.cpp @@ -12,7 +12,7 @@ #define LOCAL_TEST_PORT TEST_PORT + 4 class BigPackage: public QH::PKG::AbstractData { - QH_PACKAGE_AUTO("BigPackage") + QH_PACKAGE("BigPackage") public: BigPackage(){ @@ -22,13 +22,17 @@ class BigPackage: public QH::PKG::AbstractData { // StreamBase interface protected: - QDataStream &fromStream(QDataStream &stream) override{ + QDataStream &fromStream(QDataStream &stream) override { + AbstractData::fromStream(stream); + stream >> data; return stream; }; - QDataStream &toStream(QDataStream &stream) const override{ + QDataStream &toStream(QDataStream &stream) const override { + AbstractData::toStream(stream); + stream << data; return stream; diff --git a/HeartTests/units/multiversiontest.cpp b/HeartTests/units/multiversiontest.cpp new file mode 100644 index 0000000..a59b4e8 --- /dev/null +++ b/HeartTests/units/multiversiontest.cpp @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2023-2023 QuasarApp. + * Distributed under the lgplv3 software license, see the accompanying + * Everyone is permitted to copy and distribute verbatim copies + * of this license document, but changing it is not allowed. +*/ + +#include "multiversiontest.h" + +class TestingClient: public QH::AbstractNode { + + // AbstractNode interface +public: + const QH::PKG::Ping& getPing() const { + return _ping; + } + + NodeType nodeType() const override { + return NodeType::Node; + }; + +protected slots: + void receivePing(const QSharedPointer& ping) override { + _ping = *ping; + }; + +private: + QH::PKG::Ping _ping; +}; + +class MultiVersionPkg: public QH::PKG::AbstractData { + QH_PACKAGE("MultiVersionPkg") + +public: + int v1 = 0; + + // StreamBase interface +protected: + QDataStream &fromStream(QDataStream &stream) override { + AbstractData::fromStream(stream); + + stream >> v1; + return stream; + }; + + QDataStream &toStream(QDataStream &stream) const override{ + stream << v1; + return stream; + }; +}; + +MultiVersionTest::MultiVersionTest() { + +} + +void MultiVersionTest::test() { + +} diff --git a/HeartTests/units/multiversiontest.h b/HeartTests/units/multiversiontest.h new file mode 100644 index 0000000..8136cb9 --- /dev/null +++ b/HeartTests/units/multiversiontest.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2023-2023 QuasarApp. + * Distributed under the lgplv3 software license, see the accompanying + * Everyone is permitted to copy and distribute verbatim copies + * of this license document, but changing it is not allowed. +*/ + +#ifndef MULTIVERSIONTEST_H +#define MULTIVERSIONTEST_H + + +#include "test.h" +#include "testutils.h" + +#include +#include + +/** + * @brief The MultiVersionTest class test work of packages with different versions. + */ +class MultiVersionTest: public Test, protected TestUtils +{ +public: + MultiVersionTest(); + void test(); + +}; + +#endif // MULTIVERSIONTEST_H diff --git a/src/private/apiversion.cpp b/src/private/apiversion.cpp index 51ccfd1..ad3e75f 100644 --- a/src/private/apiversion.cpp +++ b/src/private/apiversion.cpp @@ -16,6 +16,7 @@ APIVersion::APIVersion() { } QDataStream &APIVersion::fromStream(QDataStream &stream) { + AbstractData::fromStream(stream); stream >> _apisVersions; stream >> _packagesVersions; diff --git a/src/private/apiversion.h b/src/private/apiversion.h index 11ce64d..77660c1 100644 --- a/src/private/apiversion.h +++ b/src/private/apiversion.h @@ -31,7 +31,6 @@ class APIVersion: public QH::PKG::AbstractData static QString commandText(){return "PROTOCKOL_VERSION_COMMAND";} unsigned short cmd() const override {return APIVersion::command();} - unsigned short ver() const override {return APIVersion::version();} QString cmdString() const override {return APIVersion::commandText();} diff --git a/src/private/bigdataparser.cpp b/src/private/bigdataparser.cpp index c02943b..3a32c70 100644 --- a/src/private/bigdataparser.cpp +++ b/src/private/bigdataparser.cpp @@ -135,7 +135,6 @@ bool BigDataParser::processPart(const QSharedPointer &part, } auto package = node()->genPackage(localPool.header->getCommand(), - localPool.header->pkgVersion(), sender); if (!package) return false; @@ -210,7 +209,6 @@ bool BigDataParser::sendBigDataPackage(const PKG::AbstractData *data, hdr->setPackagesCount(std::ceil(rawData.size() / static_cast(sizeLimit))); hdr->setPackageId(rand()); hdr->setCommand(data->cmd()); - hdr->setPkgVersion(data->ver()); insertNewBigData(hdr); diff --git a/src/private/versionisreceived.h b/src/private/versionisreceived.h index 401a82a..a9352cc 100644 --- a/src/private/versionisreceived.h +++ b/src/private/versionisreceived.h @@ -28,7 +28,6 @@ class VersionIsReceived: public QH::PKG::AbstractData static QString commandText(){return "PROTOCKOL_VERSION_RECEIVED_COMMAND";} unsigned short cmd() const override {return VersionIsReceived::command();} QString cmdString() const override {return VersionIsReceived::commandText();} - unsigned short ver() const override {return VersionIsReceived::version();} // StreamBase interface diff --git a/src/public/abstractnode.cpp b/src/public/abstractnode.cpp index 856d47f..eb60794 100644 --- a/src/public/abstractnode.cpp +++ b/src/public/abstractnode.cpp @@ -711,10 +711,9 @@ ParserResult AbstractNode::parsePackage(const QSharedPointer &pkg, } QSharedPointer AbstractNode::genPackage(unsigned short cmd, - unsigned short ver, AbstractNodeInfo *sender) const { if (_apiVersionParser) - return _apiVersionParser->searchPackage(cmd, ver, sender); + return _apiVersionParser->searchPackage(cmd, sender); return nullptr; } @@ -1126,7 +1125,7 @@ QSharedPointer AbstractNode::prepareData(const Package &pkg, AbstractNodeInfo *sender) const { - auto value = _apiVersionParser->searchPackage(pkg.hdr.command, pkg.hdr.packageVersion, sender); + auto value = _apiVersionParser->searchPackage(pkg.hdr.command, sender); if (!value) { QuasarAppUtils::Params::log("You try parse not registered package type." " Plese use the registerPackageType method befor parsing." diff --git a/src/public/abstractnode.h b/src/public/abstractnode.h index 50dc463..aa0fd7f 100644 --- a/src/public/abstractnode.h +++ b/src/public/abstractnode.h @@ -765,13 +765,11 @@ private slots: /** * @brief genPackage This method generate a package from the command and version * @param cmd this is command of the package. - * @param ver this is version of the package * @param sender This is sender that sent this requests. * @return empty package object. */ QSharedPointer genPackage(unsigned short cmd, - unsigned short ver, AbstractNodeInfo *sender) const; /** diff --git a/src/public/accesstoken.cpp b/src/public/accesstoken.cpp index 768a7c9..1a3c9b3 100644 --- a/src/public/accesstoken.cpp +++ b/src/public/accesstoken.cpp @@ -59,6 +59,7 @@ bool AccessToken::operator !=(const AccessToken &other) const { AccessToken& AccessToken::operator =(const AccessToken &other) = default; QDataStream &AccessToken::fromStream(QDataStream &stream) { + stream >> _data; stream >> _duration; return stream; diff --git a/src/public/apiversionparser.cpp b/src/public/apiversionparser.cpp index a6d36cf..4399c13 100644 --- a/src/public/apiversionparser.cpp +++ b/src/public/apiversionparser.cpp @@ -82,7 +82,6 @@ QString APIVersionParser::toString() const { QSharedPointer APIVersionParser::searchPackage(unsigned short cmd, - unsigned short ver, AbstractNodeInfo *sender) const { if (!sender) return nullptr; @@ -107,7 +106,7 @@ APIVersionParser::searchPackage(unsigned short cmd, continue; } - if (auto package = parser->genPackage(cmd, ver)) + if (auto package = parser->genPackage(cmd)) return package; } diff --git a/src/public/apiversionparser.h b/src/public/apiversionparser.h index 93145be..72b17a5 100644 --- a/src/public/apiversionparser.h +++ b/src/public/apiversionparser.h @@ -50,7 +50,6 @@ class APIVersionParser: public iParser */ QSharedPointer searchPackage(unsigned short cmd, - unsigned short ver, AbstractNodeInfo *sender) const; /** diff --git a/src/public/distversion.cpp b/src/public/distversion.cpp index 2862256..0775041 100644 --- a/src/public/distversion.cpp +++ b/src/public/distversion.cpp @@ -36,7 +36,16 @@ int DistVersion::getMinCompatible(const DistVersion &distVersion) const { return midMin; } +bool DistVersion::isSupport(unsigned short version) const { + return _min <= version && version <= _max; +} + +QString DistVersion::toString() const { + return QString("%0:%1").arg(_min).arg(_max); +} + QDataStream &DistVersion::fromStream(QDataStream &stream) { + stream >> _min; stream >> _max; return stream; @@ -48,6 +57,10 @@ QDataStream &DistVersion::toStream(QDataStream &stream) const { return stream; } +DistVersion::operator bool() const { + return _min || _max; +} + unsigned short DistVersion::min() const { return _min; } diff --git a/src/public/distversion.h b/src/public/distversion.h index 16bbdee..89cb5c8 100644 --- a/src/public/distversion.h +++ b/src/public/distversion.h @@ -8,6 +8,7 @@ #ifndef DISTVERSION_H #define DISTVERSION_H +#include "humanreadableobject.h" #include #include @@ -17,10 +18,12 @@ namespace QH { /** * @brief The DistVersion class This is information of supported versions of the destinations api. */ -class HEARTSHARED_EXPORT DistVersion: public StreamBase { +class HEARTSHARED_EXPORT DistVersion: public StreamBase, public QuasarAppUtils::iHRO { public: + operator bool() const; + unsigned short min() const; void setMin(unsigned short newMin); unsigned short max() const; @@ -40,6 +43,15 @@ class HEARTSHARED_EXPORT DistVersion: public StreamBase { */ int getMinCompatible(const DistVersion& distVersion) const; + /** + * @brief isSupport This method return true if the @a version is supported of this versions range. + * @param version This is checked version. + * @return true if the @a version is supported of this versions range. + */ + bool isSupport(unsigned short version) const; + + QString toString() const override; + protected: QDataStream &fromStream(QDataStream &stream) override; @@ -55,7 +67,6 @@ class HEARTSHARED_EXPORT DistVersion: public StreamBase { }; - /** * @brief VersionData This is array of all available apis and supported its versions. */ diff --git a/src/public/header.cpp b/src/public/header.cpp index 9199076..ece6596 100644 --- a/src/public/header.cpp +++ b/src/public/header.cpp @@ -19,7 +19,7 @@ bool Header::isValid() const { if (size > Package::maximumSize()) { return false; } - return command && hash && headerVersion == 1 && unusedSpace1 == 0; + return command && hash && headerVersion == 1 && unusedSpace1 == 0 && unusedSpace2 == 0 && unusedSpace3 == 0; } void Header::reset() { @@ -27,14 +27,14 @@ void Header::reset() { command = 0; triggerHash = 0; hash = 0; - packageVersion = 0; unusedSpace1 = 0; unusedSpace2 = 0; + unusedSpace3 = 0; } QString Header::toString() const { - return QString("Header description: HeaderVersion - %0, PackageVersion - %1, Size - %2, Command - %3, hash - %4, triggerHash - %5"). - arg(headerVersion).arg(packageVersion).arg(size).arg(command).arg(QString::number(hash, 16), QString::number(triggerHash, 16)); + return QString("Header description: HeaderVersion - %0, Size - %1, Command - %2, hash - %3, triggerHash - %4"). + arg(headerVersion).arg(size).arg(command).arg(QString::number(hash, 16), QString::number(triggerHash, 16)); } } diff --git a/src/public/header.h b/src/public/header.h index efdfce5..89b996e 100644 --- a/src/public/header.h +++ b/src/public/header.h @@ -27,36 +27,29 @@ struct HEARTSHARED_EXPORT Header { */ const unsigned char headerVersion = 1; //3 bytes - /** - * @brief packageVersion This is package's version - */ - unsigned short packageVersion = 0; //5 bytes - /** * @brief size This is size of package data (exclude header size). */ - unsigned int size = 0; //9 bytes + unsigned int size = 0; //7 bytes /** * @brief hash This is unique id of a package. id calc with CRC32 function for Qt implementation. */ - unsigned int hash = 0; //13 bytes + unsigned int hash = 0; //11 bytes /** * @brief triggerHash This is hash of request package that package has been responded. * The server should write to which command it responds. */ - unsigned int triggerHash = 0; //17 bytes + unsigned int triggerHash = 0; //15 bytes /** * @brief unusedSpace This is unused space for changes of the header struct in the future. */ - unsigned long long unusedSpace1 = 0; //25 bytes + unsigned long long unusedSpace1 = 0; //23 bytes + unsigned long long unusedSpace2 = 0; //31 bytes + unsigned char unusedSpace3 = 0; //32 bytes - /** - * @brief unusedSpace This is unused space for changes of the header struct in the future. - */ - unsigned long long unusedSpace2:7 ; //32 bytes /** * @brief Header default constructor */ diff --git a/src/public/iparser.cpp b/src/public/iparser.cpp index b7eff41..9e1d4fc 100644 --- a/src/public/iparser.cpp +++ b/src/public/iparser.cpp @@ -35,13 +35,12 @@ const PacksMap &iParser::registeredTypes() const { return _registeredTypes; } -QSharedPointer iParser::genPackage(unsigned short cmd, unsigned short ver) const { - return QSharedPointer(_registeredTypes.value(cmd, {}).value(ver, [](){return nullptr;})()); +QSharedPointer iParser::genPackage(unsigned short cmd) const { + return QSharedPointer(_registeredTypes.value(cmd, [](){return nullptr;})()); } -bool iParser::checkCommand(unsigned short cmd, unsigned short ver) const { - auto versions = _registeredTypes.value(cmd, {}); - return versions.contains(ver); +bool iParser::checkCommand(unsigned short cmd) const { + return _registeredTypes.contains(cmd); } AbstractNode *iParser::node() const { @@ -69,13 +68,8 @@ void iParser::initSupportedCommands() {} QString iParser::toString() const { QString message = parserId() + " supports next commands:\n"; - for (auto versionsMap = _registeredTypes.begin(); versionsMap != _registeredTypes.end(); ++versionsMap) { - auto cmd = versionsMap.key(); - auto versions = versionsMap.value(); - for (auto it = versions.begin(); it != versions.end(); ++it) { - auto pkg = genPackage(cmd, it.key()); - message += pkg->cmdString() + "-" + QString::number(pkg->cmd()) + ":v" + QString::number(it.key()) + "\n"; - } + for (auto it = _registeredTypes.keyBegin(); it != _registeredTypes.keyEnd(); ++it) { + message += genPackage(*it)->cmdString() + " - " + QString::number(*it) + "\n"; } return message; diff --git a/src/public/iparser.h b/src/public/iparser.h index ef29eee..3c2d2bc 100644 --- a/src/public/iparser.h +++ b/src/public/iparser.h @@ -24,9 +24,9 @@ class AbstractData; } /** - * @brief PacksMap This is hash map with the package id - version of package and package factory function. + * @brief PacksMap This is hash map where id is command of package and value is factory function. */ -using PacksMap = QHash>>; +using PacksMap = QHash>; /** @@ -63,14 +63,17 @@ class HEARTSHARED_EXPORT iParser: public QObject, public QuasarAppUtils::iHRO * @see initSupportedCommands */ void registerPackageType() { - _registeredTypes[T::command()][T::version()] = [](){ + + static_assert(std::is_base_of_v, + "The template type must inheret of the AbstractData class."); + + _registeredTypes[T::command()] = [](){ return new T(); }; - auto multiVersionsList = _registeredTypes.value(T::command()); - if (multiVersionsList.size() > 1) { - _multiVersionPackages[T::command()].setMax(multiVersionsList.lastKey()); - _multiVersionPackages[T::command()].setMin(multiVersionsList.firstKey()); + T tmp; + if (const DistVersion &distVersion = tmp.packageVersion()) { + _multiVersionPackages[tmp.cmd()] = distVersion; } }; @@ -199,19 +202,18 @@ class HEARTSHARED_EXPORT iParser: public QObject, public QuasarAppUtils::iHRO * @brief genPackage This is factory method that generate data pacakge objects by command. * All object should be registered before using this method. * @param cmd This is command of pacakge see Header::command. - * @param ver - This is version of the package - by default is 0 * @return shared pointer to new data object. * @see AbstractNode::registerPackageType * @see Header::command */ - QSharedPointer genPackage(unsigned short cmd, unsigned short ver = 0) const; + QSharedPointer genPackage(unsigned short cmd) const; /** * @brief checkCommand This method check command are if registered type or not. * @brief cmd This is command of a verifiable package. * @return True if the package is registered in a node. */ - bool checkCommand(unsigned short cmd, unsigned short ver = 0) const; + bool checkCommand(unsigned short cmd) const; /** * @brief parserId This is id of the parsers. All parser will be synced betwin nodes by ids. @@ -231,8 +233,7 @@ class HEARTSHARED_EXPORT iParser: public QObject, public QuasarAppUtils::iHRO * @brief multiVersionPackages return list of the supported multiversions packages. * @return list of the supported multiversions packages. */ - const PackagesVersionData& multiVersionPackages() const; - + const PackagesVersionData &multiVersionPackages() const; protected: AbstractNode *node() const; diff --git a/src/public/package.cpp b/src/public/package.cpp index 24e503c..4b7d186 100644 --- a/src/public/package.cpp +++ b/src/public/package.cpp @@ -27,10 +27,7 @@ bool Package::isValid() const { if (hdr.size > maximumSize()) return false; - if (calcHash() == hdr.hash) - return true; - - return calcHashOld() == hdr.hash; + return calcHash() == hdr.hash; } void Package::reset() { @@ -49,10 +46,6 @@ unsigned int Package::calcHash() const { return qa_common::hash32(tmp.constData(), tmp.size()); } -unsigned int Package::calcHashOld() const { - return qHash(data + QByteArray::number(hdr.command)); -} - unsigned int Package::maximumSize() { return 1024 * 1024; } diff --git a/src/public/package.h b/src/public/package.h index 50daa6d..b1e6327 100644 --- a/src/public/package.h +++ b/src/public/package.h @@ -59,13 +59,6 @@ class HEARTSHARED_EXPORT Package: public StreamBase { */ unsigned int calcHash() const; - - /** - * @brief calcHash This method recalc hash sum for this pacakge. - * @return int32 hash of pacakge. - */ - unsigned int calcHashOld() const; - /** * @brief maximumSize This method return maximu size of pacakge. If pacakge large the maximum size then package will separate to BigDataPart in sending. * @return size in bytes of pacakge. diff --git a/src/public/packages/abstractdata.cpp b/src/public/packages/abstractdata.cpp index c7456ee..cb9ab6a 100644 --- a/src/public/packages/abstractdata.cpp +++ b/src/public/packages/abstractdata.cpp @@ -30,15 +30,11 @@ bool AbstractData::toPackage(Package &package, package.data = toBytesOf(reqVersion); package.hdr.command = cmd(); - package.hdr.packageVersion = reqVersion; package.hdr.triggerHash = triggerHash; package.hdr.size = package.data.size(); - if (isOldPackage()) { - package.hdr.hash = package.calcHashOld(); - } else { - package.hdr.hash = package.calcHash(); - } + package.hdr.hash = package.calcHash(); + return package.isValid(); } @@ -49,10 +45,10 @@ bool AbstractData::isValid() const { QString AbstractData::toString() const { return QString("Type: %0 \n" - "Version: %2 \n" - "Command: %1 \n"). - arg(cmdString()). - arg(cmd()).arg(ver()); + "Version: %1 \n" + "Command: %2 \n"). + arg(cmdString(), packageVersion().toString()). + arg(cmd()); } void AbstractData::fromPakcage(const Package &pkg) { @@ -72,7 +68,7 @@ QByteArray AbstractData::toBytesOf(unsigned short reqVersion) const { } QDataStream &AbstractData::toStreamOf(QDataStream &stream, unsigned short version) const { - debug_assert(version == ver(), "from stream should be overload for the multi version packages."); + debug_assert(packageVersion().max() == version, "from stream should be overload for the multi version packages."); return toStream(stream); } @@ -81,10 +77,22 @@ AbstractData::~AbstractData() { } -bool QH::PKG::AbstractData::isOldPackage() const { - return false; +QDataStream &AbstractData::fromStream(QDataStream &stream) { + stream >> _packageVersion; + return stream; +} + +QDataStream &AbstractData::toStream(QDataStream &stream) const { + stream << _packageVersion; + return stream; } +const DistVersion &AbstractData::packageVersion() const { + return _packageVersion; +} +void AbstractData::setPackageVersion(const DistVersion &newPackageVersion) { + _packageVersion = newPackageVersion; +} } } diff --git a/src/public/packages/abstractdata.h b/src/public/packages/abstractdata.h index b4572f1..db24f03 100644 --- a/src/public/packages/abstractdata.h +++ b/src/public/packages/abstractdata.h @@ -7,6 +7,7 @@ #ifndef ABSTRACTDATA_H #define ABSTRACTDATA_H +#include "distversion.h" #include "humanreadableobject.h" #include "package.h" #include @@ -28,40 +29,20 @@ * For get global id use the cmd method. * For get quick access for global command use the ClassName::command() method. This method is static. * @arg S This is unique id of the pacakge. Shold be some on all your network devices. - * @arg V This is version of the package If you do not use multople versions use 0 or QH_PACKAGE_AUTO instand QH_PACKAGE. */ -#define QH_PACKAGE(S, V) \ +#define QH_PACKAGE(S) \ public: \ static unsigned short command(){\ QByteArray ba = QString(S).toLocal8Bit();\ return qa_common::hash16(ba.data(), ba.size());\ } \ static QString commandText(){return S;} \ - static unsigned short version(){ return V; } \ unsigned short cmd() const override {return command();} \ - unsigned short ver() const override {return V;} \ \ QString cmdString() const override {return S;} \ private: -/** - * @brief QH_PACKAGE_AUTO This macross prepare data to send and create a global id for package. - * @arg S This is unique id of the pacakge. shold be some on all your network devices. - * @note auto pacakge create a 0 version of your package. -*/ -#define QH_PACKAGE_AUTO(S) QH_PACKAGE(S, 0) - -/** - * @brief QH_PACKAGE_ONLY_VERSION This macross can be used only if parrent class alredy has QH_PACKAGE macros and int is some pacakge but with new version. - * @arg B This is new version of the package. -*/ -#define QH_PACKAGE_ONLY_VERSION(V) \ -public: \ - static unsigned short version(){ return V; } \ - unsigned short ver() const override {return V;} \ - private: \ - namespace QH { namespace PKG { @@ -112,12 +93,6 @@ class HEARTSHARED_EXPORT AbstractData : public StreamBase, public QuasarAppUtils */ virtual unsigned short cmd() const = 0; - /** - * @brief ver This method should be return number of the pacakge version. - * @return pcakge version. by default return - 0 (any version) - */ - virtual unsigned short ver() const = 0; - /** * @brief cmd - This is command string of this object, (for generate cmd use macross QH_PACKAGE) * @note Use the QH_PACKAGE macross for implement this method. @@ -195,17 +170,29 @@ class HEARTSHARED_EXPORT AbstractData : public StreamBase, public QuasarAppUtils */ virtual QDataStream& toStreamOf(QDataStream& stream, unsigned short version) const; + /** + * @brief packageVersion This method should be return number of the pacakge version. + * @return pcakge version. by default return - 0 (any version) + */ + const DistVersion& packageVersion() const; + + /** + * @brief setPackageVersion This method sets new version of package. + * @param newPackageVersion This is new version value. + */ + void setPackageVersion(const DistVersion& newPackageVersion); + protected: /** * @brief AbstractData - Base constructor of this object. */ explicit AbstractData(); - /** - * @brief isOldPackage This method mark package as a old, old pacakges use the Package::calcHashOld method for calculation hash sum of packages. - * @return true if the pacakge is old. - */ - virtual bool isOldPackage() const; + QDataStream& fromStream(QDataStream& stream) override; + QDataStream& toStream(QDataStream& stream) const override; + +private: + DistVersion _packageVersion; }; diff --git a/src/public/packages/badrequest.cpp b/src/public/packages/badrequest.cpp index 7872265..e7e4e64 100644 --- a/src/public/packages/badrequest.cpp +++ b/src/public/packages/badrequest.cpp @@ -28,6 +28,7 @@ BadRequest::BadRequest(const Package &package): } QDataStream &BadRequest::fromStream(QDataStream &stream) { + AbstractData::fromStream(stream); stream >> _errCode; stream >> _err; diff --git a/src/public/packages/badrequest.h b/src/public/packages/badrequest.h index 51100f6..9a0b316 100644 --- a/src/public/packages/badrequest.h +++ b/src/public/packages/badrequest.h @@ -33,7 +33,7 @@ struct ErrorData { */ class HEARTSHARED_EXPORT BadRequest : public AbstractData { - QH_PACKAGE_AUTO("BadRequest") + QH_PACKAGE("BadRequest") public: /** diff --git a/src/public/packages/bigdatabase.cpp b/src/public/packages/bigdatabase.cpp index ade9296..602305a 100644 --- a/src/public/packages/bigdatabase.cpp +++ b/src/public/packages/bigdatabase.cpp @@ -25,6 +25,8 @@ void BigDataBase::setPackageId(int newPackageId) { } QDataStream &BigDataBase::fromStream(QDataStream &stream) { + AbstractData::fromStream(stream); + stream >> _packageId; return stream; diff --git a/src/public/packages/bigdatabase.h b/src/public/packages/bigdatabase.h index 25d3bd5..1aab29f 100644 --- a/src/public/packages/bigdatabase.h +++ b/src/public/packages/bigdatabase.h @@ -19,7 +19,7 @@ namespace PKG { */ class HEARTSHARED_EXPORT BigDataBase: public AbstractData { - QH_PACKAGE_AUTO("BigDataBase") + QH_PACKAGE("BigDataBase") public: BigDataBase(); diff --git a/src/public/packages/bigdataheader.cpp b/src/public/packages/bigdataheader.cpp index 5ea658f..ac0c46b 100644 --- a/src/public/packages/bigdataheader.cpp +++ b/src/public/packages/bigdataheader.cpp @@ -39,7 +39,6 @@ QDataStream &BigDataHeader::fromStream(QDataStream &stream) { stream >> packagesCount; stream >> _command; - stream >> _version; return stream; } @@ -49,19 +48,10 @@ QDataStream &BigDataHeader::toStream(QDataStream &stream) const { stream << packagesCount; stream << _command; - stream << _version; return stream; } -unsigned short BigDataHeader::pkgVersion() const { - return _version; -} - -void BigDataHeader::setPkgVersion(unsigned short newVersion) { - _version = newVersion; -} - unsigned short BigDataHeader::getCommand() const { return _command; } diff --git a/src/public/packages/bigdataheader.h b/src/public/packages/bigdataheader.h index bfe5f10..c016edd 100644 --- a/src/public/packages/bigdataheader.h +++ b/src/public/packages/bigdataheader.h @@ -27,7 +27,7 @@ namespace PKG { */ class HEARTSHARED_EXPORT BigDataHeader : public BigDataBase { - QH_PACKAGE_AUTO("BigDataHeader") + QH_PACKAGE("BigDataHeader") public: BigDataHeader(); @@ -60,18 +60,6 @@ class HEARTSHARED_EXPORT BigDataHeader : public BigDataBase */ void setCommand(unsigned short newCommand); - /** - * @brief pkgVersion This is version of the moving big data package. - * @return version of the moving big data package. - */ - unsigned short pkgVersion() const; - - /** - * @brief setPkgVersion This method sets new version of bid data package. - * @param newVersion This is new version - */ - void setPkgVersion(unsigned short newVersion); - protected: QDataStream &fromStream(QDataStream &stream) override; QDataStream &toStream(QDataStream &stream) const override; @@ -79,7 +67,6 @@ class HEARTSHARED_EXPORT BigDataHeader : public BigDataBase private: int packagesCount; unsigned short _command = 0; - unsigned short _version = 0; }; } } diff --git a/src/public/packages/bigdatapart.h b/src/public/packages/bigdatapart.h index 2104059..5056bde 100644 --- a/src/public/packages/bigdatapart.h +++ b/src/public/packages/bigdatapart.h @@ -20,7 +20,7 @@ namespace PKG { */ class HEARTSHARED_EXPORT BigDataPart : public BigDataBase { - QH_PACKAGE_AUTO("BigDataPart") + QH_PACKAGE("BigDataPart") public: BigDataPart(); diff --git a/src/public/packages/bigdatarequest.h b/src/public/packages/bigdatarequest.h index 6c9fad7..684c75c 100644 --- a/src/public/packages/bigdatarequest.h +++ b/src/public/packages/bigdatarequest.h @@ -19,7 +19,7 @@ namespace PKG { */ class HEARTSHARED_EXPORT BigDataRequest: public BigDataBase { - QH_PACKAGE_AUTO("BigDataRequest") + QH_PACKAGE("BigDataRequest") public: BigDataRequest(); diff --git a/src/public/packages/bigdatawraper.h b/src/public/packages/bigdatawraper.h index 569a5bd..61b4827 100644 --- a/src/public/packages/bigdatawraper.h +++ b/src/public/packages/bigdatawraper.h @@ -19,7 +19,7 @@ namespace PKG { */ class BigDataWraper: public AbstractData { - QH_PACKAGE_AUTO("BigDataWraper") + QH_PACKAGE("BigDataWraper") public: BigDataWraper() = default; diff --git a/src/public/packages/closeconnection.h b/src/public/packages/closeconnection.h index 8250d92..cdd85c3 100644 --- a/src/public/packages/closeconnection.h +++ b/src/public/packages/closeconnection.h @@ -27,7 +27,7 @@ namespace PKG { */ class HEARTSHARED_EXPORT CloseConnection: public AbstractData { - QH_PACKAGE_AUTO("CloseConnection") + QH_PACKAGE("CloseConnection") public: CloseConnection(); diff --git a/src/public/packages/dbobject.h b/src/public/packages/dbobject.h index 5415425..3e8d4c3 100644 --- a/src/public/packages/dbobject.h +++ b/src/public/packages/dbobject.h @@ -89,7 +89,7 @@ typedef QMap DBVariantMap; */ class HEARTSHARED_EXPORT DBObject : public AbstractData { - QH_PACKAGE("DBObject", 0) + QH_PACKAGE("DBObject") public: diff --git a/src/public/packages/dbobjectset.h b/src/public/packages/dbobjectset.h index 53d542f..2a51ab3 100644 --- a/src/public/packages/dbobjectset.h +++ b/src/public/packages/dbobjectset.h @@ -22,7 +22,7 @@ namespace PKG { */ class HEARTSHARED_EXPORT DBObjectSet: public DBObject { - QH_PACKAGE_AUTO("DBObjectSet") + QH_PACKAGE("DBObjectSet") public: DBObjectSet(const QString table); diff --git a/src/public/packages/deleteobject.cpp b/src/public/packages/deleteobject.cpp index f77ae9c..874836a 100644 --- a/src/public/packages/deleteobject.cpp +++ b/src/public/packages/deleteobject.cpp @@ -43,6 +43,7 @@ bool DeleteObject::fromSqlRecord(const QSqlRecord &q) { } QDataStream &DeleteObject::fromStream(QDataStream &stream) { + AbstractData::fromStream(stream); stream >> _address; stream >> _token; diff --git a/src/public/packages/multiversiondata.cpp b/src/public/packages/multiversiondata.cpp new file mode 100644 index 0000000..9eae641 --- /dev/null +++ b/src/public/packages/multiversiondata.cpp @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2023-2023 QuasarApp. + * Distributed under the lgplv3 software license, see the accompanying + * Everyone is permitted to copy and distribute verbatim copies + * of this license document, but changing it is not allowed. +*/ + +#include "multiversiondata.h" + +namespace QH { +namespace PKG { + +MultiversionData::MultiversionData(const QMap& serializers): + _serializers(serializers) {} + +QDataStream &MultiversionData::fromStream(QDataStream &stream) { + AbstractData::fromStream(stream); + + packageVersion(); + + return stream; +} + +QDataStream &MultiversionData::toStream(QDataStream &stream) const { + AbstractData::toStream(stream); + + return stream; +} + +QDataStream &MultiversionData::toStreamOf(QDataStream &stream, unsigned short version) const { + +} +} +} diff --git a/src/public/packages/multiversiondata.h b/src/public/packages/multiversiondata.h new file mode 100644 index 0000000..e439b73 --- /dev/null +++ b/src/public/packages/multiversiondata.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2023-2023 QuasarApp. + * Distributed under the lgplv3 software license, see the accompanying + * Everyone is permitted to copy and distribute verbatim copies + * of this license document, but changing it is not allowed. +*/ + +#ifndef MULTIVERSIONDATA_H +#define MULTIVERSIONDATA_H + +#include "abstractdata.h" + + +namespace QH { +namespace PKG { + +struct SerializationBox { + std::function from; + std::function to; +}; + +/** + * @brief The MultiversionData class This class add support for multiple versions of ne command/package. + * If you need to add support multiple versions make your pakcage class children of the MultiversionData class. + * + * Example: + * + * @code{cpp} + * + * class MyPackage: public MultiversionData { + * MyPackage(): MultiversionData( + * {0, {[](auto stream){ + * // some code from stream for version 0 ; + * return stream; + * },{[](auto stream){ + * // some code to stream for version 0 ; + * return stream; + * }}, + * + * 1, {[](auto stream){ + * // some code from stream for version 1 ; + * return stream; + * },{[](auto stream){ + * // some code to stream for version 1 ; + * return stream; + * }},} + * ){ + * } + * } + * @endcode + * + * @note the default toBytes function of this class will be convert your class using latest version. + */ +class HEARTSHARED_EXPORT MultiversionData: public AbstractData +{ +public: + /** + * @brief MultiversionData main constructor + * @param serializers this is map of the all supported versions. + */ + MultiversionData(const QMap& serializers); + + QDataStream& fromStream(QDataStream& stream) override final; + QDataStream& toStream(QDataStream& stream) const override final; + QDataStream& toStreamOf(QDataStream& stream, unsigned short version) const override final; + +private: + + QMap _serializers; +}; +} +} +#endif // MULTIVERSIONDATA_H diff --git a/src/public/packages/ping.cpp b/src/public/packages/ping.cpp index 308e9bb..ade1916 100644 --- a/src/public/packages/ping.cpp +++ b/src/public/packages/ping.cpp @@ -33,6 +33,8 @@ void Ping::setAnsver(bool ansver) { } QDataStream &Ping::fromStream(QDataStream &stream) { + AbstractData::fromStream(stream); + stream >> _ansver; return stream; diff --git a/src/public/packages/ping.h b/src/public/packages/ping.h index 2d07418..0272af3 100644 --- a/src/public/packages/ping.h +++ b/src/public/packages/ping.h @@ -20,7 +20,7 @@ namespace PKG { */ class HEARTSHARED_EXPORT Ping: public AbstractData { - QH_PACKAGE_AUTO("Ping") + QH_PACKAGE("Ping") public: Ping(); diff --git a/src/public/packages/universaldata.cpp b/src/public/packages/universaldata.cpp index 5584542..44bfcd2 100644 --- a/src/public/packages/universaldata.cpp +++ b/src/public/packages/universaldata.cpp @@ -43,6 +43,8 @@ QVariant *UniversalData::ref(int key) { } QDataStream &UniversalData::fromStream(QDataStream &stream) { + AbstractData::fromStream(stream); + stream >> _data; return stream; diff --git a/src/public/packages/universaldata.h b/src/public/packages/universaldata.h index 85dc2f2..3ff4a11 100644 --- a/src/public/packages/universaldata.h +++ b/src/public/packages/universaldata.h @@ -22,7 +22,7 @@ namespace PKG { * @code{cpp} * class AuthRequest: public QH::PKG::UniversalData { - QH_PACKAGE_AUTO(RC::API::V4::AuthRequest) + QH_PACKAGE(RC::API::V4::AuthRequest) enum Filds{ UserId = 0 From fbeb3d12bac9346dc1dc876b1d014ac0c2659e28 Mon Sep 17 00:00:00 2001 From: EndrII Date: Fri, 26 May 2023 22:39:28 +0200 Subject: [PATCH 15/17] added new tests --- HeartTests/units/bigdatatest.cpp | 2 - HeartTests/units/multiversiontest.cpp | 46 ++++++++---- src/public/abstractnode.cpp | 10 +-- src/public/iparser.h | 17 ++--- src/public/packages/abstractdata.cpp | 42 +---------- src/public/packages/abstractdata.h | 36 +-------- src/public/packages/badrequest.cpp | 2 - src/public/packages/bigdatabase.cpp | 1 - src/public/packages/datapack.h | 2 +- src/public/packages/deleteobject.cpp | 1 - src/public/packages/multiversiondata.cpp | 96 ++++++++++++++++++++++-- src/public/packages/multiversiondata.h | 38 ++++++++-- src/public/packages/ping.cpp | 1 - src/public/packages/universaldata.cpp | 1 - 14 files changed, 169 insertions(+), 126 deletions(-) diff --git a/HeartTests/units/bigdatatest.cpp b/HeartTests/units/bigdatatest.cpp index bc59620..15fdf70 100644 --- a/HeartTests/units/bigdatatest.cpp +++ b/HeartTests/units/bigdatatest.cpp @@ -23,7 +23,6 @@ class BigPackage: public QH::PKG::AbstractData { // StreamBase interface protected: QDataStream &fromStream(QDataStream &stream) override { - AbstractData::fromStream(stream); stream >> data; @@ -31,7 +30,6 @@ class BigPackage: public QH::PKG::AbstractData { }; QDataStream &toStream(QDataStream &stream) const override { - AbstractData::toStream(stream); stream << data; diff --git a/HeartTests/units/multiversiontest.cpp b/HeartTests/units/multiversiontest.cpp index a59b4e8..dcc6a24 100644 --- a/HeartTests/units/multiversiontest.cpp +++ b/HeartTests/units/multiversiontest.cpp @@ -28,25 +28,45 @@ protected slots: QH::PKG::Ping _ping; }; -class MultiVersionPkg: public QH::PKG::AbstractData { +class MultiVersionPkg: public QH::PKG::MultiversionData { QH_PACKAGE("MultiVersionPkg") public: - int v1 = 0; + MultiVersionPkg(): QH::PKG::MultiversionData( + { + {0, // version 0 + { + [this](QDataStream& stream){ // from + stream >> v1; + return stream; + }, + [this](QDataStream& stream){ // to + stream << v1; - // StreamBase interface -protected: - QDataStream &fromStream(QDataStream &stream) override { - AbstractData::fromStream(stream); + return stream; + } + } + }, + {1, // version 1 + { + [this](const QDataStream* stream){ // from + stream >> v1; + stream >> v2; - stream >> v1; - return stream; - }; + return stream; + }, + [this](const QDataStream* stream){ // to + stream << v1; + stream << v2; + return stream; + } + } + } + } + ) {}; + int v1; + int v2; - QDataStream &toStream(QDataStream &stream) const override{ - stream << v1; - return stream; - }; }; MultiVersionTest::MultiVersionTest() { diff --git a/src/public/abstractnode.cpp b/src/public/abstractnode.cpp index eb60794..6729dba 100644 --- a/src/public/abstractnode.cpp +++ b/src/public/abstractnode.cpp @@ -757,18 +757,12 @@ unsigned int AbstractNode::sendData(const PKG::AbstractData *resp, return 0; } - int version = node->multiVersionPackages().value(resp->cmd()). - getMaxCompatible(_apiVersionParser->multiVersionPackages().value(resp->cmd())); - if (version < 0) { - return 0; - } - Package pkg; bool convert = false; if (req && req->isValid()) { - convert = resp->toPackage(pkg, version,req->hash); + convert = resp->toPackage(pkg, node->multiVersionPackages().value(resp->cmd()),req->hash); } else { - convert = resp->toPackage(pkg, version); + convert = resp->toPackage(pkg, node->multiVersionPackages().value(resp->cmd())); } if (!convert) { diff --git a/src/public/iparser.h b/src/public/iparser.h index 3c2d2bc..daaef14 100644 --- a/src/public/iparser.h +++ b/src/public/iparser.h @@ -12,16 +12,13 @@ #include "distversion.h" #include "hostaddress.h" #include -#include +#include namespace QH { class AbstractNodeInfo; class AbstractNode; -namespace PKG { -class AbstractData; -} /** * @brief PacksMap This is hash map where id is command of package and value is factory function. @@ -63,17 +60,15 @@ class HEARTSHARED_EXPORT iParser: public QObject, public QuasarAppUtils::iHRO * @see initSupportedCommands */ void registerPackageType() { - - static_assert(std::is_base_of_v, - "The template type must inheret of the AbstractData class."); - _registeredTypes[T::command()] = [](){ return new T(); }; - T tmp; - if (const DistVersion &distVersion = tmp.packageVersion()) { - _multiVersionPackages[tmp.cmd()] = distVersion; + if constexpr(std::is_base_of_v) { + T tmp; + if (const DistVersion &distVersion = tmp.packageVersion()) { + _multiVersionPackages[tmp.cmd()] = distVersion; + } } }; diff --git a/src/public/packages/abstractdata.cpp b/src/public/packages/abstractdata.cpp index cb9ab6a..d7cc47e 100644 --- a/src/public/packages/abstractdata.cpp +++ b/src/public/packages/abstractdata.cpp @@ -21,14 +21,14 @@ AbstractData::AbstractData() { } bool AbstractData::toPackage(Package &package, - unsigned short reqVersion, + const DistVersion& , unsigned int triggerHash) const { if (!isValid()) { return false; } - package.data = toBytesOf(reqVersion); + package.data = toBytes(); package.hdr.command = cmd(); package.hdr.triggerHash = triggerHash; package.hdr.size = package.data.size(); @@ -45,9 +45,8 @@ bool AbstractData::isValid() const { QString AbstractData::toString() const { return QString("Type: %0 \n" - "Version: %1 \n" - "Command: %2 \n"). - arg(cmdString(), packageVersion().toString()). + "Command: %1 \n"). + arg(cmdString()). arg(cmd()); } @@ -55,44 +54,11 @@ void AbstractData::fromPakcage(const Package &pkg) { fromBytes(pkg.data); } -QByteArray AbstractData::toBytesOf(unsigned short reqVersion) const { - QByteArray res; - QDataStream stream(&res, QIODevice::WriteOnly); - - if (parsingVersion()) { - stream.setVersion(parsingVersion()); - } - - toStreamOf(stream, reqVersion); - return res; -} - -QDataStream &AbstractData::toStreamOf(QDataStream &stream, unsigned short version) const { - debug_assert(packageVersion().max() == version, "from stream should be overload for the multi version packages."); - - return toStream(stream); -} - AbstractData::~AbstractData() { } -QDataStream &AbstractData::fromStream(QDataStream &stream) { - stream >> _packageVersion; - return stream; -} - -QDataStream &AbstractData::toStream(QDataStream &stream) const { - stream << _packageVersion; - return stream; -} -const DistVersion &AbstractData::packageVersion() const { - return _packageVersion; -} -void AbstractData::setPackageVersion(const DistVersion &newPackageVersion) { - _packageVersion = newPackageVersion; -} } } diff --git a/src/public/packages/abstractdata.h b/src/public/packages/abstractdata.h index db24f03..68f3bd3 100644 --- a/src/public/packages/abstractdata.h +++ b/src/public/packages/abstractdata.h @@ -109,7 +109,7 @@ class HEARTSHARED_EXPORT AbstractData : public StreamBase, public QuasarAppUtils * @param triggerHash This is hash of the package the current class is responding to. * @return True if convert to package finished successful. */ - bool toPackage(Package &package, unsigned short reqVersion, unsigned int triggerHash = 0) const; + virtual bool toPackage(Package &package, const DistVersion &reqVersion, unsigned int triggerHash = 0) const; /** * @brief isValid This method check current object to valid. @@ -154,46 +154,12 @@ class HEARTSHARED_EXPORT AbstractData : public StreamBase, public QuasarAppUtils */ static QString commandText(){return "NULL";}; - /** - * @brief toBytesOf This is overload method of StreamBase::toBytes for support multi versions of packages. - * @param version This is required version pacakge. - * @return bytes array for package. - * @note This is just wrapper method for the AbstractData::toStream method. - */ - QByteArray toBytesOf(unsigned short version) const; - - /** - * @brief toStreamOf This overrload of the base toStream method for support the multi version packages. - * @param stream this is stream object. - * @param version this is custom version of parsing function. - * @return stream object. - */ - virtual QDataStream& toStreamOf(QDataStream& stream, unsigned short version) const; - - /** - * @brief packageVersion This method should be return number of the pacakge version. - * @return pcakge version. by default return - 0 (any version) - */ - const DistVersion& packageVersion() const; - - /** - * @brief setPackageVersion This method sets new version of package. - * @param newPackageVersion This is new version value. - */ - void setPackageVersion(const DistVersion& newPackageVersion); - protected: /** * @brief AbstractData - Base constructor of this object. */ explicit AbstractData(); - QDataStream& fromStream(QDataStream& stream) override; - QDataStream& toStream(QDataStream& stream) const override; - -private: - DistVersion _packageVersion; - }; diff --git a/src/public/packages/badrequest.cpp b/src/public/packages/badrequest.cpp index e7e4e64..1a1c5f7 100644 --- a/src/public/packages/badrequest.cpp +++ b/src/public/packages/badrequest.cpp @@ -28,8 +28,6 @@ BadRequest::BadRequest(const Package &package): } QDataStream &BadRequest::fromStream(QDataStream &stream) { - AbstractData::fromStream(stream); - stream >> _errCode; stream >> _err; diff --git a/src/public/packages/bigdatabase.cpp b/src/public/packages/bigdatabase.cpp index 602305a..8b8ad7d 100644 --- a/src/public/packages/bigdatabase.cpp +++ b/src/public/packages/bigdatabase.cpp @@ -25,7 +25,6 @@ void BigDataBase::setPackageId(int newPackageId) { } QDataStream &BigDataBase::fromStream(QDataStream &stream) { - AbstractData::fromStream(stream); stream >> _packageId; diff --git a/src/public/packages/datapack.h b/src/public/packages/datapack.h index 9adb6fa..2096d0f 100644 --- a/src/public/packages/datapack.h +++ b/src/public/packages/datapack.h @@ -24,7 +24,7 @@ namespace PKG { template class DataPack final: public AbstractData { - QH_PACKAGE(Package::commandText() + "Pack", Package::version()) + QH_PACKAGE(Package::commandText() + "Pack") public: diff --git a/src/public/packages/deleteobject.cpp b/src/public/packages/deleteobject.cpp index 874836a..f77ae9c 100644 --- a/src/public/packages/deleteobject.cpp +++ b/src/public/packages/deleteobject.cpp @@ -43,7 +43,6 @@ bool DeleteObject::fromSqlRecord(const QSqlRecord &q) { } QDataStream &DeleteObject::fromStream(QDataStream &stream) { - AbstractData::fromStream(stream); stream >> _address; stream >> _token; diff --git a/src/public/packages/multiversiondata.cpp b/src/public/packages/multiversiondata.cpp index 9eae641..0f3ded0 100644 --- a/src/public/packages/multiversiondata.cpp +++ b/src/public/packages/multiversiondata.cpp @@ -6,29 +6,111 @@ */ #include "multiversiondata.h" +#include "qaglobalutils.h" + +#include namespace QH { namespace PKG { + MultiversionData::MultiversionData(const QMap& serializers): - _serializers(serializers) {} + _serializers(serializers) { + + if (serializers.size()) { + _packageVersion.setMax(serializers.lastKey()); + _packageVersion.setMin(serializers.firstKey()); + } +} QDataStream &MultiversionData::fromStream(QDataStream &stream) { - AbstractData::fromStream(stream); - packageVersion(); + if (!_serializers.size()) { + debug_assert(false, + "Your MultiversionData not support any serialized functions. " + "Please initialize it in constructor of the MultiversionData class."); + return stream; + } + + char* buf = new char[sizeof(magic)]; + stream.readRawData(buf, sizeof(magic)) ; + + unsigned short version = 0; + if (buf == magic) { + stream >> version; + } else { + stream.device()->seek(0); + } - return stream; + delete[] buf; + + return _serializers.value(version).from(stream); } QDataStream &MultiversionData::toStream(QDataStream &stream) const { - AbstractData::toStream(stream); - return stream; + if (!_serializers.size()) { + debug_assert(false, + "Your MultiversionData not support any serialized functions. " + "Please initialize it in constructor of the MultiversionData class."); + return stream; + } + + stream << magic; + stream << _serializers.lastKey(); + + return _serializers.last().to(stream); +} + +QByteArray MultiversionData::toBytesOf(const DistVersion& version) const { + QByteArray res; + QDataStream stream(&res, QIODevice::WriteOnly); + + if (parsingVersion()) { + stream.setVersion(parsingVersion()); + } + + toStreamOf(stream, version); + return res; +} + +QDataStream &MultiversionData::toStreamOf(QDataStream &stream, const DistVersion& version) const { + + auto serializer = _serializers.value(_packageVersion.getMaxCompatible(version), {}); + if (!serializer.to) { + debug_assert(false, + "Your MultiversionData not support the required version serialized functions. " + "Please initialize it in constructor of the MultiversionData class."); + return stream; + } + + stream << magic; + stream << version; + + return serializer.to(stream); } -QDataStream &MultiversionData::toStreamOf(QDataStream &stream, unsigned short version) const { +bool MultiversionData::toPackage(Package &package, + const DistVersion& reqVersion, + unsigned int triggerHash) const { + if (!isValid()) { + return false; + } + package.data = toBytesOf(reqVersion); + package.hdr.command = cmd(); + package.hdr.triggerHash = triggerHash; + package.hdr.size = package.data.size(); + + package.hdr.hash = package.calcHash(); + + + return package.isValid(); } + +const DistVersion &MultiversionData::packageVersion() const { + return _packageVersion; +} + } } diff --git a/src/public/packages/multiversiondata.h b/src/public/packages/multiversiondata.h index e439b73..3785c5b 100644 --- a/src/public/packages/multiversiondata.h +++ b/src/public/packages/multiversiondata.h @@ -15,8 +15,8 @@ namespace QH { namespace PKG { struct SerializationBox { - std::function from; - std::function to; + std::function from = nullptr; + std::function to = nullptr; }; /** @@ -44,7 +44,7 @@ struct SerializationBox { * // some code to stream for version 1 ; * return stream; * }},} - * ){ + * ) { * } * } * @endcode @@ -60,13 +60,41 @@ class HEARTSHARED_EXPORT MultiversionData: public AbstractData */ MultiversionData(const QMap& serializers); + /** + * @brief packageVersion This method should be return number of the pacakge version. + * @return pcakge version. by default return - 0 (any version) + */ + const DistVersion& packageVersion() const; + QDataStream& fromStream(QDataStream& stream) override final; QDataStream& toStream(QDataStream& stream) const override final; - QDataStream& toStreamOf(QDataStream& stream, unsigned short version) const override final; -private: + /** + * @brief toBytesOf This is overload method of StreamBase::toBytes for support multi versions of packages. + * @param version This is required version pacakge. + * @return bytes array for package. + * @note This is just wrapper method for the AbstractData::toStream method. + */ + QByteArray toBytesOf(const DistVersion &version) const; + /** + * @brief toStreamOf This overrload of the base toStream method for support the multi version packages. + * @param stream this is stream object. + * @param version this is custom version of parsing function. + * @return stream object. + */ + QDataStream& toStreamOf(QDataStream& stream, const DistVersion &version) const; + + + bool toPackage(Package &package, const DistVersion &reqVersion, unsigned int triggerHash = 0) const override final; + + +private: + DistVersion _packageVersion; QMap _serializers; + + const char* magic = "mVer"; + }; } } diff --git a/src/public/packages/ping.cpp b/src/public/packages/ping.cpp index ade1916..4674561 100644 --- a/src/public/packages/ping.cpp +++ b/src/public/packages/ping.cpp @@ -33,7 +33,6 @@ void Ping::setAnsver(bool ansver) { } QDataStream &Ping::fromStream(QDataStream &stream) { - AbstractData::fromStream(stream); stream >> _ansver; return stream; diff --git a/src/public/packages/universaldata.cpp b/src/public/packages/universaldata.cpp index 44bfcd2..75eda2b 100644 --- a/src/public/packages/universaldata.cpp +++ b/src/public/packages/universaldata.cpp @@ -43,7 +43,6 @@ QVariant *UniversalData::ref(int key) { } QDataStream &UniversalData::fromStream(QDataStream &stream) { - AbstractData::fromStream(stream); stream >> _data; From 682feb1ce86d124317d2ac19a121bd5b78cdcd43 Mon Sep 17 00:00:00 2001 From: EndrII Date: Sat, 27 May 2023 21:40:43 +0200 Subject: [PATCH 16/17] added test (still failed) --- HeartTests/tst_testprotockol.cpp | 3 + HeartTests/units/multiversiontest.cpp | 205 ++++++++++++++++++++++--- src/private/apiversion.cpp | 1 - src/public/packages/multiversiondata.h | 51 +++--- 4 files changed, 217 insertions(+), 43 deletions(-) diff --git a/HeartTests/tst_testprotockol.cpp b/HeartTests/tst_testprotockol.cpp index ac8afb5..2a105d8 100644 --- a/HeartTests/tst_testprotockol.cpp +++ b/HeartTests/tst_testprotockol.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #define TestCase(name, testClass) \ void name() { \ @@ -39,6 +40,8 @@ private slots: #endif TestCase(upgradeDataBaseTest, UpgradeDataBaseTest) + TestCase(multiVersionTest, MultiVersionTest) + // END TEST CASES diff --git a/HeartTests/units/multiversiontest.cpp b/HeartTests/units/multiversiontest.cpp index dcc6a24..6454133 100644 --- a/HeartTests/units/multiversiontest.cpp +++ b/HeartTests/units/multiversiontest.cpp @@ -7,40 +7,68 @@ #include "multiversiontest.h" -class TestingClient: public QH::AbstractNode { - - // AbstractNode interface +class MultiVersionPkg { public: - const QH::PKG::Ping& getPing() const { - return _ping; - } + int v2; + int v1; + int lastSerializedFrom = 0; + int lastSerializedto = 0; +}; - NodeType nodeType() const override { - return NodeType::Node; - }; +class MultiVersionPkg1: public QH::PKG::MultiversionData, public MultiVersionPkg { + QH_PACKAGE("MultiVersionPkg") -protected slots: - void receivePing(const QSharedPointer& ping) override { - _ping = *ping; - }; +public: + MultiVersionPkg1(): QH::PKG::MultiversionData( + { + {0, // version 0 + { + [this](QDataStream& stream) -> QDataStream&{ // from + stream >> v1; + return stream; + }, + [this](QDataStream& stream) -> QDataStream&{ // to + stream << v1; -private: - QH::PKG::Ping _ping; + return stream; + } + } + }, + {1, // version 1 + { + [this](QDataStream& stream) -> QDataStream&{ // from + stream >> v1; + stream >> v2; + + return stream; + }, + [this](QDataStream& stream) -> QDataStream&{ // to + stream << v1; + stream << v2; + return stream; + } + } + } + } + ) {}; }; -class MultiVersionPkg: public QH::PKG::MultiversionData { +class MultiVersionPkg2: public QH::PKG::MultiversionData, public MultiVersionPkg { QH_PACKAGE("MultiVersionPkg") public: - MultiVersionPkg(): QH::PKG::MultiversionData( + MultiVersionPkg2(): QH::PKG::MultiversionData( { {0, // version 0 { - [this](QDataStream& stream){ // from + [this](QDataStream& stream) -> QDataStream&{ // from + lastSerializedFrom = 0; stream >> v1; return stream; }, - [this](QDataStream& stream){ // to + [this](QDataStream& stream) -> QDataStream&{ // to + lastSerializedto = 0; + stream << v1; return stream; @@ -49,14 +77,35 @@ class MultiVersionPkg: public QH::PKG::MultiversionData { }, {1, // version 1 { - [this](const QDataStream* stream){ // from + [this](QDataStream& stream) -> QDataStream&{ // from + lastSerializedFrom = 1; + stream >> v1; stream >> v2; return stream; }, - [this](const QDataStream* stream){ // to + [this](QDataStream& stream) -> QDataStream&{ // to + lastSerializedto = 1; + stream << v1; + stream << v2; + return stream; + } + } + }, + {2, // version 2 + { + [this](QDataStream& stream) -> QDataStream&{ // from + lastSerializedFrom = 2; + + stream >> v2; + + return stream; + }, + [this](QDataStream& stream) -> QDataStream&{ // to + lastSerializedto = 2; + stream << v2; return stream; } @@ -64,9 +113,64 @@ class MultiVersionPkg: public QH::PKG::MultiversionData { } } ) {}; - int v1; - int v2; +}; + +template +class TestAPI: public QH::iParser { +public: + TestAPI(QH::AbstractNode* parentNode): QH::iParser(parentNode) { + registerPackageType(); + } + + // iParser interface +public: + + QH::ParserResult parsePackage(const QSharedPointer &pkg, + const QH::Header &, + QH::AbstractNodeInfo *) override { + + if (pkg->cmd() == Base::command()) { + data = pkg; + return QH::ParserResult::Processed; + } + + return QH::ParserResult::NotProcessed; + }; + int version() const override {return 0;}; + QString parserId() const override {return "BigDataTestParser";}; + + QSharedPointer getData() const{ + return data; + }; + +private: + QSharedPointer data = nullptr; + +}; + +template +class TestingClient: public QH::AbstractNode { + + // AbstractNode interface +public: + TestingClient() { + _parser = addApiParser>(); + } + bool sendRequest(const Base& data, int port) { + return sendData(&data, QH::HostAddress(TEST_LOCAL_HOST, port)); + } + + NodeType nodeType() const override { + return NodeType::Node; + }; + + const QSharedPointer& parser() const { + return _parser; + } + +private: + QSharedPointer _parser; }; MultiVersionTest::MultiVersionTest() { @@ -75,4 +179,59 @@ MultiVersionTest::MultiVersionTest() { void MultiVersionTest::test() { + TestingClient nodeWithV1; + TestingClient nodeWithV2; + + int nodev1Port = TEST_PORT + 5; + int nodev2Port = TEST_PORT + 6; + + QVERIFY(nodeWithV1.run(TEST_LOCAL_HOST, nodev1Port)); + QVERIFY(nodeWithV2.run(TEST_LOCAL_HOST, nodev2Port)); + + // from new to old + { + MultiVersionPkg2 pkg; + pkg.v1 = 10; + pkg.v2 = 20; + + QVERIFY(nodeWithV2.sendRequest(pkg, nodev1Port)); + + // should use the maximum available serialization. it is 1 + QVERIFY(pkg.lastSerializedto == 1); + + QVERIFY(wait([&nodeWithV1](){ + return nodeWithV1.parser().staticCast>()-> + getData().staticCast()->lastSerializedFrom == 1; + }, WAIT_RESPOCE_TIME)); + + auto data = nodeWithV1.parser().staticCast>()-> + getData().staticCast(); + + QVERIFY(data->v1 == pkg.v1); + QVERIFY(data->v2 == pkg.v2); + } + + // from old to new + + { + MultiVersionPkg1 pkg; + pkg.v1 = 10; + pkg.v2 = 20; + + QVERIFY(nodeWithV1.sendRequest(pkg, nodev1Port)); + + // should use the maximum available serialization. it is 1 + QVERIFY(pkg.lastSerializedto == 1); + + QVERIFY(wait([&nodeWithV2](){ + return nodeWithV2.parser().staticCast>()-> + getData().staticCast()->lastSerializedFrom == 1; + }, WAIT_RESPOCE_TIME)); + + auto data = nodeWithV2.parser().staticCast>()-> + getData().staticCast(); + + QVERIFY(data->v1 == pkg.v1); + QVERIFY(data->v2 == pkg.v2); + } } diff --git a/src/private/apiversion.cpp b/src/private/apiversion.cpp index ad3e75f..51ccfd1 100644 --- a/src/private/apiversion.cpp +++ b/src/private/apiversion.cpp @@ -16,7 +16,6 @@ APIVersion::APIVersion() { } QDataStream &APIVersion::fromStream(QDataStream &stream) { - AbstractData::fromStream(stream); stream >> _apisVersions; stream >> _packagesVersions; diff --git a/src/public/packages/multiversiondata.h b/src/public/packages/multiversiondata.h index 3785c5b..bde71a4 100644 --- a/src/public/packages/multiversiondata.h +++ b/src/public/packages/multiversiondata.h @@ -28,25 +28,38 @@ struct SerializationBox { * @code{cpp} * * class MyPackage: public MultiversionData { - * MyPackage(): MultiversionData( - * {0, {[](auto stream){ - * // some code from stream for version 0 ; - * return stream; - * },{[](auto stream){ - * // some code to stream for version 0 ; - * return stream; - * }}, - * - * 1, {[](auto stream){ - * // some code from stream for version 1 ; - * return stream; - * },{[](auto stream){ - * // some code to stream for version 1 ; - * return stream; - * }},} - * ) { - * } - * } + MyPackage(): QH::PKG::MultiversionData( + { + {0, // version 0 + { + [this](QDataStream& stream) -> QDataStream&{ // from + stream >> v1; + return stream; + }, + [this](QDataStream& stream) -> QDataStream&{ // to + stream << v1; + + return stream; + } + } + }, + {1, // version 1 + { + [this](QDataStream& stream) -> QDataStream&{ // from + stream >> v1; + stream >> v2; + + return stream; + }, + [this](QDataStream& stream) -> QDataStream&{ // to + stream << v1; + stream << v2; + return stream; + } + } + } + } + ) {}; * @endcode * * @note the default toBytes function of this class will be convert your class using latest version. From 12e11650bb46b83eb1a72e3928984cea52114c96 Mon Sep 17 00:00:00 2001 From: EndrII Date: Sun, 28 May 2023 12:33:55 +0200 Subject: [PATCH 17/17] fix tests --- HeartTests/units/multiversiontest.cpp | 231 +++++++++++++++++------ HeartTests/units/multiversiontest.h | 10 + src/public/packages/multiversiondata.cpp | 20 +- src/public/packages/multiversiondata.h | 1 - 4 files changed, 198 insertions(+), 64 deletions(-) diff --git a/HeartTests/units/multiversiontest.cpp b/HeartTests/units/multiversiontest.cpp index 6454133..8930c35 100644 --- a/HeartTests/units/multiversiontest.cpp +++ b/HeartTests/units/multiversiontest.cpp @@ -7,10 +7,13 @@ #include "multiversiontest.h" +#define LOCAL_TEST_PORT TEST_PORT + 6 + class MultiVersionPkg { public: int v2; int v1; + bool responce = false; int lastSerializedFrom = 0; int lastSerializedto = 0; }; @@ -21,36 +24,70 @@ class MultiVersionPkg1: public QH::PKG::MultiversionData, public MultiVersionPkg public: MultiVersionPkg1(): QH::PKG::MultiversionData( { - {0, // version 0 - { - [this](QDataStream& stream) -> QDataStream&{ // from - stream >> v1; - return stream; - }, - [this](QDataStream& stream) -> QDataStream&{ // to - stream << v1; + {0, // version 0 + { + [this](QDataStream& stream) -> QDataStream&{ // from + lastSerializedFrom = 0; + stream >> v1; + stream >> responce; + + return stream; + }, + [this](QDataStream& stream) -> QDataStream&{ // to + lastSerializedto = 0; + + stream << v1; + stream << responce; + + return stream; + } + } + }, + {1, // version 1 + { + [this](QDataStream& stream) -> QDataStream&{ // from + lastSerializedFrom = 1; + + stream >> v1; + stream >> responce; + + stream >> v2; + + return stream; + }, + [this](QDataStream& stream) -> QDataStream&{ // to + lastSerializedto = 1; + + stream << v1; + stream << responce; + + stream << v2; + return stream; + } + } + }, + } + ) {}; +}; - return stream; - } - } - }, - {1, // version 1 - { - [this](QDataStream& stream) -> QDataStream&{ // from - stream >> v1; - stream >> v2; +class SingleVersionPkg: public QH::PKG::AbstractData, public MultiVersionPkg { + QH_PACKAGE("MultiVersionPkg") - return stream; - }, - [this](QDataStream& stream) -> QDataStream&{ // to - stream << v1; - stream << v2; - return stream; - } - } - } - } - ) {}; + // StreamBase interface +protected: + QDataStream &fromStream(QDataStream &stream) override { + lastSerializedFrom = 0; + stream >> v1; + stream >> responce; + + return stream; + }; + QDataStream &toStream(QDataStream &stream) const override { + stream << v1; + stream << responce; + + return stream; + }; }; class MultiVersionPkg2: public QH::PKG::MultiversionData, public MultiVersionPkg { @@ -64,12 +101,15 @@ class MultiVersionPkg2: public QH::PKG::MultiversionData, public MultiVersionPkg [this](QDataStream& stream) -> QDataStream&{ // from lastSerializedFrom = 0; stream >> v1; + stream >> responce; + return stream; }, [this](QDataStream& stream) -> QDataStream&{ // to lastSerializedto = 0; stream << v1; + stream << responce; return stream; } @@ -78,9 +118,11 @@ class MultiVersionPkg2: public QH::PKG::MultiversionData, public MultiVersionPkg {1, // version 1 { [this](QDataStream& stream) -> QDataStream&{ // from - lastSerializedFrom = 1; + lastSerializedFrom = 1; stream >> v1; + stream >> responce; + stream >> v2; return stream; @@ -89,6 +131,8 @@ class MultiVersionPkg2: public QH::PKG::MultiversionData, public MultiVersionPkg lastSerializedto = 1; stream << v1; + stream << responce; + stream << v2; return stream; } @@ -100,6 +144,7 @@ class MultiVersionPkg2: public QH::PKG::MultiversionData, public MultiVersionPkg lastSerializedFrom = 2; stream >> v2; + stream >> responce; return stream; }, @@ -107,6 +152,8 @@ class MultiVersionPkg2: public QH::PKG::MultiversionData, public MultiVersionPkg lastSerializedto = 2; stream << v2; + stream << responce; + return stream; } } @@ -126,11 +173,19 @@ class TestAPI: public QH::iParser { public: QH::ParserResult parsePackage(const QSharedPointer &pkg, - const QH::Header &, - QH::AbstractNodeInfo *) override { + const QH::Header &hdr, + QH::AbstractNodeInfo *sender) override { if (pkg->cmd() == Base::command()) { data = pkg; + + if (!data.dynamicCast()->responce) { + data.dynamicCast()->responce = true; + if (!sendData(pkg.data(), sender, &hdr)) { + return QH::ParserResult::Error; + } + } + return QH::ParserResult::Processed; } @@ -143,6 +198,10 @@ class TestAPI: public QH::iParser { return data; }; + void dropData() { + data = nullptr; + }; + private: QSharedPointer data = nullptr; @@ -174,64 +233,128 @@ class TestingClient: public QH::AbstractNode { }; MultiVersionTest::MultiVersionTest() { + _nodeV1 = new TestingClient; + _nodeV2 = new TestingClient; + _nodeOld = new TestingClient; + +} + +MultiVersionTest::~MultiVersionTest() { + _nodeV1->softDelete(); + _nodeV2->softDelete(); + _nodeOld->softDelete(); } void MultiVersionTest::test() { + QVERIFY(_nodeV1->run(TEST_LOCAL_HOST, LOCAL_TEST_PORT)); - TestingClient nodeWithV1; - TestingClient nodeWithV2; + QVERIFY(connectFunc(_nodeV2, TEST_LOCAL_HOST, LOCAL_TEST_PORT)); + QVERIFY(connectFunc(_nodeOld, TEST_LOCAL_HOST, LOCAL_TEST_PORT)); - int nodev1Port = TEST_PORT + 5; - int nodev2Port = TEST_PORT + 6; + testMultipacakges(); + testSinglePackages(); +} - QVERIFY(nodeWithV1.run(TEST_LOCAL_HOST, nodev1Port)); - QVERIFY(nodeWithV2.run(TEST_LOCAL_HOST, nodev2Port)); +void MultiVersionTest::testMultipacakges() { + auto nodeWithV1 = dynamic_cast*>(_nodeV1); + auto nodeWithV2 = dynamic_cast*>(_nodeV2); + + // clean old data; + nodeWithV1->parser().staticCast>()->dropData(); + nodeWithV2->parser().staticCast>()->dropData(); // from new to old { + + // initialize test values. MultiVersionPkg2 pkg; pkg.v1 = 10; pkg.v2 = 20; - QVERIFY(nodeWithV2.sendRequest(pkg, nodev1Port)); + // send test values into dist node + QVERIFY(nodeWithV2->sendRequest(pkg, LOCAL_TEST_PORT)); // should use the maximum available serialization. it is 1 QVERIFY(pkg.lastSerializedto == 1); - QVERIFY(wait([&nodeWithV1](){ - return nodeWithV1.parser().staticCast>()-> - getData().staticCast()->lastSerializedFrom == 1; + // wait for receive packge on distanation node + QVERIFY(wait([&nodeWithV1]() { + if (auto data = nodeWithV1->parser().staticCast>()-> + getData().staticCast()) { + return data->lastSerializedFrom == 1; + } + return false; + }, WAIT_RESPOCE_TIME)); - auto data = nodeWithV1.parser().staticCast>()-> - getData().staticCast(); + // wait for package on sender node. + QVERIFY(wait([&nodeWithV2]() { + if (auto data = nodeWithV2->parser().staticCast>()-> + getData().staticCast()) { + return data->responce == true; + } + return false; + + }, WAIT_RESPOCE_TIME)); + + // chec data all data should not be changed. + auto data = nodeWithV2->parser().staticCast>()-> + getData().staticCast(); QVERIFY(data->v1 == pkg.v1); QVERIFY(data->v2 == pkg.v2); } +} + +void MultiVersionTest::testSinglePackages() { + auto nodeWithSingle = dynamic_cast*>(_nodeOld); + auto nodeWithV1 = dynamic_cast*>(_nodeV1); - // from old to new + // clean old data; + nodeWithSingle->parser().staticCast>()->dropData(); + nodeWithV1->parser().staticCast>()->dropData(); + + // from single package to new { - MultiVersionPkg1 pkg; + // initialize test values. + SingleVersionPkg pkg; pkg.v1 = 10; pkg.v2 = 20; - QVERIFY(nodeWithV1.sendRequest(pkg, nodev1Port)); + // send test values into dist node + QVERIFY(nodeWithSingle->sendRequest(pkg, LOCAL_TEST_PORT)); - // should use the maximum available serialization. it is 1 - QVERIFY(pkg.lastSerializedto == 1); + // should use the maximum available serialization. it is 0 + QVERIFY(pkg.lastSerializedto == 0); + + // wait for receive packge on distanation node + QVERIFY(wait([&nodeWithV1]() { + if (auto data = nodeWithV1->parser().staticCast>()-> + getData().staticCast()) { + return data->lastSerializedFrom == 0; + } + return false; - QVERIFY(wait([&nodeWithV2](){ - return nodeWithV2.parser().staticCast>()-> - getData().staticCast()->lastSerializedFrom == 1; }, WAIT_RESPOCE_TIME)); - auto data = nodeWithV2.parser().staticCast>()-> - getData().staticCast(); + // wait for package on sender node. + QVERIFY(wait([&nodeWithSingle]() { + if (auto data = nodeWithSingle->parser().staticCast>()-> + getData().staticCast()) { + return data->responce == true; + } + return false; + + }, WAIT_RESPOCE_TIME)); + + // chec data all data should not be changed. + auto data = nodeWithSingle->parser().staticCast>()-> + getData().staticCast(); QVERIFY(data->v1 == pkg.v1); - QVERIFY(data->v2 == pkg.v2); + // v2 is not supported on the v0 parser + QVERIFY(data->v2 == 0); } } diff --git a/HeartTests/units/multiversiontest.h b/HeartTests/units/multiversiontest.h index 8136cb9..ac5c5f4 100644 --- a/HeartTests/units/multiversiontest.h +++ b/HeartTests/units/multiversiontest.h @@ -22,7 +22,17 @@ class MultiVersionTest: public Test, protected TestUtils { public: MultiVersionTest(); + ~MultiVersionTest(); void test(); +protected: + + void testMultipacakges(); + void testSinglePackages(); + +private: + QH::AbstractNode *_nodeV1 = nullptr; + QH::AbstractNode *_nodeV2 = nullptr; + QH::AbstractNode *_nodeOld = nullptr; }; diff --git a/src/public/packages/multiversiondata.cpp b/src/public/packages/multiversiondata.cpp index 0f3ded0..b8d4e6a 100644 --- a/src/public/packages/multiversiondata.cpp +++ b/src/public/packages/multiversiondata.cpp @@ -13,6 +13,7 @@ namespace QH { namespace PKG { +#define MAGIC "mver" MultiversionData::MultiversionData(const QMap& serializers): _serializers(serializers) { @@ -32,18 +33,16 @@ QDataStream &MultiversionData::fromStream(QDataStream &stream) { return stream; } - char* buf = new char[sizeof(magic)]; - stream.readRawData(buf, sizeof(magic)) ; + QByteArray magic; + stream >> magic; unsigned short version = 0; - if (buf == magic) { + if (magic == MAGIC) { stream >> version; } else { stream.device()->seek(0); } - delete[] buf; - return _serializers.value(version).from(stream); } @@ -56,7 +55,7 @@ QDataStream &MultiversionData::toStream(QDataStream &stream) const { return stream; } - stream << magic; + stream << QByteArray{MAGIC}; stream << _serializers.lastKey(); return _serializers.last().to(stream); @@ -76,7 +75,8 @@ QByteArray MultiversionData::toBytesOf(const DistVersion& version) const { QDataStream &MultiversionData::toStreamOf(QDataStream &stream, const DistVersion& version) const { - auto serializer = _serializers.value(_packageVersion.getMaxCompatible(version), {}); + unsigned short ver = _packageVersion.getMaxCompatible(version); + auto serializer = _serializers.value(ver, {}); if (!serializer.to) { debug_assert(false, "Your MultiversionData not support the required version serialized functions. " @@ -84,8 +84,10 @@ QDataStream &MultiversionData::toStreamOf(QDataStream &stream, const DistVersion return stream; } - stream << magic; - stream << version; + if (ver) { + stream << QByteArray{MAGIC}; + stream << ver; + } return serializer.to(stream); } diff --git a/src/public/packages/multiversiondata.h b/src/public/packages/multiversiondata.h index bde71a4..ce62f0c 100644 --- a/src/public/packages/multiversiondata.h +++ b/src/public/packages/multiversiondata.h @@ -106,7 +106,6 @@ class HEARTSHARED_EXPORT MultiversionData: public AbstractData DistVersion _packageVersion; QMap _serializers; - const char* magic = "mVer"; }; }