# HG changeset patch # User Sebastien Jodogne # Date 1610113203 -3600 # Node ID a51ce147dbe06eb50bc6fd47ef9bd16364ae1bce # Parent 3236894320d60641547a74d7de64c061f0d83e6c refactoring using new class StorageAreaBuffer diff -r 3236894320d6 -r a51ce147dbe0 Framework/Plugins/StorageAreaBuffer.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Plugins/StorageAreaBuffer.cpp Fri Jan 08 14:40:03 2021 +0100 @@ -0,0 +1,98 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2021 Osimis S.A., Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + **/ + + +#include "StorageAreaBuffer.h" + +#include + +#include +#include + + +namespace OrthancDatabases +{ + StorageAreaBuffer::StorageAreaBuffer() : + data_(NULL), + size_(0) + { + } + + + void StorageAreaBuffer::Clear() + { + if (data_ != NULL) + { + free(data_); + data_ = NULL; + size_ = 0; + } + } + + + void StorageAreaBuffer::Assign(const std::string& content) + { + Clear(); + + size_ = static_cast(content.size()); + + if (static_cast(size_) != content.size()) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_NotEnoughMemory, + "File cannot be stored in a 63bit buffer"); + } + + if (content.empty()) + { + data_ = NULL; + } + else + { + data_ = malloc(size_); + + if (data_ == NULL) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_NotEnoughMemory); + } + + memcpy(data_, content.c_str(), size_); + } + } + + + void* StorageAreaBuffer::ReleaseData() + { + void* result = data_; + data_ = NULL; + size_ = 0; + return result; + } + + + void StorageAreaBuffer::ToString(std::string& target) + { + target.resize(size_); + + if (size_ != 0) + { + memcpy(&target[0], data_, size_); + } + } +} diff -r 3236894320d6 -r a51ce147dbe0 Framework/Plugins/StorageAreaBuffer.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Plugins/StorageAreaBuffer.h Fri Jan 08 14:40:03 2021 +0100 @@ -0,0 +1,64 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2021 Osimis S.A., Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + **/ + + +#pragma once + +#include + +#include +#include + + +namespace OrthancDatabases +{ + class StorageAreaBuffer : public boost::noncopyable + { + private: + void* data_; + int64_t size_; + + public: + StorageAreaBuffer(); + + ~StorageAreaBuffer() + { + Clear(); + } + + void Clear(); + + void Assign(const std::string& content); + + int64_t GetSize() const + { + return size_; + } + + const void* GetData() const + { + return data_; + } + + void* ReleaseData(); + + void ToString(std::string& target); + }; +} diff -r 3236894320d6 -r a51ce147dbe0 Framework/Plugins/StorageBackend.cpp --- a/Framework/Plugins/StorageBackend.cpp Wed Jan 06 17:40:27 2021 +0100 +++ b/Framework/Plugins/StorageBackend.cpp Fri Jan 08 14:40:03 2021 +0100 @@ -31,6 +31,8 @@ #include // For std::unique_ptr<> #include +#include + #define ORTHANC_PLUGINS_DATABASE_CATCH \ catch (::Orthanc::OrthancException& e) \ @@ -52,69 +54,12 @@ namespace OrthancDatabases { - void StorageBackend::ReadFromString(void*& buffer, - size_t& size, - const std::string& content) - { - size = content.size(); - - if (content.empty()) - { - buffer = NULL; - } - else - { - buffer = malloc(size); - - if (buffer == NULL) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_NotEnoughMemory); - } - - memcpy(buffer, content.c_str(), size); - } - } - - StorageBackend::StorageBackend(IDatabaseFactory* factory) : manager_(factory) { } - void StorageBackend::ReadToString(std::string& content, - DatabaseManager::Transaction& transaction, - const std::string& uuid, - OrthancPluginContentType type) - { - void* buffer = NULL; - size_t size; - Read(buffer, size, transaction, uuid, type); - - try - { - content.resize(size); - } - catch (std::bad_alloc&) - { - if (size != 0) - { - free(buffer); - } - - throw Orthanc::OrthancException(Orthanc::ErrorCode_NotEnoughMemory); - } - - if (size != 0) - { - assert(buffer != NULL); - memcpy(&content[0], buffer, size); - } - - free(buffer); - } - - void StorageBackend::Create(DatabaseManager::Transaction& transaction, const std::string& uuid, const void* content, @@ -138,8 +83,7 @@ } - void StorageBackend::Read(void*& content, - size_t& size, + void StorageBackend::Read(StorageAreaBuffer& target, DatabaseManager::Transaction& transaction, const std::string& uuid, OrthancPluginContentType type) @@ -172,13 +116,11 @@ switch (value.GetType()) { case ValueType_File: - ReadFromString(content, size, - dynamic_cast(value).GetContent()); + target.Assign(dynamic_cast(value).GetContent()); break; case ValueType_BinaryString: - ReadFromString(content, size, - dynamic_cast(value).GetContent()); + target.Assign(dynamic_cast(value).GetContent()); break; default: @@ -235,11 +177,17 @@ { try { - DatabaseManager::Transaction transaction(backend_->GetManager()); - size_t tmp; - backend_->Read(*content, tmp, transaction, uuid, type); - *size = static_cast(tmp); - transaction.Commit(); + StorageAreaBuffer buffer; + + { + DatabaseManager::Transaction transaction(backend_->GetManager()); + backend_->Read(buffer, transaction, uuid, type); + transaction.Commit(); + } + + *size = buffer.GetSize(); + *content = buffer.ReleaseData(); + return OrthancPluginErrorCode_Success; } ORTHANC_PLUGINS_DATABASE_CATCH; diff -r 3236894320d6 -r a51ce147dbe0 Framework/Plugins/StorageBackend.h --- a/Framework/Plugins/StorageBackend.h Wed Jan 06 17:40:27 2021 +0100 +++ b/Framework/Plugins/StorageBackend.h Fri Jan 08 14:40:03 2021 +0100 @@ -21,7 +21,9 @@ #pragma once +#include "StorageAreaBuffer.h" #include "../Common/DatabaseManager.h" + #include @@ -32,11 +34,6 @@ private: DatabaseManager manager_; - protected: - void ReadFromString(void*& buffer, - size_t& size, - const std::string& content); - public: explicit StorageBackend(IDatabaseFactory* factory); @@ -58,8 +55,7 @@ size_t size, OrthancPluginContentType type); - virtual void Read(void*& content, - size_t& size, + virtual void Read(StorageAreaBuffer& target, DatabaseManager::Transaction& transaction, const std::string& uuid, OrthancPluginContentType type); @@ -71,12 +67,6 @@ static void Register(OrthancPluginContext* context, StorageBackend* backend); // Takes ownership - // For unit testing! - void ReadToString(std::string& content, - DatabaseManager::Transaction& transaction, - const std::string& uuid, - OrthancPluginContentType type); - static void Finalize(); }; } diff -r 3236894320d6 -r a51ce147dbe0 MySQL/UnitTests/UnitTestsMain.cpp --- a/MySQL/UnitTests/UnitTestsMain.cpp Wed Jan 06 17:40:27 2021 +0100 +++ b/MySQL/UnitTests/UnitTestsMain.cpp Fri Jan 08 14:40:03 2021 +0100 @@ -163,8 +163,8 @@ storageArea.Create(transaction, uuid, value.c_str(), value.size(), OrthancPluginContentType_Unknown); } - std::string tmp; - ASSERT_THROW(storageArea.ReadToString(tmp, transaction, "nope", OrthancPluginContentType_Unknown), + OrthancDatabases::StorageAreaBuffer buffer; + ASSERT_THROW(storageArea.Read(buffer, transaction, "nope", OrthancPluginContentType_Unknown), Orthanc::OrthancException); ASSERT_EQ(10, CountFiles(db)); @@ -180,13 +180,16 @@ if (i == 5) { - ASSERT_THROW(storageArea.ReadToString(content, transaction, uuid, OrthancPluginContentType_Unknown), + ASSERT_THROW(storageArea.Read(buffer, transaction, uuid, OrthancPluginContentType_Unknown), Orthanc::OrthancException); } else { - storageArea.ReadToString(content, transaction, uuid, OrthancPluginContentType_Unknown); - ASSERT_EQ(expected, content); + storageArea.Read(buffer, transaction, uuid, OrthancPluginContentType_Unknown); + + std::string s; + buffer.ToString(s); + ASSERT_EQ(expected, s); } } diff -r 3236894320d6 -r a51ce147dbe0 PostgreSQL/UnitTests/PostgreSQLTests.cpp --- a/PostgreSQL/UnitTests/PostgreSQLTests.cpp Wed Jan 06 17:40:27 2021 +0100 +++ b/PostgreSQL/UnitTests/PostgreSQLTests.cpp Fri Jan 08 14:40:03 2021 +0100 @@ -356,8 +356,8 @@ storageArea.Create(transaction, uuid, value.c_str(), value.size(), OrthancPluginContentType_Unknown); } - std::string tmp; - ASSERT_THROW(storageArea.ReadToString(tmp, transaction, "nope", OrthancPluginContentType_Unknown), + StorageAreaBuffer buffer; + ASSERT_THROW(storageArea.Read(buffer, transaction, "nope", OrthancPluginContentType_Unknown), Orthanc::OrthancException); ASSERT_EQ(10, CountLargeObjects(db)); @@ -369,17 +369,19 @@ { std::string uuid = boost::lexical_cast(i); std::string expected = "Value " + boost::lexical_cast(i * 2); - std::string content; if (i == 5) { - ASSERT_THROW(storageArea.ReadToString(content, transaction, uuid, OrthancPluginContentType_Unknown), + ASSERT_THROW(storageArea.Read(buffer, transaction, uuid, OrthancPluginContentType_Unknown), Orthanc::OrthancException); } else { - storageArea.ReadToString(content, transaction, uuid, OrthancPluginContentType_Unknown); - ASSERT_EQ(expected, content); + storageArea.Read(buffer, transaction, uuid, OrthancPluginContentType_Unknown); + + std::string s; + buffer.ToString(s); + ASSERT_EQ(expected, s); } } diff -r 3236894320d6 -r a51ce147dbe0 Resources/CMake/DatabasesPluginConfiguration.cmake --- a/Resources/CMake/DatabasesPluginConfiguration.cmake Wed Jan 06 17:40:27 2021 +0100 +++ b/Resources/CMake/DatabasesPluginConfiguration.cmake Fri Jan 08 14:40:03 2021 +0100 @@ -70,6 +70,7 @@ ${ORTHANC_CORE_SOURCES} ${ORTHANC_DATABASES_ROOT}/Framework/Plugins/GlobalProperties.cpp ${ORTHANC_DATABASES_ROOT}/Framework/Plugins/IndexBackend.cpp + ${ORTHANC_DATABASES_ROOT}/Framework/Plugins/StorageAreaBuffer.cpp ${ORTHANC_DATABASES_ROOT}/Framework/Plugins/StorageBackend.cpp ${ORTHANC_DATABASES_ROOT}/Resources/Orthanc/Databases/DatabaseConstraint.cpp ${ORTHANC_DATABASES_ROOT}/Resources/Orthanc/Databases/ISqlLookupFormatter.cpp