# HG changeset patch # User Sebastien Jodogne # Date 1418043267 -3600 # Node ID 32fcc5dc7562cf6991f47accd14216374fd5e3a2 # Parent 54bf0f0245f4eb2f23e9b94fcb0503a82e11d1a9 abstraction diff -r 54bf0f0245f4 -r 32fcc5dc7562 CMakeLists.txt --- a/CMakeLists.txt Mon Dec 08 12:56:30 2014 +0100 +++ b/CMakeLists.txt Mon Dec 08 13:54:27 2014 +0100 @@ -164,6 +164,7 @@ OrthancServer/ServerToolbox.cpp OrthancServer/OrthancFindRequestHandler.cpp OrthancServer/OrthancMoveRequestHandler.cpp + OrthancServer/ExportedResource.cpp # From "lua-scripting" branch OrthancServer/DicomInstanceToStore.cpp diff -r 54bf0f0245f4 -r 32fcc5dc7562 OrthancServer/DatabaseWrapper.cpp --- a/OrthancServer/DatabaseWrapper.cpp Mon Dec 08 12:56:30 2014 +0100 +++ b/OrthancServer/DatabaseWrapper.cpp Mon Dec 08 13:54:27 2014 +0100 @@ -39,6 +39,7 @@ #include #include +#include namespace Orthanc { @@ -359,10 +360,11 @@ s.BindInt64(0, id); s.Run(); - if (signalRemainingAncestor_->HasRemainingAncestor()) + if (signalRemainingAncestor_->HasRemainingAncestor() && + listener_ != NULL) { - listener_.SignalRemainingAncestor(signalRemainingAncestor_->GetRemainingAncestorType(), - signalRemainingAncestor_->GetRemainingAncestorId()); + listener_->SignalRemainingAncestor(signalRemainingAncestor_->GetRemainingAncestorType(), + signalRemainingAncestor_->GetRemainingAncestorId()); } } @@ -610,7 +612,8 @@ s.Run(); } - listener_.SignalChange(change); + assert(listener_ != NULL); + listener_->SignalChange(change); } @@ -785,16 +788,13 @@ } - DatabaseWrapper::DatabaseWrapper(const std::string& path, - IServerIndexListener& listener) : - listener_(listener) + DatabaseWrapper::DatabaseWrapper(const std::string& path) : listener_(NULL) { db_.Open(path); Open(); } - DatabaseWrapper::DatabaseWrapper(IServerIndexListener& listener) : - listener_(listener) + DatabaseWrapper::DatabaseWrapper() : listener_(NULL) { db_.OpenInMemory(); Open(); @@ -870,8 +870,13 @@ signalRemainingAncestor_ = new Internals::SignalRemainingAncestor; db_.Register(signalRemainingAncestor_); - db_.Register(new Internals::SignalFileDeleted(listener_)); - db_.Register(new Internals::SignalResourceDeleted(listener_)); + } + + void DatabaseWrapper::SetListener(IServerIndexListener& listener) + { + listener_ = &listener; + db_.Register(new Internals::SignalFileDeleted(listener)); + db_.Register(new Internals::SignalResourceDeleted(listener)); } uint64_t DatabaseWrapper::GetResourceCount(ResourceType resourceType) diff -r 54bf0f0245f4 -r 32fcc5dc7562 OrthancServer/DatabaseWrapper.h --- a/OrthancServer/DatabaseWrapper.h Mon Dec 08 12:56:30 2014 +0100 +++ b/OrthancServer/DatabaseWrapper.h Mon Dec 08 13:54:27 2014 +0100 @@ -32,16 +32,10 @@ #pragma once +#include "IDatabaseWrapper.h" + #include "../Core/SQLite/Connection.h" #include "../Core/SQLite/Transaction.h" -#include "../Core/DicomFormat/DicomInstanceHasher.h" -#include "../Core/FileStorage/FileInfo.h" -#include "IServerIndexListener.h" - -#include -#include - -#include "ExportedResource.h" namespace Orthanc { @@ -55,10 +49,10 @@ * translates low-level requests into SQL statements. Mutual * exclusion MUST be implemented at a higher level. **/ - class DatabaseWrapper + class DatabaseWrapper : public IDatabaseWrapper { private: - IServerIndexListener& listener_; + IServerIndexListener* listener_; SQLite::Connection db_; Internals::SignalRemainingAncestor* signalRemainingAncestor_; @@ -75,141 +69,137 @@ unsigned int maxResults); public: - void SetGlobalProperty(GlobalProperty property, - const std::string& value); + DatabaseWrapper(const std::string& path); + + DatabaseWrapper(); + + virtual void SetListener(IServerIndexListener& listener); - bool LookupGlobalProperty(std::string& target, - GlobalProperty property); + virtual void SetGlobalProperty(GlobalProperty property, + const std::string& value); - int64_t CreateResource(const std::string& publicId, - ResourceType type); + virtual bool LookupGlobalProperty(std::string& target, + GlobalProperty property); + + virtual int64_t CreateResource(const std::string& publicId, + ResourceType type); - bool LookupResource(const std::string& publicId, - int64_t& id, - ResourceType& type); + virtual bool LookupResource(const std::string& publicId, + int64_t& id, + ResourceType& type); - bool LookupParent(int64_t& parentId, - int64_t resourceId); + virtual bool LookupParent(int64_t& parentId, + int64_t resourceId); - std::string GetPublicId(int64_t resourceId); + virtual std::string GetPublicId(int64_t resourceId); + + virtual ResourceType GetResourceType(int64_t resourceId); - ResourceType GetResourceType(int64_t resourceId); + virtual void AttachChild(int64_t parent, + int64_t child); - void AttachChild(int64_t parent, - int64_t child); + virtual void DeleteResource(int64_t id); - void DeleteResource(int64_t id); + virtual void SetMetadata(int64_t id, + MetadataType type, + const std::string& value); + + virtual void DeleteMetadata(int64_t id, + MetadataType type); - void SetMetadata(int64_t id, - MetadataType type, - const std::string& value); + virtual bool LookupMetadata(std::string& target, + int64_t id, + MetadataType type); - void DeleteMetadata(int64_t id, - MetadataType type); + virtual void ListAvailableMetadata(std::list& target, + int64_t id); - bool LookupMetadata(std::string& target, - int64_t id, - MetadataType type); + virtual void AddAttachment(int64_t id, + const FileInfo& attachment); - void ListAvailableMetadata(std::list& target, - int64_t id); + virtual void DeleteAttachment(int64_t id, + FileContentType attachment); + + virtual void ListAvailableAttachments(std::list& result, + int64_t id); - void AddAttachment(int64_t id, - const FileInfo& attachment); + virtual bool LookupAttachment(FileInfo& attachment, + int64_t id, + FileContentType contentType); - void DeleteAttachment(int64_t id, - FileContentType attachment); + virtual void SetMainDicomTags(int64_t id, + const DicomMap& tags); - void ListAvailableAttachments(std::list& result, + virtual void GetMainDicomTags(DicomMap& map, int64_t id); - bool LookupAttachment(FileInfo& attachment, - int64_t id, - FileContentType contentType); + virtual void GetChildrenPublicId(std::list& result, + int64_t id); - void SetMainDicomTags(int64_t id, - const DicomMap& tags); + virtual void GetChildrenInternalId(std::list& result, + int64_t id); - void GetMainDicomTags(DicomMap& map, - int64_t id); - - void GetChildrenPublicId(std::list& result, - int64_t id); + virtual void LogChange(int64_t internalId, + const ServerIndexChange& change); - void GetChildrenInternalId(std::list& result, - int64_t id); - - void LogChange(int64_t internalId, - const ServerIndexChange& change); + virtual void GetChanges(std::list& target /*out*/, + bool& done /*out*/, + int64_t since, + unsigned int maxResults); - void GetChanges(std::list& target /*out*/, - bool& done /*out*/, - int64_t since, - unsigned int maxResults); + virtual void GetLastChange(std::list& target /*out*/); - void GetLastChange(std::list& target /*out*/); - - void LogExportedResource(const ExportedResource& resource); + virtual void LogExportedResource(const ExportedResource& resource); - void GetExportedResources(std::list& target /*out*/, - bool& done /*out*/, - int64_t since, - unsigned int maxResults); - - void GetLastExportedResource(std::list& target /*out*/); + virtual void GetExportedResources(std::list& target /*out*/, + bool& done /*out*/, + int64_t since, + unsigned int maxResults); - uint64_t GetTotalCompressedSize(); - - uint64_t GetTotalUncompressedSize(); + virtual void GetLastExportedResource(std::list& target /*out*/); - uint64_t GetResourceCount(ResourceType resourceType); + virtual uint64_t GetTotalCompressedSize(); + + virtual uint64_t GetTotalUncompressedSize(); - void GetAllPublicIds(std::list& target, - ResourceType resourceType); + virtual uint64_t GetResourceCount(ResourceType resourceType); - bool SelectPatientToRecycle(int64_t& internalId); + virtual void GetAllPublicIds(std::list& target, + ResourceType resourceType); - bool SelectPatientToRecycle(int64_t& internalId, - int64_t patientIdToAvoid); - - bool IsProtectedPatient(int64_t internalId); + virtual bool SelectPatientToRecycle(int64_t& internalId); - void SetProtectedPatient(int64_t internalId, - bool isProtected); + virtual bool SelectPatientToRecycle(int64_t& internalId, + int64_t patientIdToAvoid); + + virtual bool IsProtectedPatient(int64_t internalId); - DatabaseWrapper(const std::string& path, - IServerIndexListener& listener); + virtual void SetProtectedPatient(int64_t internalId, + bool isProtected); - DatabaseWrapper(IServerIndexListener& listener); - - SQLite::ITransaction* StartTransaction() + virtual SQLite::ITransaction* StartTransaction() { return new SQLite::Transaction(db_); } - const char* GetErrorMessage() const - { - return db_.GetErrorMessage(); - } - - void FlushToDisk() + virtual void FlushToDisk() { db_.FlushToDisk(); } - void ClearTable(const std::string& tableName); + virtual void ClearTable(const std::string& tableName); - bool IsExistingResource(int64_t internalId); + virtual bool IsExistingResource(int64_t internalId); - void LookupIdentifier(std::list& result, - const DicomTag& tag, - const std::string& value); + virtual void LookupIdentifier(std::list& result, + const DicomTag& tag, + const std::string& value); - void LookupIdentifier(std::list& result, - const std::string& value); + virtual void LookupIdentifier(std::list& result, + const std::string& value); - void GetAllMetadata(std::map& result, - int64_t id); + virtual void GetAllMetadata(std::map& result, + int64_t id); @@ -218,6 +208,11 @@ * The methods declared below are for unit testing only! **/ + const char* GetErrorMessage() const + { + return db_.GetErrorMessage(); + } + void GetChildren(std::list& childrenPublicIds, int64_t id); diff -r 54bf0f0245f4 -r 32fcc5dc7562 OrthancServer/ExportedResource.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancServer/ExportedResource.cpp Mon Dec 08 13:54:27 2014 +0100 @@ -0,0 +1,69 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2014 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 "ExportedResource.h" + +#include "../Core/OrthancException.h" + +namespace Orthanc +{ + void ExportedResource::Format(Json::Value& item) const + { + item = Json::objectValue; + item["Seq"] = static_cast(seq_); + item["ResourceType"] = EnumerationToString(resourceType_); + item["ID"] = publicId_; + item["Path"] = GetBasePath(resourceType_, publicId_); + item["RemoteModality"] = modality_; + item["Date"] = date_; + + // WARNING: Do not add "break" below and do not reorder the case items! + switch (resourceType_) + { + case ResourceType_Instance: + item["SOPInstanceUID"] = sopInstanceUid_; + + case ResourceType_Series: + item["SeriesInstanceUID"] = seriesInstanceUid_; + + case ResourceType_Study: + item["StudyInstanceUID"] = studyInstanceUid_; + + case ResourceType_Patient: + item["PatientID"] = patientId_; + break; + + default: + throw OrthancException(ErrorCode_InternalError); + } + } +} diff -r 54bf0f0245f4 -r 32fcc5dc7562 OrthancServer/ExportedResource.h --- a/OrthancServer/ExportedResource.h Mon Dec 08 12:56:30 2014 +0100 +++ b/OrthancServer/ExportedResource.h Mon Dec 08 13:54:27 2014 +0100 @@ -40,7 +40,7 @@ namespace Orthanc { - struct ExportedResource + class ExportedResource { private: int64_t seq_; @@ -120,35 +120,6 @@ return sopInstanceUid_; } - void Format(Json::Value& item) const - { - item = Json::objectValue; - item["Seq"] = static_cast(seq_); - item["ResourceType"] = EnumerationToString(resourceType_); - item["ID"] = publicId_; - item["Path"] = GetBasePath(resourceType_, publicId_); - item["RemoteModality"] = modality_; - item["Date"] = date_; - - // WARNING: Do not add "break" below and do not reorder the case items! - switch (resourceType_) - { - case ResourceType_Instance: - item["SOPInstanceUID"] = sopInstanceUid_; - - case ResourceType_Series: - item["SeriesInstanceUID"] = seriesInstanceUid_; - - case ResourceType_Study: - item["StudyInstanceUID"] = studyInstanceUid_; - - case ResourceType_Patient: - item["PatientID"] = patientId_; - break; - - default: - throw OrthancException(ErrorCode_InternalError); - } - } + void Format(Json::Value& item) const; }; } diff -r 54bf0f0245f4 -r 32fcc5dc7562 OrthancServer/IDatabaseWrapper.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancServer/IDatabaseWrapper.h Mon Dec 08 13:54:27 2014 +0100 @@ -0,0 +1,176 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2014 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 "../Core/DicomFormat/DicomMap.h" +#include "../Core/SQLite/ITransaction.h" +#include "../Core/FileStorage/FileInfo.h" +#include "IServerIndexListener.h" +#include "ExportedResource.h" + +#include +#include + +namespace Orthanc +{ + class IDatabaseWrapper : public boost::noncopyable + { + public: + virtual ~IDatabaseWrapper() + { + } + + virtual void AddAttachment(int64_t id, + const FileInfo& attachment) = 0; + + virtual void AttachChild(int64_t parent, + int64_t child) = 0; + + virtual void ClearTable(const std::string& tableName) = 0; + + virtual int64_t CreateResource(const std::string& publicId, + ResourceType type) = 0; + + virtual void DeleteAttachment(int64_t id, + FileContentType attachment) = 0; + + virtual void DeleteMetadata(int64_t id, + MetadataType type) = 0; + + virtual void DeleteResource(int64_t id) = 0; + + virtual void FlushToDisk() = 0; + + virtual void GetAllMetadata(std::map& result, + int64_t id) = 0; + + virtual void GetAllPublicIds(std::list& target, + ResourceType resourceType) = 0; + + + virtual void GetChanges(std::list& target /*out*/, + bool& done /*out*/, + int64_t since, + unsigned int maxResults) = 0; + + virtual void GetChildrenInternalId(std::list& result, + int64_t id) = 0; + + virtual void GetChildrenPublicId(std::list& result, + int64_t id) = 0; + + virtual void GetExportedResources(std::list& target /*out*/, + bool& done /*out*/, + int64_t since, + unsigned int maxResults) = 0; + + virtual void GetLastChange(std::list& target /*out*/) = 0; + + virtual void GetLastExportedResource(std::list& target /*out*/) = 0; + + virtual void GetMainDicomTags(DicomMap& map, + int64_t id) = 0; + + virtual std::string GetPublicId(int64_t resourceId) = 0; + + virtual uint64_t GetResourceCount(ResourceType resourceType) = 0; + + virtual ResourceType GetResourceType(int64_t resourceId) = 0; + + virtual uint64_t GetTotalCompressedSize() = 0; + + virtual uint64_t GetTotalUncompressedSize() = 0; + + virtual bool IsExistingResource(int64_t internalId) = 0; + + virtual bool IsProtectedPatient(int64_t internalId) = 0; + + virtual void ListAvailableMetadata(std::list& target, + int64_t id) = 0; + + virtual void ListAvailableAttachments(std::list& result, + int64_t id) = 0; + + virtual void LogChange(int64_t internalId, + const ServerIndexChange& change) = 0; + + virtual void LogExportedResource(const ExportedResource& resource) = 0; + + virtual bool LookupAttachment(FileInfo& attachment, + int64_t id, + FileContentType contentType) = 0; + + virtual bool LookupGlobalProperty(std::string& target, + GlobalProperty property) = 0; + + virtual void LookupIdentifier(std::list& result, + const DicomTag& tag, + const std::string& value) = 0; + + virtual void LookupIdentifier(std::list& result, + const std::string& value) = 0; + + virtual bool LookupMetadata(std::string& target, + int64_t id, + MetadataType type) = 0; + + virtual bool LookupParent(int64_t& parentId, + int64_t resourceId) = 0; + + virtual bool LookupResource(const std::string& publicId, + int64_t& id, + ResourceType& type) = 0; + + virtual bool SelectPatientToRecycle(int64_t& internalId) = 0; + + virtual bool SelectPatientToRecycle(int64_t& internalId, + int64_t patientIdToAvoid) = 0; + + virtual void SetGlobalProperty(GlobalProperty property, + const std::string& value) = 0; + + virtual void SetMainDicomTags(int64_t id, + const DicomMap& tags) = 0; + + virtual void SetMetadata(int64_t id, + MetadataType type, + const std::string& value) = 0; + + virtual void SetProtectedPatient(int64_t internalId, + bool isProtected) = 0; + + virtual SQLite::ITransaction* StartTransaction() = 0; + + virtual void SetListener(IServerIndexListener& listener) = 0; + }; +} diff -r 54bf0f0245f4 -r 32fcc5dc7562 OrthancServer/OrthancRestApi/OrthancRestChanges.cpp --- a/OrthancServer/OrthancRestApi/OrthancRestChanges.cpp Mon Dec 08 12:56:30 2014 +0100 +++ b/OrthancServer/OrthancRestApi/OrthancRestChanges.cpp Mon Dec 08 13:54:27 2014 +0100 @@ -81,11 +81,16 @@ GetSinceAndLimit(since, limit, last, call); Json::Value result; - if ((!last && context.GetIndex().GetChanges(result, since, limit)) || - ( last && context.GetIndex().GetLastChange(result))) + if (last) { - call.GetOutput().AnswerJson(result); + context.GetIndex().GetLastChange(result); } + else + { + context.GetIndex().GetChanges(result, since, limit); + } + + call.GetOutput().AnswerJson(result); } @@ -108,11 +113,16 @@ GetSinceAndLimit(since, limit, last, call); Json::Value result; - if ((!last && context.GetIndex().GetExportedResources(result, since, limit)) || - ( last && context.GetIndex().GetLastExportedResource(result))) + if (last) { - call.GetOutput().AnswerJson(result); + context.GetIndex().GetLastExportedResource(result); } + else + { + context.GetIndex().GetExportedResources(result, since, limit); + } + + call.GetOutput().AnswerJson(result); } diff -r 54bf0f0245f4 -r 32fcc5dc7562 OrthancServer/ServerContext.cpp --- a/OrthancServer/ServerContext.cpp Mon Dec 08 12:56:30 2014 +0100 +++ b/OrthancServer/ServerContext.cpp Mon Dec 08 13:54:27 2014 +0100 @@ -71,8 +71,8 @@ namespace Orthanc { - ServerContext::ServerContext(const boost::filesystem::path& indexPath) : - index_(*this, indexPath.string()), + ServerContext::ServerContext(IDatabaseWrapper& database) : + index_(*this, database), compressionEnabled_(false), provider_(*this), dicomCache_(provider_, DICOM_CACHE_SIZE), diff -r 54bf0f0245f4 -r 32fcc5dc7562 OrthancServer/ServerContext.h --- a/OrthancServer/ServerContext.h Mon Dec 08 12:56:30 2014 +0100 +++ b/OrthancServer/ServerContext.h Mon Dec 08 13:54:27 2014 +0100 @@ -137,7 +137,7 @@ }; - ServerContext(const boost::filesystem::path& indexPath); + ServerContext(IDatabaseWrapper& database); void SetStorageArea(IStorageArea& storage) { diff -r 54bf0f0245f4 -r 32fcc5dc7562 OrthancServer/ServerIndex.cpp --- a/OrthancServer/ServerIndex.cpp Mon Dec 08 12:56:30 2014 +0100 +++ b/OrthancServer/ServerIndex.cpp Mon Dec 08 13:54:27 2014 +0100 @@ -221,9 +221,9 @@ index_(index), isCommitted_(false) { - assert(index_.currentStorageSize_ == index_.db_->GetTotalCompressedSize()); + assert(index_.currentStorageSize_ == index_.db_.GetTotalCompressedSize()); - transaction_.reset(index_.db_->StartTransaction()); + transaction_.reset(index_.db_.StartTransaction()); transaction_->Begin(); index_.listener_->StartTransaction(); @@ -250,7 +250,7 @@ assert(index_.currentStorageSize_ >= index_.listener_->GetSizeOfFilesToRemove()); index_.currentStorageSize_ -= index_.listener_->GetSizeOfFilesToRemove(); - assert(index_.currentStorageSize_ == index_.db_->GetTotalCompressedSize()); + assert(index_.currentStorageSize_ == index_.db_.GetTotalCompressedSize()); // Send all the pending changes to the Orthanc plugins index_.listener_->CommitChanges(); @@ -308,13 +308,13 @@ int64_t id; ResourceType type; - if (!db_->LookupResource(uuid, id, type) || + if (!db_.LookupResource(uuid, id, type) || expectedType != type) { return false; } - db_->DeleteResource(id); + db_.DeleteResource(id); if (listener_->HasRemainingLevel()) { @@ -347,7 +347,7 @@ boost::mutex::scoped_lock lock(that->mutex_); std::string sleepString; - if (that->db_->LookupGlobalProperty(sleepString, GlobalProperty_FlushSleep) && + if (that->db_.LookupGlobalProperty(sleepString, GlobalProperty_FlushSleep) && Toolbox::IsInteger(sleepString)) { sleep = boost::lexical_cast(sleepString); @@ -371,7 +371,7 @@ } boost::mutex::scoped_lock lock(that->mutex_); - that->db_->FlushToDisk(); + that->db_.FlushToDisk(); count = 0; } @@ -379,7 +379,7 @@ } - static void ComputeExpectedNumberOfInstances(DatabaseWrapper& db, + static void ComputeExpectedNumberOfInstances(IDatabaseWrapper& db, int64_t series, const DicomMap& dicomSummary) { @@ -426,7 +426,7 @@ MetadataType type) { std::string s; - if (!db_->LookupMetadata(s, id, type)) + if (!db_.LookupMetadata(s, id, type)) { return false; } @@ -448,14 +448,14 @@ { std::string oldValue; - if (db_->LookupGlobalProperty(oldValue, property)) + if (db_.LookupGlobalProperty(oldValue, property)) { uint64_t oldNumber; try { oldNumber = boost::lexical_cast(oldValue); - db_->SetGlobalProperty(property, boost::lexical_cast(oldNumber + 1)); + db_.SetGlobalProperty(property, boost::lexical_cast(oldNumber + 1)); return oldNumber + 1; } catch (boost::bad_lexical_cast&) @@ -466,7 +466,7 @@ else { // Initialize the sequence at "1" - db_->SetGlobalProperty(property, "1"); + db_.SetGlobalProperty(property, "1"); return 1; } } @@ -474,33 +474,16 @@ ServerIndex::ServerIndex(ServerContext& context, - const std::string& dbPath) : + IDatabaseWrapper& db) : done_(false), + db_(db), maximumStorageSize_(0), maximumPatients_(0) { listener_.reset(new Internals::ServerIndexListener(context)); - - if (dbPath == ":memory:") - { - db_.reset(new DatabaseWrapper(*listener_)); - } - else - { - boost::filesystem::path p = dbPath; + db_.SetListener(*listener_); - try - { - boost::filesystem::create_directories(p); - } - catch (boost::filesystem::filesystem_error) - { - } - - db_.reset(new DatabaseWrapper(p.string() + "/index", *listener_)); - } - - currentStorageSize_ = db_->GetTotalCompressedSize(); + currentStorageSize_ = db_.GetTotalCompressedSize(); // Initial recycling if the parameters have changed since the last // execution of Orthanc @@ -547,10 +530,10 @@ { ResourceType type; int64_t tmp; - if (db_->LookupResource(hasher.HashInstance(), tmp, type)) + if (db_.LookupResource(hasher.HashInstance(), tmp, type)) { assert(type == ResourceType_Instance); - db_->GetAllMetadata(instanceMetadata, tmp); + db_.GetAllMetadata(instanceMetadata, tmp); return StoreStatus_AlreadyStored; } } @@ -566,11 +549,11 @@ Recycle(instanceSize, hasher.HashPatient()); // Create the instance - int64_t instance = db_->CreateResource(hasher.HashInstance(), ResourceType_Instance); + int64_t instance = db_.CreateResource(hasher.HashInstance(), ResourceType_Instance); DicomMap dicom; dicomSummary.ExtractInstanceInformation(dicom); - db_->SetMainDicomTags(instance, dicom); + db_.SetMainDicomTags(instance, dicom); // Detect up to which level the patient/study/series/instance // hierarchy must be created @@ -582,26 +565,26 @@ { ResourceType dummy; - if (db_->LookupResource(hasher.HashSeries(), series, dummy)) + if (db_.LookupResource(hasher.HashSeries(), series, dummy)) { assert(dummy == ResourceType_Series); // The patient, the study and the series already exist - bool ok = (db_->LookupResource(hasher.HashPatient(), patient, dummy) && - db_->LookupResource(hasher.HashStudy(), study, dummy)); + bool ok = (db_.LookupResource(hasher.HashPatient(), patient, dummy) && + db_.LookupResource(hasher.HashStudy(), study, dummy)); assert(ok); } - else if (db_->LookupResource(hasher.HashStudy(), study, dummy)) + else if (db_.LookupResource(hasher.HashStudy(), study, dummy)) { assert(dummy == ResourceType_Study); // New series: The patient and the study already exist isNewSeries = true; - bool ok = db_->LookupResource(hasher.HashPatient(), patient, dummy); + bool ok = db_.LookupResource(hasher.HashPatient(), patient, dummy); assert(ok); } - else if (db_->LookupResource(hasher.HashPatient(), patient, dummy)) + else if (db_.LookupResource(hasher.HashPatient(), patient, dummy)) { assert(dummy == ResourceType_Patient); @@ -621,38 +604,38 @@ // Create the series if needed if (isNewSeries) { - series = db_->CreateResource(hasher.HashSeries(), ResourceType_Series); + series = db_.CreateResource(hasher.HashSeries(), ResourceType_Series); dicomSummary.ExtractSeriesInformation(dicom); - db_->SetMainDicomTags(series, dicom); + db_.SetMainDicomTags(series, dicom); } // Create the study if needed if (isNewStudy) { - study = db_->CreateResource(hasher.HashStudy(), ResourceType_Study); + study = db_.CreateResource(hasher.HashStudy(), ResourceType_Study); dicomSummary.ExtractStudyInformation(dicom); - db_->SetMainDicomTags(study, dicom); + db_.SetMainDicomTags(study, dicom); } // Create the patient if needed if (isNewPatient) { - patient = db_->CreateResource(hasher.HashPatient(), ResourceType_Patient); + patient = db_.CreateResource(hasher.HashPatient(), ResourceType_Patient); dicomSummary.ExtractPatientInformation(dicom); - db_->SetMainDicomTags(patient, dicom); + db_.SetMainDicomTags(patient, dicom); } // Create the parent-to-child links - db_->AttachChild(series, instance); + db_.AttachChild(series, instance); if (isNewSeries) { - db_->AttachChild(study, series); + db_.AttachChild(study, series); } if (isNewStudy) { - db_->AttachChild(patient, study); + db_.AttachChild(patient, study); } // Sanity checks @@ -665,7 +648,7 @@ for (Attachments::const_iterator it = attachments.begin(); it != attachments.end(); ++it) { - db_->AddAttachment(instance, *it); + db_.AddAttachment(instance, *it); } // Attach the user-specified metadata @@ -675,19 +658,19 @@ switch (it->first.first) { case ResourceType_Patient: - db_->SetMetadata(patient, it->first.second, it->second); + db_.SetMetadata(patient, it->first.second, it->second); break; case ResourceType_Study: - db_->SetMetadata(study, it->first.second, it->second); + db_.SetMetadata(study, it->first.second, it->second); break; case ResourceType_Series: - db_->SetMetadata(series, it->first.second, it->second); + db_.SetMetadata(series, it->first.second, it->second); break; case ResourceType_Instance: - db_->SetMetadata(instance, it->first.second, it->second); + db_.SetMetadata(instance, it->first.second, it->second); instanceMetadata[it->first.second] = it->second; break; @@ -698,30 +681,30 @@ // Attach the auto-computed metadata for the patient/study/series levels std::string now = Toolbox::GetNowIsoString(); - db_->SetMetadata(series, MetadataType_LastUpdate, now); - db_->SetMetadata(study, MetadataType_LastUpdate, now); - db_->SetMetadata(patient, MetadataType_LastUpdate, now); + db_.SetMetadata(series, MetadataType_LastUpdate, now); + db_.SetMetadata(study, MetadataType_LastUpdate, now); + db_.SetMetadata(patient, MetadataType_LastUpdate, now); // Attach the auto-computed metadata for the instance level, // reflecting these additions into the input metadata map - db_->SetMetadata(instance, MetadataType_Instance_ReceptionDate, now); + db_.SetMetadata(instance, MetadataType_Instance_ReceptionDate, now); instanceMetadata[MetadataType_Instance_ReceptionDate] = now; - db_->SetMetadata(instance, MetadataType_Instance_RemoteAet, remoteAet); + db_.SetMetadata(instance, MetadataType_Instance_RemoteAet, remoteAet); instanceMetadata[MetadataType_Instance_RemoteAet] = remoteAet; const DicomValue* value; if ((value = dicomSummary.TestAndGetValue(DICOM_TAG_INSTANCE_NUMBER)) != NULL || (value = dicomSummary.TestAndGetValue(DICOM_TAG_IMAGE_INDEX)) != NULL) { - db_->SetMetadata(instance, MetadataType_Instance_IndexInSeries, value->AsString()); + db_.SetMetadata(instance, MetadataType_Instance_IndexInSeries, value->AsString()); instanceMetadata[MetadataType_Instance_IndexInSeries] = value->AsString(); } // Check whether the series of this new instance is now completed if (isNewSeries) { - ComputeExpectedNumberOfInstances(*db_, series, dicomSummary); + ComputeExpectedNumberOfInstances(db_, series, dicomSummary); } SeriesStatus seriesStatus = GetSeriesStatus(series); @@ -741,8 +724,7 @@ } catch (OrthancException& e) { - LOG(ERROR) << "EXCEPTION [" << e.What() << "]" - << " (SQLite status: " << db_->GetErrorMessage() << ")"; + LOG(ERROR) << "EXCEPTION [" << e.What() << "]"; } return StoreStatus_Failure; @@ -755,17 +737,17 @@ target = Json::objectValue; uint64_t cs = currentStorageSize_; - assert(cs == db_->GetTotalCompressedSize()); - uint64_t us = db_->GetTotalUncompressedSize(); + assert(cs == db_.GetTotalCompressedSize()); + uint64_t us = db_.GetTotalUncompressedSize(); target["TotalDiskSize"] = boost::lexical_cast(cs); target["TotalUncompressedSize"] = boost::lexical_cast(us); target["TotalDiskSizeMB"] = boost::lexical_cast(cs / MEGA_BYTES); target["TotalUncompressedSizeMB"] = boost::lexical_cast(us / MEGA_BYTES); - target["CountPatients"] = static_cast(db_->GetResourceCount(ResourceType_Patient)); - target["CountStudies"] = static_cast(db_->GetResourceCount(ResourceType_Study)); - target["CountSeries"] = static_cast(db_->GetResourceCount(ResourceType_Series)); - target["CountInstances"] = static_cast(db_->GetResourceCount(ResourceType_Instance)); + target["CountPatients"] = static_cast(db_.GetResourceCount(ResourceType_Patient)); + target["CountStudies"] = static_cast(db_.GetResourceCount(ResourceType_Study)); + target["CountSeries"] = static_cast(db_.GetResourceCount(ResourceType_Series)); + target["CountInstances"] = static_cast(db_.GetResourceCount(ResourceType_Instance)); } @@ -781,7 +763,7 @@ // Loop over the instances of this series std::list children; - db_->GetChildrenInternalId(children, id); + db_.GetChildrenInternalId(children, id); std::set instances; for (std::list::const_iterator @@ -825,7 +807,7 @@ int64_t resourceId) { DicomMap tags; - db_->GetMainDicomTags(tags, resourceId); + db_.GetMainDicomTags(tags, resourceId); target["MainDicomTags"] = Json::objectValue; FromDcmtkBridge::ToJson(target["MainDicomTags"], tags); } @@ -841,7 +823,7 @@ // Lookup for the requested resource int64_t id; ResourceType type; - if (!db_->LookupResource(publicId, id, type) || + if (!db_.LookupResource(publicId, id, type) || type != expectedType) { return false; @@ -851,12 +833,12 @@ if (type != ResourceType_Patient) { int64_t parentId; - if (!db_->LookupParent(parentId, id)) + if (!db_.LookupParent(parentId, id)) { throw OrthancException(ErrorCode_InternalError); } - std::string parent = db_->GetPublicId(parentId); + std::string parent = db_.GetPublicId(parentId); switch (type) { @@ -879,7 +861,7 @@ // List the children resources std::list children; - db_->GetChildrenPublicId(children, id); + db_.GetChildrenPublicId(children, id); if (type != ResourceType_Instance) { @@ -940,7 +922,7 @@ result["Type"] = "Instance"; FileInfo attachment; - if (!db_->LookupAttachment(attachment, id, FileContentType_Dicom)) + if (!db_.LookupAttachment(attachment, id, FileContentType_Dicom)) { throw OrthancException(ErrorCode_InternalError); } @@ -967,12 +949,12 @@ std::string tmp; - if (db_->LookupMetadata(tmp, id, MetadataType_AnonymizedFrom)) + if (db_.LookupMetadata(tmp, id, MetadataType_AnonymizedFrom)) { result["AnonymizedFrom"] = tmp; } - if (db_->LookupMetadata(tmp, id, MetadataType_ModifiedFrom)) + if (db_.LookupMetadata(tmp, id, MetadataType_ModifiedFrom)) { result["ModifiedFrom"] = tmp; } @@ -983,7 +965,7 @@ { result["IsStable"] = !unstableResources_.Contains(id); - if (db_->LookupMetadata(tmp, id, MetadataType_LastUpdate)) + if (db_.LookupMetadata(tmp, id, MetadataType_LastUpdate)) { result["LastUpdate"] = tmp; } @@ -1001,12 +983,12 @@ int64_t id; ResourceType type; - if (!db_->LookupResource(instanceUuid, id, type)) + if (!db_.LookupResource(instanceUuid, id, type)) { throw OrthancException(ErrorCode_UnknownResource); } - if (db_->LookupAttachment(attachment, id, contentType)) + if (db_.LookupAttachment(attachment, id, contentType)) { assert(attachment.GetContentType() == contentType); return true; @@ -1026,7 +1008,7 @@ { boost::mutex::scoped_lock lock(mutex_); - db_->GetAllPublicIds(lst, resourceType); + db_.GetAllPublicIds(lst, resourceType); } target = Json::arrayValue; @@ -1063,7 +1045,7 @@ } - bool ServerIndex::GetChanges(Json::Value& target, + void ServerIndex::GetChanges(Json::Value& target, int64_t since, unsigned int maxResults) { @@ -1072,25 +1054,23 @@ { boost::mutex::scoped_lock lock(mutex_); - db_->GetChanges(changes, done, since, maxResults); + db_.GetChanges(changes, done, since, maxResults); } FormatLog(target, changes, "Changes", done, since); - return true; } - bool ServerIndex::GetLastChange(Json::Value& target) + void ServerIndex::GetLastChange(Json::Value& target) { std::list changes; { boost::mutex::scoped_lock lock(mutex_); - db_->GetLastChange(changes); + db_.GetLastChange(changes); } FormatLog(target, changes, "Changes", true, 0); - return true; } @@ -1101,7 +1081,7 @@ int64_t id; ResourceType type; - if (!db_->LookupResource(publicId, id, type)) + if (!db_.LookupResource(publicId, id, type)) { throw OrthancException(ErrorCode_InternalError); } @@ -1119,7 +1099,7 @@ while (!done) { DicomMap map; - db_->GetMainDicomTags(map, currentId); + db_.GetMainDicomTags(map, currentId); switch (currentType) { @@ -1151,7 +1131,7 @@ // the current resource if (!done) { - bool ok = db_->LookupParent(currentId, currentId); + bool ok = db_.LookupParent(currentId, currentId); assert(ok); } } @@ -1166,11 +1146,11 @@ studyInstanceUid, seriesInstanceUid, sopInstanceUid); - db_->LogExportedResource(resource); + db_.LogExportedResource(resource); } - bool ServerIndex::GetExportedResources(Json::Value& target, + void ServerIndex::GetExportedResources(Json::Value& target, int64_t since, unsigned int maxResults) { @@ -1179,25 +1159,23 @@ { boost::mutex::scoped_lock lock(mutex_); - db_->GetExportedResources(exported, done, since, maxResults); + db_.GetExportedResources(exported, done, since, maxResults); } FormatLog(target, exported, "Exports", done, since); - return true; } - bool ServerIndex::GetLastExportedResource(Json::Value& target) + void ServerIndex::GetLastExportedResource(Json::Value& target) { std::list exported; { boost::mutex::scoped_lock lock(mutex_); - db_->GetLastExportedResource(exported); + db_.GetLastExportedResource(exported); } FormatLog(target, exported, "Exports", true, 0); - return true; } @@ -1206,7 +1184,7 @@ if (maximumStorageSize_ != 0) { uint64_t currentSize = currentStorageSize_ - listener_->GetSizeOfFilesToRemove(); - assert(db_->GetTotalCompressedSize() == currentSize); + assert(db_.GetTotalCompressedSize() == currentSize); if (currentSize + instanceSize > maximumStorageSize_) { @@ -1216,7 +1194,7 @@ if (maximumPatients_ != 0) { - uint64_t patientCount = db_->GetResourceCount(ResourceType_Patient); + uint64_t patientCount = db_.GetResourceCount(ResourceType_Patient); if (patientCount > maximumPatients_) { return true; @@ -1239,7 +1217,7 @@ // already stored int64_t patientToAvoid; ResourceType type; - bool hasPatientToAvoid = db_->LookupResource(newPatientId, patientToAvoid, type); + bool hasPatientToAvoid = db_.LookupResource(newPatientId, patientToAvoid, type); if (hasPatientToAvoid && type != ResourceType_Patient) { @@ -1254,8 +1232,8 @@ // If other instances of this patient are already in the store, // we must avoid to recycle them bool ok = hasPatientToAvoid ? - db_->SelectPatientToRecycle(patientToRecycle, patientToAvoid) : - db_->SelectPatientToRecycle(patientToRecycle); + db_.SelectPatientToRecycle(patientToRecycle, patientToAvoid) : + db_.SelectPatientToRecycle(patientToRecycle); if (!ok) { @@ -1263,7 +1241,7 @@ } LOG(INFO) << "Recycling one patient"; - db_->DeleteResource(patientToRecycle); + db_.DeleteResource(patientToRecycle); if (!IsRecyclingNeeded(instanceSize)) { @@ -1323,13 +1301,13 @@ // Lookup for the requested resource int64_t id; ResourceType type; - if (!db_->LookupResource(publicId, id, type) || + if (!db_.LookupResource(publicId, id, type) || type != ResourceType_Patient) { throw OrthancException(ErrorCode_ParameterOutOfRange); } - return db_->IsProtectedPatient(id); + return db_.IsProtectedPatient(id); } @@ -1341,14 +1319,14 @@ // Lookup for the requested resource int64_t id; ResourceType type; - if (!db_->LookupResource(publicId, id, type) || + if (!db_.LookupResource(publicId, id, type) || type != ResourceType_Patient) { throw OrthancException(ErrorCode_ParameterOutOfRange); } // No need for a SQLite::ITransaction here, as we only make 1 write to the DB - db_->SetProtectedPatient(id, isProtected); + db_.SetProtectedPatient(id, isProtected); if (isProtected) LOG(INFO) << "Patient " << publicId << " has been protected"; @@ -1366,7 +1344,7 @@ ResourceType type; int64_t resource; - if (!db_->LookupResource(publicId, resource, type)) + if (!db_.LookupResource(publicId, resource, type)) { throw OrthancException(ErrorCode_UnknownResource); } @@ -1378,12 +1356,12 @@ } std::list tmp; - db_->GetChildrenInternalId(tmp, resource); + db_.GetChildrenInternalId(tmp, resource); for (std::list::const_iterator it = tmp.begin(); it != tmp.end(); ++it) { - result.push_back(db_->GetPublicId(*it)); + result.push_back(db_.GetPublicId(*it)); } } @@ -1397,7 +1375,7 @@ ResourceType type; int64_t top; - if (!db_->LookupResource(publicId, top, type)) + if (!db_.LookupResource(publicId, top, type)) { throw OrthancException(ErrorCode_UnknownResource); } @@ -1420,14 +1398,14 @@ int64_t resource = toExplore.top(); toExplore.pop(); - if (db_->GetResourceType(resource) == ResourceType_Instance) + if (db_.GetResourceType(resource) == ResourceType_Instance) { - result.push_back(db_->GetPublicId(resource)); + result.push_back(db_.GetPublicId(resource)); } else { // Tag all the children of this resource as to be explored - db_->GetChildrenInternalId(tmp, resource); + db_.GetChildrenInternalId(tmp, resource); for (std::list::const_iterator it = tmp.begin(); it != tmp.end(); ++it) { @@ -1446,12 +1424,12 @@ ResourceType rtype; int64_t id; - if (!db_->LookupResource(publicId, id, rtype)) + if (!db_.LookupResource(publicId, id, rtype)) { throw OrthancException(ErrorCode_UnknownResource); } - db_->SetMetadata(id, type, value); + db_.SetMetadata(id, type, value); } @@ -1462,12 +1440,12 @@ ResourceType rtype; int64_t id; - if (!db_->LookupResource(publicId, id, rtype)) + if (!db_.LookupResource(publicId, id, rtype)) { throw OrthancException(ErrorCode_UnknownResource); } - db_->DeleteMetadata(id, type); + db_.DeleteMetadata(id, type); } @@ -1479,12 +1457,12 @@ ResourceType rtype; int64_t id; - if (!db_->LookupResource(publicId, id, rtype)) + if (!db_.LookupResource(publicId, id, rtype)) { throw OrthancException(ErrorCode_UnknownResource); } - return db_->LookupMetadata(target, id, type); + return db_.LookupMetadata(target, id, type); } @@ -1495,12 +1473,12 @@ ResourceType rtype; int64_t id; - if (!db_->LookupResource(publicId, id, rtype)) + if (!db_.LookupResource(publicId, id, rtype)) { throw OrthancException(ErrorCode_UnknownResource); } - db_->ListAvailableMetadata(target, id); + db_.ListAvailableMetadata(target, id); } @@ -1512,13 +1490,13 @@ ResourceType type; int64_t id; - if (!db_->LookupResource(publicId, id, type) || + if (!db_.LookupResource(publicId, id, type) || expectedType != type) { throw OrthancException(ErrorCode_UnknownResource); } - db_->ListAvailableAttachments(target, id); + db_.ListAvailableAttachments(target, id); } @@ -1529,15 +1507,15 @@ ResourceType type; int64_t id; - if (!db_->LookupResource(publicId, id, type)) + if (!db_.LookupResource(publicId, id, type)) { throw OrthancException(ErrorCode_UnknownResource); } int64_t parentId; - if (db_->LookupParent(parentId, id)) + if (db_.LookupParent(parentId, id)) { - target = db_->GetPublicId(parentId); + target = db_.GetPublicId(parentId); return true; } else @@ -1551,7 +1529,7 @@ { boost::mutex::scoped_lock lock(mutex_); - std::auto_ptr transaction(db_->StartTransaction()); + std::auto_ptr transaction(db_.StartTransaction()); transaction->Begin(); uint64_t seq = IncrementGlobalSequenceInternal(sequence); @@ -1566,12 +1544,12 @@ const std::string& publicId) { boost::mutex::scoped_lock lock(mutex_); - std::auto_ptr transaction(db_->StartTransaction()); + std::auto_ptr transaction(db_.StartTransaction()); transaction->Begin(); int64_t id; ResourceType type; - if (!db_->LookupResource(publicId, id, type)) + if (!db_.LookupResource(publicId, id, type)) { throw OrthancException(ErrorCode_UnknownResource); } @@ -1585,13 +1563,13 @@ void ServerIndex::DeleteChanges() { boost::mutex::scoped_lock lock(mutex_); - db_->ClearTable("Changes"); + db_.ClearTable("Changes"); } void ServerIndex::DeleteExportedResources() { boost::mutex::scoped_lock lock(mutex_); - db_->ClearTable("ExportedResources"); + db_.ClearTable("ExportedResources"); } @@ -1618,16 +1596,16 @@ int64_t resource = toExplore.top(); toExplore.pop(); - ResourceType thisType = db_->GetResourceType(resource); + ResourceType thisType = db_.GetResourceType(resource); std::list f; - db_->ListAvailableAttachments(f, resource); + db_.ListAvailableAttachments(f, resource); for (std::list::const_iterator it = f.begin(); it != f.end(); ++it) { FileInfo attachment; - if (db_->LookupAttachment(attachment, resource, *it)) + if (db_.LookupAttachment(attachment, resource, *it)) { compressedSize += attachment.GetCompressedSize(); uncompressedSize += attachment.GetUncompressedSize(); @@ -1656,7 +1634,7 @@ // Tag all the children of this resource as to be explored std::list tmp; - db_->GetChildrenInternalId(tmp, resource); + db_.GetChildrenInternalId(tmp, resource); for (std::list::const_iterator it = tmp.begin(); it != tmp.end(); ++it) { @@ -1685,7 +1663,7 @@ ResourceType type; int64_t top; - if (!db_->LookupResource(publicId, top, type)) + if (!db_.LookupResource(publicId, top, type)) { throw OrthancException(ErrorCode_UnknownResource); } @@ -1734,7 +1712,7 @@ ResourceType type; int64_t top; - if (!db_->LookupResource(publicId, top, type)) + if (!db_.LookupResource(publicId, top, type)) { throw OrthancException(ErrorCode_UnknownResource); } @@ -1771,7 +1749,7 @@ int64_t id = that->unstableResources_.RemoveOldest(payload); // Ensure that the resource is still existing before logging the change - if (that->db_->IsExistingResource(id)) + if (that->db_.IsExistingResource(id)) { switch (payload.GetResourceType()) { @@ -1829,14 +1807,14 @@ boost::mutex::scoped_lock lock(mutex_); std::list id; - db_->LookupIdentifier(id, tag, value); + db_.LookupIdentifier(id, tag, value); for (std::list::const_iterator it = id.begin(); it != id.end(); ++it) { - if (db_->GetResourceType(*it) == type) + if (db_.GetResourceType(*it) == type) { - result.push_back(db_->GetPublicId(*it)); + result.push_back(db_.GetPublicId(*it)); } } } @@ -1851,12 +1829,12 @@ boost::mutex::scoped_lock lock(mutex_); std::list id; - db_->LookupIdentifier(id, tag, value); + db_.LookupIdentifier(id, tag, value); for (std::list::const_iterator it = id.begin(); it != id.end(); ++it) { - result.push_back(db_->GetPublicId(*it)); + result.push_back(db_.GetPublicId(*it)); } } @@ -1869,13 +1847,13 @@ boost::mutex::scoped_lock lock(mutex_); std::list id; - db_->LookupIdentifier(id, value); + db_.LookupIdentifier(id, value); for (std::list::const_iterator it = id.begin(); it != id.end(); ++it) { - result.push_back(std::make_pair(db_->GetResourceType(*it), - db_->GetPublicId(*it))); + result.push_back(std::make_pair(db_.GetResourceType(*it), + db_.GetPublicId(*it))); } } @@ -1889,20 +1867,20 @@ ResourceType resourceType; int64_t resourceId; - if (!db_->LookupResource(publicId, resourceId, resourceType)) + if (!db_.LookupResource(publicId, resourceId, resourceType)) { return StoreStatus_Failure; // Inexistent resource } // Remove possible previous attachment - db_->DeleteAttachment(resourceId, attachment.GetContentType()); + db_.DeleteAttachment(resourceId, attachment.GetContentType()); // Locate the patient of the target resource int64_t patientId = resourceId; for (;;) { int64_t parent; - if (db_->LookupParent(parent, patientId)) + if (db_.LookupParent(parent, patientId)) { // We have not reached the patient level yet patientId = parent; @@ -1915,10 +1893,10 @@ } // Possibly apply the recycling mechanism while preserving this patient - assert(db_->GetResourceType(patientId) == ResourceType_Patient); - Recycle(attachment.GetCompressedSize(), db_->GetPublicId(patientId)); + assert(db_.GetResourceType(patientId) == ResourceType_Patient); + Recycle(attachment.GetCompressedSize(), db_.GetPublicId(patientId)); - db_->AddAttachment(resourceId, attachment); + db_.AddAttachment(resourceId, attachment); t.Commit(attachment.GetCompressedSize()); @@ -1935,12 +1913,12 @@ ResourceType rtype; int64_t id; - if (!db_->LookupResource(publicId, id, rtype)) + if (!db_.LookupResource(publicId, id, rtype)) { throw OrthancException(ErrorCode_UnknownResource); } - db_->DeleteAttachment(id, type); + db_.DeleteAttachment(id, type); t.Commit(0); } @@ -1955,13 +1933,13 @@ ResourceType type; int64_t id; - if (!db_->LookupResource(publicId, id, type)) + if (!db_.LookupResource(publicId, id, type)) { return false; } std::list metadata; - db_->ListAvailableMetadata(metadata, id); + db_.ListAvailableMetadata(metadata, id); for (std::list::const_iterator it = metadata.begin(); it != metadata.end(); it++) @@ -1969,7 +1947,7 @@ std::string key = EnumerationToString(*it); std::string value; - if (!db_->LookupMetadata(value, id, *it)) + if (!db_.LookupMetadata(value, id, *it)) { value.clear(); } @@ -1987,7 +1965,7 @@ boost::mutex::scoped_lock lock(mutex_); std::string value; - if (db_->LookupGlobalProperty(value, property)) + if (db_.LookupGlobalProperty(value, property)) { return value; } diff -r 54bf0f0245f4 -r 32fcc5dc7562 OrthancServer/ServerIndex.h --- a/OrthancServer/ServerIndex.h Mon Dec 08 12:56:30 2014 +0100 +++ b/OrthancServer/ServerIndex.h Mon Dec 08 13:54:27 2014 +0100 @@ -40,7 +40,7 @@ #include "../Core/DicomFormat/DicomInstanceHasher.h" #include "ServerEnumerations.h" -#include "DatabaseWrapper.h" +#include "IDatabaseWrapper.h" namespace Orthanc @@ -68,7 +68,7 @@ boost::thread unstableResourcesMonitorThread_; std::auto_ptr listener_; - std::auto_ptr db_; + IDatabaseWrapper& db_; LeastRecentlyUsedIndex unstableResources_; uint64_t currentStorageSize_; @@ -113,7 +113,7 @@ const std::string& publicId) { ServerIndexChange change(changeType, resourceType, publicId); - db_->LogChange(internalId, change); + db_.LogChange(internalId, change); } uint64_t IncrementGlobalSequenceInternal(GlobalProperty property); @@ -121,7 +121,7 @@ public: ServerIndex(ServerContext& context, - const std::string& dbPath); + IDatabaseWrapper& database); ~ServerIndex(); @@ -164,20 +164,20 @@ const std::string& uuid, ResourceType expectedType); - bool GetChanges(Json::Value& target, + void GetChanges(Json::Value& target, int64_t since, unsigned int maxResults); - bool GetLastChange(Json::Value& target); + void GetLastChange(Json::Value& target); void LogExportedResource(const std::string& publicId, const std::string& remoteModality); - bool GetExportedResources(Json::Value& target, + void GetExportedResources(Json::Value& target, int64_t since, unsigned int maxResults); - bool GetLastExportedResource(Json::Value& target); + void GetLastExportedResource(Json::Value& target); bool IsProtectedPatient(const std::string& publicId); diff -r 54bf0f0245f4 -r 32fcc5dc7562 OrthancServer/main.cpp --- a/OrthancServer/main.cpp Mon Dec 08 12:56:30 2014 +0100 +++ b/OrthancServer/main.cpp Mon Dec 08 13:54:27 2014 +0100 @@ -50,6 +50,7 @@ #include "OrthancFindRequestHandler.h" #include "OrthancMoveRequestHandler.h" #include "ServerToolbox.h" +#include "DatabaseWrapper.h" #include "../Plugins/Engine/PluginsManager.h" #include "../Plugins/Engine/OrthancPlugins.h" @@ -431,13 +432,29 @@ static bool StartOrthanc() { std::string storageDirectoryStr = Configuration::GetGlobalStringParameter("StorageDirectory", "OrthancStorage"); + + + // Open the database boost::filesystem::path indexDirectory = Configuration::InterpretStringParameterAsPath( Configuration::GetGlobalStringParameter("IndexDirectory", storageDirectoryStr)); + std::auto_ptr database; + try + { + boost::filesystem::create_directories(indexDirectory); + } + catch (boost::filesystem::filesystem_error) + { + } + + database.reset(new DatabaseWrapper(indexDirectory.string() + "/index")); + + // "storage" must be declared BEFORE "ServerContext context", to // avoid mess in the invokation order of the destructors. std::auto_ptr storage; - ServerContext context(indexDirectory); + + ServerContext context(*database); LOG(WARNING) << "Index directory: " << indexDirectory; diff -r 54bf0f0245f4 -r 32fcc5dc7562 UnitTestsSources/ServerIndexTests.cpp --- a/UnitTestsSources/ServerIndexTests.cpp Mon Dec 08 12:56:30 2014 +0100 +++ b/UnitTestsSources/ServerIndexTests.cpp Mon Dec 08 13:54:27 2014 +0100 @@ -110,7 +110,8 @@ virtual void SetUp() { listener_.reset(new ServerIndexListener); - index_.reset(new DatabaseWrapper(*listener_)); + index_.reset(new DatabaseWrapper()); + index_->SetListener(*listener_); } virtual void TearDown() @@ -547,7 +548,8 @@ Toolbox::RemoveFile(path + "/index"); FilesystemStorage storage(path); - ServerContext context(":memory:"); // The SQLite DB is in memory + DatabaseWrapper db; // The SQLite DB is in memory + ServerContext context(db); context.SetStorageArea(storage); ServerIndex& index = context.GetIndex(); @@ -614,7 +616,8 @@ Toolbox::RemoveFile(path + "/index"); FilesystemStorage storage(path); - ServerContext context(":memory:"); // The SQLite DB is in memory + DatabaseWrapper db; // The SQLite DB is in memory + ServerContext context(db); context.SetStorageArea(storage); ServerIndex& index = context.GetIndex();