Mercurial > hg > orthanc
changeset 2222:21713ce8717b
Fix handling of Move Originator AET and ID in C-MOVE SCP
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Tue, 13 Dec 2016 14:34:33 +0100 |
parents | e7beca979562 |
children | 29689b30f9ae |
files | Core/DicomFormat/DicomTag.h NEWS OrthancServer/DicomProtocol/DicomUserConnection.cpp OrthancServer/DicomProtocol/DicomUserConnection.h OrthancServer/DicomProtocol/IMoveRequestHandler.h OrthancServer/Internals/MoveScp.cpp OrthancServer/LuaScripting.cpp OrthancServer/OrthancMoveRequestHandler.cpp OrthancServer/OrthancMoveRequestHandler.h OrthancServer/OrthancRestApi/OrthancRestModalities.cpp OrthancServer/Scheduler/StoreScuCommand.cpp OrthancServer/Scheduler/StoreScuCommand.h Plugins/Engine/OrthancPlugins.cpp Plugins/Include/orthanc/OrthancCPlugin.h UnitTestsSources/MultiThreadingTests.cpp |
diffstat | 15 files changed, 145 insertions(+), 89 deletions(-) [+] |
line wrap: on
line diff
--- a/Core/DicomFormat/DicomTag.h Tue Dec 13 12:13:12 2016 +0100 +++ b/Core/DicomFormat/DicomTag.h Tue Dec 13 14:34:33 2016 +0100 @@ -128,6 +128,7 @@ static const DicomTag DICOM_TAG_TEMPORAL_POSITION_IDENTIFIER(0x0020, 0x0100); // Tags for C-FIND and C-MOVE + static const DicomTag DICOM_TAG_MESSAGE_ID(0x0000, 0x0110); static const DicomTag DICOM_TAG_SPECIFIC_CHARACTER_SET(0x0008, 0x0005); static const DicomTag DICOM_TAG_QUERY_RETRIEVE_LEVEL(0x0008, 0x0052); static const DicomTag DICOM_TAG_MODALITIES_IN_STUDY(0x0008, 0x0061);
--- a/NEWS Tue Dec 13 12:13:12 2016 +0100 +++ b/NEWS Tue Dec 13 14:34:33 2016 +0100 @@ -13,7 +13,7 @@ * "/tools/invalidate-tags" to invalidate the JSON summary of all the DICOM files (useful if private tags are registered, or if changing the default encoding) -* "Permissive" flag for URI "/modalities/{...}/store" to ignore C-Store transfer errors +* "Permissive" flag for URI "/modalities/{...}/store" to ignore C-STORE transfer errors * "Asynchronous" flag for URIs "/modalities/{...}/store" and "/peers/{...}/store" to avoid waiting for the completion of image transfers * Possibility to DELETE "dicom-as-json" attachments to reconstruct the JSON summaries @@ -29,7 +29,7 @@ * New function: "OrthancPluginRegisterPrivateDictionaryTag()" to register private tags * More control over client cache in the ServeFolders plugin * New C++ help wrappers in "Plugins/Samples/Common/" to read DICOM datasets from REST API -* New data structure: "OrthancPluginFindMatcher" to match DICOM against C-Find queries +* New data structure: "OrthancPluginFindMatcher" to match DICOM against C-FIND queries Maintenance ----------- @@ -46,6 +46,7 @@ * Content-Type for JSON documents is now "application/json; charset=utf-8" * Ignore "Group Length" tags in C-FIND queries * Fix handling of worklist SCP with ReferencedStudySequence and ReferencedPatientSequence +* Fix handling of Move Originator AET and ID in C-MOVE SCP Version 1.1.0 (2016/06/27) @@ -63,23 +64,23 @@ -------- * New URI: "/instances/.../frames/.../raw" to access the raw frames (bypass image decoding) -* New URI "/modalities/.../move" to issue C-Move SCU requests +* New URI "/modalities/.../move" to issue C-MOVE SCU requests * "MoveOriginatorID" can be specified for "/modalities/.../store" Dicom protocol -------------- -* Support of optional tags for counting resources in C-Find: +* Support of optional tags for counting resources in C-FIND: 0008-0061, 0008-0062, 0020-1200, 0020-1202, 0020-1204, 0020-1206, 0020-1208, 0020-1209 -* Support of Move Originator Message ID (0000,1031) in C-Store responses driven by C-Move +* Support of Move Originator Message ID (0000,1031) in C-STORE responses driven by C-MOVE Plugins ------- * Speedup in plugins by removing unnecessary locks * New callback to filter incoming HTTP requests: OrthancPluginRegisterIncomingHttpRequestFilter() -* New callback to handle non-worklists C-Find requests: OrthancPluginRegisterFindCallback() -* New callback to handle C-Move requests: OrthancPluginRegisterMoveCallback() +* New callback to handle non-worklists C-FIND requests: OrthancPluginRegisterFindCallback() +* New callback to handle C-MOVE requests: OrthancPluginRegisterMoveCallback() * New function: "OrthancPluginHttpClient()" to do HTTP requests with full control * New function: "OrthancPluginGenerateUuid()" to generate a UUID * More than one custom image decoder can be installed (e.g. to handle different transfer syntaxes) @@ -87,7 +88,7 @@ Lua --- -* Possibility to dynamically fix outgoing C-Find requests using "OutgoingFindRequestFilter()" +* Possibility to dynamically fix outgoing C-FIND requests using "OutgoingFindRequestFilter()" * Access to the HTTP headers in the "IncomingHttpRequestFilter()" callback Image decoding @@ -122,7 +123,7 @@ Version 1.0.0 (2015/12/15) ========================== -* Lua: "IncomingFindRequestFilter()" to apply filters to incoming C-Find requests +* Lua: "IncomingFindRequestFilter()" to apply filters to incoming C-FIND requests * New function in plugin SDK: "OrthancPluginSendMultipartItem2()" * Fix of DICOMDIR generation with DCMTK 3.6.1, support of encodings * Fix range search if the lower or upper limit is absent
--- a/OrthancServer/DicomProtocol/DicomUserConnection.cpp Tue Dec 13 12:13:12 2016 +0100 +++ b/OrthancServer/DicomProtocol/DicomUserConnection.cpp Tue Dec 13 14:34:33 2016 +0100 @@ -154,6 +154,7 @@ void Store(DcmInputStream& is, DicomUserConnection& connection, + const std::string& moveOriginatorAET, uint16_t moveOriginatorID); }; @@ -259,6 +260,7 @@ void DicomUserConnection::PImpl::Store(DcmInputStream& is, DicomUserConnection& connection, + const std::string& moveOriginatorAET, uint16_t moveOriginatorID) { CheckIsOpen(); @@ -341,12 +343,12 @@ request.DataSetType = DIMSE_DATASET_PRESENT; strncpy(request.AffectedSOPInstanceUID, sopInstance, DIC_UI_LEN); - strncpy(request.MoveOriginatorApplicationEntityTitle, - connection.GetLocalApplicationEntityTitle().c_str(), DIC_AE_LEN); - request.opts = O_STORE_MOVEORIGINATORAETITLE; + if (!moveOriginatorAET.empty()) + { + strncpy(request.MoveOriginatorApplicationEntityTitle, + moveOriginatorAET.c_str(), DIC_AE_LEN); + request.opts = O_STORE_MOVEORIGINATORAETITLE; - if (moveOriginatorID != 0) - { request.MoveOriginatorID = moveOriginatorID; // The type DIC_US is an alias for uint16_t request.opts |= O_STORE_MOVEORIGINATORID; } @@ -961,6 +963,7 @@ void DicomUserConnection::Store(const char* buffer, size_t size, + const std::string& moveOriginatorAET, uint16_t moveOriginatorID) { // Prepare an input stream for the memory buffer @@ -969,24 +972,26 @@ is.setBuffer(buffer, size); is.setEos(); - pimpl_->Store(is, *this, moveOriginatorID); + pimpl_->Store(is, *this, moveOriginatorAET, moveOriginatorID); } void DicomUserConnection::Store(const std::string& buffer, + const std::string& moveOriginatorAET, uint16_t moveOriginatorID) { if (buffer.size() > 0) - Store(reinterpret_cast<const char*>(&buffer[0]), buffer.size(), moveOriginatorID); + Store(reinterpret_cast<const char*>(&buffer[0]), buffer.size(), moveOriginatorAET, moveOriginatorID); else - Store(NULL, 0, moveOriginatorID); + Store(NULL, 0, moveOriginatorAET, moveOriginatorID); } void DicomUserConnection::StoreFile(const std::string& path, + const std::string& moveOriginatorAET, uint16_t moveOriginatorID) { // Prepare an input stream for the file DcmInputFileStream is(path.c_str()); - pimpl_->Store(is, *this, moveOriginatorID); + pimpl_->Store(is, *this, moveOriginatorAET, moveOriginatorID); } bool DicomUserConnection::Echo()
--- a/OrthancServer/DicomProtocol/DicomUserConnection.h Tue Dec 13 12:13:12 2016 +0100 +++ b/OrthancServer/DicomProtocol/DicomUserConnection.h Tue Dec 13 14:34:33 2016 +0100 @@ -135,14 +135,33 @@ void Store(const char* buffer, size_t size, + const std::string& moveOriginatorAET, uint16_t moveOriginatorID); + void Store(const char* buffer, + size_t size) + { + Store(buffer, size, "", 0); // Not a C-Move + } + void Store(const std::string& buffer, + const std::string& moveOriginatorAET, uint16_t moveOriginatorID); + void Store(const std::string& buffer) + { + Store(buffer, "", 0); // Not a C-Move + } + void StoreFile(const std::string& path, + const std::string& moveOriginatorAET, uint16_t moveOriginatorID); + void StoreFile(const std::string& path) + { + StoreFile(path, "", 0); // Not a C-Move + } + void Find(DicomFindAnswers& result, ResourceType level, const DicomMap& fields);
--- a/OrthancServer/DicomProtocol/IMoveRequestHandler.h Tue Dec 13 12:13:12 2016 +0100 +++ b/OrthancServer/DicomProtocol/IMoveRequestHandler.h Tue Dec 13 14:34:33 2016 +0100 @@ -67,12 +67,12 @@ { } - virtual IMoveRequestIterator* Handle(const std::string& target, + virtual IMoveRequestIterator* Handle(const std::string& targetAet, const DicomMap& input, - const std::string& remoteIp, - const std::string& remoteAet, + const std::string& originatorIp, + const std::string& originatorAet, const std::string& calledAet, - uint16_t messageId) = 0; + uint16_t originatorId) = 0; }; }
--- a/OrthancServer/Internals/MoveScp.cpp Tue Dec 13 12:13:12 2016 +0100 +++ b/OrthancServer/Internals/MoveScp.cpp Tue Dec 13 14:34:33 2016 +0100 @@ -90,6 +90,8 @@ #include "../../Core/Logging.h" #include "../../Core/OrthancException.h" +#include <boost/lexical_cast.hpp> + namespace Orthanc { @@ -110,6 +112,42 @@ }; + + static uint16_t GetMessageId(const DicomMap& message) + { + /** + * Retrieve the Message ID (0000,0110) for this C-MOVE request, if + * any. If present, this Message ID will be stored in the Move + * Originator Message ID (0000,1031) field of the C-MOVE response. + * http://dicom.nema.org/dicom/2013/output/chtml/part07/chapter_E.html + **/ + + const DicomValue* value = message.TestAndGetValue(DICOM_TAG_MESSAGE_ID); + + if (value != NULL && + !value->IsNull() && + !value->IsBinary()) + { + try + { + int tmp = boost::lexical_cast<int>(value->GetContent()); + if (tmp >= 0 && tmp <= 0xffff) + { + return static_cast<uint16_t>(tmp); + } + } + catch (boost::bad_lexical_cast&) + { + LOG(WARNING) << "Cannot convert the Message ID (\"" << value->GetContent() + << "\") of an incoming C-MOVE request to an integer, assuming zero"; + } + } + + return 0; + } + + + void MoveScpCallback( /* in */ void *callbackData, @@ -134,9 +172,8 @@ try { - data.iterator_.reset(data.handler_->Handle(data.target_, input, - *data.remoteIp_, *data.remoteAet_, - *data.calledAet_, request->MessageID)); + data.iterator_.reset(data.handler_->Handle(data.target_, input, *data.remoteIp_, *data.remoteAet_, + *data.calledAet_, GetMessageId(input))); if (data.iterator_.get() == NULL) {
--- a/OrthancServer/LuaScripting.cpp Tue Dec 13 12:13:12 2016 +0100 +++ b/OrthancServer/LuaScripting.cpp Tue Dec 13 14:34:33 2016 +0100 @@ -252,9 +252,10 @@ std::string modality = parameters["Modality"].asString(); LOG(INFO) << "Lua script to send resource " << parameters["Resource"].asString() << " to modality " << modality << " using Store-SCU"; + + // This is not a C-MOVE: No need to call "StoreScuCommand::SetMoveOriginator()" return new StoreScuCommand(context_, localAet, - Configuration::GetModalityUsingSymbolicName(modality), - true, 0 /* not a C-MOVE */); + Configuration::GetModalityUsingSymbolicName(modality), true); } if (operation == "store-peer")
--- a/OrthancServer/OrthancMoveRequestHandler.cpp Tue Dec 13 12:13:12 2016 +0100 +++ b/OrthancServer/OrthancMoveRequestHandler.cpp Tue Dec 13 14:34:33 2016 +0100 @@ -52,17 +52,20 @@ std::vector<std::string> instances_; size_t position_; RemoteModalityParameters remote_; - uint16_t moveRequestID_; + std::string originatorAet_; + uint16_t originatorId_; public: OrthancMoveRequestIterator(ServerContext& context, const std::string& aet, const std::string& publicId, - uint16_t moveRequestID) : + const std::string& originatorAet, + uint16_t originatorId) : context_(context), localAet_(context.GetDefaultLocalApplicationEntityTitle()), position_(0), - moveRequestID_(moveRequestID) + originatorAet_(originatorAet), + originatorId_(originatorId) { LOG(INFO) << "Sending resource " << publicId << " to modality \"" << aet << "\""; @@ -98,7 +101,7 @@ { ReusableDicomUserConnection::Locker locker (context_.GetReusableDicomUserConnection(), localAet_, remote_); - locker.GetConnection().Store(dicom, moveRequestID_); + locker.GetConnection().Store(dicom, originatorAet_, originatorId_); } return Status_Success; @@ -167,10 +170,10 @@ IMoveRequestIterator* OrthancMoveRequestHandler::Handle(const std::string& targetAet, const DicomMap& input, - const std::string& remoteIp, - const std::string& remoteAet, + const std::string& originatorIp, + const std::string& originatorAet, const std::string& calledAet, - uint16_t messageId) + uint16_t originatorId) { LOG(WARNING) << "Move-SCU request received for AET \"" << targetAet << "\""; @@ -188,36 +191,6 @@ } -#if 0 - /** - * Retrieve the Message ID (0000,0110) for this C-MOVE request, if - * any. If present, this Message ID will be stored in the Move - * Originator Message ID (0000,1031) field of the C-MOVE response. - * http://dicom.nema.org/medical/dicom/current/output/html/part07.html#sect_9.3.1 - **/ - - static const DicomTag MESSAGE_ID(0x0000, 0x0110); - const DicomValue* messageIdTmp = input.TestAndGetValue(MESSAGE_ID); - - messageId = 0; - - if (messageIdTmp != NULL && - !messageIdTmp->IsNull() && - !messageIdTmp->IsBinary()) - { - try - { - messageId = boost::lexical_cast<uint16_t>(messageIdTmp->GetContent()); - } - catch (boost::bad_lexical_cast&) - { - LOG(WARNING) << "Cannot convert the Message ID (\"" << messageIdTmp ->GetContent() - << "\") of an incoming C-MOVE request to an integer, assuming zero"; - } - } -#endif - - /** * Retrieve the query level. **/ @@ -241,7 +214,7 @@ LookupIdentifier(publicId, ResourceType_Study, input) || LookupIdentifier(publicId, ResourceType_Patient, input)) { - return new OrthancMoveRequestIterator(context_, targetAet, publicId, messageId); + return new OrthancMoveRequestIterator(context_, targetAet, publicId, originatorAet, originatorId); } else { @@ -262,7 +235,7 @@ if (LookupIdentifier(publicId, level, input)) { - return new OrthancMoveRequestIterator(context_, targetAet, publicId, messageId); + return new OrthancMoveRequestIterator(context_, targetAet, publicId, originatorAet, originatorId); } else {
--- a/OrthancServer/OrthancMoveRequestHandler.h Tue Dec 13 12:13:12 2016 +0100 +++ b/OrthancServer/OrthancMoveRequestHandler.h Tue Dec 13 14:34:33 2016 +0100 @@ -53,9 +53,9 @@ virtual IMoveRequestIterator* Handle(const std::string& targetAet, const DicomMap& input, - const std::string& remoteIp, - const std::string& remoteAet, + const std::string& originatorIp, + const std::string& originatorAet, const std::string& calledAet, - uint16_t messageId); + uint16_t originatorId); }; }
--- a/OrthancServer/OrthancRestApi/OrthancRestModalities.cpp Tue Dec 13 12:13:12 2016 +0100 +++ b/OrthancServer/OrthancRestApi/OrthancRestModalities.cpp Tue Dec 13 14:34:33 2016 +0100 @@ -686,6 +686,7 @@ std::string localAet = Toolbox::GetJsonStringField(request, "LocalAet", context.GetDefaultLocalApplicationEntityTitle()); bool permissive = Toolbox::GetJsonBooleanField(request, "Permissive", false); bool asynchronous = Toolbox::GetJsonBooleanField(request, "Asynchronous", false); + std::string moveOriginatorAET = Toolbox::GetJsonStringField(request, "MoveOriginatorAet", context.GetDefaultLocalApplicationEntityTitle()); int moveOriginatorID = Toolbox::GetJsonIntegerField(request, "MoveOriginatorID", 0 /* By default, not a C-MOVE */); if (moveOriginatorID < 0 || @@ -700,8 +701,14 @@ for (std::list<std::string>::const_iterator it = instances.begin(); it != instances.end(); ++it) { - job.AddCommand(new StoreScuCommand(context, localAet, p, permissive, - static_cast<uint16_t>(moveOriginatorID))).AddInput(*it); + std::auto_ptr<StoreScuCommand> command(new StoreScuCommand(context, localAet, p, permissive)); + + if (moveOriginatorID != 0) + { + command->SetMoveOriginator(moveOriginatorAET, static_cast<uint16_t>(moveOriginatorID)); + } + + job.AddCommand(command.release()).AddInput(*it); } job.SetDescription("HTTP request: Store-SCU to peer \"" + remote + "\"");
--- a/OrthancServer/Scheduler/StoreScuCommand.cpp Tue Dec 13 12:13:12 2016 +0100 +++ b/OrthancServer/Scheduler/StoreScuCommand.cpp Tue Dec 13 14:34:33 2016 +0100 @@ -40,16 +40,24 @@ StoreScuCommand::StoreScuCommand(ServerContext& context, const std::string& localAet, const RemoteModalityParameters& modality, - bool ignoreExceptions, - uint16_t moveOriginatorID) : + bool ignoreExceptions) : context_(context), modality_(modality), ignoreExceptions_(ignoreExceptions), localAet_(localAet), - moveOriginatorID_(moveOriginatorID) + moveOriginatorID_(0) { } + + void StoreScuCommand::SetMoveOriginator(const std::string& aet, + uint16_t id) + { + moveOriginatorAET_ = aet; + moveOriginatorID_ = id; + } + + bool StoreScuCommand::Apply(ListOfStrings& outputs, const ListOfStrings& inputs) { @@ -66,7 +74,7 @@ std::string dicom; context_.ReadDicom(dicom, *it); - locker.GetConnection().Store(dicom, moveOriginatorID_); + locker.GetConnection().Store(dicom, moveOriginatorAET_, moveOriginatorID_); // Only chain with other commands if this command succeeds outputs.push_back(*it);
--- a/OrthancServer/Scheduler/StoreScuCommand.h Tue Dec 13 12:13:12 2016 +0100 +++ b/OrthancServer/Scheduler/StoreScuCommand.h Tue Dec 13 14:34:33 2016 +0100 @@ -44,15 +44,17 @@ RemoteModalityParameters modality_; bool ignoreExceptions_; std::string localAet_; + std::string moveOriginatorAET_; uint16_t moveOriginatorID_; public: StoreScuCommand(ServerContext& context, const std::string& localAet, const RemoteModalityParameters& modality, - bool ignoreExceptions, - uint16_t moveOriginatorID /* only makes sense if this - command results from a C-MOVE */); + bool ignoreExceptions); + + void SetMoveOriginator(const std::string& aet, + uint16_t id); virtual bool Apply(ListOfStrings& outputs, const ListOfStrings& inputs);
--- a/Plugins/Engine/OrthancPlugins.cpp Tue Dec 13 12:13:12 2016 +0100 +++ b/Plugins/Engine/OrthancPlugins.cpp Tue Dec 13 14:34:33 2016 +0100 @@ -687,10 +687,10 @@ virtual IMoveRequestIterator* Handle(const std::string& targetAet, const DicomMap& input, - const std::string& remoteIp, - const std::string& remoteAet, + const std::string& originatorIp, + const std::string& originatorAet, const std::string& calledAet, - uint16_t messageId) + uint16_t originatorId) { std::string levelString = ReadTag(input, DICOM_TAG_QUERY_RETRIEVE_LEVEL); std::string patientId = ReadTag(input, DICOM_TAG_PATIENT_ID); @@ -712,10 +712,10 @@ studyInstanceUid.empty() ? NULL : studyInstanceUid.c_str(), seriesInstanceUid.empty() ? NULL : seriesInstanceUid.c_str(), sopInstanceUid.empty() ? NULL : sopInstanceUid.c_str(), - remoteAet.c_str(), + originatorAet.c_str(), calledAet.c_str(), targetAet.c_str(), - messageId); + originatorId); if (driver == NULL) {
--- a/Plugins/Include/orthanc/OrthancCPlugin.h Tue Dec 13 12:13:12 2016 +0100 +++ b/Plugins/Include/orthanc/OrthancCPlugin.h Tue Dec 13 14:34:33 2016 +0100 @@ -1059,18 +1059,20 @@ * @param resourceType The type of the resource of interest. Note * that this might be set to ResourceType_None if the * QueryRetrieveLevel (0008,0052) tag was not provided by the - * issuer. + * issuer (i.e. the originator modality). * @param patientId Content of the PatientID (0x0010, 0x0020) tag of the resource of interest. Might be NULL. * @param accessionNumber Content of the AccessionNumber (0x0008, 0x0050) tag. Might be NULL. * @param studyInstanceUid Content of the StudyInstanceUID (0x0020, 0x000d) tag. Might be NULL. * @param seriesInstanceUid Content of the SeriesInstanceUID (0x0020, 0x000e) tag. Might be NULL. * @param sopInstanceUid Content of the SOPInstanceUID (0x0008, 0x0018) tag. Might be NULL. - * @param issuerAet The Application Entity Title (AET) of the + * @param originatorAet The Application Entity Title (AET) of the * modality from which the request originates. * @param sourceAet The Application Entity Title (AET) of the * modality that should send its DICOM files to another modality. * @param targetAet The Application Entity Title (AET) of the * modality that should receive the DICOM files. + * @param originatorId The Message ID issued by the originator modality, + * as found in tag (0000,0110) of the DICOM query emitted by the issuer. * * @return The NULL value if the plugin cannot deal with this query, * or a pointer to the driver object that is responsible for @@ -1086,10 +1088,10 @@ const char* studyInstanceUid, const char* seriesInstanceUid, const char* sopInstanceUid, - const char* issuerAet, + const char* originatorAet, const char* sourceAet, const char* targetAet, - uint16_t moveOriginatorId); + uint16_t originatorId); /**
--- a/UnitTestsSources/MultiThreadingTests.cpp Tue Dec 13 12:13:12 2016 +0100 +++ b/UnitTestsSources/MultiThreadingTests.cpp Tue Dec 13 14:34:33 2016 +0100 @@ -139,7 +139,7 @@ { RemoteModalityParameters remote("STORESCP", "localhost", 2000, ModalityManufacturer_Generic); ReusableDicomUserConnection::Locker lock(c, "ORTHANC", remote); - lock.GetConnection().StoreFile("/home/jodogne/DICOM/Cardiac/MR.X.1.2.276.0.7230010.3.1.4.2831157719.2256.1336386844.676281", 0); + lock.GetConnection().StoreFile("/home/jodogne/DICOM/Cardiac/MR.X.1.2.276.0.7230010.3.1.4.2831157719.2256.1336386844.676281"); } printf("**\n"); fflush(stdout); @@ -149,7 +149,7 @@ { RemoteModalityParameters remote("STORESCP", "localhost", 2000, ModalityManufacturer_Generic); ReusableDicomUserConnection::Locker lock(c, "ORTHANC", remote); - lock.GetConnection().StoreFile("/home/jodogne/DICOM/Cardiac/MR.X.1.2.276.0.7230010.3.1.4.2831157719.2256.1336386844.676277", 0); + lock.GetConnection().StoreFile("/home/jodogne/DICOM/Cardiac/MR.X.1.2.276.0.7230010.3.1.4.2831157719.2256.1336386844.676277"); } SystemToolbox::ServerBarrier();