Mercurial > hg > orthanc
changeset 4484:64f06e7d5fc7
new abstraction IMemoryBuffer to avoid unnecessary copies of std::string buffers
line wrap: on
line diff
--- a/OrthancFramework/Resources/CMake/OrthancFrameworkConfiguration.cmake Thu Jan 28 16:59:40 2021 +0100 +++ b/OrthancFramework/Resources/CMake/OrthancFrameworkConfiguration.cmake Thu Jan 28 19:03:19 2021 +0100 @@ -158,11 +158,13 @@ ${CMAKE_CURRENT_LIST_DIR}/../../Sources/HttpServer/MultipartStreamReader.cpp ${CMAKE_CURRENT_LIST_DIR}/../../Sources/HttpServer/StringMatcher.cpp ${CMAKE_CURRENT_LIST_DIR}/../../Sources/Logging.cpp + ${CMAKE_CURRENT_LIST_DIR}/../../Sources/MallocMemoryBuffer.cpp ${CMAKE_CURRENT_LIST_DIR}/../../Sources/OrthancException.cpp ${CMAKE_CURRENT_LIST_DIR}/../../Sources/OrthancFramework.cpp ${CMAKE_CURRENT_LIST_DIR}/../../Sources/RestApi/RestApiHierarchy.cpp ${CMAKE_CURRENT_LIST_DIR}/../../Sources/RestApi/RestApiPath.cpp ${CMAKE_CURRENT_LIST_DIR}/../../Sources/SerializationToolbox.cpp + ${CMAKE_CURRENT_LIST_DIR}/../../Sources/StringMemoryBuffer.cpp ${CMAKE_CURRENT_LIST_DIR}/../../Sources/Toolbox.cpp ${CMAKE_CURRENT_LIST_DIR}/../../Sources/WebServiceParameters.cpp )
--- a/OrthancFramework/Sources/FileStorage/FilesystemStorage.cpp Thu Jan 28 16:59:40 2021 +0100 +++ b/OrthancFramework/Sources/FileStorage/FilesystemStorage.cpp Thu Jan 28 19:03:19 2021 +0100 @@ -28,8 +28,9 @@ #include "../Logging.h" #include "../OrthancException.h" +#include "../StringMemoryBuffer.h" +#include "../SystemToolbox.h" #include "../Toolbox.h" -#include "../SystemToolbox.h" #include <boost/filesystem/fstream.hpp> @@ -150,15 +151,16 @@ } - void FilesystemStorage::Read(std::string& content, - const std::string& uuid, - FileContentType type) + IMemoryBuffer* FilesystemStorage::Read(const std::string& uuid, + FileContentType type) { LOG(INFO) << "Reading attachment \"" << uuid << "\" of \"" << GetDescriptionInternal(type) << "\" content type"; - content.clear(); + std::string content; SystemToolbox::ReadFile(content, GetPath(uuid).string()); + + return StringMemoryBuffer::CreateFromSwap(content); } @@ -282,4 +284,15 @@ Setup(root); } #endif + + +#if ORTHANC_BUILDING_FRAMEWORK_LIBRARY == 1 + void FilesystemStorage::Read(std::string& content, + const std::string& uuid, + FileContentType type) + { + std::unique_ptr<IMemoryBuffer> buffer(Read(uuid, type)); + buffer->MoveToString(content); + } +#endif }
--- a/OrthancFramework/Sources/FileStorage/FilesystemStorage.h Thu Jan 28 16:59:40 2021 +0100 +++ b/OrthancFramework/Sources/FileStorage/FilesystemStorage.h Thu Jan 28 19:03:19 2021 +0100 @@ -60,6 +60,13 @@ explicit FilesystemStorage(std::string root); #endif +#if ORTHANC_BUILDING_FRAMEWORK_LIBRARY == 1 + // Binary compatibility with Orthanc Framework <= 1.8.2 + void Read(std::string& content, + const std::string& uuid, + FileContentType type); +#endif + public: explicit FilesystemStorage(const std::string& root); @@ -71,9 +78,8 @@ size_t size, FileContentType type) ORTHANC_OVERRIDE; - virtual void Read(std::string& content, - const std::string& uuid, - FileContentType type) ORTHANC_OVERRIDE; + virtual IMemoryBuffer* Read(const std::string& uuid, + FileContentType type) ORTHANC_OVERRIDE; virtual void Remove(const std::string& uuid, FileContentType type) ORTHANC_OVERRIDE;
--- a/OrthancFramework/Sources/FileStorage/IStorageArea.h Thu Jan 28 16:59:40 2021 +0100 +++ b/OrthancFramework/Sources/FileStorage/IStorageArea.h Thu Jan 28 19:03:19 2021 +0100 @@ -22,10 +22,10 @@ #pragma once +#include "../IMemoryBuffer.h" #include "../Enumerations.h" #include <string> -#include <boost/noncopyable.hpp> namespace Orthanc { @@ -41,9 +41,8 @@ size_t size, FileContentType type) = 0; - virtual void Read(std::string& content, - const std::string& uuid, - FileContentType type) = 0; + virtual IMemoryBuffer* Read(const std::string& uuid, + FileContentType type) = 0; virtual void Remove(const std::string& uuid, FileContentType type) = 0;
--- a/OrthancFramework/Sources/FileStorage/MemoryStorageArea.cpp Thu Jan 28 16:59:40 2021 +0100 +++ b/OrthancFramework/Sources/FileStorage/MemoryStorageArea.cpp Thu Jan 28 19:03:19 2021 +0100 @@ -23,8 +23,9 @@ #include "../PrecompiledHeaders.h" #include "MemoryStorageArea.h" +#include "../Logging.h" #include "../OrthancException.h" -#include "../Logging.h" +#include "../StringMemoryBuffer.h" namespace Orthanc { @@ -65,9 +66,8 @@ } - void MemoryStorageArea::Read(std::string& content, - const std::string& uuid, - FileContentType type) + IMemoryBuffer* MemoryStorageArea::Read(const std::string& uuid, + FileContentType type) { LOG(INFO) << "Reading attachment \"" << uuid << "\" of \"" << static_cast<int>(type) << "\" content type"; @@ -86,7 +86,7 @@ } else { - content.assign(*found->second); + return StringMemoryBuffer::CreateFromCopy(*found->second); } }
--- a/OrthancFramework/Sources/FileStorage/MemoryStorageArea.h Thu Jan 28 16:59:40 2021 +0100 +++ b/OrthancFramework/Sources/FileStorage/MemoryStorageArea.h Thu Jan 28 19:03:19 2021 +0100 @@ -47,9 +47,8 @@ size_t size, FileContentType type) ORTHANC_OVERRIDE; - virtual void Read(std::string& content, - const std::string& uuid, - FileContentType type) ORTHANC_OVERRIDE; + virtual IMemoryBuffer* Read(const std::string& uuid, + FileContentType type) ORTHANC_OVERRIDE; virtual void Remove(const std::string& uuid, FileContentType type) ORTHANC_OVERRIDE;
--- a/OrthancFramework/Sources/FileStorage/StorageAccessor.cpp Thu Jan 28 16:59:40 2021 +0100 +++ b/OrthancFramework/Sources/FileStorage/StorageAccessor.cpp Thu Jan 28 19:03:19 2021 +0100 @@ -147,10 +147,12 @@ { switch (info.GetCompressionType()) { - case CompressionType_None: - { - MetricsTimer timer(*this, METRICS_READ); - area_.Read(content, info.GetUuid(), info.GetContentType()); + case CompressionType_None: + { + MetricsTimer timer(*this, METRICS_READ); + + std::unique_ptr<IMemoryBuffer> buffer(area_.Read(info.GetUuid(), info.GetContentType())); + buffer->MoveToString(content); break; } @@ -158,14 +160,14 @@ { ZlibCompressor zlib; - std::string compressed; + std::unique_ptr<IMemoryBuffer> compressed; { MetricsTimer timer(*this, METRICS_READ); - area_.Read(compressed, info.GetUuid(), info.GetContentType()); + compressed.reset(area_.Read(info.GetUuid(), info.GetContentType())); } - IBufferCompressor::Uncompress(content, zlib, compressed); + zlib.Uncompress(content, compressed->GetData(), compressed->GetSize()); break; } @@ -183,7 +185,9 @@ const FileInfo& info) { MetricsTimer timer(*this, METRICS_READ); - area_.Read(content, info.GetUuid(), info.GetContentType()); + + std::unique_ptr<IMemoryBuffer> buffer(area_.Read(info.GetUuid(), info.GetContentType())); + buffer->MoveToString(content); } @@ -206,7 +210,8 @@ { { MetricsTimer timer(*this, METRICS_READ); - area_.Read(sender.GetBuffer(), info.GetUuid(), info.GetContentType()); + std::unique_ptr<IMemoryBuffer> buffer(area_.Read(info.GetUuid(), info.GetContentType())); + buffer->MoveToString(sender.GetBuffer()); } sender.SetContentType(mime);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancFramework/Sources/IMemoryBuffer.h Thu Jan 28 19:03:19 2021 +0100 @@ -0,0 +1,48 @@ +/** + * 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 Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include <string> +#include <boost/noncopyable.hpp> + +namespace Orthanc +{ + /** + * This class abstracts a memory buffer and its memory unallocation + * function. + **/ + class IMemoryBuffer : public boost::noncopyable + { + public: + virtual ~IMemoryBuffer() + { + } + + // The content of the memory buffer will emptied after this call + virtual void MoveToString(std::string& target) = 0; + + virtual const void* GetData() const = 0; + + virtual size_t GetSize() const = 0; + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancFramework/Sources/MallocMemoryBuffer.cpp Thu Jan 28 19:03:19 2021 +0100 @@ -0,0 +1,87 @@ +/** + * 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 Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/>. + **/ + + +#include "PrecompiledHeaders.h" +#include "MallocMemoryBuffer.h" + +#include "OrthancException.h" + +#include <string.h> + + +namespace Orthanc +{ + MallocMemoryBuffer::MallocMemoryBuffer() : + buffer_(NULL), + size_(0), + free_(NULL) + { + } + + + void MallocMemoryBuffer::Clear() + { + if (size_ != 0) + { + if (free_ == NULL) + { + throw OrthancException(ErrorCode_InternalError); + } + + free_(buffer_); + buffer_ = NULL; + size_ = 0; + free_ = NULL; + } + } + + + void MallocMemoryBuffer::Assign(void* buffer, + size_t size, + FreeFunction freeFunction) + { + Clear(); + + buffer_ = buffer; + size_ = size; + free_ = freeFunction; + + if (size_ != 0 && + free_ == NULL) + { + throw OrthancException(ErrorCode_ParameterOutOfRange, "No valid free() function provided"); + } + } + + + void MallocMemoryBuffer::MoveToString(std::string& target) + { + target.resize(size_); + + if (size_ != 0) + { + memcpy(&target[0], buffer_, size_); + } + + Clear(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancFramework/Sources/MallocMemoryBuffer.h Thu Jan 28 19:03:19 2021 +0100 @@ -0,0 +1,67 @@ +/** + * 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 Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include "IMemoryBuffer.h" +#include "Compatibility.h" + + +namespace Orthanc +{ + class MallocMemoryBuffer : public IMemoryBuffer + { + public: + typedef void (*FreeFunction) (void* buffer); + + private: + void* buffer_; + size_t size_; + FreeFunction free_; + + public: + MallocMemoryBuffer(); + + virtual ~MallocMemoryBuffer() + { + Clear(); + } + + void Clear(); + + void Assign(void* buffer, + size_t size, + FreeFunction freeFunction); + + virtual void MoveToString(std::string& target) ORTHANC_OVERRIDE; + + virtual const void* GetData() const ORTHANC_OVERRIDE + { + return buffer_; + } + + virtual size_t GetSize() const ORTHANC_OVERRIDE + { + return size_; + } + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancFramework/Sources/StringMemoryBuffer.cpp Thu Jan 28 19:03:19 2021 +0100 @@ -0,0 +1,50 @@ +/** + * 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 Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/>. + **/ + + +#include "PrecompiledHeaders.h" +#include "StringMemoryBuffer.h" + + +namespace Orthanc +{ + void StringMemoryBuffer::MoveToString(std::string& target) + { + buffer_.swap(target); + buffer_.clear(); + } + + + IMemoryBuffer* StringMemoryBuffer::CreateFromSwap(std::string& buffer) + { + std::unique_ptr<StringMemoryBuffer> result(new StringMemoryBuffer); + result->Swap(buffer); + return result.release(); + } + + + IMemoryBuffer* StringMemoryBuffer::CreateFromCopy(const std::string& buffer) + { + std::unique_ptr<StringMemoryBuffer> result(new StringMemoryBuffer); + result->Copy(buffer); + return result.release(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancFramework/Sources/StringMemoryBuffer.h Thu Jan 28 19:03:19 2021 +0100 @@ -0,0 +1,62 @@ +/** + * 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 Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include "IMemoryBuffer.h" +#include "Compatibility.h" + +namespace Orthanc +{ + class StringMemoryBuffer : public IMemoryBuffer + { + private: + std::string buffer_; + + public: + void Copy(const std::string& buffer) + { + buffer_ = buffer; + } + + void Swap(std::string& buffer) + { + buffer_.swap(buffer); + } + + virtual void MoveToString(std::string& target) ORTHANC_OVERRIDE; + + virtual const void* GetData() const ORTHANC_OVERRIDE + { + return (buffer_.empty() ? NULL : buffer_.c_str()); + } + + virtual size_t GetSize() const ORTHANC_OVERRIDE + { + return buffer_.size(); + } + + static IMemoryBuffer* CreateFromSwap(std::string& buffer); + + static IMemoryBuffer* CreateFromCopy(const std::string& buffer); + }; +}
--- a/OrthancFramework/UnitTestsSources/FileStorageTests.cpp Thu Jan 28 16:59:40 2021 +0100 +++ b/OrthancFramework/UnitTestsSources/FileStorageTests.cpp Thu Jan 28 19:03:19 2021 +0100 @@ -58,7 +58,10 @@ std::string uid = Toolbox::GenerateUuid(); s.Create(uid.c_str(), &data[0], data.size(), FileContentType_Unknown); std::string d; - s.Read(d, uid, FileContentType_Unknown); + { + std::unique_ptr<IMemoryBuffer> buffer(s.Read(uid, FileContentType_Unknown)); + buffer->MoveToString(d); + } ASSERT_EQ(d.size(), data.size()); ASSERT_FALSE(memcmp(&d[0], &data[0], data.size())); ASSERT_EQ(s.GetSize(uid), data.size()); @@ -73,7 +76,10 @@ std::string uid = Toolbox::GenerateUuid(); s.Create(uid.c_str(), &data[0], data.size(), FileContentType_Unknown); std::string d; - s.Read(d, uid, FileContentType_Unknown); + { + std::unique_ptr<IMemoryBuffer> buffer(s.Read(uid, FileContentType_Unknown)); + buffer->MoveToString(d); + } ASSERT_EQ(d.size(), data.size()); ASSERT_FALSE(memcmp(&d[0], &data[0], data.size())); ASSERT_EQ(s.GetSize(uid), data.size());
--- a/OrthancServer/Plugins/Engine/OrthancPlugins.cpp Thu Jan 28 16:59:40 2021 +0100 +++ b/OrthancServer/Plugins/Engine/OrthancPlugins.cpp Thu Jan 28 19:03:19 2021 +0100 @@ -59,6 +59,7 @@ #include "../../../OrthancFramework/Sources/Images/PngWriter.h" #include "../../../OrthancFramework/Sources/Logging.h" #include "../../../OrthancFramework/Sources/Lua/LuaFunctionCall.h" +#include "../../../OrthancFramework/Sources/MallocMemoryBuffer.h" #include "../../../OrthancFramework/Sources/MetricsRegistry.h" #include "../../../OrthancFramework/Sources/OrthancException.h" #include "../../../OrthancFramework/Sources/SerializationToolbox.h" @@ -198,51 +199,6 @@ }; - class MemoryBuffer64Raii : public boost::noncopyable - { - private: - OrthancPluginMemoryBuffer64 buffer_; - - public: - MemoryBuffer64Raii() - { - buffer_.size = 0; - buffer_.data = NULL; - } - - ~MemoryBuffer64Raii() - { - if (buffer_.size != 0) - { - free(buffer_.data); - } - } - - OrthancPluginMemoryBuffer64* GetObject() - { - return &buffer_; - } - - void ToString(std::string& target) const - { - if ((buffer_.data == NULL && buffer_.size != 0) || - (buffer_.data != NULL && buffer_.size == 0)) - { - throw OrthancException(ErrorCode_Plugin); - } - else - { - target.resize(buffer_.size); - - if (buffer_.size != 0) - { - memcpy(&target[0], buffer_.data, buffer_.size); - } - } - } - }; - - class StorageAreaBase : public IStorageArea { private: @@ -328,38 +284,27 @@ } } - virtual void Read(std::string& content, - const std::string& uuid, - FileContentType type) ORTHANC_OVERRIDE - { + virtual IMemoryBuffer* Read(const std::string& uuid, + FileContentType type) ORTHANC_OVERRIDE + { + std::unique_ptr<MallocMemoryBuffer> result(new MallocMemoryBuffer); + void* buffer = NULL; int64_t size = 0; OrthancPluginErrorCode error = read_ (&buffer, &size, uuid.c_str(), Plugins::Convert(type)); - if (error != OrthancPluginErrorCode_Success) + if (error == OrthancPluginErrorCode_Success) + { + result->Assign(buffer, size, free_); + return result.release(); + } + else { GetErrorDictionary().LogError(error, true); throw OrthancException(static_cast<ErrorCode>(error)); } - - try - { - content.resize(static_cast<size_t>(size)); - } - catch (...) - { - Free(buffer); - throw OrthancException(ErrorCode_NotEnoughMemory); - } - - if (size > 0) - { - memcpy(&content[0], buffer, static_cast<size_t>(size)); - } - - Free(buffer); } }; @@ -384,22 +329,25 @@ } } - virtual void Read(std::string& content, - const std::string& uuid, - FileContentType type) ORTHANC_OVERRIDE - { - MemoryBuffer64Raii buffer; + virtual IMemoryBuffer* Read(const std::string& uuid, + FileContentType type) ORTHANC_OVERRIDE + { + std::unique_ptr<MallocMemoryBuffer> result(new MallocMemoryBuffer); + + OrthancPluginMemoryBuffer64 buffer; - OrthancPluginErrorCode error = readWhole_ - (buffer.GetObject(), uuid.c_str(), Plugins::Convert(type)); - - if (error != OrthancPluginErrorCode_Success) + OrthancPluginErrorCode error = readWhole_(&buffer, uuid.c_str(), Plugins::Convert(type)); + + if (error == OrthancPluginErrorCode_Success) + { + result->Assign(buffer.data, buffer.size, ::free); + return result.release(); + } + else { GetErrorDictionary().LogError(error, true); throw OrthancException(static_cast<ErrorCode>(error)); } - - buffer.ToString(content); } }; @@ -4196,9 +4144,8 @@ const _OrthancPluginStorageAreaRead& p = *reinterpret_cast<const _OrthancPluginStorageAreaRead*>(parameters); IStorageArea& storage = *reinterpret_cast<IStorageArea*>(p.storageArea); - std::string content; - storage.Read(content, p.uuid, Plugins::Convert(p.type)); - CopyToMemoryBuffer(*p.target, content); + std::unique_ptr<IMemoryBuffer> content(storage.Read(p.uuid, Plugins::Convert(p.type))); + CopyToMemoryBuffer(*p.target, content->GetData(), content->GetSize()); return true; }
--- a/OrthancServer/Sources/OrthancInitialization.cpp Thu Jan 28 16:59:40 2021 +0100 +++ b/OrthancServer/Sources/OrthancInitialization.cpp Thu Jan 28 19:03:19 2021 +0100 @@ -359,7 +359,7 @@ virtual void Create(const std::string& uuid, const void* content, size_t size, - FileContentType type) + FileContentType type) ORTHANC_OVERRIDE { if (type != FileContentType_Dicom) { @@ -367,13 +367,12 @@ } } - virtual void Read(std::string& content, - const std::string& uuid, - FileContentType type) + virtual IMemoryBuffer* Read(const std::string& uuid, + FileContentType type) ORTHANC_OVERRIDE { if (type != FileContentType_Dicom) { - storage_.Read(content, uuid, type); + return storage_.Read(uuid, type); } else { @@ -382,7 +381,7 @@ } virtual void Remove(const std::string& uuid, - FileContentType type) + FileContentType type) ORTHANC_OVERRIDE { if (type != FileContentType_Dicom) {