diff --git a/services/backup/src/Constants.h b/services/backup/src/Constants.h index 5aea75fae..8711dcea3 100644 --- a/services/backup/src/Constants.h +++ b/services/backup/src/Constants.h @@ -1,22 +1,23 @@ #pragma once +#include "GlobalTools.h" #include "Tools.h" #include namespace comm { namespace network { const std::string LOG_TABLE_NAME = decorateTableName("backup-service-log"); const std::string BACKUP_TABLE_NAME = decorateTableName("backup-service-backup"); // This has to be smaller than GRPC_CHUNK_SIZE_LIMIT because we need to // recognize if we may receive multiple chunks or just one. If it was larger // than the chunk limit, once we get the amount of data of size equal to the // limit, we wouldn't know if we should put this in the database right away or // wait for more data. const size_t LOG_DATA_SIZE_DATABASE_LIMIT = 1 * 1024 * 1024; } // namespace network } // namespace comm diff --git a/services/backup/src/DatabaseManager.cpp b/services/backup/src/DatabaseManager.cpp index fe9b82cf9..b2fa94009 100644 --- a/services/backup/src/DatabaseManager.cpp +++ b/services/backup/src/DatabaseManager.cpp @@ -1,184 +1,185 @@ #include "DatabaseManager.h" #include "Constants.h" +#include "GlobalTools.h" #include "Tools.h" #include #include #include #include #include namespace comm { namespace network { namespace database { DatabaseManager &DatabaseManager::getInstance() { static DatabaseManager instance; return instance; } void DatabaseManager::innerPutItem( std::shared_ptr item, const Aws::DynamoDB::Model::PutItemRequest &request) { const Aws::DynamoDB::Model::PutItemOutcome outcome = getDynamoDBClient()->PutItem(request); if (!outcome.IsSuccess()) { throw std::runtime_error(outcome.GetError().GetMessage()); } } void DatabaseManager::innerRemoveItem(const Item &item) { Aws::DynamoDB::Model::DeleteItemRequest request; request.SetTableName(item.getTableName()); PrimaryKey pk = item.getPrimaryKey(); PrimaryKeyValue primaryKeyValue = item.getPrimaryKeyValue(); request.AddKey( pk.partitionKey, Aws::DynamoDB::Model::AttributeValue(primaryKeyValue.partitionKey)); if (pk.sortKey != nullptr && primaryKeyValue.sortKey != nullptr) { request.AddKey( *pk.sortKey, Aws::DynamoDB::Model::AttributeValue(*primaryKeyValue.sortKey)); } const Aws::DynamoDB::Model::DeleteItemOutcome &outcome = getDynamoDBClient()->DeleteItem(request); if (!outcome.IsSuccess()) { throw std::runtime_error(outcome.GetError().GetMessage()); } } void DatabaseManager::putBackupItem(const BackupItem &item) { Aws::DynamoDB::Model::PutItemRequest request; request.SetTableName(BackupItem::tableName); request.AddItem( BackupItem::FIELD_USER_ID, Aws::DynamoDB::Model::AttributeValue(item.getUserID())); request.AddItem( BackupItem::FIELD_CREATED, Aws::DynamoDB::Model::AttributeValue( std::to_string(getCurrentTimestamp()))); request.AddItem( BackupItem::FIELD_BACKUP_ID, Aws::DynamoDB::Model::AttributeValue(item.getBackupID())); request.AddItem( BackupItem::FIELD_RECOVERY_DATA, Aws::DynamoDB::Model::AttributeValue(item.getRecoveryData())); request.AddItem( BackupItem::FIELD_COMPACTION_HOLDER, Aws::DynamoDB::Model::AttributeValue(item.getCompactionHolder())); if (!item.getAttachmentHolders().empty()) { request.AddItem( BackupItem::FIELD_ATTACHMENT_HOLDERS, Aws::DynamoDB::Model::AttributeValue(item.getAttachmentHolders())); } this->innerPutItem(std::make_shared(item), request); } std::shared_ptr DatabaseManager::findBackupItem( const std::string &userID, const std::string &backupID) { Aws::DynamoDB::Model::GetItemRequest request; request.AddKey( BackupItem::FIELD_USER_ID, Aws::DynamoDB::Model::AttributeValue(userID)); request.AddKey( BackupItem::FIELD_BACKUP_ID, Aws::DynamoDB::Model::AttributeValue(backupID)); return std::move(this->innerFindItem(request)); } std::shared_ptr DatabaseManager::findLastBackupItem(const std::string &userID) { std::shared_ptr item = createItemByType(); Aws::DynamoDB::Model::QueryRequest req; req.SetTableName(BackupItem::tableName); req.SetKeyConditionExpression(BackupItem::FIELD_USER_ID + " = :valueToMatch"); AttributeValues attributeValues; attributeValues.emplace(":valueToMatch", userID); req.SetExpressionAttributeValues(attributeValues); req.SetIndexName("userID-created-index"); req.SetLimit(1); req.SetScanIndexForward(false); const Aws::DynamoDB::Model::QueryOutcome &outcome = getDynamoDBClient()->Query(req); if (!outcome.IsSuccess()) { throw std::runtime_error(outcome.GetError().GetMessage()); } const Aws::Vector &items = outcome.GetResult().GetItems(); if (items.empty()) { return nullptr; } return std::make_shared(items[0]); } void DatabaseManager::removeBackupItem(std::shared_ptr item) { this->innerRemoveItem(*item); } void DatabaseManager::putLogItem(const LogItem &item) { Aws::DynamoDB::Model::PutItemRequest request; request.SetTableName(LogItem::tableName); request.AddItem( LogItem::FIELD_BACKUP_ID, Aws::DynamoDB::Model::AttributeValue(item.getBackupID())); request.AddItem( LogItem::FIELD_LOG_ID, Aws::DynamoDB::Model::AttributeValue(item.getLogID())); request.AddItem( LogItem::FIELD_PERSISTED_IN_BLOB, Aws::DynamoDB::Model::AttributeValue( std::to_string(item.getPersistedInBlob()))); request.AddItem( LogItem::FIELD_VALUE, Aws::DynamoDB::Model::AttributeValue(item.getValue())); if (!item.getAttachmentHolders().empty()) { request.AddItem( LogItem::FIELD_ATTACHMENT_HOLDERS, Aws::DynamoDB::Model::AttributeValue(item.getAttachmentHolders())); } this->innerPutItem(std::make_shared(item), request); } std::vector> DatabaseManager::findLogItemsForBackup(const std::string &backupID) { std::vector> result; std::shared_ptr item = createItemByType(); Aws::DynamoDB::Model::QueryRequest req; req.SetTableName(LogItem::tableName); req.SetKeyConditionExpression(LogItem::FIELD_BACKUP_ID + " = :valueToMatch"); AttributeValues attributeValues; attributeValues.emplace(":valueToMatch", backupID); req.SetExpressionAttributeValues(attributeValues); const Aws::DynamoDB::Model::QueryOutcome &outcome = getDynamoDBClient()->Query(req); if (!outcome.IsSuccess()) { throw std::runtime_error(outcome.GetError().GetMessage()); } const Aws::Vector &items = outcome.GetResult().GetItems(); for (auto &item : items) { result.push_back(std::make_shared(item)); } return result; } void DatabaseManager::removeLogItem(std::shared_ptr item) { this->innerRemoveItem(*item); } } // namespace database } // namespace network } // namespace comm diff --git a/services/backup/src/Reactors/server/CreateNewBackupReactor.cpp b/services/backup/src/Reactors/server/CreateNewBackupReactor.cpp index 3977f3757..11b502347 100644 --- a/services/backup/src/Reactors/server/CreateNewBackupReactor.cpp +++ b/services/backup/src/Reactors/server/CreateNewBackupReactor.cpp @@ -1,100 +1,101 @@ #include "CreateNewBackupReactor.h" #include "DatabaseManager.h" +#include "GlobalTools.h" #include "Tools.h" namespace comm { namespace network { namespace reactor { std::string CreateNewBackupReactor::generateBackupID() { // mock return generateRandomString(); } std::unique_ptr CreateNewBackupReactor::handleRequest( backup::CreateNewBackupRequest request, backup::CreateNewBackupResponse *response) { // we make sure that the blob client's state is flushed to the main memory // as there may be multiple threads from the pool taking over here const std::lock_guard lock(this->reactorStateMutex); switch (this->state) { case State::USER_ID: { if (!request.has_userid()) { throw std::runtime_error("user id expected but not received"); } this->userID = request.userid(); this->state = State::KEY_ENTROPY; return nullptr; } case State::KEY_ENTROPY: { if (!request.has_keyentropy()) { throw std::runtime_error( "backup key entropy expected but not received"); } this->keyEntropy = request.keyentropy(); this->state = State::DATA_HASH; return nullptr; } case State::DATA_HASH: { if (!request.has_newcompactionhash()) { throw std::runtime_error("data hash expected but not received"); } this->dataHash = request.newcompactionhash(); this->state = State::DATA_CHUNKS; // TODO confirm - holder may be a backup id this->backupID = this->generateBackupID(); response->set_backupid(this->backupID); this->holder = this->backupID; this->putReactor = std::make_shared( this->holder, this->dataHash, &this->blobPutDoneCV); this->blobClient.put(this->putReactor); return nullptr; } case State::DATA_CHUNKS: { this->putReactor->scheduleSendingDataChunk(std::make_unique( std::move(*request.mutable_newcompactionchunk()))); return nullptr; } } throw std::runtime_error("new backup - invalid state"); } void CreateNewBackupReactor::terminateCallback() { const std::lock_guard lock(this->reactorStateMutex); if (this->putReactor == nullptr) { return; } this->putReactor->scheduleSendingDataChunk(std::make_unique("")); std::unique_lock lock2(this->blobPutDoneCVMutex); if (this->putReactor->getUtility()->state == ReactorState::DONE && !this->putReactor->getUtility()->getStatus().ok()) { throw std::runtime_error( this->putReactor->getUtility()->getStatus().error_message()); } if (this->putReactor->getUtility()->state != ReactorState::DONE) { this->blobPutDoneCV.wait(lock2); } else if (!this->putReactor->getUtility()->getStatus().ok()) { throw std::runtime_error( this->putReactor->getUtility()->getStatus().error_message()); } try { // TODO add recovery data // TODO handle attachments holders database::BackupItem backupItem( this->userID, this->backupID, getCurrentTimestamp(), generateRandomString(), this->holder, {}); database::DatabaseManager::getInstance().putBackupItem(backupItem); } catch (std::runtime_error &e) { std::cout << "db operations error: " << e.what() << std::endl; } } } // namespace reactor } // namespace network } // namespace comm diff --git a/services/backup/src/Tools.cpp b/services/backup/src/Tools.cpp index 467cca9f4..fa469f166 100644 --- a/services/backup/src/Tools.cpp +++ b/services/backup/src/Tools.cpp @@ -1,45 +1,23 @@ #include "Tools.h" #include #include #include namespace comm { namespace network { std::string generateRandomString(std::size_t length) { const std::string CHARACTERS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; thread_local std::random_device generator; std::uniform_int_distribution<> distribution(0, CHARACTERS.size() - 1); std::string random_string; for (std::size_t i = 0; i < length; ++i) { random_string += CHARACTERS[distribution(generator)]; } return random_string; } -uint64_t getCurrentTimestamp() { - using namespace std::chrono; - return duration_cast(system_clock::now().time_since_epoch()) - .count(); -} - -std::string decorateTableName(const std::string &baseName) { - std::string suffix = ""; - if (std::getenv("COMM_TEST_SERVICES") != nullptr && - std::string(std::getenv("COMM_TEST_SERVICES")) == "1") { - suffix = "-test"; - } - return baseName + suffix; -} - -bool isDevMode() { - if (std::getenv("COMM_SERVICES_DEV_MODE") == nullptr) { - return false; - } - return std::string(std::getenv("COMM_SERVICES_DEV_MODE")) == "1"; -} - } // namespace network } // namespace comm diff --git a/services/backup/src/Tools.h b/services/backup/src/Tools.h index e057a7a92..2fa862d1e 100644 --- a/services/backup/src/Tools.h +++ b/services/backup/src/Tools.h @@ -1,15 +1,11 @@ #pragma once -#include #include namespace comm { namespace network { std::string generateRandomString(std::size_t length = 20); -uint64_t getCurrentTimestamp(); -std::string decorateTableName(const std::string &baseName); -bool isDevMode(); } // namespace network } // namespace comm diff --git a/services/backup/test/DatabaseManagerTest.cpp b/services/backup/test/DatabaseManagerTest.cpp index bf91d4cfd..8e9928203 100644 --- a/services/backup/test/DatabaseManagerTest.cpp +++ b/services/backup/test/DatabaseManagerTest.cpp @@ -1,103 +1,104 @@ #include #include "DatabaseManager.h" +#include "GlobalTools.h" #include "Tools.h" #include #include #include #include using namespace comm::network::database; class DatabaseManagerTest : public testing::Test { protected: virtual void SetUp() { Aws::InitAPI({}); } virtual void TearDown() { Aws::ShutdownAPI({}); } }; std::string generateName(const std::string prefix = "") { return prefix + "-" + std::to_string(comm::network::getCurrentTimestamp()); } BackupItem generateBackupItem(const std::string &userID, const std::string &backupID) { return BackupItem( userID, backupID, comm::network::getCurrentTimestamp(), "xxx", "xxx", {""}); } LogItem generateLogItem(const std::string &backupID, const std::string &logID) { return LogItem(backupID, logID, false, "xxx", {""}); } TEST_F(DatabaseManagerTest, TestOperationsOnBackupItems) { const std::string userID = generateName("user001"); std::vector backupIDs = {"backup001", "backup002", "backup003"}; for (const std::string &backupID : backupIDs) { DatabaseManager::getInstance().putBackupItem( generateBackupItem(userID, backupID)); } std::shared_ptr item; while (!backupIDs.empty()) { item = DatabaseManager::getInstance().findLastBackupItem(userID); EXPECT_NE(item, nullptr); EXPECT_EQ(item->getBackupID(), backupIDs.back()); backupIDs.pop_back(); DatabaseManager::getInstance().removeBackupItem(item); }; EXPECT_EQ(DatabaseManager::getInstance().findLastBackupItem(userID), nullptr); } TEST_F(DatabaseManagerTest, TestOperationsOnLogItems) { const std::string backupID1 = generateName("backup001"); const std::string backupID2 = generateName("backup002"); std::vector logIDs1 = {"log001", "log002", "log003"}; for (const std::string &logID : logIDs1) { DatabaseManager::getInstance().putLogItem( generateLogItem(backupID1, logID)); } std::vector logIDs2 = {"log021", "log022"}; for (const std::string &logID : logIDs2) { DatabaseManager::getInstance().putLogItem( generateLogItem(backupID2, logID)); } std::vector> items1 = DatabaseManager::getInstance().findLogItemsForBackup(backupID1); std::vector> items2 = DatabaseManager::getInstance().findLogItemsForBackup(backupID2); EXPECT_EQ(items1.size(), 3); EXPECT_EQ(items2.size(), 2); for (size_t i = 0; i < items1.size(); ++i) { EXPECT_EQ(logIDs1.at(i), items1.at(i)->getLogID()); DatabaseManager::getInstance().removeLogItem(items1.at(i)); } EXPECT_EQ( DatabaseManager::getInstance().findLogItemsForBackup(backupID1).size(), 0); for (size_t i = 0; i < items2.size(); ++i) { EXPECT_EQ(logIDs2.at(i), items2.at(i)->getLogID()); DatabaseManager::getInstance().removeLogItem(items2.at(i)); } EXPECT_EQ( DatabaseManager::getInstance().findLogItemsForBackup(backupID2).size(), 0); } diff --git a/services/blob/src/Constants.h b/services/blob/src/Constants.h index 947feebc2..1325fee1d 100644 --- a/services/blob/src/Constants.h +++ b/services/blob/src/Constants.h @@ -1,20 +1,21 @@ #pragma once +#include "GlobalTools.h" #include "Tools.h" #include namespace comm { namespace network { // 5MB limit const size_t AWS_MULTIPART_UPLOAD_MINIMUM_CHUNK_SIZE = 5 * 1024 * 1024; const std::string BLOB_BUCKET_NAME = "commapp-blob"; const std::string BLOB_TABLE_NAME = decorateTableName("blob-service-blob"); const std::string REVERSE_INDEX_TABLE_NAME = decorateTableName("blob-service-reverse-index"); } // namespace network } // namespace comm diff --git a/services/blob/src/DatabaseManager.cpp b/services/blob/src/DatabaseManager.cpp index 6f36dfe97..dfd814588 100644 --- a/services/blob/src/DatabaseManager.cpp +++ b/services/blob/src/DatabaseManager.cpp @@ -1,152 +1,153 @@ #include "DatabaseManager.h" +#include "GlobalTools.h" #include "Tools.h" #include #include #include #include #include namespace comm { namespace network { namespace database { DatabaseManager &DatabaseManager::getInstance() { static DatabaseManager instance; return instance; } void DatabaseManager::innerPutItem( std::shared_ptr item, const Aws::DynamoDB::Model::PutItemRequest &request) { const Aws::DynamoDB::Model::PutItemOutcome outcome = getDynamoDBClient()->PutItem(request); if (!outcome.IsSuccess()) { throw std::runtime_error(outcome.GetError().GetMessage()); } } void DatabaseManager::innerRemoveItem(const Item &item) { Aws::DynamoDB::Model::DeleteItemRequest request; request.SetTableName(item.getTableName()); PrimaryKey pk = item.getPrimaryKey(); PrimaryKeyValue primaryKeyValue = item.getPrimaryKeyValue(); request.AddKey( pk.partitionKey, Aws::DynamoDB::Model::AttributeValue(primaryKeyValue.partitionKey)); if (pk.sortKey != nullptr && primaryKeyValue.sortKey != nullptr) { request.AddKey( *pk.sortKey, Aws::DynamoDB::Model::AttributeValue(*primaryKeyValue.sortKey)); } const Aws::DynamoDB::Model::DeleteItemOutcome &outcome = getDynamoDBClient()->DeleteItem(request); if (!outcome.IsSuccess()) { throw std::runtime_error(outcome.GetError().GetMessage()); } } void DatabaseManager::putBlobItem(const BlobItem &item) { Aws::DynamoDB::Model::PutItemRequest request; request.SetTableName(BlobItem::tableName); request.AddItem( BlobItem::FIELD_BLOB_HASH, Aws::DynamoDB::Model::AttributeValue(item.getBlobHash())); request.AddItem( BlobItem::FIELD_S3_PATH, Aws::DynamoDB::Model::AttributeValue(item.getS3Path().getFullPath())); request.AddItem( BlobItem::FIELD_CREATED, Aws::DynamoDB::Model::AttributeValue( std::to_string(getCurrentTimestamp()))); this->innerPutItem(std::make_shared(item), request); } std::shared_ptr DatabaseManager::findBlobItem(const std::string &blobHash) { Aws::DynamoDB::Model::GetItemRequest request; request.AddKey( BlobItem::FIELD_BLOB_HASH, Aws::DynamoDB::Model::AttributeValue(blobHash)); return std::move(this->innerFindItem(request)); } void DatabaseManager::removeBlobItem(const std::string &blobHash) { std::shared_ptr item = this->findBlobItem(blobHash); if (item == nullptr) { return; } this->innerRemoveItem(*item); } void DatabaseManager::putReverseIndexItem(const ReverseIndexItem &item) { if (this->findReverseIndexItemByHolder(item.getHolder()) != nullptr) { throw std::runtime_error( "An item for the given holder [" + item.getHolder() + "] already exists"); } Aws::DynamoDB::Model::PutItemRequest request; request.SetTableName(ReverseIndexItem::tableName); request.AddItem( ReverseIndexItem::FIELD_HOLDER, Aws::DynamoDB::Model::AttributeValue(item.getHolder())); request.AddItem( ReverseIndexItem::FIELD_BLOB_HASH, Aws::DynamoDB::Model::AttributeValue(item.getBlobHash())); this->innerPutItem(std::make_shared(item), request); } std::shared_ptr DatabaseManager::findReverseIndexItemByHolder(const std::string &holder) { Aws::DynamoDB::Model::GetItemRequest request; request.AddKey( ReverseIndexItem::FIELD_HOLDER, Aws::DynamoDB::Model::AttributeValue(holder)); return std::move(this->innerFindItem(request)); } std::vector> DatabaseManager::findReverseIndexItemsByHash(const std::string &blobHash) { std::vector> result; Aws::DynamoDB::Model::QueryRequest req; req.SetTableName(ReverseIndexItem::tableName); req.SetKeyConditionExpression("blobHash = :valueToMatch"); AttributeValues attributeValues; attributeValues.emplace(":valueToMatch", blobHash); req.SetExpressionAttributeValues(attributeValues); req.SetIndexName("blobHash-index"); const Aws::DynamoDB::Model::QueryOutcome &outcome = getDynamoDBClient()->Query(req); if (!outcome.IsSuccess()) { throw std::runtime_error(outcome.GetError().GetMessage()); } const Aws::Vector &items = outcome.GetResult().GetItems(); for (auto &item : items) { result.push_back(std::make_shared(item)); } return result; } bool DatabaseManager::removeReverseIndexItem(const std::string &holder) { std::shared_ptr item = findReverseIndexItemByHolder(holder); if (item == nullptr) { return false; } this->innerRemoveItem(*item); return true; } } // namespace database } // namespace network } // namespace comm diff --git a/services/blob/src/S3Tools.cpp b/services/blob/src/S3Tools.cpp index 96dc14a6e..919d8add4 100644 --- a/services/blob/src/S3Tools.cpp +++ b/services/blob/src/S3Tools.cpp @@ -1,46 +1,47 @@ #include "S3Tools.h" #include "Constants.h" #include "GlobalConstants.h" +#include "GlobalTools.h" #include "Tools.h" #include #include namespace comm { namespace network { AwsS3Bucket getBucket(const std::string &bucketName) { return AwsS3Bucket(bucketName); } std::vector listBuckets() { Aws::S3::Model::ListBucketsOutcome outcome = getS3Client()->ListBuckets(); std::vector result; if (!outcome.IsSuccess()) { throw std::runtime_error(outcome.GetError().GetMessage()); } Aws::Vector buckets = outcome.GetResult().GetBuckets(); for (Aws::S3::Model::Bucket &bucket : buckets) { result.push_back(bucket.GetName()); } return result; } std::unique_ptr getS3Client() { Aws::Client::ClientConfiguration config; config.region = AWS_REGION; if (isDevMode()) { config.endpointOverride = Aws::String("localstack:4566"); config.scheme = Aws::Http::Scheme::HTTP; return std::make_unique( config, Aws::Client::AWSAuthV4Signer::PayloadSigningPolicy::Never, false); } return std::make_unique(config); } } // namespace network } // namespace comm diff --git a/services/blob/src/Tools.cpp b/services/blob/src/Tools.cpp index 83e0c585a..22ebbabc3 100644 --- a/services/blob/src/Tools.cpp +++ b/services/blob/src/Tools.cpp @@ -1,95 +1,73 @@ #include "Tools.h" #include "Constants.h" #include "DatabaseEntitiesTools.h" #include "DatabaseManager.h" #include "GlobalConstants.h" #include "S3Tools.h" #include #include #include #include #include namespace comm { namespace network { database::S3Path generateS3Path(const std::string &bucketName, const std::string &blobHash) { return database::S3Path(bucketName, blobHash); } std::string computeHashForFile(const database::S3Path &s3Path) { SHA512_CTX ctx; SHA512_Init(&ctx); const std::function callback = [&ctx](const std::string &chunk) { SHA512_Update(&ctx, chunk.data(), chunk.size()); }; getBucket(s3Path.getBucketName()) .getObjectDataChunks( s3Path.getObjectName(), callback, GRPC_CHUNK_SIZE_LIMIT); unsigned char hash[SHA512_DIGEST_LENGTH]; SHA512_Final(hash, &ctx); std::ostringstream hashStream; for (int i = 0; i < SHA512_DIGEST_LENGTH; i++) { hashStream << std::hex << std::setfill('0') << std::setw(2) << std::nouppercase << (int)hash[i]; } return hashStream.str(); } database::S3Path findS3Path(const std::string &holder) { std::shared_ptr reverseIndexItem = database::DatabaseManager::getInstance().findReverseIndexItemByHolder( holder); if (reverseIndexItem == nullptr) { throw std::runtime_error( "provided holder: [" + holder + "] has not been found in the database"); } return findS3Path(*reverseIndexItem); } database::S3Path findS3Path(const database::ReverseIndexItem &reverseIndexItem) { std::shared_ptr blobItem = database::DatabaseManager::getInstance().findBlobItem( reverseIndexItem.getBlobHash()); if (blobItem == nullptr) { throw std::runtime_error( "no blob found for blobHash: [" + reverseIndexItem.getBlobHash() + "]"); } database::S3Path result = blobItem->getS3Path(); return result; } -uint64_t getCurrentTimestamp() { - using namespace std::chrono; - return duration_cast(system_clock::now().time_since_epoch()) - .count(); -} - -std::string decorateTableName(const std::string &baseName) { - std::string suffix = ""; - if (std::getenv("COMM_TEST_SERVICES") != nullptr && - std::string(std::getenv("COMM_TEST_SERVICES")) == "1") { - suffix = "-test"; - } - return baseName + suffix; -} - -bool isDevMode() { - if (std::getenv("COMM_SERVICES_DEV_MODE") == nullptr) { - return false; - } - return std::string(std::getenv("COMM_SERVICES_DEV_MODE")) == "1"; -} - } // namespace network } // namespace comm diff --git a/services/blob/src/Tools.h b/services/blob/src/Tools.h index 71fb53d2e..4b5bf58d2 100644 --- a/services/blob/src/Tools.h +++ b/services/blob/src/Tools.h @@ -1,32 +1,26 @@ #pragma once #include "DatabaseEntitiesTools.h" #include "S3Path.h" namespace comm { namespace network { database::S3Path generateS3Path(const std::string &bucketName, const std::string &blobHash); std::string computeHashForFile(const database::S3Path &s3Path); database::S3Path findS3Path(const std::string &holder); database::S3Path findS3Path(const database::ReverseIndexItem &reverseIndexItem); -uint64_t getCurrentTimestamp(); - -std::string decorateTableName(const std::string &baseName); - -bool isDevMode(); - class invalid_argument_error : public std::runtime_error { public: invalid_argument_error(std::string errorMessage) : std::runtime_error(errorMessage) { } }; } // namespace network } // namespace comm diff --git a/services/lib/src/DynamoDBTools.cpp b/services/lib/src/DynamoDBTools.cpp index 73cfa7db5..bcfdad144 100644 --- a/services/lib/src/DynamoDBTools.cpp +++ b/services/lib/src/DynamoDBTools.cpp @@ -1,19 +1,20 @@ #include "DynamoDBTools.h" #include "Constants.h" #include "GlobalConstants.h" +#include "GlobalTools.h" namespace comm { namespace network { std::unique_ptr getDynamoDBClient() { Aws::Client::ClientConfiguration config; config.region = AWS_REGION; if (isDevMode()) { config.endpointOverride = Aws::String("localstack:4566"); config.scheme = Aws::Http::Scheme::HTTP; } return std::make_unique(config); } } // namespace network } // namespace comm diff --git a/services/backup/src/Tools.cpp b/services/lib/src/GlobalTools.cpp similarity index 58% copy from services/backup/src/Tools.cpp copy to services/lib/src/GlobalTools.cpp index 467cca9f4..85f8e3a0b 100644 --- a/services/backup/src/Tools.cpp +++ b/services/lib/src/GlobalTools.cpp @@ -1,45 +1,35 @@ -#include "Tools.h" +#include "GlobalTools.h" + +#include #include -#include -#include +#include +#include namespace comm { namespace network { -std::string generateRandomString(std::size_t length) { - const std::string CHARACTERS = - "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; - thread_local std::random_device generator; - std::uniform_int_distribution<> distribution(0, CHARACTERS.size() - 1); - std::string random_string; - for (std::size_t i = 0; i < length; ++i) { - random_string += CHARACTERS[distribution(generator)]; - } - return random_string; -} - uint64_t getCurrentTimestamp() { using namespace std::chrono; return duration_cast(system_clock::now().time_since_epoch()) .count(); } std::string decorateTableName(const std::string &baseName) { std::string suffix = ""; if (std::getenv("COMM_TEST_SERVICES") != nullptr && std::string(std::getenv("COMM_TEST_SERVICES")) == "1") { suffix = "-test"; } return baseName + suffix; } bool isDevMode() { if (std::getenv("COMM_SERVICES_DEV_MODE") == nullptr) { return false; } return std::string(std::getenv("COMM_SERVICES_DEV_MODE")) == "1"; } } // namespace network } // namespace comm diff --git a/services/backup/src/Tools.h b/services/lib/src/GlobalTools.h similarity index 80% copy from services/backup/src/Tools.h copy to services/lib/src/GlobalTools.h index e057a7a92..8f8c6836c 100644 --- a/services/backup/src/Tools.h +++ b/services/lib/src/GlobalTools.h @@ -1,15 +1,16 @@ #pragma once #include #include namespace comm { namespace network { -std::string generateRandomString(std::size_t length = 20); uint64_t getCurrentTimestamp(); + std::string decorateTableName(const std::string &baseName); + bool isDevMode(); } // namespace network } // namespace comm