# HG changeset patch # User Sebastien Jodogne # Date 1536163026 -7200 # Node ID 37583cd183edb1f979a52b44ee30dea1ea2076bb # Parent 6356e2ceb493b3212aa339cfbae6d255794911fb primitives to create jobs from plugins diff -r 6356e2ceb493 -r 37583cd183ed CMakeLists.txt --- a/CMakeLists.txt Tue Sep 04 15:58:26 2018 +0200 +++ b/CMakeLists.txt Wed Sep 05 17:57:06 2018 +0200 @@ -125,6 +125,7 @@ Plugins/Engine/OrthancPlugins.cpp Plugins/Engine/PluginsEnumerations.cpp Plugins/Engine/PluginsErrorDictionary.cpp + Plugins/Engine/PluginsJob.cpp Plugins/Engine/PluginsManager.cpp ) diff -r 6356e2ceb493 -r 37583cd183ed OrthancServer/ServerContext.cpp --- a/OrthancServer/ServerContext.cpp Tue Sep 04 15:58:26 2018 +0200 +++ b/OrthancServer/ServerContext.cpp Wed Sep 05 17:57:06 2018 +0200 @@ -165,11 +165,24 @@ if (index_.LookupGlobalProperty(serialized, GlobalProperty_JobsRegistry)) { LOG(WARNING) << "Reloading the jobs from the last execution of Orthanc"; - OrthancJobUnserializer unserializer(*this); try { - jobsEngine_.LoadRegistryFromString(unserializer, serialized); + bool plugin = false; + +#if ORTHANC_ENABLE_PLUGINS == 1 + if (HasPlugins() && + plugins_->UnserializeJob(serialized)) + { + plugin = true; + } +#endif + + if (!plugin) + { + OrthancJobUnserializer unserializer(*this); + jobsEngine_.LoadRegistryFromString(unserializer, serialized); + } } catch (OrthancException& e) { diff -r 6356e2ceb493 -r 37583cd183ed Plugins/Engine/OrthancPlugins.cpp --- a/Plugins/Engine/OrthancPlugins.cpp Tue Sep 04 15:58:26 2018 +0200 +++ b/Plugins/Engine/OrthancPlugins.cpp Wed Sep 05 17:57:06 2018 +0200 @@ -44,6 +44,7 @@ #include "../../Core/HttpServer/HttpToolbox.h" #include "../../Core/Logging.h" #include "../../Core/OrthancException.h" +#include "../../Core/SerializationToolbox.h" #include "../../Core/Toolbox.h" #include "../../Core/DicomParsing/FromDcmtkBridge.h" #include "../../Core/DicomParsing/ToDcmtkBridge.h" @@ -62,6 +63,7 @@ #include "../../Core/Images/ImageProcessing.h" #include "../../OrthancServer/DefaultDicomImageDecoder.h" #include "PluginsEnumerations.h" +#include "PluginsJob.h" #include #include @@ -402,6 +404,7 @@ typedef std::list IncomingHttpRequestFilters; typedef std::list IncomingHttpRequestFilters2; typedef std::list DecodeImageCallbacks; + typedef std::list JobsUnserializers; typedef std::map Properties; PluginsManager manager_; @@ -412,6 +415,7 @@ OrthancPluginFindCallback findCallback_; OrthancPluginWorklistCallback worklistCallback_; DecodeImageCallbacks decodeImageCallbacks_; + JobsUnserializers jobsUnserializers_; _OrthancPluginMoveCallback moveCallbacks_; IncomingHttpRequestFilters incomingHttpRequestFilters_; IncomingHttpRequestFilters2 incomingHttpRequestFilters2_; @@ -423,6 +427,7 @@ boost::mutex findCallbackMutex_; boost::mutex worklistCallbackMutex_; boost::mutex decodeImageCallbackMutex_; + boost::mutex jobsUnserializersMutex_; boost::recursive_mutex invokeServiceMutex_; Properties properties_; @@ -809,6 +814,7 @@ sizeof(int32_t) != sizeof(_OrthancPluginDatabaseAnswerType) || sizeof(int32_t) != sizeof(OrthancPluginIdentifierConstraint) || sizeof(int32_t) != sizeof(OrthancPluginInstanceOrigin) || + sizeof(int32_t) != sizeof(OrthancPluginJobStepStatus) || static_cast(OrthancPluginDicomToJsonFlags_IncludeBinary) != static_cast(DicomToJsonFlags_IncludeBinary) || static_cast(OrthancPluginDicomToJsonFlags_IncludePrivateTags) != static_cast(DicomToJsonFlags_IncludePrivateTags) || static_cast(OrthancPluginDicomToJsonFlags_IncludeUnknownTags) != static_cast(DicomToJsonFlags_IncludeUnknownTags) || @@ -1168,6 +1174,19 @@ } + void OrthancPlugins::RegisterJobsUnserializer(const void* parameters) + { + const _OrthancPluginJobsUnserializer& p = + *reinterpret_cast(parameters); + + boost::mutex::scoped_lock lock(pimpl_->jobsUnserializersMutex_); + + pimpl_->jobsUnserializers_.push_back(p.unserializer); + LOG(INFO) << "Plugin has registered a callback to unserialize jobs (" + << pimpl_->jobsUnserializers_.size() << " unserializer(s) now active)"; + } + + void OrthancPlugins::RegisterIncomingHttpRequestFilter(const void* parameters) { const _OrthancPluginIncomingHttpRequestFilter& p = @@ -2857,6 +2876,19 @@ CallPeerApi(parameters); return true; + case _OrthancPluginService_SubmitJob: + { + const _OrthancPluginSubmitJob& p = + *reinterpret_cast(parameters); + + std::string uuid; + + PImpl::ServerContextLock lock(*pimpl_); + lock.GetContext().GetJobsEngine().GetRegistry().Submit(uuid, new PluginsJob(p), p.priority_); + + return true; + } + default: return false; } @@ -2906,6 +2938,10 @@ RegisterDecodeImageCallback(parameters); return true; + case _OrthancPluginService_RegisterJobsUnserializer: + RegisterJobsUnserializer(parameters); + return true; + case _OrthancPluginService_RegisterIncomingHttpRequestFilter: RegisterIncomingHttpRequestFilter(parameters); return true; @@ -3319,7 +3355,7 @@ } } - + bool OrthancPlugins::IsAllowed(HttpMethod method, const char* uri, const char* ip, @@ -3394,4 +3430,25 @@ return true; } + + + bool OrthancPlugins::UnserializeJob(const Json::Value& value) + { + const std::string type = SerializationToolbox::ReadString(value, "Type"); + const std::string serialized = value.toStyledString(); + + boost::mutex::scoped_lock lock(pimpl_->jobsUnserializersMutex_); + + for (PImpl::JobsUnserializers::iterator + unserializer = pimpl_->jobsUnserializers_.begin(); + unserializer != pimpl_->jobsUnserializers_.end(); ++unserializer) + { + if ((*unserializer) (type.c_str(), serialized.c_str()) == OrthancPluginErrorCode_Success) + { + return true; + } + } + + return false; + } } diff -r 6356e2ceb493 -r 37583cd183ed Plugins/Engine/OrthancPlugins.h --- a/Plugins/Engine/OrthancPlugins.h Tue Sep 04 15:58:26 2018 +0200 +++ b/Plugins/Engine/OrthancPlugins.h Wed Sep 05 17:57:06 2018 +0200 @@ -104,6 +104,8 @@ void RegisterDecodeImageCallback(const void* parameters); + void RegisterJobsUnserializer(const void* parameters); + void RegisterIncomingHttpRequestFilter(const void* parameters); void RegisterIncomingHttpRequestFilter2(const void* parameters); @@ -305,6 +307,8 @@ bool HasMoveHandler(); virtual IMoveRequestHandler* ConstructMoveRequestHandler(); + + bool UnserializeJob(const Json::Value& value); }; } diff -r 6356e2ceb493 -r 37583cd183ed Plugins/Engine/PluginsEnumerations.cpp --- a/Plugins/Engine/PluginsEnumerations.cpp Tue Sep 04 15:58:26 2018 +0200 +++ b/Plugins/Engine/PluginsEnumerations.cpp Wed Sep 05 17:57:06 2018 +0200 @@ -553,5 +553,42 @@ throw OrthancException(ErrorCode_ParameterOutOfRange); } } + + + OrthancPluginJobStepStatus Convert(JobStepCode step) + { + switch (step) + { + case JobStepCode_Success: + return OrthancPluginJobStepStatus_Success; + + case JobStepCode_Failure: + return OrthancPluginJobStepStatus_Failure; + + case JobStepCode_Continue: + return OrthancPluginJobStepStatus_Continue; + + default: + throw OrthancException(ErrorCode_ParameterOutOfRange); + } + } + + JobStepCode Convert(OrthancPluginJobStepStatus step) + { + switch (step) + { + case OrthancPluginJobStepStatus_Success: + return JobStepCode_Success; + + case OrthancPluginJobStepStatus_Failure: + return JobStepCode_Failure; + + case OrthancPluginJobStepStatus_Continue: + return JobStepCode_Continue; + + default: + throw OrthancException(ErrorCode_ParameterOutOfRange); + } + } } } diff -r 6356e2ceb493 -r 37583cd183ed Plugins/Engine/PluginsEnumerations.h --- a/Plugins/Engine/PluginsEnumerations.h Tue Sep 04 15:58:26 2018 +0200 +++ b/Plugins/Engine/PluginsEnumerations.h Wed Sep 05 17:57:06 2018 +0200 @@ -69,6 +69,10 @@ ValueRepresentation Convert(OrthancPluginValueRepresentation vr); OrthancPluginValueRepresentation Convert(ValueRepresentation vr); + + OrthancPluginJobStepStatus Convert(JobStepCode step); + + JobStepCode Convert(OrthancPluginJobStepStatus step); } } diff -r 6356e2ceb493 -r 37583cd183ed Plugins/Include/orthanc/OrthancCPlugin.h --- a/Plugins/Include/orthanc/OrthancCPlugin.h Tue Sep 04 15:58:26 2018 +0200 +++ b/Plugins/Include/orthanc/OrthancCPlugin.h Wed Sep 05 17:57:06 2018 +0200 @@ -23,6 +23,7 @@ * - Possibly register a handler for C-Move SCP using OrthancPluginRegisterMoveCallback(). * - Possibly register a custom decoder for DICOM images using OrthancPluginRegisterDecodeImageCallback(). * - Possibly register a callback to filter incoming HTTP requests using OrthancPluginRegisterIncomingHttpRequestFilter2(). + * - Possibly register a callback to unserialize jobs using OrthancPluginRegisterJobsUnserializer(). * -# void OrthancPluginFinalize(): * This function is invoked by Orthanc during its shutdown. The plugin * must free all its memory. @@ -422,6 +423,7 @@ _OrthancPluginService_CallHttpClient2 = 27, _OrthancPluginService_GenerateUuid = 28, _OrthancPluginService_RegisterPrivateDictionaryTag = 29, + _OrthancPluginService_SubmitJob = 30, /* Registration of callbacks */ _OrthancPluginService_RegisterRestCallback = 1000, @@ -435,6 +437,7 @@ _OrthancPluginService_RegisterFindCallback = 1008, _OrthancPluginService_RegisterMoveCallback = 1009, _OrthancPluginService_RegisterIncomingHttpRequestFilter2 = 1010, + _OrthancPluginService_RegisterJobsUnserializer = 1011, /* Sending answers to REST calls */ _OrthancPluginService_AnswerBuffer = 2000, @@ -839,6 +842,17 @@ /** + * The possible status for one single step of a job. + **/ + typedef enum + { + OrthancPluginJobStepStatus_Success, /*!< The job has successfully executed all its steps */ + OrthancPluginJobStepStatus_Failure, /*!< The job has failed while executing this step */ + OrthancPluginJobStepStatus_Continue /*!< The job has still data to process after this step */ + } OrthancPluginJobStepStatus; + + + /** * @brief A memory buffer allocated by the core system of Orthanc. * * A memory buffer allocated by the core system of Orthanc. When the @@ -1243,6 +1257,16 @@ + typedef void (*OrthancPluginJobFree) (void* job); + typedef float (*OrthancPluginJobGetProgress) (void* job); + typedef OrthancPluginJobStepStatus (*OrthancPluginJobStep) (void* job); + typedef OrthancPluginErrorCode (*OrthancPluginJobReleaseResources) (void* job); + typedef OrthancPluginErrorCode (*OrthancPluginJobReset) (void* job); + typedef OrthancPluginErrorCode (*OrthancPluginJobsUnserializer) (const char* jobType, + const char* serialized); + + + /** * @brief Data structure that contains information about the Orthanc core. **/ @@ -1333,7 +1357,8 @@ sizeof(int32_t) != sizeof(OrthancPluginDicomToJsonFlags) || sizeof(int32_t) != sizeof(OrthancPluginCreateDicomFlags) || sizeof(int32_t) != sizeof(OrthancPluginIdentifierConstraint) || - sizeof(int32_t) != sizeof(OrthancPluginInstanceOrigin)) + sizeof(int32_t) != sizeof(OrthancPluginInstanceOrigin) || + sizeof(int32_t) != sizeof(OrthancPluginJobStepStatus)) { /* Mismatch in the size of the enumerations */ return 0; @@ -5995,8 +6020,84 @@ return context->InvokeService(context, _OrthancPluginService_CallPeerApi, ¶ms); } + + + + typedef struct + { + char** resultId_; + void *job_; + int priority_; + const char *type_; + const char *content_; + const char *serialized_; + OrthancPluginJobFree free_; + OrthancPluginJobGetProgress getProgress_; + OrthancPluginJobStep step_; + OrthancPluginJobReleaseResources releaseResources_; + OrthancPluginJobReset reset_; + } _OrthancPluginSubmitJob; + + ORTHANC_PLUGIN_INLINE char *OrthancPluginSubmitJob( + OrthancPluginContext *context, + void *job, + int priority, + const char *type, + const char *content, + const char *serialized, + OrthancPluginJobFree freeJob, + OrthancPluginJobGetProgress getProgress, + OrthancPluginJobStep step, + OrthancPluginJobReleaseResources releaseResources, + OrthancPluginJobReset reset) + { + char* resultId = NULL; + + _OrthancPluginSubmitJob params; + memset(¶ms, 0, sizeof(params)); + + params.resultId_ = &resultId; + params.job_ = job; + params.priority_ = priority; + params.free_ = freeJob; + params.type_ = type; + params.content_ = content; + params.serialized_ = serialized; + params.getProgress_ = getProgress; + params.step_ = step; + params.releaseResources_ = releaseResources; + params.reset_ = reset; + + if (context->InvokeService(context, _OrthancPluginService_SubmitJob, ¶ms) != OrthancPluginErrorCode_Success || + resultId == NULL) + { + /* Error */ + return NULL; + } + else + { + return resultId; + } + } + + typedef struct + { + OrthancPluginJobsUnserializer unserializer; + } _OrthancPluginJobsUnserializer; + + ORTHANC_PLUGIN_INLINE void OrthancPluginRegisterJobsUnserializer( + OrthancPluginContext* context, + OrthancPluginJobsUnserializer unserializer) + { + _OrthancPluginJobsUnserializer params; + params.unserializer = unserializer; + + context->InvokeService(context, _OrthancPluginService_RegisterJobsUnserializer, ¶ms); + } + + #ifdef __cplusplus } #endif