# HG changeset patch # User Sebastien Jodogne # Date 1527785045 -7200 # Node ID e1893d31652a46b2336ee5281043f181b53a1dc0 # Parent 73d7d95dd75ec8d69a8cccc040399d80e0f5056b serialization of JobHandler diff -r 73d7d95dd75e -r e1893d31652a Core/JobsEngine/GenericJobUnserializer.cpp --- a/Core/JobsEngine/GenericJobUnserializer.cpp Thu May 31 17:45:09 2018 +0200 +++ b/Core/JobsEngine/GenericJobUnserializer.cpp Thu May 31 18:44:05 2018 +0200 @@ -43,10 +43,9 @@ namespace Orthanc { - IJob* GenericJobUnserializer::UnserializeJob(const Json::Value& source) + IJob* GenericJobUnserializer::UnserializeJob(const std::string& type, + const Json::Value& source) { - const std::string type = GetString(source, "Type"); - JobState state = StringToJobState(GetString(source, "State")); LOG(ERROR) << "Cannot unserialize job of type: " << type; throw OrthancException(ErrorCode_BadFileFormat); diff -r 73d7d95dd75e -r e1893d31652a Core/JobsEngine/GenericJobUnserializer.h --- a/Core/JobsEngine/GenericJobUnserializer.h Thu May 31 17:45:09 2018 +0200 +++ b/Core/JobsEngine/GenericJobUnserializer.h Thu May 31 18:44:05 2018 +0200 @@ -40,10 +40,11 @@ class GenericJobUnserializer : public IJobUnserializer { public: - virtual IJob* UnserializeJob(const Json::Value& source); + virtual IJob* UnserializeJob(const std::string& type, + const Json::Value& value); - virtual IJobOperation* UnserializeOperation(const Json::Value& source); + virtual IJobOperation* UnserializeOperation(const Json::Value& value); - virtual JobOperationValue* UnserializeValue(const Json::Value& source); + virtual JobOperationValue* UnserializeValue(const Json::Value& value); }; } diff -r 73d7d95dd75e -r e1893d31652a Core/JobsEngine/IJob.h --- a/Core/JobsEngine/IJob.h Thu May 31 17:45:09 2018 +0200 +++ b/Core/JobsEngine/IJob.h Thu May 31 18:44:05 2018 +0200 @@ -63,6 +63,6 @@ virtual void GetPublicContent(Json::Value& value) = 0; - virtual void GetInternalContent(Json::Value& value) = 0; + virtual void Serialize(Json::Value& value) = 0; }; } diff -r 73d7d95dd75e -r e1893d31652a Core/JobsEngine/IJobUnserializer.cpp --- a/Core/JobsEngine/IJobUnserializer.cpp Thu May 31 17:45:09 2018 +0200 +++ b/Core/JobsEngine/IJobUnserializer.cpp Thu May 31 18:44:05 2018 +0200 @@ -38,58 +38,43 @@ namespace Orthanc { - void IJobUnserializer::CheckType(const Json::Value& source, - const std::string& expectedType) - { - static const char* TYPE = "Type"; - - if (source.type() != Json::objectValue || - !source.isMember(TYPE) || - source[TYPE].type() != Json::stringValue || - source[TYPE].asString() != expectedType) - { - throw OrthancException(ErrorCode_BadFileFormat); - } - } - - - std::string IJobUnserializer::GetString(const Json::Value& source, + std::string IJobUnserializer::GetString(const Json::Value& value, const std::string& name) { - if (source.type() != Json::objectValue || - !source.isMember(name.c_str()) || - source[name.c_str()].type() != Json::stringValue) + if (value.type() != Json::objectValue || + !value.isMember(name.c_str()) || + value[name.c_str()].type() != Json::stringValue) { throw OrthancException(ErrorCode_BadFileFormat); } else { - return source[name.c_str()].asString(); + return value[name.c_str()].asString(); } } - int IJobUnserializer::GetInteger(const Json::Value& source, + int IJobUnserializer::GetInteger(const Json::Value& value, const std::string& name) { - if (source.type() != Json::objectValue || - !source.isMember(name.c_str()) || - (source[name.c_str()].type() != Json::intValue && - source[name.c_str()].type() != Json::uintValue)) + if (value.type() != Json::objectValue || + !value.isMember(name.c_str()) || + (value[name.c_str()].type() != Json::intValue && + value[name.c_str()].type() != Json::uintValue)) { throw OrthancException(ErrorCode_BadFileFormat); } else { - return source[name.c_str()].asInt(); + return value[name.c_str()].asInt(); } } - unsigned int IJobUnserializer::GetUnsignedInteger(const Json::Value& source, + unsigned int IJobUnserializer::GetUnsignedInteger(const Json::Value& value, const std::string& name) { - int tmp = GetInteger(source, name); + int tmp = GetInteger(value, name); if (tmp < 0) { diff -r 73d7d95dd75e -r e1893d31652a Core/JobsEngine/IJobUnserializer.h --- a/Core/JobsEngine/IJobUnserializer.h Thu May 31 17:45:09 2018 +0200 +++ b/Core/JobsEngine/IJobUnserializer.h Thu May 31 18:44:05 2018 +0200 @@ -46,22 +46,20 @@ { } - virtual IJob* UnserializeJob(const Json::Value& source) = 0; - - virtual IJobOperation* UnserializeOperation(const Json::Value& source) = 0; + virtual IJob* UnserializeJob(const std::string& jobType, + const Json::Value& value) = 0; - virtual JobOperationValue* UnserializeValue(const Json::Value& source) = 0; + virtual IJobOperation* UnserializeOperation(const Json::Value& value) = 0; - static void CheckType(const Json::Value& source, - const std::string& expectedType); + virtual JobOperationValue* UnserializeValue(const Json::Value& value) = 0; - static std::string GetString(const Json::Value& source, + static std::string GetString(const Json::Value& value, const std::string& name); - static int GetInteger(const Json::Value& source, + static int GetInteger(const Json::Value& value, const std::string& name); - static unsigned int GetUnsignedInteger(const Json::Value& source, + static unsigned int GetUnsignedInteger(const Json::Value& value, const std::string& name); }; } diff -r 73d7d95dd75e -r e1893d31652a Core/JobsEngine/JobStatus.cpp --- a/Core/JobsEngine/JobStatus.cpp Thu May 31 17:45:09 2018 +0200 +++ b/Core/JobsEngine/JobStatus.cpp Thu May 31 18:44:05 2018 +0200 @@ -40,7 +40,8 @@ errorCode_(ErrorCode_InternalError), progress_(0), jobType_("Invalid"), - publicContent_(Json::objectValue) + publicContent_(Json::objectValue), + serialized_(Json::objectValue) { } @@ -63,5 +64,6 @@ job.GetJobType(jobType_); job.GetPublicContent(publicContent_); + job.Serialize(serialized_); } } diff -r 73d7d95dd75e -r e1893d31652a Core/JobsEngine/JobStatus.h --- a/Core/JobsEngine/JobStatus.h Thu May 31 17:45:09 2018 +0200 +++ b/Core/JobsEngine/JobStatus.h Thu May 31 18:44:05 2018 +0200 @@ -44,6 +44,7 @@ float progress_; std::string jobType_; Json::Value publicContent_; + Json::Value serialized_; public: JobStatus(); @@ -75,5 +76,10 @@ { return publicContent_; } + + const Json::Value& GetSerialized() const + { + return serialized_; + } }; } diff -r 73d7d95dd75e -r e1893d31652a Core/JobsEngine/JobsRegistry.cpp --- a/Core/JobsEngine/JobsRegistry.cpp Thu May 31 17:45:09 2018 +0200 +++ b/Core/JobsEngine/JobsRegistry.cpp Thu May 31 18:44:05 2018 +0200 @@ -45,6 +45,7 @@ private: std::string id_; JobState state_; + std::string jobType_; std::auto_ptr job_; int priority_; // "+inf()" means highest priority boost::posix_time::ptime creationTime_; @@ -94,9 +95,10 @@ throw OrthancException(ErrorCode_NullPointer); } + job->GetJobType(jobType_); job->Start(); - lastStatus_ = JobStatus(ErrorCode_Success, *job); + lastStatus_ = JobStatus(ErrorCode_Success, *job_); } const std::string& GetId() const @@ -231,6 +233,65 @@ { lastStatus_.SetErrorCode(code); } + + void Serialize(Json::Value& target) const + { + target["State"] = EnumerationToString(state_); + target["JobType"] = jobType_; + target["Priority"] = priority_; + target["CreationTime"] = boost::posix_time::to_iso_string(creationTime_); + target["Runtime"] = static_cast(runtime_.total_milliseconds()); + + if (state_ == JobState_Running) + { + // WARNING: Cannot directly access the "job_" member, as long + // as a "RunningJob" instance is running. We do not use a + // mutex at the "JobHandler" level, as serialization would be + // blocked while a step in the job is running. Instead, we + // save a snapshot of the serialized job. + target["Job"] = lastStatus_.GetSerialized(); + } + else + { + job_->Serialize(target["Job"]); + } + } + + JobHandler(IJobUnserializer& unserializer, + const std::string& id, + const Json::Value& serialized) : + id_(id), + lastStateChangeTime_(boost::posix_time::microsec_clock::universal_time()), + pauseScheduled_(false), + cancelScheduled_(false) + { + state_ = StringToJobState(IJobUnserializer::GetString(serialized, "State")); + jobType_ = IJobUnserializer::GetString(serialized, "Type"); + priority_ = IJobUnserializer::GetInteger(serialized, "Priority"); + creationTime_ = boost::posix_time::from_iso_string + (IJobUnserializer::GetString(serialized, "CreationTime")); + runtime_ = boost::posix_time::milliseconds(IJobUnserializer::GetInteger(serialized, "Runtime")); + + retryTime_ = creationTime_; + + if (state_ == JobState_Retry || + state_ == JobState_Running) + { + state_ = JobState_Pending; + } + + job_.reset(unserializer.UnserializeJob(jobType_, serialized["Job"])); + + std::string s; + job_->GetJobType(s); + if (s != jobType_) + { + throw OrthancException(ErrorCode_InternalError); + } + + job_->Start(); + lastStatus_ = JobStatus(ErrorCode_Success, *job_); + } }; @@ -501,6 +562,22 @@ } + void JobsRegistry::Serialize(Json::Value& target) + { + boost::mutex::scoped_lock lock(mutex_); + CheckInvariants(); + + target = Json::objectValue; + + for (JobsIndex::const_iterator it = jobsIndex_.begin(); + it != jobsIndex_.end(); ++it) + { + Json::Value& v = target[it->first]; + it->second->Serialize(v); + } + } + + void JobsRegistry::Submit(std::string& id, IJob* job, // Takes ownership int priority) diff -r 73d7d95dd75e -r e1893d31652a Core/JobsEngine/JobsRegistry.h --- a/Core/JobsEngine/JobsRegistry.h Thu May 31 17:45:09 2018 +0200 +++ b/Core/JobsEngine/JobsRegistry.h Thu May 31 18:44:05 2018 +0200 @@ -42,6 +42,7 @@ #endif #include "JobInfo.h" +#include "IJobUnserializer.h" #include #include @@ -126,6 +127,8 @@ bool GetJobInfo(JobInfo& target, const std::string& id); + + void Serialize(Json::Value& target); void Submit(std::string& id, IJob* job, // Takes ownership diff -r 73d7d95dd75e -r e1893d31652a Core/JobsEngine/Operations/SequenceOfOperationsJob.cpp --- a/Core/JobsEngine/Operations/SequenceOfOperationsJob.cpp Thu May 31 17:45:09 2018 +0200 +++ b/Core/JobsEngine/Operations/SequenceOfOperationsJob.cpp Thu May 31 18:44:05 2018 +0200 @@ -361,7 +361,7 @@ } - void SequenceOfOperationsJob::GetInternalContent(Json::Value& value) + void SequenceOfOperationsJob::Serialize(Json::Value& value) { boost::mutex::scoped_lock lock(mutex_); diff -r 73d7d95dd75e -r e1893d31652a Core/JobsEngine/Operations/SequenceOfOperationsJob.h --- a/Core/JobsEngine/Operations/SequenceOfOperationsJob.h Thu May 31 17:45:09 2018 +0200 +++ b/Core/JobsEngine/Operations/SequenceOfOperationsJob.h Thu May 31 18:44:05 2018 +0200 @@ -138,7 +138,7 @@ virtual void GetPublicContent(Json::Value& value); - virtual void GetInternalContent(Json::Value& value); + virtual void Serialize(Json::Value& value); void AwakeTrailingSleep() { diff -r 73d7d95dd75e -r e1893d31652a Core/JobsEngine/SetOfInstancesJob.cpp --- a/Core/JobsEngine/SetOfInstancesJob.cpp Thu May 31 17:45:09 2018 +0200 +++ b/Core/JobsEngine/SetOfInstancesJob.cpp Thu May 31 18:44:05 2018 +0200 @@ -186,7 +186,7 @@ } - void SetOfInstancesJob::GetInternalContent(Json::Value& value) + void SetOfInstancesJob::Serialize(Json::Value& value) { Json::Value v = Json::arrayValue; diff -r 73d7d95dd75e -r e1893d31652a Core/JobsEngine/SetOfInstancesJob.h --- a/Core/JobsEngine/SetOfInstancesJob.h Thu May 31 17:45:09 2018 +0200 +++ b/Core/JobsEngine/SetOfInstancesJob.h Thu May 31 18:44:05 2018 +0200 @@ -109,6 +109,6 @@ virtual void GetPublicContent(Json::Value& value); - virtual void GetInternalContent(Json::Value& value); + virtual void Serialize(Json::Value& value); }; } diff -r 73d7d95dd75e -r e1893d31652a OrthancServer/ServerJobs/ArchiveJob.cpp --- a/OrthancServer/ServerJobs/ArchiveJob.cpp Thu May 31 17:45:09 2018 +0200 +++ b/OrthancServer/ServerJobs/ArchiveJob.cpp Thu May 31 18:44:05 2018 +0200 @@ -903,7 +903,7 @@ } - void ArchiveJob::GetInternalContent(Json::Value& value) + void ArchiveJob::Serialize(Json::Value& value) { // TODO } diff -r 73d7d95dd75e -r e1893d31652a OrthancServer/ServerJobs/ArchiveJob.h --- a/OrthancServer/ServerJobs/ArchiveJob.h Thu May 31 17:45:09 2018 +0200 +++ b/OrthancServer/ServerJobs/ArchiveJob.h Thu May 31 18:44:05 2018 +0200 @@ -97,6 +97,6 @@ virtual void GetPublicContent(Json::Value& value); - virtual void GetInternalContent(Json::Value& value); + virtual void Serialize(Json::Value& value); }; } diff -r 73d7d95dd75e -r e1893d31652a OrthancServer/ServerJobs/OrthancJobUnserializer.cpp --- a/OrthancServer/ServerJobs/OrthancJobUnserializer.cpp Thu May 31 17:45:09 2018 +0200 +++ b/OrthancServer/ServerJobs/OrthancJobUnserializer.cpp Thu May 31 18:44:05 2018 +0200 @@ -41,11 +41,10 @@ namespace Orthanc { - IJob* OrthancJobUnserializer::UnserializeJob(const Json::Value& source) + IJob* OrthancJobUnserializer::UnserializeJob(const std::string& type, + const Json::Value& source) { - const std::string type = GetString(source, "Type"); - - return GenericJobUnserializer::UnserializeJob(source); + return GenericJobUnserializer::UnserializeJob(type, source); } diff -r 73d7d95dd75e -r e1893d31652a OrthancServer/ServerJobs/OrthancJobUnserializer.h --- a/OrthancServer/ServerJobs/OrthancJobUnserializer.h Thu May 31 17:45:09 2018 +0200 +++ b/OrthancServer/ServerJobs/OrthancJobUnserializer.h Thu May 31 18:44:05 2018 +0200 @@ -49,10 +49,11 @@ { } - virtual IJob* UnserializeJob(const Json::Value& source); + virtual IJob* UnserializeJob(const std::string& type, + const Json::Value& value); - virtual IJobOperation* UnserializeOperation(const Json::Value& source); + virtual IJobOperation* UnserializeOperation(const Json::Value& value); - virtual JobOperationValue* UnserializeValue(const Json::Value& source); + virtual JobOperationValue* UnserializeValue(const Json::Value& value); }; } diff -r 73d7d95dd75e -r e1893d31652a OrthancServer/ServerJobs/ResourceModificationJob.cpp --- a/OrthancServer/ServerJobs/ResourceModificationJob.cpp Thu May 31 17:45:09 2018 +0200 +++ b/OrthancServer/ServerJobs/ResourceModificationJob.cpp Thu May 31 18:44:05 2018 +0200 @@ -273,9 +273,9 @@ } - void ResourceModificationJob::GetInternalContent(Json::Value& value) + void ResourceModificationJob::Serialize(Json::Value& value) { - SetOfInstancesJob::GetInternalContent(value); + SetOfInstancesJob::Serialize(value); Json::Value tmp; modification_->Serialize(tmp); diff -r 73d7d95dd75e -r e1893d31652a OrthancServer/ServerJobs/ResourceModificationJob.h --- a/OrthancServer/ServerJobs/ResourceModificationJob.h Thu May 31 17:45:09 2018 +0200 +++ b/OrthancServer/ServerJobs/ResourceModificationJob.h Thu May 31 18:44:05 2018 +0200 @@ -104,6 +104,6 @@ virtual void GetPublicContent(Json::Value& value); - virtual void GetInternalContent(Json::Value& value); + virtual void Serialize(Json::Value& value); }; } diff -r 73d7d95dd75e -r e1893d31652a UnitTestsSources/MultiThreadingTests.cpp --- a/UnitTestsSources/MultiThreadingTests.cpp Thu May 31 17:45:09 2018 +0200 +++ b/UnitTestsSources/MultiThreadingTests.cpp Thu May 31 18:44:05 2018 +0200 @@ -167,7 +167,7 @@ type = "DummyJob"; } - virtual void GetInternalContent(Json::Value& value) + virtual void Serialize(Json::Value& value) { }