diff --git a/services/backup/src/DatabaseManager.cpp b/services/backup/src/DatabaseManager.cpp index b2fa94009..fccad31db 100644 --- a/services/backup/src/DatabaseManager.cpp +++ b/services/backup/src/DatabaseManager.cpp @@ -1,185 +1,154 @@ #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/DatabaseManager.h b/services/backup/src/DatabaseManager.h index 84187853d..0c9c5db2b 100644 --- a/services/backup/src/DatabaseManager.h +++ b/services/backup/src/DatabaseManager.h @@ -1,64 +1,38 @@ #pragma once #include "DatabaseEntitiesTools.h" +#include "DatabaseManagerBase.h" #include "DynamoDBTools.h" #include #include #include #include #include #include namespace comm { namespace network { namespace database { // this class should be thread-safe in case any shared resources appear -class DatabaseManager { - void innerPutItem( - std::shared_ptr item, - const Aws::DynamoDB::Model::PutItemRequest &request); - - template - std::shared_ptr - innerFindItem(Aws::DynamoDB::Model::GetItemRequest &request); - void innerRemoveItem(const Item &item); - +class DatabaseManager : public DatabaseManagerBase { public: static DatabaseManager &getInstance(); void putBackupItem(const BackupItem &item); std::shared_ptr findBackupItem(const std::string &userID, const std::string &backupID); std::shared_ptr findLastBackupItem(const std::string &userID); void removeBackupItem(std::shared_ptr item); void putLogItem(const LogItem &item); std::vector> findLogItemsForBackup(const std::string &backupID); void removeLogItem(std::shared_ptr item); }; -template -std::shared_ptr -DatabaseManager::innerFindItem(Aws::DynamoDB::Model::GetItemRequest &request) { - std::shared_ptr item = createItemByType(); - request.SetTableName(item->getTableName()); - const Aws::DynamoDB::Model::GetItemOutcome &outcome = - getDynamoDBClient()->GetItem(request); - if (!outcome.IsSuccess()) { - throw std::runtime_error(outcome.GetError().GetMessage()); - } - const AttributeValues &outcomeItem = outcome.GetResult().GetItem(); - if (!outcomeItem.size()) { - return nullptr; - } - item->assignItemFromDatabase(outcomeItem); - return item; -} - } // namespace database } // namespace network } // namespace comm diff --git a/services/blob/src/DatabaseManager.cpp b/services/blob/src/DatabaseManager.cpp index dfd814588..e1f89c353 100644 --- a/services/blob/src/DatabaseManager.cpp +++ b/services/blob/src/DatabaseManager.cpp @@ -1,153 +1,122 @@ #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/DatabaseManager.h b/services/blob/src/DatabaseManager.h index 22d517a32..250203493 100644 --- a/services/blob/src/DatabaseManager.h +++ b/services/blob/src/DatabaseManager.h @@ -1,68 +1,41 @@ #pragma once #include "DatabaseEntitiesTools.h" +#include "DatabaseManagerBase.h" #include "DynamoDBTools.h" #include #include #include #include #include #include #include #include #include namespace comm { namespace network { namespace database { // this class should be thread-safe in case any shared resources appear -class DatabaseManager { - - void innerPutItem( - std::shared_ptr item, - const Aws::DynamoDB::Model::PutItemRequest &request); - - template - std::shared_ptr - innerFindItem(Aws::DynamoDB::Model::GetItemRequest &request); - void innerRemoveItem(const Item &item); - +class DatabaseManager : public DatabaseManagerBase { public: static DatabaseManager &getInstance(); void putBlobItem(const BlobItem &item); std::shared_ptr findBlobItem(const std::string &blobHash); void removeBlobItem(const std::string &blobHash); void putReverseIndexItem(const ReverseIndexItem &item); std::shared_ptr findReverseIndexItemByHolder(const std::string &holder); std::vector> findReverseIndexItemsByHash(const std::string &blobHash); bool removeReverseIndexItem(const std::string &holder); }; -template -std::shared_ptr -DatabaseManager::innerFindItem(Aws::DynamoDB::Model::GetItemRequest &request) { - std::shared_ptr item = createItemByType(); - request.SetTableName(item->getTableName()); - const Aws::DynamoDB::Model::GetItemOutcome &outcome = - getDynamoDBClient()->GetItem(request); - if (!outcome.IsSuccess()) { - throw std::runtime_error(outcome.GetError().GetMessage()); - } - const AttributeValues &outcomeItem = outcome.GetResult().GetItem(); - if (!outcomeItem.size()) { - return nullptr; - } - item->assignItemFromDatabase(outcomeItem); - return std::move(item); -} - } // namespace database } // namespace network } // namespace comm diff --git a/services/lib/src/DatabaseManagerBase.cpp b/services/lib/src/DatabaseManagerBase.cpp new file mode 100644 index 000000000..530bf3389 --- /dev/null +++ b/services/lib/src/DatabaseManagerBase.cpp @@ -0,0 +1,45 @@ +#include "DatabaseManagerBase.h" + +#include +#include + +#include + +namespace comm { +namespace network { +namespace database { + +void DatabaseManagerBase::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 DatabaseManagerBase::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()); + } +} + +} // namespace database +} // namespace network +} // namespace comm diff --git a/services/backup/src/DatabaseManager.h b/services/lib/src/DatabaseManagerBase.h similarity index 61% copy from services/backup/src/DatabaseManager.h copy to services/lib/src/DatabaseManagerBase.h index 84187853d..28b372292 100644 --- a/services/backup/src/DatabaseManager.h +++ b/services/lib/src/DatabaseManagerBase.h @@ -1,64 +1,50 @@ #pragma once #include "DatabaseEntitiesTools.h" #include "DynamoDBTools.h" #include -#include #include #include #include -#include namespace comm { namespace network { namespace database { // this class should be thread-safe in case any shared resources appear -class DatabaseManager { +class DatabaseManagerBase { +protected: void innerPutItem( std::shared_ptr item, const Aws::DynamoDB::Model::PutItemRequest &request); template std::shared_ptr innerFindItem(Aws::DynamoDB::Model::GetItemRequest &request); - void innerRemoveItem(const Item &item); - -public: - static DatabaseManager &getInstance(); - void putBackupItem(const BackupItem &item); - std::shared_ptr - findBackupItem(const std::string &userID, const std::string &backupID); - std::shared_ptr findLastBackupItem(const std::string &userID); - void removeBackupItem(std::shared_ptr item); - - void putLogItem(const LogItem &item); - std::vector> - findLogItemsForBackup(const std::string &backupID); - void removeLogItem(std::shared_ptr item); + void innerRemoveItem(const Item &item); }; template -std::shared_ptr -DatabaseManager::innerFindItem(Aws::DynamoDB::Model::GetItemRequest &request) { +std::shared_ptr DatabaseManagerBase::innerFindItem( + Aws::DynamoDB::Model::GetItemRequest &request) { std::shared_ptr item = createItemByType(); request.SetTableName(item->getTableName()); const Aws::DynamoDB::Model::GetItemOutcome &outcome = getDynamoDBClient()->GetItem(request); if (!outcome.IsSuccess()) { throw std::runtime_error(outcome.GetError().GetMessage()); } const AttributeValues &outcomeItem = outcome.GetResult().GetItem(); if (!outcomeItem.size()) { return nullptr; } item->assignItemFromDatabase(outcomeItem); - return item; + return std::move(item); } } // namespace database } // namespace network } // namespace comm