# HG changeset patch # User Sebastien Jodogne # Date 1354208466 -3600 # Node ID e7432706b354479531527b46cd9084fb111a3dec # Parent bb8c260c0092b70005bd2acb63fee37e06eba4e7 accessors to storage diff -r bb8c260c0092 -r e7432706b354 CMakeLists.txt --- a/CMakeLists.txt Thu Nov 29 15:06:50 2012 +0100 +++ b/CMakeLists.txt Thu Nov 29 18:01:06 2012 +0100 @@ -104,6 +104,8 @@ Core/DicomFormat/DicomIntegerPixelAccessor.cpp Core/DicomFormat/DicomInstanceHasher.cpp Core/FileStorage.cpp + Core/FileStorage/StorageAccessor.cpp + Core/FileStorage/CompressedFileStorageAccessor.cpp Core/HttpServer/EmbeddedResourceHttpHandler.cpp Core/HttpServer/FilesystemHttpHandler.cpp Core/HttpServer/HttpHandler.cpp diff -r bb8c260c0092 -r e7432706b354 Core/Compression/ZlibCompressor.cpp --- a/Core/Compression/ZlibCompressor.cpp Thu Nov 29 15:06:50 2012 +0100 +++ b/Core/Compression/ZlibCompressor.cpp Thu Nov 29 18:01:06 2012 +0100 @@ -110,7 +110,15 @@ size_t uncompressedLength; memcpy(&uncompressedLength, compressed, sizeof(size_t)); - uncompressed.resize(uncompressedLength); + + try + { + uncompressed.resize(uncompressedLength); + } + catch (...) + { + throw OrthancException("Zlib: Corrupted compressed buffer"); + } uLongf tmp = uncompressedLength; int error = uncompress diff -r bb8c260c0092 -r e7432706b354 Core/Enumerations.h --- a/Core/Enumerations.h Thu Nov 29 15:06:50 2012 +0100 +++ b/Core/Enumerations.h Thu Nov 29 18:01:06 2012 +0100 @@ -63,4 +63,10 @@ PixelFormat_Grayscale8, PixelFormat_Grayscale16 }; + + enum CompressionType + { + CompressionType_None = 1, + CompressionType_Zlib = 2 + }; } diff -r bb8c260c0092 -r e7432706b354 Core/FileStorage.h --- a/Core/FileStorage.h Thu Nov 29 15:06:50 2012 +0100 +++ b/Core/FileStorage.h Thu Nov 29 18:01:06 2012 +0100 @@ -42,8 +42,8 @@ class FileStorage : public boost::noncopyable { // TODO REMOVE THIS - friend class HttpOutput; friend class FilesystemHttpSender; + friend class FileStorageAccessor; private: std::auto_ptr compressor_; diff -r bb8c260c0092 -r e7432706b354 Core/FileStorage/CompressedFileStorageAccessor.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/FileStorage/CompressedFileStorageAccessor.cpp Thu Nov 29 18:01:06 2012 +0100 @@ -0,0 +1,114 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * In addition, as a special exception, the copyright holders of this + * program give permission to link the code of its release with the + * OpenSSL project's "OpenSSL" library (or with modified versions of it + * that use the same license as the "OpenSSL" library), and distribute + * the linked executables. You must obey the GNU General Public License + * in all respects for all of the code used other than "OpenSSL". If you + * modify file(s) with this exception, you may extend this exception to + * your version of the file(s), but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source files + * in the program, then also delete it here. + * + * 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + **/ + + +#include "CompressedFileStorageAccessor.h" + +#include "../OrthancException.h" +#include "FileStorageAccessor.h" +#include "../HttpServer/BufferHttpSender.h" + +namespace Orthanc +{ + std::string CompressedFileStorageAccessor::WriteInternal(const void* data, + size_t size) + { + switch (compressionType_) + { + case CompressionType_None: + return storage_.Create(data, size); + + case CompressionType_Zlib: + { + std::string compressed; + zlib_.Compress(compressed, data, size); + return storage_.Create(compressed); + } + + default: + throw OrthancException(ErrorCode_NotImplemented); + } + } + + CompressedFileStorageAccessor::CompressedFileStorageAccessor(FileStorage& storage) : + storage_(storage) + { + compressionType_ = CompressionType_Zlib; + } + + void CompressedFileStorageAccessor::Read(std::string& content, + const std::string& uuid) + { + switch (compressionType_) + { + case CompressionType_None: + storage_.ReadFile(content, uuid); + break; + + case CompressionType_Zlib: + { + std::string compressed; + storage_.ReadFile(compressed, uuid); + zlib_.Uncompress(content, compressed); + break; + } + + default: + throw OrthancException(ErrorCode_NotImplemented); + } + } + + HttpFileSender* CompressedFileStorageAccessor::ConstructHttpFileSender(const std::string& uuid) + { + switch (compressionType_) + { + case CompressionType_None: + { + FileStorageAccessor uncompressedAccessor(storage_); + return uncompressedAccessor.ConstructHttpFileSender(uuid); + } + + case CompressionType_Zlib: + { + std::string compressed; + storage_.ReadFile(compressed, uuid); + + std::auto_ptr sender(new BufferHttpSender); + zlib_.Uncompress(sender->GetBuffer(), compressed); + + return sender.release(); + } + + default: + throw OrthancException(ErrorCode_NotImplemented); + } + } +} diff -r bb8c260c0092 -r e7432706b354 Core/FileStorage/CompressedFileStorageAccessor.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/FileStorage/CompressedFileStorageAccessor.h Thu Nov 29 18:01:06 2012 +0100 @@ -0,0 +1,70 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * In addition, as a special exception, the copyright holders of this + * program give permission to link the code of its release with the + * OpenSSL project's "OpenSSL" library (or with modified versions of it + * that use the same license as the "OpenSSL" library), and distribute + * the linked executables. You must obey the GNU General Public License + * in all respects for all of the code used other than "OpenSSL". If you + * modify file(s) with this exception, you may extend this exception to + * your version of the file(s), but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source files + * in the program, then also delete it here. + * + * 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + **/ + + +#pragma once + +#include "StorageAccessor.h" +#include "../FileStorage.h" +#include "../Compression/ZlibCompressor.h" + +namespace Orthanc +{ + class CompressedFileStorageAccessor : public StorageAccessor + { + private: + FileStorage& storage_; + ZlibCompressor zlib_; + CompressionType compressionType_; + + protected: + virtual std::string WriteInternal(const void* data, + size_t size); + + public: + CompressedFileStorageAccessor(FileStorage& storage); + + void SetCompressionForNextOperations(CompressionType compression) + { + compressionType_ = compression; + } + + CompressionType GetCompressionForNextOperations() + { + return compressionType_; + } + + virtual void Read(std::string& content, + const std::string& uuid); + + virtual HttpFileSender* ConstructHttpFileSender(const std::string& uuid); + }; +} diff -r bb8c260c0092 -r e7432706b354 Core/FileStorage/FileStorageAccessor.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/FileStorage/FileStorageAccessor.h Thu Nov 29 18:01:06 2012 +0100 @@ -0,0 +1,69 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * In addition, as a special exception, the copyright holders of this + * program give permission to link the code of its release with the + * OpenSSL project's "OpenSSL" library (or with modified versions of it + * that use the same license as the "OpenSSL" library), and distribute + * the linked executables. You must obey the GNU General Public License + * in all respects for all of the code used other than "OpenSSL". If you + * modify file(s) with this exception, you may extend this exception to + * your version of the file(s), but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source files + * in the program, then also delete it here. + * + * 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + **/ + + +#pragma once + +#include "StorageAccessor.h" +#include "../FileStorage.h" +#include "../HttpServer/FilesystemHttpSender.h" + +namespace Orthanc +{ + class FileStorageAccessor : public StorageAccessor + { + private: + FileStorage& storage_; + + protected: + virtual std::string WriteInternal(const void* data, + size_t size) + { + return storage_.Create(data, size); + } + + public: + FileStorageAccessor(FileStorage& storage) : storage_(storage) + { + } + + virtual void Read(std::string& content, + const std::string& uuid) + { + storage_.ReadFile(content, uuid); + } + + virtual HttpFileSender* ConstructHttpFileSender(const std::string& uuid) + { + return new FilesystemHttpSender(storage_.GetPath(uuid)); + } + }; +} diff -r bb8c260c0092 -r e7432706b354 Core/FileStorage/StorageAccessor.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/FileStorage/StorageAccessor.cpp Thu Nov 29 18:01:06 2012 +0100 @@ -0,0 +1,60 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * In addition, as a special exception, the copyright holders of this + * program give permission to link the code of its release with the + * OpenSSL project's "OpenSSL" library (or with modified versions of it + * that use the same license as the "OpenSSL" library), and distribute + * the linked executables. You must obey the GNU General Public License + * in all respects for all of the code used other than "OpenSSL". If you + * modify file(s) with this exception, you may extend this exception to + * your version of the file(s), but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source files + * in the program, then also delete it here. + * + * 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + **/ + + +#include "StorageAccessor.h" + +namespace Orthanc +{ + std::string StorageAccessor::Write(const std::vector& content) + { + if (content.size() == 0) + { + return WriteInternal(NULL, 0); + } + else + { + return WriteInternal(&content[0], content.size()); + } + } + + std::string StorageAccessor::Write(const std::string& content) + { + if (content.size() == 0) + { + return WriteInternal(NULL, 0); + } + else + { + return WriteInternal(&content[0], content.size()); + } + } +} diff -r bb8c260c0092 -r e7432706b354 Core/FileStorage/StorageAccessor.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/FileStorage/StorageAccessor.h Thu Nov 29 18:01:06 2012 +0100 @@ -0,0 +1,70 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * In addition, as a special exception, the copyright holders of this + * program give permission to link the code of its release with the + * OpenSSL project's "OpenSSL" library (or with modified versions of it + * that use the same license as the "OpenSSL" library), and distribute + * the linked executables. You must obey the GNU General Public License + * in all respects for all of the code used other than "OpenSSL". If you + * modify file(s) with this exception, you may extend this exception to + * your version of the file(s), but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source files + * in the program, then also delete it here. + * + * 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + **/ + + +#pragma once + +#include "../HttpServer/HttpFileSender.h" + +#include +#include +#include +#include + +namespace Orthanc +{ + class StorageAccessor : boost::noncopyable + { + protected: + virtual std::string WriteInternal(const void* data, + size_t size) = 0; + + public: + virtual ~StorageAccessor() + { + } + + std::string Write(const void* data, + size_t size) + { + return WriteInternal(data, size); + } + + std::string Write(const std::vector& content); + + std::string Write(const std::string& content); + + virtual void Read(std::string& content, + const std::string& uuid) = 0; + + virtual HttpFileSender* ConstructHttpFileSender(const std::string& uuid) = 0; + }; +} diff -r bb8c260c0092 -r e7432706b354 Core/HttpServer/BufferHttpSender.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/HttpServer/BufferHttpSender.h Thu Nov 29 18:01:06 2012 +0100 @@ -0,0 +1,68 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * In addition, as a special exception, the copyright holders of this + * program give permission to link the code of its release with the + * OpenSSL project's "OpenSSL" library (or with modified versions of it + * that use the same license as the "OpenSSL" library), and distribute + * the linked executables. You must obey the GNU General Public License + * in all respects for all of the code used other than "OpenSSL". If you + * modify file(s) with this exception, you may extend this exception to + * your version of the file(s), but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source files + * in the program, then also delete it here. + * + * 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + **/ + +#pragma once + +#include "HttpFileSender.h" + +namespace Orthanc +{ + class BufferHttpSender : public HttpFileSender + { + private: + std::string buffer_; + + protected: + virtual uint64_t GetFileSize() + { + return buffer_.size(); + } + + virtual bool SendData(HttpOutput& output) + { + if (buffer_.size()) + output.Send(&buffer_[0], buffer_.size()); + + return true; + } + + public: + std::string& GetBuffer() + { + return buffer_; + } + + const std::string& GetBuffer() const + { + return buffer_; + } + }; +} diff -r bb8c260c0092 -r e7432706b354 OrthancServer/ServerEnumerations.h --- a/OrthancServer/ServerEnumerations.h Thu Nov 29 15:06:50 2012 +0100 +++ b/OrthancServer/ServerEnumerations.h Thu Nov 29 18:01:06 2012 +0100 @@ -63,12 +63,6 @@ ResourceType_Instance = 4 }; - enum CompressionType - { - CompressionType_None = 1, - CompressionType_Zlib = 2 - }; - enum MetadataType { MetadataType_Instance_IndexInSeries = 2, diff -r bb8c260c0092 -r e7432706b354 UnitTests/RestApi.cpp --- a/UnitTests/RestApi.cpp Thu Nov 29 15:06:50 2012 +0100 +++ b/UnitTests/RestApi.cpp Thu Nov 29 18:01:06 2012 +0100 @@ -4,6 +4,9 @@ #include #include "../Core/RestApi/RestApi.h" +#include "../Core/Uuid.h" +#include "../Core/OrthancException.h" +#include "../Core/Compression/ZlibCompressor.h" using namespace Orthanc; @@ -85,3 +88,88 @@ } #endif + + + +#include "../Core/FileStorage.h" +#include "../Core/HttpServer/FilesystemHttpSender.h" +#include "../Core/HttpServer/BufferHttpSender.h" +#include "../Core/FileStorage/FileStorageAccessor.h" +#include "../Core/FileStorage/CompressedFileStorageAccessor.h" + + + +TEST(FileStorageAccessor, Simple) +{ + FileStorage s("FileStorageUnitTests"); + FileStorageAccessor accessor(s); + + std::string data = "Hello world"; + std::string id = accessor.Write(data); + + std::string r; + accessor.Read(r, id); + + ASSERT_EQ(data, r); +} + + + +TEST(FileStorageAccessor, NoCompression) +{ + FileStorage s("FileStorageUnitTests"); + CompressedFileStorageAccessor accessor(s); + + accessor.SetCompressionForNextOperations(CompressionType_None); + std::string data = "Hello world"; + std::string id = accessor.Write(data); + + std::string r; + accessor.Read(r, id); + + ASSERT_EQ(data, r); +} + + +TEST(FileStorageAccessor, Compression) +{ + FileStorage s("FileStorageUnitTests"); + CompressedFileStorageAccessor accessor(s); + + accessor.SetCompressionForNextOperations(CompressionType_Zlib); + std::string data = "Hello world"; + std::string id = accessor.Write(data); + + std::string r; + accessor.Read(r, id); + + ASSERT_EQ(data, r); +} + + +TEST(FileStorageAccessor, Mix) +{ + FileStorage s("FileStorageUnitTests"); + CompressedFileStorageAccessor accessor(s); + + std::string r; + std::string compressedData = "Hello"; + std::string uncompressedData = "HelloWorld"; + + accessor.SetCompressionForNextOperations(CompressionType_Zlib); + std::string compressedId = accessor.Write(compressedData); + + accessor.SetCompressionForNextOperations(CompressionType_None); + std::string uncompressedId = accessor.Write(uncompressedData); + + accessor.SetCompressionForNextOperations(CompressionType_Zlib); + accessor.Read(r, compressedId); + ASSERT_EQ(compressedData, r); + + accessor.SetCompressionForNextOperations(CompressionType_None); + accessor.Read(r, compressedId); + ASSERT_NE(compressedData, r); + + accessor.SetCompressionForNextOperations(CompressionType_Zlib); + ASSERT_THROW(accessor.Read(r, uncompressedId), OrthancException); +}