# HG changeset patch # User Sebastien Jodogne # Date 1544016827 -3600 # Node ID 9c0b0a6d8b549972aa40326fdf53d52848124340 # Parent 6896a7c1cbe205089cf2d93b5cabb3c8db429188 MediaArchiveSize configuration option diff -r 6896a7c1cbe2 -r 9c0b0a6d8b54 OrthancServer/OrthancRestApi/OrthancRestApi.cpp --- a/OrthancServer/OrthancRestApi/OrthancRestApi.cpp Wed Dec 05 12:58:56 2018 +0100 +++ b/OrthancServer/OrthancRestApi/OrthancRestApi.cpp Wed Dec 05 14:33:47 2018 +0100 @@ -173,6 +173,78 @@ static const char* KEY_PRIORITY = "Priority"; static const char* KEY_SYNCHRONOUS = "Synchronous"; static const char* KEY_ASYNCHRONOUS = "Asynchronous"; + + + bool OrthancRestApi::IsSynchronousJobRequest(bool isDefaultSynchronous, + const Json::Value& body) const + { + if (body.isMember(KEY_SYNCHRONOUS)) + { + return SerializationToolbox::ReadBoolean(body, KEY_SYNCHRONOUS); + } + else if (body.isMember(KEY_ASYNCHRONOUS)) + { + return !SerializationToolbox::ReadBoolean(body, KEY_ASYNCHRONOUS); + } + else + { + return isDefaultSynchronous; + } + } + + + void OrthancRestApi::SubmitGenericJob(RestApiPostCall& call, + IJob* job, + bool isDefaultSynchronous, + const Json::Value& body) const + { + std::auto_ptr raii(job); + + if (job == NULL) + { + throw OrthancException(ErrorCode_NullPointer); + } + + if (body.type() != Json::objectValue) + { + throw OrthancException(ErrorCode_BadFileFormat); + } + + int priority = 0; + + if (body.isMember(KEY_PRIORITY)) + { + priority = SerializationToolbox::ReadInteger(body, KEY_PRIORITY); + } + + if (IsSynchronousJobRequest(isDefaultSynchronous, body)) + { + Json::Value successContent; + if (context_.GetJobsEngine().GetRegistry().SubmitAndWait + (successContent, raii.release(), priority)) + { + // Success in synchronous execution + call.GetOutput().AnswerJson(successContent); + } + else + { + // Error during synchronous execution + call.GetOutput().SignalError(HttpStatus_500_InternalServerError); + } + } + else + { + // Asynchronous mode: Submit the job, but don't wait for its completion + std::string id; + context_.GetJobsEngine().GetRegistry().Submit(id, raii.release(), priority); + + Json::Value v; + v["ID"] = id; + v["Path"] = "/jobs/" + id; + call.GetOutput().AnswerJson(v); + } + } + void OrthancRestApi::SubmitCommandsJob(RestApiPostCall& call, SetOfCommandsJob* job, @@ -202,66 +274,6 @@ job->SetPermissive(false); } - int priority = 0; - - if (body.isMember(KEY_PRIORITY)) - { - priority = SerializationToolbox::ReadInteger(body, KEY_PRIORITY); - } - - bool synchronous = isDefaultSynchronous; - - if (body.isMember(KEY_SYNCHRONOUS)) - { - synchronous = SerializationToolbox::ReadBoolean(body, KEY_SYNCHRONOUS); - } - else if (body.isMember(KEY_ASYNCHRONOUS)) - { - synchronous = !SerializationToolbox::ReadBoolean(body, KEY_ASYNCHRONOUS); - } - - if (synchronous) - { - Json::Value successContent; - if (context_.GetJobsEngine().GetRegistry().SubmitAndWait - (successContent, raii.release(), priority)) - { - // Success in synchronous execution - call.GetOutput().AnswerJson(successContent); - } - else - { - // Error during synchronous execution - call.GetOutput().SignalError(HttpStatus_500_InternalServerError); - } - } - else - { - // Asynchronous mode: Submit the job, but don't wait for its completion - std::string id; - context_.GetJobsEngine().GetRegistry().Submit(id, raii.release(), priority); - - Json::Value v; - v["ID"] = id; - v["Path"] = "/jobs/" + id; - call.GetOutput().AnswerJson(v); - } - } - - - void OrthancRestApi::SubmitCommandsJob(RestApiPostCall& call, - SetOfCommandsJob* job, - bool isDefaultSynchronous) const - { - std::auto_ptr raii(job); - - Json::Value body; - - if (!call.ParseJsonRequest(body)) - { - body = Json::objectValue; - } - - SubmitCommandsJob(call, raii.release(), isDefaultSynchronous, body); + SubmitGenericJob(call, raii.release(), isDefaultSynchronous, body); } } diff -r 6896a7c1cbe2 -r 9c0b0a6d8b54 OrthancServer/OrthancRestApi/OrthancRestApi.h --- a/OrthancServer/OrthancRestApi/OrthancRestApi.h Wed Dec 05 12:58:56 2018 +0100 +++ b/OrthancServer/OrthancRestApi/OrthancRestApi.h Wed Dec 05 14:33:47 2018 +0100 @@ -103,13 +103,17 @@ ResourceType resourceType, StoreStatus status) const; + bool IsSynchronousJobRequest(bool isDefaultSynchronous, + const Json::Value& body) const; + + void SubmitGenericJob(RestApiPostCall& call, + IJob* job, + bool isDefaultSynchronous, + const Json::Value& body) const; + void SubmitCommandsJob(RestApiPostCall& call, SetOfCommandsJob* job, bool isDefaultSynchronous, const Json::Value& body) const; - - void SubmitCommandsJob(RestApiPostCall& call, - SetOfCommandsJob* job, - bool isDefaultSynchronous) const; }; } diff -r 6896a7c1cbe2 -r 9c0b0a6d8b54 OrthancServer/ServerContext.cpp --- a/OrthancServer/ServerContext.cpp Wed Dec 05 12:58:56 2018 +0100 +++ b/OrthancServer/ServerContext.cpp Wed Dec 05 14:33:47 2018 +0100 @@ -235,8 +235,11 @@ { { OrthancConfiguration::ReaderLock lock; + queryRetrieveArchive_.reset( new SharedArchive(lock.GetConfiguration().GetUnsignedIntegerParameter("QueryRetrieveSize", 10))); + mediaArchive_.reset( + new SharedArchive(lock.GetConfiguration().GetUnsignedIntegerParameter("MediaArchiveSize", 1))); defaultLocalAet_ = lock.GetConfiguration().GetStringParameter("DicomAet", "ORTHANC"); jobsEngine_.SetWorkersCount(lock.GetConfiguration().GetUnsignedIntegerParameter("ConcurrentJobs", 2)); } diff -r 6896a7c1cbe2 -r 9c0b0a6d8b54 OrthancServer/ServerContext.h --- a/OrthancServer/ServerContext.h Wed Dec 05 12:58:56 2018 +0100 +++ b/OrthancServer/ServerContext.h Wed Dec 05 14:33:47 2018 +0100 @@ -189,6 +189,8 @@ std::string defaultLocalAet_; OrthancHttpHandler httpHandler_; + std::auto_ptr mediaArchive_; + public: class DicomCacheLocker : public boost::noncopyable { @@ -310,6 +312,11 @@ return *queryRetrieveArchive_; } + SharedArchive& GetMediaArchive() + { + return *mediaArchive_; + } + const std::string& GetDefaultLocalApplicationEntityTitle() const { return defaultLocalAet_; diff -r 6896a7c1cbe2 -r 9c0b0a6d8b54 OrthancServer/ServerJobs/ArchiveJob.cpp --- a/OrthancServer/ServerJobs/ArchiveJob.cpp Wed Dec 05 12:58:56 2018 +0100 +++ b/OrthancServer/ServerJobs/ArchiveJob.cpp Wed Dec 05 14:33:47 2018 +0100 @@ -778,11 +778,11 @@ }; - ArchiveJob::ArchiveJob(boost::shared_ptr& target, + ArchiveJob::ArchiveJob(boost::shared_ptr& synchronousTarget, ServerContext& context, bool isMedia, bool enableExtendedSopClass) : - target_(target), + synchronousTarget_(synchronousTarget), context_(context), archive_(new ArchiveIndex(ResourceType_Patient)), // root isMedia_(isMedia), @@ -791,7 +791,7 @@ instancesCount_(0), uncompressedSize_(0) { - if (target.get() == NULL) + if (synchronousTarget.get() == NULL) { throw OrthancException(ErrorCode_NullPointer); } @@ -824,7 +824,7 @@ throw OrthancException(ErrorCode_BadSequenceOfCalls); } - writer_.reset(new ZipWriterIterator(*target_, context_, *archive_, + writer_.reset(new ZipWriterIterator(*synchronousTarget_, context_, *archive_, isMedia_, enableExtendedSopClass_)); instancesCount_ = writer_->GetInstancesCount(); @@ -836,7 +836,7 @@ { assert(writer_.get() != NULL); - if (target_.unique()) + if (synchronousTarget_.unique()) { LOG(WARNING) << "A client has disconnected while creating an archive"; return JobStepResult::Failure(ErrorCode_NetworkProtocol); diff -r 6896a7c1cbe2 -r 9c0b0a6d8b54 OrthancServer/ServerJobs/ArchiveJob.h --- a/OrthancServer/ServerJobs/ArchiveJob.h Wed Dec 05 12:58:56 2018 +0100 +++ b/OrthancServer/ServerJobs/ArchiveJob.h Wed Dec 05 14:33:47 2018 +0100 @@ -50,7 +50,7 @@ class ZipCommands; class ZipWriterIterator; - boost::shared_ptr target_; + boost::shared_ptr synchronousTarget_; ServerContext& context_; boost::shared_ptr archive_; bool isMedia_; @@ -63,7 +63,7 @@ uint64_t uncompressedSize_; public: - ArchiveJob(boost::shared_ptr& target, + ArchiveJob(boost::shared_ptr& synchronousTarget, ServerContext& context, bool isMedia, bool enableExtendedSopClass); diff -r 6896a7c1cbe2 -r 9c0b0a6d8b54 Resources/Configuration.json --- a/Resources/Configuration.json Wed Dec 05 12:58:56 2018 +0100 +++ b/Resources/Configuration.json Wed Dec 05 14:33:47 2018 +0100 @@ -440,5 +440,12 @@ // instance replaces the old one. If set to "false", the new // instance is discarded and the old one is kept. Up to Orthanc // 1.4.1, the implicit behavior corresponded to "false". - "OverwriteInstances" : false + "OverwriteInstances" : false, + + // Maximum number of ZIP/media archives that are maintained by + // Orthanc, as a response to the asynchronous creation of archives. + // The least recently used archives get deleted as new archives are + // generated. This option was introduced in Orthanc 1.4.3, and has + // no effect on the synchronous generation of archives. + "MediaArchiveSize" : 1 }