From 03b56e8b6cde8fa24aa2a49e1c282e649f2a09e2 Mon Sep 17 00:00:00 2001 From: Leonid Pospelov Date: Tue, 23 Jul 2024 16:34:47 +0500 Subject: [PATCH] WIP --- .../database_drivers/MongoDatabase.cpp | 136 +++++++++++++++++- 1 file changed, 131 insertions(+), 5 deletions(-) diff --git a/skymp5-server/cpp/server_guest_lib/database_drivers/MongoDatabase.cpp b/skymp5-server/cpp/server_guest_lib/database_drivers/MongoDatabase.cpp index c08c6ecf5d..ee904ec714 100644 --- a/skymp5-server/cpp/server_guest_lib/database_drivers/MongoDatabase.cpp +++ b/skymp5-server/cpp/server_guest_lib/database_drivers/MongoDatabase.cpp @@ -1,7 +1,7 @@ #include "MongoDatabase.h" #include "JsonUtils.h" - +#include "ScopedTask.h" #include #include #include @@ -12,13 +12,139 @@ #include #include #include - -#include - #include +#include #include +#include +#include -#include "ScopedTask.h" +namespace { +std::string BytesToHex(const uint8_t* bytes, size_t length) +{ + std::ostringstream hexStream; + hexStream << std::hex << std::setfill('0'); + for (size_t i = 0; i < length; ++i) { + hexStream << std::setw(2) << static_cast(bytes[i]); + } + return hexStream.str(); +} + +std::string GetSha256Hash(const std::string& input) +{ + unsigned char hash[SHA256_DIGEST_LENGTH]; + SHA256_CTX sha256; + SHA256_Init(&sha256); + SHA256_Update(&sha256, input.c_str(), input.size()); + SHA256_Final(hash, &sha256); + return BytesToHex(hash, SHA256_DIGEST_LENGTH); +} + +// std::string PushVersionHash(std::function getCurrentHash, +// const std::string& versionToAdd) +// { +// GetSha256Hash(getCurrentHash() + versionToAdd); +// } + +class IVersionHashStore +{ +public: + virtual ~IVersionHashStore() = default; + + void PushVersionHash(const std::string& versionToAdd) + { + auto currentHash = GetVersionHash(); + SetVersionHash(GetSha256Hash(currentHash + versionToAdd)); + } + +protected: + virtual std::string GetVersionHash() = 0; + virtual void SetVersionHash(const std::string& newVersionHash) = 0; +}; + +class RedisTransactionVersionHashStore : public IVersionHashStore +{ +public: + explicit RedisTransactionVersionHashStore( + std::shared_ptr transaction_) + : transaction(transaction_) + { + // TODO + } + + std::string GetVersionHash() override { return transaction->get("version"); } + + void SetVersionHash(const std::string& newVersionHash) override {} + +private: + std::shared_ptr transaction; +}; + +class MongodbTransactionVersionHashStore : public IVersionHashStore +{ +public: + explicit MongodbTransactionVersionHashStore( + const std::shared_ptr& session_, + const std::string& versionCollectionName_, + const std::shared_ptr& versionCollection_) + : session(session_) + , versionCollectionName(versionCollectionName_) + , versionCollection(versionCollection_) + { + } + + std::string GetVersionHash() override + { + std::optional document = + versionCollection->find_one({}); + + if (!document) { + spdlog::trace("MongodbTransactionVersionHashStore::GetVersionHash - " + "No version document found"); + return "0"; + } + + auto view = document->view(); + auto it = view.find("version"); + + if (it == view.end()) { + spdlog::trace("MongodbTransactionVersionHashStore::GetVersionHash - " + "No version field found"); + return "0"; + } + + if (it->type() != bsoncxx::type::k_string) { + spdlog::trace("MongodbTransactionVersionHashStore::GetVersionHash - " + "Version field is not a string"); + return "0"; + } + + std::string result = it->get_utf8().value.data(); + + spdlog::trace("MongodbTransactionVersionHashStore::GetVersionHash - " + "Version: {}", + result); + + return result; + } + + void SetVersionHash(const std::string& newVersionHash) override + { + versionCollection->update_one( + {}, + bsoncxx::builder::stream::document{} + << "$set" << bsoncxx::builder::stream::open_document << "version" + << newVersionHash << bsoncxx::builder::stream::close_document + << bsoncxx::builder::stream::finalize, + mongocxx::options::update().upsert(true)); + } + +private: + const std::shared_ptr session; + const std::string versionCollectionName; + std::shared_ptr versionCollection; +}; + +} namespace { template