# HG changeset patch # User Alain Mazy # Date 1591698063 -7200 # Node ID 52bc28f8ac8c7a5733ac194ab919b276b3050ffe # Parent ceba3213cb9ecd266ac3ef9f1a5d67fdfd95c134# Parent 1d2b31fc782feb7900a13545b4c852dac23db892 merge diff -r ceba3213cb9e -r 52bc28f8ac8c Core/JobsEngine/JobsRegistry.cpp --- a/Core/JobsEngine/JobsRegistry.cpp Tue Jun 09 11:37:52 2020 +0200 +++ b/Core/JobsEngine/JobsRegistry.cpp Tue Jun 09 12:21:03 2020 +0200 @@ -20,7 +20,7 @@ * 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 @@ -50,10 +50,10 @@ static const char* CREATION_TIME = "CreationTime"; static const char* LAST_CHANGE_TIME = "LastChangeTime"; static const char* RUNTIME = "Runtime"; - + class JobsRegistry::JobHandler : public boost::noncopyable - { + { private: std::string id_; JobState state_; @@ -80,7 +80,7 @@ lastStateChangeTime_ = now; } - void SetStateInternal(JobState state) + void SetStateInternal(JobState state) { state_ = state; pauseScheduled_ = false; @@ -139,7 +139,7 @@ return state_; } - void SetState(JobState state) + void SetState(JobState state) { if (state == JobState_Retry) { @@ -157,7 +157,7 @@ if (state_ == JobState_Running) { SetStateInternal(JobState_Retry); - retryTime_ = (boost::posix_time::microsec_clock::universal_time() + + retryTime_ = (boost::posix_time::microsec_clock::universal_time() + boost::posix_time::milliseconds(timeout)); } else @@ -275,7 +275,7 @@ ok = false; } } - else + else { ok = job_->Serialize(target[JOB]); } @@ -327,14 +327,14 @@ JobHandler*& b) const { return a->GetPriority() < b->GetPriority(); - } + } #if defined(NDEBUG) void JobsRegistry::CheckInvariants() const { } - + #else bool JobsRegistry::IsPendingJob(const JobHandler& job) const { @@ -409,16 +409,16 @@ case JobState_Pending: assert(!IsRetryJob(job) && IsPendingJob(job) && !IsCompletedJob(job)); break; - + case JobState_Success: case JobState_Failure: assert(!IsRetryJob(job) && !IsPendingJob(job) && IsCompletedJob(job)); break; - + case JobState_Retry: assert(IsRetryJob(job) && !IsPendingJob(job) && !IsCompletedJob(job)); break; - + case JobState_Running: case JobState_Paused: assert(!IsRetryJob(job) && !IsPendingJob(job) && !IsCompletedJob(job)); @@ -482,7 +482,7 @@ default: throw OrthancException(ErrorCode_InternalError); } - + LOG(INFO) << "Job has completed with " << tmp << ": " << job.GetId(); CheckInvariants(); @@ -560,7 +560,7 @@ } } - + JobsRegistry::~JobsRegistry() { for (JobsIndex::iterator it = jobsIndex_.begin(); it != jobsIndex_.end(); ++it) @@ -668,13 +668,13 @@ { throw OrthancException(ErrorCode_NullPointer); } - + std::unique_ptr protection(handler); { boost::mutex::scoped_lock lock(mutex_); CheckInvariants(); - + id = handler->GetId(); int priority = handler->GetPriority(); @@ -689,18 +689,18 @@ pendingJobs_.push(handler); pendingJobAvailable_.notify_one(); break; - + case JobState_Success: SetCompletedJob(*handler, true); break; - + case JobState_Failure: SetCompletedJob(*handler, false); break; case JobState_Paused: break; - + default: { std::string details = ("A job should not be loaded from state: " + @@ -798,7 +798,7 @@ const JobStatus& status = it->second->GetLastStatus(); successContent = status.GetPublicContent(); } - + return; } else @@ -875,7 +875,7 @@ void JobsRegistry::RemoveRetryJob(JobHandler* handler) { RetryJobs::iterator item = retryJobs_.find(handler); - assert(item != retryJobs_.end()); + assert(item != retryJobs_.end()); retryJobs_.erase(item); } @@ -962,7 +962,7 @@ SetCompletedJob(*found->second, false); found->second->SetLastErrorCode(ErrorCode_CanceledJob); break; - + case JobState_Success: case JobState_Failure: // Nothing to be done @@ -1010,7 +1010,7 @@ pendingJobs_.push(found->second); pendingJobAvailable_.notify_one(); CheckInvariants(); - return true; + return true; } } @@ -1037,9 +1037,9 @@ else { found->second->GetJob().Reset(); - + bool ok = false; - for (CompletedJobs::iterator it = completedJobs_.begin(); + for (CompletedJobs::iterator it = completedJobs_.begin(); it != completedJobs_.end(); ++it) { if (*it == found->second) @@ -1106,14 +1106,14 @@ observer_ = &observer; } - + void JobsRegistry::ResetObserver() { boost::mutex::scoped_lock lock(mutex_); observer_ = NULL; } - + JobsRegistry::RunningJob::RunningJob(JobsRegistry& registry, unsigned int timeout) : registry_(registry), @@ -1156,7 +1156,7 @@ } } - + JobsRegistry::RunningJob::~RunningJob() { if (IsValid()) @@ -1176,26 +1176,26 @@ case JobState_Paused: registry_.MarkRunningAsPaused(*handler_); - break; + break; case JobState_Retry: registry_.MarkRunningAsRetry(*handler_, targetRetryTimeout_); break; - + default: assert(0); } } } - + bool JobsRegistry::RunningJob::IsValid() const { return (handler_ != NULL && job_ != NULL); } - + const std::string& JobsRegistry::RunningJob::GetId() const { if (!IsValid()) @@ -1208,7 +1208,7 @@ } } - + int JobsRegistry::RunningJob::GetPriority() const { if (!IsValid()) @@ -1220,7 +1220,7 @@ return priority_; } } - + IJob& JobsRegistry::RunningJob::GetJob() { @@ -1234,7 +1234,7 @@ } } - + bool JobsRegistry::RunningJob::IsPauseScheduled() { if (!IsValid()) @@ -1246,12 +1246,12 @@ boost::mutex::scoped_lock lock(registry_.mutex_); registry_.CheckInvariants(); assert(handler_->GetState() == JobState_Running); - + return handler_->IsPauseScheduled(); } } - + bool JobsRegistry::RunningJob::IsCancelScheduled() { if (!IsValid()) @@ -1263,12 +1263,12 @@ boost::mutex::scoped_lock lock(registry_.mutex_); registry_.CheckInvariants(); assert(handler_->GetState() == JobState_Running); - + return handler_->IsCancelScheduled(); } } - + void JobsRegistry::RunningJob::MarkSuccess() { if (!IsValid()) @@ -1281,7 +1281,7 @@ } } - + void JobsRegistry::RunningJob::MarkFailure() { if (!IsValid()) @@ -1294,7 +1294,7 @@ } } - + void JobsRegistry::RunningJob::MarkCanceled() { if (!IsValid()) @@ -1308,7 +1308,7 @@ } } - + void JobsRegistry::RunningJob::MarkPause() { if (!IsValid()) @@ -1321,7 +1321,7 @@ } } - + void JobsRegistry::RunningJob::MarkRetry(unsigned int timeout) { if (!IsValid()) @@ -1334,7 +1334,7 @@ targetRetryTimeout_ = timeout; } } - + void JobsRegistry::RunningJob::UpdateStatus(ErrorCode code, const std::string& details) @@ -1346,11 +1346,11 @@ else { JobStatus status(code, details, *job_); - + boost::mutex::scoped_lock lock(registry_.mutex_); registry_.CheckInvariants(); assert(handler_->GetState() == JobState_Running); - + handler_->SetLastStatus(status); } } @@ -1365,8 +1365,8 @@ target = Json::objectValue; target[TYPE] = JOBS_REGISTRY; target[JOBS] = Json::objectValue; - - for (JobsIndex::const_iterator it = jobsIndex_.begin(); + + for (JobsIndex::const_iterator it = jobsIndex_.begin(); it != jobsIndex_.end(); ++it) { Json::Value v; @@ -1440,7 +1440,7 @@ running = 0; success = 0; failed = 0; - + for (JobsIndex::const_iterator it = jobsIndex_.begin(); it != jobsIndex_.end(); ++it) { @@ -1457,7 +1457,7 @@ case JobState_Running: running ++; break; - + case JobState_Success: success ++; break; @@ -1469,6 +1469,6 @@ default: throw OrthancException(ErrorCode_InternalError); } - } + } } } diff -r ceba3213cb9e -r 52bc28f8ac8c Core/JobsEngine/JobsRegistry.h --- a/Core/JobsEngine/JobsRegistry.h Tue Jun 09 11:37:52 2020 +0200 +++ b/Core/JobsEngine/JobsRegistry.h Tue Jun 09 12:21:03 2020 +0200 @@ -20,7 +20,7 @@ * 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 @@ -69,7 +69,7 @@ virtual void SignalJobFailure(const std::string& jobId) = 0; }; - + private: enum CompletedReason { @@ -77,7 +77,7 @@ CompletedReason_Failure, CompletedReason_Canceled }; - + class JobHandler; struct PriorityComparator @@ -89,7 +89,7 @@ typedef std::map JobsIndex; typedef std::list CompletedJobs; typedef std::set RetryJobs; - typedef std::priority_queue, // Could be a "std::deque" PriorityComparator> PendingJobs; @@ -110,7 +110,7 @@ bool IsPendingJob(const JobHandler& job) const; bool IsCompletedJob(JobHandler& job) const; - + bool IsRetryJob(JobHandler& job) const; #endif @@ -120,25 +120,25 @@ void SetCompletedJob(JobHandler& job, bool success); - + void MarkRunningAsCompleted(JobHandler& job, CompletedReason reason); void MarkRunningAsRetry(JobHandler& job, unsigned int timeout); - + void MarkRunningAsPaused(JobHandler& job); - + bool GetStateInternal(JobState& state, const std::string& id); void RemovePendingJob(const std::string& id); - + void RemoveRetryJob(JobHandler* handler); - + void SubmitInternal(std::string& id, JobHandler* handler); - + public: JobsRegistry(size_t maxCompletedJobs) : maxCompletedJobs_(maxCompletedJobs), @@ -153,7 +153,7 @@ ~JobsRegistry(); void SetMaxCompletedJobs(size_t i); - + size_t GetMaxCompletedJobs(); void ListJobs(std::set& target); @@ -167,31 +167,31 @@ const std::string& key); void Serialize(Json::Value& target); - + void Submit(std::string& id, IJob* job, // Takes ownership int priority); - + void Submit(IJob* job, // Takes ownership int priority); void SubmitAndWait(Json::Value& successContent, IJob* job, // Takes ownership int priority); - + bool SetPriority(const std::string& id, int priority); bool Pause(const std::string& id); - + bool Resume(const std::string& id); bool Resubmit(const std::string& id); bool Cancel(const std::string& id); - + void ScheduleRetries(); - + bool GetState(JobState& state, const std::string& id); @@ -219,7 +219,7 @@ JobState targetState_; unsigned int targetRetryTimeout_; bool canceled_; - + public: RunningJob(JobsRegistry& registry, unsigned int timeout); diff -r ceba3213cb9e -r 52bc28f8ac8c NEWS --- a/NEWS Tue Jun 09 11:37:52 2020 +0200 +++ b/NEWS Tue Jun 09 12:21:03 2020 +0200 @@ -3,6 +3,12 @@ * Private tags returned by C-FIND SCP (cf. option "DefaultPrivateCreator") +Plugins +------- + +* New functions in the SDK: + - new "changes": JobSubmitted, JobSuccess, JobFailure + Version 1.7.1 (2020-05-27) ========================== diff -r ceba3213cb9e -r 52bc28f8ac8c OrthancServer/ServerContext.cpp --- a/OrthancServer/ServerContext.cpp Tue Jun 09 11:37:52 2020 +0200 +++ b/OrthancServer/ServerContext.cpp Tue Jun 09 12:21:03 2020 +0200 @@ -143,6 +143,7 @@ { haveJobsChanged_ = true; mainLua_.SignalJobSubmitted(jobId); + plugins_->SignalJobSubmitted(jobId); } @@ -150,6 +151,7 @@ { haveJobsChanged_ = true; mainLua_.SignalJobSuccess(jobId); + plugins_->SignalJobSuccess(jobId); } @@ -157,6 +159,7 @@ { haveJobsChanged_ = true; mainLua_.SignalJobFailure(jobId); + plugins_->SignalJobFailure(jobId); } diff -r ceba3213cb9e -r 52bc28f8ac8c Plugins/Engine/OrthancPlugins.h --- a/Plugins/Engine/OrthancPlugins.h Tue Jun 09 11:37:52 2020 +0200 +++ b/Plugins/Engine/OrthancPlugins.h Tue Jun 09 12:21:03 2020 +0200 @@ -311,6 +311,21 @@ SignalChangeInternal(OrthancPluginChangeType_OrthancStopped, OrthancPluginResourceType_None, NULL); } + void SignalJobSubmitted(const std::string& jobId) + { + SignalChangeInternal(OrthancPluginChangeType_JobSubmitted, OrthancPluginResourceType_None, jobId.c_str()); + } + + void SignalJobSuccess(const std::string& jobId) + { + SignalChangeInternal(OrthancPluginChangeType_JobSuccess, OrthancPluginResourceType_None, jobId.c_str()); + } + + void SignalJobFailure(const std::string& jobId) + { + SignalChangeInternal(OrthancPluginChangeType_JobFailure, OrthancPluginResourceType_None, jobId.c_str()); + } + void SignalUpdatedPeers() { SignalChangeInternal(OrthancPluginChangeType_UpdatedPeers, OrthancPluginResourceType_None, NULL); diff -r ceba3213cb9e -r 52bc28f8ac8c Plugins/Engine/PluginsEnumerations.cpp diff -r ceba3213cb9e -r 52bc28f8ac8c Plugins/Engine/PluginsEnumerations.h diff -r ceba3213cb9e -r 52bc28f8ac8c Plugins/Include/orthanc/OrthancCPlugin.h --- a/Plugins/Include/orthanc/OrthancCPlugin.h Tue Jun 09 11:37:52 2020 +0200 +++ b/Plugins/Include/orthanc/OrthancCPlugin.h Tue Jun 09 12:21:03 2020 +0200 @@ -716,7 +716,7 @@ /** - * The supported types of changes that can happen to DICOM resources. + * The supported types of changes that can be signaled to the change callback. * @ingroup Callbacks **/ typedef enum @@ -737,6 +737,9 @@ OrthancPluginChangeType_UpdatedMetadata = 13, /*!< Some user-defined metadata has changed for this resource */ OrthancPluginChangeType_UpdatedPeers = 14, /*!< The list of Orthanc peers has changed */ OrthancPluginChangeType_UpdatedModalities = 15, /*!< The list of DICOM modalities has changed */ + OrthancPluginChangeType_JobSubmitted = 16, /*!< New Job submitted */ + OrthancPluginChangeType_JobSuccess = 17, /*!< A Job has completed successfully */ + OrthancPluginChangeType_JobFailure = 18, /*!< A Job has failed */ _OrthancPluginChangeType_INTERNAL = 0x7fffffff } OrthancPluginChangeType;