Mercurial > hg > orthanc
changeset 4796:94616af363ec filter-store-instance
added ReceivedCStoreInstanceFilter lua callback + OrthancPluginRegisterIncomingCStoreInstanceFilter in sdk
line wrap: on
line diff
--- a/NEWS Thu Sep 30 17:52:07 2021 +0200 +++ b/NEWS Fri Oct 01 18:36:45 2021 +0200 @@ -1,11 +1,23 @@ Pending changes in the mainline =============================== + * Fix handling of option "DeidentifyLogs", notably for tags (0010,0010) and (0010,0020) * New configuration options: - "DicomThreadsCount" to set the number of threads in the embedded DICOM server +Lua +--- + +* New "ReceivedCStoreInstanceFilter" Lua callback to filter instances received + through C-Store and return a specific C-Store status code. + + +Plugins +------- + +* New function in the SDK: OrthancPluginRegisterIncomingCStoreInstanceFilter() Version 1.9.7 (2021-08-31) ==========================
--- a/OrthancFramework/Sources/DicomNetworking/IStoreRequestHandler.h Thu Sep 30 17:52:07 2021 +0200 +++ b/OrthancFramework/Sources/DicomNetworking/IStoreRequestHandler.h Fri Oct 01 18:36:45 2021 +0200 @@ -39,9 +39,9 @@ { } - virtual void Handle(DcmDataset& dicom, - const std::string& remoteIp, - const std::string& remoteAet, - const std::string& calledAet) = 0; + virtual uint16_t Handle(DcmDataset& dicom, + const std::string& remoteIp, + const std::string& remoteAet, + const std::string& calledAet) = 0; }; }
--- a/OrthancFramework/Sources/DicomNetworking/Internals/StoreScp.cpp Thu Sep 30 17:52:07 2021 +0200 +++ b/OrthancFramework/Sources/DicomNetworking/Internals/StoreScp.cpp Fri Oct 01 18:36:45 2021 +0200 @@ -161,14 +161,14 @@ // which SOP class and SOP instance ? #if DCMTK_VERSION_NUMBER >= 364 - if (!DU_findSOPClassAndInstanceInDataSet(*imageDataSet, sopClass, sizeof(sopClass), - sopInstance, sizeof(sopInstance), /*opt_correctUIDPadding*/ OFFalse)) + if (!DU_findSOPClassAndInstanceInDataSet(*imageDataSet, sopClass, sizeof(sopClass), + sopInstance, sizeof(sopInstance), /*opt_correctUIDPadding*/ OFFalse)) #else if (!DU_findSOPClassAndInstanceInDataSet(*imageDataSet, sopClass, sopInstance, /*opt_correctUIDPadding*/ OFFalse)) #endif { - //LOG4CPP_ERROR(Internals::GetLogger(), "bad DICOM file: " << fileName); - rsp->DimseStatus = STATUS_STORE_Error_CannotUnderstand; + //LOG4CPP_ERROR(Internals::GetLogger(), "bad DICOM file: " << fileName); + rsp->DimseStatus = STATUS_STORE_Error_CannotUnderstand; } else if (strcmp(sopClass, req->AffectedSOPClassUID) != 0) { @@ -182,7 +182,7 @@ { try { - cbdata->handler->Handle(**imageDataSet, *cbdata->remoteIp, cbdata->remoteAET, cbdata->calledAET); + rsp->DimseStatus = cbdata->handler->Handle(**imageDataSet, *cbdata->remoteIp, cbdata->remoteAET, cbdata->calledAET); } catch (OrthancException& e) {
--- a/OrthancFramework/Sources/Lua/LuaFunctionCall.cpp Thu Sep 30 17:52:07 2021 +0200 +++ b/OrthancFramework/Sources/Lua/LuaFunctionCall.cpp Fri Oct 01 18:36:45 2021 +0200 @@ -146,6 +146,20 @@ } } + void LuaFunctionCall::ExecuteToInt(int& result) + { + ExecuteInternal(1); + + int top = lua_gettop(context_.lua_); + if (lua_isnumber(context_.lua_, top)) + { + result = static_cast<int>(lua_tointeger(context_.lua_, top)); + } + else + { + throw OrthancException(ErrorCode_LuaReturnsNoString); + } + } void LuaFunctionCall::PushStringMap(const std::map<std::string, std::string>& value) {
--- a/OrthancFramework/Sources/Lua/LuaFunctionCall.h Thu Sep 30 17:52:07 2021 +0200 +++ b/OrthancFramework/Sources/Lua/LuaFunctionCall.h Fri Oct 01 18:36:45 2021 +0200 @@ -78,6 +78,8 @@ void ExecuteToString(std::string& result); + void ExecuteToInt(int& result); + #if ORTHANC_ENABLE_DCMTK == 1 void ExecuteToDicom(DicomMap& target); #endif
--- a/OrthancServer/Plugins/Engine/OrthancPlugins.cpp Thu Sep 30 17:52:07 2021 +0200 +++ b/OrthancServer/Plugins/Engine/OrthancPlugins.cpp Fri Oct 01 18:36:45 2021 +0200 @@ -79,6 +79,7 @@ #include <boost/regex.hpp> #include <dcmtk/dcmdata/dcdict.h> #include <dcmtk/dcmdata/dcdicent.h> +#include <dcmtk/dcmnet/dimse.h> #define ERROR_MESSAGE_64BIT "A 64bit version of the Orthanc API is necessary" @@ -1165,6 +1166,7 @@ typedef std::list<OrthancPluginIncomingHttpRequestFilter> IncomingHttpRequestFilters; typedef std::list<OrthancPluginIncomingHttpRequestFilter2> IncomingHttpRequestFilters2; typedef std::list<OrthancPluginIncomingDicomInstanceFilter> IncomingDicomInstanceFilters; + typedef std::list<OrthancPluginIncomingCStoreInstanceFilter> IncomingCStoreInstanceFilters; typedef std::list<OrthancPluginDecodeImageCallback> DecodeImageCallbacks; typedef std::list<OrthancPluginTranscoderCallback> TranscoderCallbacks; typedef std::list<OrthancPluginJobsUnserializer> JobsUnserializers; @@ -1187,6 +1189,7 @@ IncomingHttpRequestFilters incomingHttpRequestFilters_; IncomingHttpRequestFilters2 incomingHttpRequestFilters2_; IncomingDicomInstanceFilters incomingDicomInstanceFilters_; + IncomingCStoreInstanceFilters incomingCStoreInstanceFilters_; // New in Orthanc 1.9.8 RefreshMetricsCallbacks refreshMetricsCallbacks_; StorageCommitmentScpCallbacks storageCommitmentScpCallbacks_; std::unique_ptr<StorageAreaFactory> storageArea_; @@ -2261,7 +2264,36 @@ return true; } - + + + uint16_t OrthancPlugins::FilterIncomingCStoreInstance(const DicomInstanceToStore& instance, + const Json::Value& simplified) + { + DicomInstanceFromCallback wrapped(instance); + + boost::recursive_mutex::scoped_lock lock(pimpl_->invokeServiceMutex_); + + for (PImpl::IncomingCStoreInstanceFilters::const_iterator + filter = pimpl_->incomingCStoreInstanceFilters_.begin(); + filter != pimpl_->incomingCStoreInstanceFilters_.end(); ++filter) + { + int32_t filterResult = (*filter) (reinterpret_cast<const OrthancPluginDicomInstance*>(&wrapped)); + + if (filterResult >= 0 && filterResult <= 0xFFFF) + { + return static_cast<uint16_t>(filterResult); + } + else + { + // The callback is only allowed to answer uint16_t + throw OrthancException(ErrorCode_Plugin); + } + } + + return STATUS_Success; + } + + void OrthancPlugins::SignalChangeInternal(OrthancPluginChangeType changeType, OrthancPluginResourceType resourceType, const char* resource) @@ -2479,6 +2511,18 @@ } + void OrthancPlugins::RegisterIncomingCStoreInstanceFilter(const void* parameters) + { + const _OrthancPluginIncomingCStoreInstanceFilter& p = + *reinterpret_cast<const _OrthancPluginIncomingCStoreInstanceFilter*>(parameters); + + CLOG(INFO, PLUGINS) << "Plugin has registered a callback to filter incoming C-Store DICOM instances"; + pimpl_->incomingCStoreInstanceFilters_.push_back(p.callback); + } + + + void RegisterIncomingCStoreInstanceFilter(const void* parameters); + void OrthancPlugins::RegisterRefreshMetricsCallback(const void* parameters) { const _OrthancPluginRegisterRefreshMetricsCallback& p =
--- a/OrthancServer/Plugins/Engine/OrthancPlugins.h Thu Sep 30 17:52:07 2021 +0200 +++ b/OrthancServer/Plugins/Engine/OrthancPlugins.h Fri Oct 01 18:36:45 2021 +0200 @@ -133,6 +133,8 @@ void RegisterIncomingDicomInstanceFilter(const void* parameters); + void RegisterIncomingCStoreInstanceFilter(const void* parameters); + void RegisterRefreshMetricsCallback(const void* parameters); void RegisterStorageCommitmentScpCallback(const void* parameters); @@ -279,6 +281,9 @@ virtual bool FilterIncomingInstance(const DicomInstanceToStore& instance, const Json::Value& simplified) ORTHANC_OVERRIDE; + virtual uint16_t FilterIncomingCStoreInstance(const DicomInstanceToStore& instance, + const Json::Value& simplified) ORTHANC_OVERRIDE; + bool HasStorageArea() const; IStorageArea* CreateStorageArea(); // To be freed after use
--- a/OrthancServer/Plugins/Include/orthanc/OrthancCPlugin.h Thu Sep 30 17:52:07 2021 +0200 +++ b/OrthancServer/Plugins/Include/orthanc/OrthancCPlugin.h Fri Oct 01 18:36:45 2021 +0200 @@ -461,7 +461,8 @@ _OrthancPluginService_RegisterIncomingDicomInstanceFilter = 1014, _OrthancPluginService_RegisterTranscoderCallback = 1015, /* New in Orthanc 1.7.0 */ _OrthancPluginService_RegisterStorageArea2 = 1016, /* New in Orthanc 1.9.0 */ - + _OrthancPluginService_RegisterIncomingCStoreInstanceFilter = 1017, /* New in Orthanc 1.9.8 */ + /* Sending answers to REST calls */ _OrthancPluginService_AnswerBuffer = 2000, _OrthancPluginService_CompressAndAnswerPngImage = 2001, /* Unused as of Orthanc 0.9.4 */ @@ -7764,6 +7765,63 @@ /** + * @brief Callback to filter incoming DICOM instances received by + * Orthanc through C-Store. + * + * Signature of a callback function that is triggered whenever + * Orthanc receives a new DICOM instance (through DICOM protocol), + * and that answers whether this DICOM instance should be accepted + * or discarded by Orthanc. If the instance is discarded, the callback + * can specify the C-Store error code. + * + * Note that the metadata information is not available + * (i.e. GetInstanceMetadata() should not be used on "instance"). + * + * @param instance The received DICOM instance. + * @return 0 to accept the instance, any valid C-Store error code + * to reject the instance, -1 if error. + * @ingroup Callback + **/ + typedef int32_t (*OrthancPluginIncomingCStoreInstanceFilter) ( + const OrthancPluginDicomInstance* instance); + + + typedef struct + { + OrthancPluginIncomingCStoreInstanceFilter callback; + } _OrthancPluginIncomingCStoreInstanceFilter; + + /** + * @brief Register a callback to filter incoming DICOM instances + * received by Orthanc through C-Store. + * + * + * @warning Your callback function will be called synchronously with + * the core of Orthanc. This implies that deadlocks might emerge if + * you call other core primitives of Orthanc in your callback (such + * deadlocks are particular visible in the presence of other plugins + * or Lua scripts). It is thus strongly advised to avoid any call to + * the REST API of Orthanc in the callback. If you have to call + * other primitives of Orthanc, you should make these calls in a + * separate thread, passing the pending events to be processed + * through a message queue. + * + * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). + * @param callback The callback. + * @return 0 if success, other value if error. + * @ingroup Callbacks + **/ + ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginRegisterIncomingCStoreInstanceFilter( + OrthancPluginContext* context, + OrthancPluginIncomingCStoreInstanceFilter callback) + { + _OrthancPluginIncomingCStoreInstanceFilter params; + params.callback = callback; + + return context->InvokeService(context, _OrthancPluginService_RegisterIncomingCStoreInstanceFilter, ¶ms); + } + + /** * @brief Get the transfer syntax of a DICOM file. * * This function returns a pointer to a newly created string that
--- a/OrthancServer/Sources/IServerListener.h Thu Sep 30 17:52:07 2021 +0200 +++ b/OrthancServer/Sources/IServerListener.h Fri Oct 01 18:36:45 2021 +0200 @@ -55,5 +55,9 @@ virtual bool FilterIncomingInstance(const DicomInstanceToStore& instance, const Json::Value& simplified) = 0; + + virtual uint16_t FilterIncomingCStoreInstance(const DicomInstanceToStore& instance, + const Json::Value& simplified) = 0; + }; }
--- a/OrthancServer/Sources/LuaScripting.cpp Thu Sep 30 17:52:07 2021 +0200 +++ b/OrthancServer/Sources/LuaScripting.cpp Fri Oct 01 18:36:45 2021 +0200 @@ -43,6 +43,8 @@ #include "../../OrthancFramework/Sources/Logging.h" #include "../../OrthancFramework/Sources/Lua/LuaFunctionCall.h" +#include <dcmtk/dcmnet/dimse.h> + #include <OrthancServerResources.h> @@ -945,6 +947,41 @@ return true; } + uint16_t LuaScripting::FilterIncomingCStoreInstance(const DicomInstanceToStore& instance, + const Json::Value& simplified) + { + static const char* NAME = "ReceivedCStoreInstanceFilter"; + + boost::recursive_mutex::scoped_lock lock(mutex_); + + if (lua_.IsExistingFunction(NAME)) + { + LuaFunctionCall call(lua_, NAME); + call.PushJson(simplified); + + Json::Value origin; + instance.GetOrigin().Format(origin); + call.PushJson(origin); + + Json::Value info = Json::objectValue; + info["HasPixelData"] = instance.HasPixelData(); + + DicomTransferSyntax s; + if (instance.LookupTransferSyntax(s)) + { + info["TransferSyntaxUID"] = GetTransferSyntaxUid(s); + } + + call.PushJson(info); + + int result; + call.ExecuteToInt(result); + return static_cast<uint16_t>(result); + } + + return STATUS_Success; + } + void LuaScripting::Execute(const std::string& command) {
--- a/OrthancServer/Sources/LuaScripting.h Thu Sep 30 17:52:07 2021 +0200 +++ b/OrthancServer/Sources/LuaScripting.h Fri Oct 01 18:36:45 2021 +0200 @@ -129,6 +129,9 @@ bool FilterIncomingInstance(const DicomInstanceToStore& instance, const Json::Value& simplifiedTags); + uint16_t FilterIncomingCStoreInstance(const DicomInstanceToStore& instance, + const Json::Value& simplified); + void Execute(const std::string& command); void SignalJobSubmitted(const std::string& jobId);
--- a/OrthancServer/Sources/OrthancRestApi/OrthancRestAnonymizeModify.cpp Thu Sep 30 17:52:07 2021 +0200 +++ b/OrthancServer/Sources/OrthancRestApi/OrthancRestAnonymizeModify.cpp Fri Oct 01 18:36:45 2021 +0200 @@ -554,16 +554,16 @@ toStore->SetOrigin(DicomInstanceOrigin::FromRest(call)); ServerContext& context = OrthancRestApi::GetContext(call); - StoreStatus status = context.Store(id, *toStore, StoreInstanceMode_Default); + ServerContext::StoreResult result = context.Store(id, *toStore, StoreInstanceMode_Default); - if (status == StoreStatus_Failure) + if (result.GetStatus() == StoreStatus_Failure) { throw OrthancException(ErrorCode_CannotStoreInstance); } if (sendAnswer) { - OrthancRestApi::GetApi(call).AnswerStoredInstance(call, *toStore, status, id); + OrthancRestApi::GetApi(call).AnswerStoredInstance(call, *toStore, result.GetStatus(), id); } }
--- a/OrthancServer/Sources/OrthancRestApi/OrthancRestApi.cpp Thu Sep 30 17:52:07 2021 +0200 +++ b/OrthancServer/Sources/OrthancRestApi/OrthancRestApi.cpp Fri Oct 01 18:36:45 2021 +0200 @@ -199,10 +199,10 @@ try { - StoreStatus status = context.Store(publicId, *toStore, StoreInstanceMode_Default); + ServerContext::StoreResult result = context.Store(publicId, *toStore, StoreInstanceMode_Default); Json::Value info; - SetupResourceAnswer(info, *toStore, status, publicId); + SetupResourceAnswer(info, *toStore, result.GetStatus(), publicId); answer.append(info); } catch (OrthancException& e) @@ -252,9 +252,9 @@ toStore->SetOrigin(DicomInstanceOrigin::FromRest(call)); std::string publicId; - StoreStatus status = context.Store(publicId, *toStore, StoreInstanceMode_Default); + ServerContext::StoreResult result = context.Store(publicId, *toStore, StoreInstanceMode_Default); - OrthancRestApi::GetApi(call).AnswerStoredInstance(call, *toStore, status, publicId); + OrthancRestApi::GetApi(call).AnswerStoredInstance(call, *toStore, result.GetStatus(), publicId); } }
--- a/OrthancServer/Sources/OrthancWebDav.cpp Thu Sep 30 17:52:07 2021 +0200 +++ b/OrthancServer/Sources/OrthancWebDav.cpp Fri Oct 01 18:36:45 2021 +0200 @@ -1313,9 +1313,9 @@ try { std::string publicId; - StoreStatus status = context_.Store(publicId, *instance, StoreInstanceMode_Default); - if (status == StoreStatus_Success || - status == StoreStatus_AlreadyStored) + ServerContext::StoreResult result = context_.Store(publicId, *instance, StoreInstanceMode_Default); + if (result.GetStatus() == StoreStatus_Success || + result.GetStatus() == StoreStatus_AlreadyStored) { LOG(INFO) << "Successfully imported DICOM instance from WebDAV: " << path << " (Orthanc ID: " << publicId << ")";
--- a/OrthancServer/Sources/ServerContext.cpp Thu Sep 30 17:52:07 2021 +0200 +++ b/OrthancServer/Sources/ServerContext.cpp Fri Oct 01 18:36:45 2021 +0200 @@ -57,6 +57,7 @@ #include "StorageCommitmentReports.h" #include <dcmtk/dcmdata/dcfilefo.h> +#include <dcmtk/dcmnet/dimse.h> static size_t DICOM_CACHE_SIZE = 128 * 1024 * 1024; // 128 MB @@ -100,6 +101,13 @@ transferSyntax != DicomTransferSyntax_XML); } + + ServerContext::StoreResult::StoreResult() : + status_(StoreStatus_Failure), + cstoreStatusCode_(0) + { + } + void ServerContext::ChangeThread(ServerContext* that, unsigned int sleepDelay) @@ -489,9 +497,9 @@ } - StoreStatus ServerContext::StoreAfterTranscoding(std::string& resultPublicId, - DicomInstanceToStore& dicom, - StoreInstanceMode mode) + ServerContext::StoreResult ServerContext::StoreAfterTranscoding(std::string& resultPublicId, + DicomInstanceToStore& dicom, + StoreInstanceMode mode) { bool overwrite; switch (mode) @@ -538,7 +546,7 @@ Toolbox::SimplifyDicomAsJson(simplifiedTags, dicomAsJson, DicomToJsonFormat_Human); // Test if the instance must be filtered out - bool accepted = true; + StoreResult result; { boost::shared_lock<boost::shared_mutex> lock(listenersMutex_); @@ -549,9 +557,22 @@ { if (!it->GetListener().FilterIncomingInstance(dicom, simplifiedTags)) { - accepted = false; + result.SetStatus(StoreStatus_FilteredOut); + result.SetCStoreStatusCode(STATUS_Success); // to keep backward compatibility, we still return 'success' break; } + + if (dicom.GetOrigin().GetRequestOrigin() == Orthanc::RequestOrigin_DicomProtocol) + { + uint16_t filterResult = it->GetListener().FilterIncomingCStoreInstance(dicom, simplifiedTags); + if (it->GetListener().FilterIncomingCStoreInstance(dicom, simplifiedTags) != 0x0000) + { + result.SetStatus(StoreStatus_FilteredOut); + result.SetCStoreStatusCode(filterResult); + break; + } + } + } catch (OrthancException& e) { @@ -563,10 +584,10 @@ } } - if (!accepted) + if (result.GetStatus() == StoreStatus_FilteredOut) { LOG(INFO) << "An incoming instance has been discarded by the filter"; - return StoreStatus_FilteredOut; + return result; } // Remove the file from the DicomCache (useful if @@ -595,9 +616,9 @@ typedef std::map<MetadataType, std::string> InstanceMetadata; InstanceMetadata instanceMetadata; - StoreStatus status = index_.Store( + result.SetStatus(index_.Store( instanceMetadata, summary, attachments, dicom.GetMetadata(), dicom.GetOrigin(), overwrite, - hasTransferSyntax, transferSyntax, hasPixelDataOffset, pixelDataOffset); + hasTransferSyntax, transferSyntax, hasPixelDataOffset, pixelDataOffset)); // Only keep the metadata for the "instance" level dicom.ClearMetadata(); @@ -608,7 +629,7 @@ dicom.AddMetadata(ResourceType_Instance, it->first, it->second); } - if (status != StoreStatus_Success) + if (result.GetStatus() != StoreStatus_Success) { accessor.Remove(dicomInfo); @@ -618,7 +639,7 @@ } } - switch (status) + switch (result.GetStatus()) { case StoreStatus_Success: LOG(INFO) << "New instance stored"; @@ -637,8 +658,8 @@ break; } - if (status == StoreStatus_Success || - status == StoreStatus_AlreadyStored) + if (result.GetStatus() == StoreStatus_Success || + result.GetStatus() == StoreStatus_AlreadyStored) { boost::shared_lock<boost::shared_mutex> lock(listenersMutex_); @@ -657,7 +678,7 @@ } } - return status; + return result; } catch (OrthancException& e) { @@ -671,9 +692,9 @@ } - StoreStatus ServerContext::Store(std::string& resultPublicId, - DicomInstanceToStore& dicom, - StoreInstanceMode mode) + ServerContext::StoreResult ServerContext::Store(std::string& resultPublicId, + DicomInstanceToStore& dicom, + StoreInstanceMode mode) { if (!isIngestTranscoding_) { @@ -733,10 +754,10 @@ std::unique_ptr<DicomInstanceToStore> toStore(DicomInstanceToStore::CreateFromParsedDicomFile(*tmp)); toStore->SetOrigin(dicom.GetOrigin()); - StoreStatus ok = StoreAfterTranscoding(resultPublicId, *toStore, mode); + StoreResult result = StoreAfterTranscoding(resultPublicId, *toStore, mode); assert(resultPublicId == tmp->GetHasher().HashInstance()); - return ok; + return result; } else {
--- a/OrthancServer/Sources/ServerContext.h Thu Sep 30 17:52:07 2021 +0200 +++ b/OrthancServer/Sources/ServerContext.h Fri Oct 01 18:36:45 2021 +0200 @@ -93,6 +93,36 @@ const Json::Value* dicomAsJson) = 0; }; + struct StoreResult + { + private: + StoreStatus status_; + uint16_t cstoreStatusCode_; + // uint16_t httpStatusCode_; // for future use + + public: + StoreResult(); + + void SetStatus(StoreStatus status) + { + status_ = status; + } + + StoreStatus GetStatus() + { + return status_; + } + + void SetCStoreStatusCode(uint16_t statusCode) + { + cstoreStatusCode_ = statusCode; + } + + uint16_t GetCStoreStatusCode() + { + return cstoreStatusCode_; + } + }; private: class LuaServerListener : public IServerListener @@ -123,6 +153,12 @@ { return context_.filterLua_.FilterIncomingInstance(instance, simplified); } + + virtual uint16_t FilterIncomingCStoreInstance(const DicomInstanceToStore& instance, + const Json::Value& simplified) ORTHANC_OVERRIDE + { + return context_.filterLua_.FilterIncomingCStoreInstance(instance, simplified); + } }; class ServerListener @@ -231,7 +267,7 @@ bool isUnknownSopClassAccepted_; std::set<DicomTransferSyntax> acceptedTransferSyntaxes_; - StoreStatus StoreAfterTranscoding(std::string& resultPublicId, + StoreResult StoreAfterTranscoding(std::string& resultPublicId, DicomInstanceToStore& dicom, StoreInstanceMode mode); @@ -304,7 +340,7 @@ int64_t oldRevision, const std::string& oldMD5); - StoreStatus Store(std::string& resultPublicId, + StoreResult Store(std::string& resultPublicId, DicomInstanceToStore& dicom, StoreInstanceMode mode);
--- a/OrthancServer/Sources/ServerJobs/MergeStudyJob.cpp Thu Sep 30 17:52:07 2021 +0200 +++ b/OrthancServer/Sources/ServerJobs/MergeStudyJob.cpp Fri Oct 01 18:36:45 2021 +0200 @@ -161,8 +161,8 @@ toStore->SetOrigin(origin_); std::string modifiedInstance; - if (GetContext().Store(modifiedInstance, *toStore, - StoreInstanceMode_Default) != StoreStatus_Success) + ServerContext::StoreResult result = GetContext().Store(modifiedInstance, *toStore, StoreInstanceMode_Default); + if (result.GetStatus() != StoreStatus_Success) { LOG(ERROR) << "Error while storing a modified instance " << instance; return false;
--- a/OrthancServer/Sources/ServerJobs/ResourceModificationJob.cpp Thu Sep 30 17:52:07 2021 +0200 +++ b/OrthancServer/Sources/ServerJobs/ResourceModificationJob.cpp Fri Oct 01 18:36:45 2021 +0200 @@ -290,8 +290,8 @@ **/ std::string modifiedInstance; - if (GetContext().Store(modifiedInstance, *toStore, - StoreInstanceMode_Default) != StoreStatus_Success) + ServerContext::StoreResult result = GetContext().Store(modifiedInstance, *toStore, StoreInstanceMode_Default); + if (result.GetStatus() != StoreStatus_Success) { throw OrthancException(ErrorCode_CannotStoreInstance, "Error while storing a modified instance " + instance);
--- a/OrthancServer/Sources/ServerJobs/SplitStudyJob.cpp Thu Sep 30 17:52:07 2021 +0200 +++ b/OrthancServer/Sources/ServerJobs/SplitStudyJob.cpp Fri Oct 01 18:36:45 2021 +0200 @@ -143,8 +143,8 @@ toStore->SetOrigin(origin_); std::string modifiedInstance; - if (GetContext().Store(modifiedInstance, *toStore, - StoreInstanceMode_Default) != StoreStatus_Success) + ServerContext::StoreResult result = GetContext().Store(modifiedInstance, *toStore, StoreInstanceMode_Default); + if (result.GetStatus() != StoreStatus_Success) { LOG(ERROR) << "Error while storing a modified instance " << instance; return false;
--- a/OrthancServer/Sources/main.cpp Thu Sep 30 17:52:07 2021 +0200 +++ b/OrthancServer/Sources/main.cpp Fri Oct 01 18:36:45 2021 +0200 @@ -84,10 +84,10 @@ } - virtual void Handle(DcmDataset& dicom, - const std::string& remoteIp, - const std::string& remoteAet, - const std::string& calledAet) ORTHANC_OVERRIDE + virtual uint16_t Handle(DcmDataset& dicom, + const std::string& remoteIp, + const std::string& remoteAet, + const std::string& calledAet) ORTHANC_OVERRIDE { std::unique_ptr<DicomInstanceToStore> toStore(DicomInstanceToStore::CreateFromDcmDataset(dicom)); @@ -97,8 +97,11 @@ (remoteIp.c_str(), remoteAet.c_str(), calledAet.c_str())); std::string id; - context_.Store(id, *toStore, StoreInstanceMode_Default); + ServerContext::StoreResult result = context_.Store(id, *toStore, StoreInstanceMode_Default); + return result.GetCStoreStatusCode(); } + + return STATUS_STORE_Error_CannotUnderstand; } };
--- a/OrthancServer/UnitTestsSources/ServerIndexTests.cpp Thu Sep 30 17:52:07 2021 +0200 +++ b/OrthancServer/UnitTestsSources/ServerIndexTests.cpp Fri Oct 01 18:36:45 2021 +0200 @@ -859,7 +859,8 @@ ASSERT_EQ(id, hasher.HashInstance()); std::string id2; - ASSERT_EQ(StoreStatus_Success, context.Store(id2, *toStore, StoreInstanceMode_Default)); + ServerContext::StoreResult result = context.Store(id2, *toStore, StoreInstanceMode_Default); + ASSERT_EQ(StoreStatus_Success, result.GetStatus()); ASSERT_EQ(id, id2); } @@ -908,8 +909,8 @@ toStore->SetOrigin(DicomInstanceOrigin::FromPlugins()); std::string id2; - ASSERT_EQ(overwrite ? StoreStatus_Success : StoreStatus_AlreadyStored, - context.Store(id2, *toStore, StoreInstanceMode_Default)); + ServerContext::StoreResult result = context.Store(id2, *toStore, StoreInstanceMode_Default); + ASSERT_EQ(overwrite ? StoreStatus_Success : StoreStatus_AlreadyStored, result.GetStatus()); ASSERT_EQ(id, id2); } @@ -1008,7 +1009,8 @@ std::unique_ptr<DicomInstanceToStore> toStore(DicomInstanceToStore::CreateFromParsedDicomFile(dicom)); dicomSize = toStore->GetBufferSize(); toStore->SetOrigin(DicomInstanceOrigin::FromPlugins()); - ASSERT_EQ(StoreStatus_Success, context.Store(id, *toStore, StoreInstanceMode_Default)); + ServerContext::StoreResult result = context.Store(id, *toStore, StoreInstanceMode_Default); + ASSERT_EQ(StoreStatus_Success, result.GetStatus()); } std::set<FileContentType> attachments;
--- a/OrthancServer/UnitTestsSources/ServerJobsTests.cpp Thu Sep 30 17:52:07 2021 +0200 +++ b/OrthancServer/UnitTestsSources/ServerJobsTests.cpp Fri Oct 01 18:36:45 2021 +0200 @@ -537,7 +537,8 @@ std::unique_ptr<DicomInstanceToStore> toStore(DicomInstanceToStore::CreateFromParsedDicomFile(dicom)); - return (context_->Store(id, *toStore, StoreInstanceMode_Default) == StoreStatus_Success); + ServerContext::StoreResult result = context_->Store(id, *toStore, StoreInstanceMode_Default); + return (result.GetStatus() == StoreStatus_Success); } }; }