# HG changeset patch # User Sebastien Jodogne # Date 1538748454 -7200 # Node ID 8b00e4cb4a6be6d0ef1234b40c9c8c2c58dd0524 # Parent dedc2befbf417b3be982ccca0c3f1f941a23971b SetOfCommandsJob diff -r dedc2befbf41 -r 8b00e4cb4a6b Core/JobsEngine/SetOfCommandsJob.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/JobsEngine/SetOfCommandsJob.cpp Fri Oct 05 16:07:34 2018 +0200 @@ -0,0 +1,302 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2018 Osimis S.A., Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * In addition, as a special exception, the copyright holders of this + * program give permission to link the code of its release with the + * OpenSSL project's "OpenSSL" library (or with modified versions of it + * that use the same license as the "OpenSSL" library), and distribute + * the linked executables. You must obey the GNU General Public License + * in all respects for all of the code used other than "OpenSSL". If you + * modify file(s) with this exception, you may extend this exception to + * your version of the file(s), but you are not obligated to do so. If + * 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + **/ + + +#include "../PrecompiledHeaders.h" +#include "SetOfCommandsJob.h" + +#include "../Logging.h" +#include "../OrthancException.h" +#include "../SerializationToolbox.h" + +#include + +namespace Orthanc +{ + SetOfCommandsJob::SetOfCommandsJob() : + started_(false), + permissive_(false), + position_(0) + { + } + + + SetOfCommandsJob::~SetOfCommandsJob() + { + for (size_t i = 0; i < commands_.size(); i++) + { + assert(commands_[i] != NULL); + delete commands_[i]; + } + } + + + void SetOfCommandsJob::Reserve(size_t size) + { + if (started_) + { + throw OrthancException(ErrorCode_BadSequenceOfCalls); + } + else + { + commands_.reserve(size); + } + } + + + void SetOfCommandsJob::AddCommand(ICommand* command) + { + if (command == NULL) + { + throw OrthancException(ErrorCode_NullPointer); + } + else if (started_) + { + throw OrthancException(ErrorCode_BadSequenceOfCalls); + } + else + { + commands_.push_back(command); + } + } + + + void SetOfCommandsJob::SetPermissive(bool permissive) + { + if (started_) + { + throw OrthancException(ErrorCode_BadSequenceOfCalls); + } + else + { + permissive_ = permissive; + } + } + + + void SetOfCommandsJob::Reset() + { + if (started_) + { + position_ = 0; + } + else + { + throw OrthancException(ErrorCode_BadSequenceOfCalls); + } + } + + + float SetOfCommandsJob::GetProgress() + { + if (commands_.empty()) + { + return 1; + } + else + { + return (static_cast(position_) / + static_cast(commands_.size())); + } + } + + + const SetOfCommandsJob::ICommand& SetOfCommandsJob::GetCommand(size_t index) const + { + if (index >= commands_.size()) + { + throw OrthancException(ErrorCode_ParameterOutOfRange); + } + else + { + assert(commands_[index] != NULL); + return *commands_[index]; + } + } + + + JobStepResult SetOfCommandsJob::Step() + { + if (!started_) + { + throw OrthancException(ErrorCode_InternalError); + } + + if (commands_.empty() && + position_ == 0) + { + // No command to handle: We're done + position_ = 1; + return JobStepResult::Success(); + } + + if (position_ >= commands_.size()) + { + // Already done + throw OrthancException(ErrorCode_BadSequenceOfCalls); + } + + try + { + // Not at the trailing step: Handle the current command + if (!commands_[position_]->Execute()) + { + // Error + if (!permissive_) + { + return JobStepResult::Failure(ErrorCode_InternalError); + } + } + } + catch (OrthancException& e) + { + if (permissive_) + { + LOG(WARNING) << "Ignoring an error in a permissive job: " << e.What(); + } + else + { + return JobStepResult::Failure(e.GetErrorCode()); + } + } + + position_ += 1; + + if (position_ == commands_.size()) + { + // We're done + return JobStepResult::Success(); + } + else + { + return JobStepResult::Continue(); + } + } + + + + static const char* KEY_DESCRIPTION = "Description"; + static const char* KEY_PERMISSIVE = "Permissive"; + static const char* KEY_POSITION = "Position"; + static const char* KEY_TYPE = "Type"; + static const char* KEY_COMMANDS = "Commands"; + + + void SetOfCommandsJob::GetPublicContent(Json::Value& value) + { + value[KEY_DESCRIPTION] = GetDescription(); + } + + + bool SetOfCommandsJob::Serialize(Json::Value& target) + { + target = Json::objectValue; + + std::string type; + GetJobType(type); + target[KEY_TYPE] = type; + + target[KEY_PERMISSIVE] = permissive_; + target[KEY_POSITION] = static_cast(position_); + target[KEY_DESCRIPTION] = description_; + + target[KEY_COMMANDS] = Json::arrayValue; + Json::Value& tmp = target[KEY_COMMANDS]; + + for (size_t i = 0; i < commands_.size(); i++) + { + assert(commands_[i] != NULL); + + Json::Value command; + commands_[i]->Serialize(command); + tmp.append(command); + } + + return true; + } + + + SetOfCommandsJob::SetOfCommandsJob(ICommandUnserializer* unserializer, + const Json::Value& source) : + started_(false) + { + std::auto_ptr raii(unserializer); + + permissive_ = SerializationToolbox::ReadBoolean(source, KEY_PERMISSIVE); + position_ = SerializationToolbox::ReadUnsignedInteger(source, KEY_POSITION); + description_ = SerializationToolbox::ReadString(source, KEY_DESCRIPTION); + + if (!source.isMember(KEY_COMMANDS) || + source[KEY_COMMANDS].type() != Json::arrayValue) + { + throw OrthancException(ErrorCode_BadFileFormat); + } + else + { + const Json::Value& tmp = source[KEY_COMMANDS]; + commands_.resize(tmp.size()); + + for (Json::Value::ArrayIndex i = 0; i < tmp.size(); i++) + { + try + { + commands_[i] = unserializer->Unserialize(tmp[i]); + } + catch (OrthancException&) + { + } + + if (commands_[i] == NULL) + { + for (size_t j = 0; j < i; j++) + { + delete commands_[j]; + } + + throw OrthancException(ErrorCode_BadFileFormat); + } + } + } + + if (commands_.empty()) + { + if (position_ > 1) + { + throw OrthancException(ErrorCode_BadFileFormat); + } + } + else if (position_ > commands_.size()) + { + throw OrthancException(ErrorCode_BadFileFormat); + } + } +} diff -r dedc2befbf41 -r 8b00e4cb4a6b Core/JobsEngine/SetOfCommandsJob.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/JobsEngine/SetOfCommandsJob.h Fri Oct 05 16:07:34 2018 +0200 @@ -0,0 +1,135 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2018 Osimis S.A., Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * In addition, as a special exception, the copyright holders of this + * program give permission to link the code of its release with the + * OpenSSL project's "OpenSSL" library (or with modified versions of it + * that use the same license as the "OpenSSL" library), and distribute + * the linked executables. You must obey the GNU General Public License + * in all respects for all of the code used other than "OpenSSL". If you + * modify file(s) with this exception, you may extend this exception to + * your version of the file(s), but you are not obligated to do so. If + * 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + **/ + + +#pragma once + +#include "IJob.h" + +#include + +namespace Orthanc +{ + class SetOfCommandsJob : public IJob + { + public: + class ICommand : public boost::noncopyable + { + public: + virtual ~ICommand() + { + } + + virtual bool Execute() = 0; + + virtual void Serialize(Json::Value& target) const = 0; + }; + + class ICommandUnserializer : public boost::noncopyable + { + public: + virtual ~ICommandUnserializer() + { + } + + virtual ICommand* Unserialize(const Json::Value& source) const = 0; + }; + + private: + bool started_; + std::vector commands_; + bool permissive_; + size_t position_; + std::string description_; + + public: + SetOfCommandsJob(); + + SetOfCommandsJob(ICommandUnserializer* unserializer /* takes ownership */, + const Json::Value& source); + + virtual ~SetOfCommandsJob(); + + size_t GetPosition() const + { + return position_; + } + + void SetDescription(const std::string& description) + { + description_ = description; + } + + const std::string& GetDescription() const + { + return description_; + } + + void Reserve(size_t size); + + size_t GetCommandsCount() const + { + return commands_.size(); + } + + void AddCommand(ICommand* command); // Takes ownership + + bool IsPermissive() const + { + return permissive_; + } + + void SetPermissive(bool permissive); + + virtual void Reset(); + + virtual void Start() + { + started_ = true; + } + + virtual float GetProgress(); + + bool IsStarted() const + { + return started_; + } + + const ICommand& GetCommand(size_t index) const; + + virtual JobStepResult Step(); + + virtual void GetPublicContent(Json::Value& value); + + virtual bool Serialize(Json::Value& target); + }; +} diff -r dedc2befbf41 -r 8b00e4cb4a6b Core/JobsEngine/SetOfInstancesJob.cpp --- a/Core/JobsEngine/SetOfInstancesJob.cpp Fri Oct 05 10:44:59 2018 +0200 +++ b/Core/JobsEngine/SetOfInstancesJob.cpp Fri Oct 05 16:07:34 2018 +0200 @@ -37,249 +37,204 @@ #include "../OrthancException.h" #include "../SerializationToolbox.h" +#include + namespace Orthanc { - SetOfInstancesJob::SetOfInstancesJob(bool hasTrailingStep) : - hasTrailingStep_(hasTrailingStep), - started_(false), - permissive_(false), - position_(0) + class SetOfInstancesJob::InstanceCommand : public SetOfInstancesJob::ICommand + { + private: + SetOfInstancesJob& that_; + std::string instance_; + + public: + InstanceCommand(SetOfInstancesJob& that, + const std::string& instance) : + that_(that), + instance_(instance) + { + } + + const std::string& GetInstance() const + { + return instance_; + } + + virtual bool Execute() + { + if (!that_.HandleInstance(instance_)) + { + that_.failedInstances_.insert(instance_); + return false; + } + else + { + return true; + } + } + + virtual void Serialize(Json::Value& target) const + { + target = instance_; + } + }; + + + class SetOfInstancesJob::TrailingStepCommand : public SetOfInstancesJob::ICommand + { + private: + SetOfInstancesJob& that_; + + public: + TrailingStepCommand(SetOfInstancesJob& that) : + that_(that) + { + } + + virtual bool Execute() + { + return that_.HandleTrailingStep(); + } + + virtual void Serialize(Json::Value& target) const + { + target = Json::nullValue; + } + }; + + + class SetOfInstancesJob::InstanceUnserializer : + public SetOfInstancesJob::ICommandUnserializer + { + private: + SetOfInstancesJob& that_; + + public: + InstanceUnserializer(SetOfInstancesJob& that) : + that_(that) + { + } + + virtual ICommand* Unserialize(const Json::Value& source) const + { + if (source.type() == Json::nullValue) + { + return new TrailingStepCommand(that_); + } + else if (source.type() == Json::stringValue) + { + return new InstanceCommand(that_, source.asString()); + } + else + { + throw OrthancException(ErrorCode_BadFileFormat); + } + } + }; + + + SetOfInstancesJob::SetOfInstancesJob() : + hasTrailingStep_(false) { } - void SetOfInstancesJob::Reserve(size_t size) - { - if (started_) - { - throw OrthancException(ErrorCode_BadSequenceOfCalls); - } - else - { - instances_.reserve(size); - } - } - - - size_t SetOfInstancesJob::GetStepsCount() const - { - if (HasTrailingStep()) - { - return instances_.size() + 1; - } - else - { - return instances_.size(); - } - } - - void SetOfInstancesJob::AddInstance(const std::string& instance) { - if (started_) - { - throw OrthancException(ErrorCode_BadSequenceOfCalls); - } - else - { - instances_.push_back(instance); - } + AddCommand(new InstanceCommand(*this, instance)); } - void SetOfInstancesJob::SetPermissive(bool permissive) + void SetOfInstancesJob::AddTrailingStep() { - if (started_) - { - throw OrthancException(ErrorCode_BadSequenceOfCalls); - } - else + AddCommand(new TrailingStepCommand(*this)); + hasTrailingStep_ = true; + } + + + size_t SetOfInstancesJob::GetInstancesCount() const + { + if (hasTrailingStep_) { - permissive_ = permissive; - } - } - - - void SetOfInstancesJob::Reset() - { - if (started_) - { - position_ = 0; - failedInstances_.clear(); + assert(GetCommandsCount() > 0); + return GetCommandsCount() - 1; } else { - throw OrthancException(ErrorCode_BadSequenceOfCalls); + return GetCommandsCount(); } } - - float SetOfInstancesJob::GetProgress() - { - const size_t steps = GetStepsCount(); - - if (steps == 0) - { - return 0; - } - else - { - return (static_cast(position_) / - static_cast(steps)); - } - } - - + const std::string& SetOfInstancesJob::GetInstance(size_t index) const { - if (index >= instances_.size()) + if (index >= GetInstancesCount()) { throw OrthancException(ErrorCode_ParameterOutOfRange); } else { - return instances_[index]; - } - } - - - JobStepResult SetOfInstancesJob::Step() - { - if (!started_) - { - throw OrthancException(ErrorCode_InternalError); - } - - const size_t steps = GetStepsCount(); - - if (steps == 0 && - position_ == 0) - { - // Nothing to handle (no instance, nor trailing step): We're done - position_ = 1; - return JobStepResult::Success(); - } - - if (position_ >= steps) - { - // Already done - throw OrthancException(ErrorCode_BadSequenceOfCalls); - } - - bool isTrailingStep = (hasTrailingStep_ && - position_ + 1 == steps); - - bool ok; - - try - { - if (isTrailingStep) - { - ok = HandleTrailingStep(); - } - else - { - // Not at the trailing step: Handle the current instance - ok = HandleInstance(instances_[position_]); - } - - if (!ok && !permissive_) - { - return JobStepResult::Failure(ErrorCode_InternalError); - } - } - catch (OrthancException&) - { - if (permissive_) - { - ok = false; - } - else - { - throw; - } - } - - if (!ok && - !isTrailingStep) - { - failedInstances_.insert(instances_[position_]); - } - - position_ += 1; - - if (position_ == steps) - { - // We're done - return JobStepResult::Success(); - } - else - { - return JobStepResult::Continue(); + return dynamic_cast(GetCommand(index)).GetInstance(); } } + void SetOfInstancesJob::Start() + { + SetOfCommandsJob::Start(); + } - static const char* KEY_DESCRIPTION = "Description"; - static const char* KEY_PERMISSIVE = "Permissive"; - static const char* KEY_POSITION = "Position"; - static const char* KEY_TYPE = "Type"; - static const char* KEY_INSTANCES = "Instances"; - static const char* KEY_FAILED_INSTANCES = "FailedInstances"; - static const char* KEY_TRAILING_STEP = "TrailingStep"; + + void SetOfInstancesJob::Reset() + { + SetOfCommandsJob::Reset(); - - void SetOfInstancesJob::GetPublicContent(Json::Value& value) + failedInstances_.clear(); + } + + + void SetOfInstancesJob::GetPublicContent(Json::Value& target) { - value[KEY_DESCRIPTION] = GetDescription(); - value["InstancesCount"] = static_cast(instances_.size()); - value["FailedInstancesCount"] = static_cast(failedInstances_.size()); + SetOfCommandsJob::GetPublicContent(target); + target["InstancesCount"] = static_cast(GetInstancesCount()); + target["FailedInstancesCount"] = static_cast(failedInstances_.size()); } - bool SetOfInstancesJob::Serialize(Json::Value& value) - { - value = Json::objectValue; - std::string type; - GetJobType(type); - value[KEY_TYPE] = type; - - value[KEY_PERMISSIVE] = permissive_; - value[KEY_POSITION] = static_cast(position_); - value[KEY_DESCRIPTION] = description_; - value[KEY_TRAILING_STEP] = hasTrailingStep_; - - SerializationToolbox::WriteArrayOfStrings(value, instances_, KEY_INSTANCES); - SerializationToolbox::WriteSetOfStrings(value, failedInstances_, KEY_FAILED_INSTANCES); + static const char* KEY_TRAILING_STEP = "TrailingStep"; + static const char* KEY_FAILED_INSTANCES = "FailedInstances"; - return true; + bool SetOfInstancesJob::Serialize(Json::Value& target) + { + if (SetOfCommandsJob::Serialize(target)) + { + target[KEY_TRAILING_STEP] = hasTrailingStep_; + SerializationToolbox::WriteSetOfStrings(target, failedInstances_, KEY_FAILED_INSTANCES); + return true; + } + else + { + return false; + } } - + - SetOfInstancesJob::SetOfInstancesJob(const Json::Value& value) : - started_(false), - permissive_(SerializationToolbox::ReadBoolean(value, KEY_PERMISSIVE)), - position_(SerializationToolbox::ReadUnsignedInteger(value, KEY_POSITION)), - description_(SerializationToolbox::ReadString(value, KEY_DESCRIPTION)) + SetOfInstancesJob::SetOfInstancesJob(const Json::Value& source) : + SetOfCommandsJob(new InstanceUnserializer(*this), source) { - SerializationToolbox::ReadArrayOfStrings(instances_, value, KEY_INSTANCES); - SerializationToolbox::ReadSetOfStrings(failedInstances_, value, KEY_FAILED_INSTANCES); + SerializationToolbox::ReadSetOfStrings(failedInstances_, source, KEY_FAILED_INSTANCES); - if (value.isMember(KEY_TRAILING_STEP)) + if (source.isMember(KEY_TRAILING_STEP)) { - hasTrailingStep_ = SerializationToolbox::ReadBoolean(value, KEY_TRAILING_STEP); + hasTrailingStep_ = SerializationToolbox::ReadBoolean(source, KEY_TRAILING_STEP); } else { // Backward compatibility with Orthanc <= 1.4.2 hasTrailingStep_ = false; } + } + - if (position_ > GetStepsCount() + 1) - { - throw OrthancException(ErrorCode_BadFileFormat); - } - } } diff -r dedc2befbf41 -r 8b00e4cb4a6b Core/JobsEngine/SetOfInstancesJob.h --- a/Core/JobsEngine/SetOfInstancesJob.h Fri Oct 05 10:44:59 2018 +0200 +++ b/Core/JobsEngine/SetOfInstancesJob.h Fri Oct 05 16:07:34 2018 +0200 @@ -34,86 +34,48 @@ #pragma once #include "IJob.h" +#include "SetOfCommandsJob.h" #include namespace Orthanc { - class SetOfInstancesJob : public IJob + class SetOfInstancesJob : public SetOfCommandsJob { private: - bool hasTrailingStep_; - bool started_; - std::vector instances_; - bool permissive_; - size_t position_; - std::set failedInstances_; - std::string description_; + class InstanceCommand; + class TrailingStepCommand; + class InstanceUnserializer; + + bool hasTrailingStep_; + std::set failedInstances_; protected: virtual bool HandleInstance(const std::string& instance) = 0; virtual bool HandleTrailingStep() = 0; + // Hiding this method, use AddInstance() instead + using SetOfCommandsJob::AddCommand; + public: - SetOfInstancesJob(bool hasTrailingStep); + SetOfInstancesJob(); + + SetOfInstancesJob(const Json::Value& source); // Unserialization + + void AddInstance(const std::string& instance); - SetOfInstancesJob(const Json::Value& s); // Unserialization + void AddTrailingStep(); + + size_t GetInstancesCount() const; + + const std::string& GetInstance(size_t index) const; bool HasTrailingStep() const { return hasTrailingStep_; } - - size_t GetPosition() const - { - return position_; - } - void SetDescription(const std::string& description) - { - description_ = description; - } - - const std::string& GetDescription() const - { - return description_; - } - - void Reserve(size_t size); - - size_t GetInstancesCount() const - { - return instances_.size(); - } - - size_t GetStepsCount() const; - - void AddInstance(const std::string& instance); - - bool IsPermissive() const - { - return permissive_; - } - - void SetPermissive(bool permissive); - - virtual void Reset(); - - virtual void Start() - { - started_ = true; - } - - virtual float GetProgress(); - - bool IsStarted() const - { - return started_; - } - - const std::string& GetInstance(size_t index) const; - const std::set& GetFailedInstances() const { return failedInstances_; @@ -123,11 +85,13 @@ { return failedInstances_.find(instance) != failedInstances_.end(); } - - virtual JobStepResult Step(); - - virtual void GetPublicContent(Json::Value& value); - - virtual bool Serialize(Json::Value& value); + + virtual void Start(); + + virtual void Reset(); + + virtual void GetPublicContent(Json::Value& target); + + virtual bool Serialize(Json::Value& target); }; } diff -r dedc2befbf41 -r 8b00e4cb4a6b OrthancServer/OrthancRestApi/OrthancRestAnonymizeModify.cpp --- a/OrthancServer/OrthancRestApi/OrthancRestAnonymizeModify.cpp Fri Oct 05 10:44:59 2018 +0200 +++ b/OrthancServer/OrthancRestApi/OrthancRestAnonymizeModify.cpp Fri Oct 05 16:07:34 2018 +0200 @@ -681,6 +681,8 @@ job->AddSourceSeries(series[i]); } + job->AddTrailingStep(); + static const char* KEEP_SOURCE = "KeepSource"; if (request.isMember(KEEP_SOURCE)) { @@ -768,6 +770,8 @@ job->AddSource(resources[i]); } + job->AddTrailingStep(); + static const char* KEEP_SOURCE = "KeepSource"; if (request.isMember(KEEP_SOURCE)) { diff -r dedc2befbf41 -r 8b00e4cb4a6b OrthancServer/ServerJobs/DicomModalityStoreJob.cpp --- a/OrthancServer/ServerJobs/DicomModalityStoreJob.cpp Fri Oct 05 10:44:59 2018 +0200 +++ b/OrthancServer/ServerJobs/DicomModalityStoreJob.cpp Fri Oct 05 16:07:34 2018 +0200 @@ -92,7 +92,6 @@ DicomModalityStoreJob::DicomModalityStoreJob(ServerContext& context) : - SetOfInstancesJob(false /* no trailing step */), context_(context), localAet_("ORTHANC"), moveOriginatorId_(0) // By default, not a C-MOVE diff -r dedc2befbf41 -r 8b00e4cb4a6b OrthancServer/ServerJobs/MergeStudyJob.cpp --- a/OrthancServer/ServerJobs/MergeStudyJob.cpp Fri Oct 05 10:44:59 2018 +0200 +++ b/OrthancServer/ServerJobs/MergeStudyJob.cpp Fri Oct 05 16:07:34 2018 +0200 @@ -170,7 +170,6 @@ MergeStudyJob::MergeStudyJob(ServerContext& context, const std::string& targetStudy) : - SetOfInstancesJob(true /* with trailing step */), context_(context), keepSource_(false), targetStudy_(targetStudy) diff -r dedc2befbf41 -r 8b00e4cb4a6b OrthancServer/ServerJobs/OrthancPeerStoreJob.h --- a/OrthancServer/ServerJobs/OrthancPeerStoreJob.h Fri Oct 05 10:44:59 2018 +0200 +++ b/OrthancServer/ServerJobs/OrthancPeerStoreJob.h Fri Oct 05 16:07:34 2018 +0200 @@ -55,7 +55,6 @@ public: OrthancPeerStoreJob(ServerContext& context) : - SetOfInstancesJob(false /* no trailing step */), context_(context) { } diff -r dedc2befbf41 -r 8b00e4cb4a6b OrthancServer/ServerJobs/ResourceModificationJob.h --- a/OrthancServer/ServerJobs/ResourceModificationJob.h Fri Oct 05 10:44:59 2018 +0200 +++ b/OrthancServer/ServerJobs/ResourceModificationJob.h Fri Oct 05 16:07:34 2018 +0200 @@ -79,7 +79,6 @@ public: ResourceModificationJob(ServerContext& context) : - SetOfInstancesJob(false /* no trailing step */), context_(context), isAnonymization_(false) { diff -r dedc2befbf41 -r 8b00e4cb4a6b OrthancServer/ServerJobs/SplitStudyJob.cpp --- a/OrthancServer/ServerJobs/SplitStudyJob.cpp Fri Oct 05 10:44:59 2018 +0200 +++ b/OrthancServer/ServerJobs/SplitStudyJob.cpp Fri Oct 05 16:07:34 2018 +0200 @@ -161,7 +161,6 @@ SplitStudyJob::SplitStudyJob(ServerContext& context, const std::string& sourceStudy) : - SetOfInstancesJob(true /* with trailing step */), context_(context), keepSource_(false), sourceStudy_(sourceStudy), diff -r dedc2befbf41 -r 8b00e4cb4a6b Resources/CMake/OrthancFrameworkConfiguration.cmake --- a/Resources/CMake/OrthancFrameworkConfiguration.cmake Fri Oct 05 10:44:59 2018 +0200 +++ b/Resources/CMake/OrthancFrameworkConfiguration.cmake Fri Oct 05 16:07:34 2018 +0200 @@ -167,6 +167,7 @@ ${ORTHANC_ROOT}/Core/JobsEngine/Operations/JobOperationValues.cpp ${ORTHANC_ROOT}/Core/JobsEngine/Operations/LogJobOperation.cpp ${ORTHANC_ROOT}/Core/JobsEngine/Operations/SequenceOfOperationsJob.cpp + ${ORTHANC_ROOT}/Core/JobsEngine/SetOfCommandsJob.cpp ${ORTHANC_ROOT}/Core/JobsEngine/SetOfInstancesJob.cpp ) endif() diff -r dedc2befbf41 -r 8b00e4cb4a6b UnitTestsSources/MultiThreadingTests.cpp --- a/UnitTestsSources/MultiThreadingTests.cpp Fri Oct 05 10:44:59 2018 +0200 +++ b/UnitTestsSources/MultiThreadingTests.cpp Fri Oct 05 16:07:34 2018 +0200 @@ -178,8 +178,7 @@ } public: - DummyInstancesJob(bool hasTrailingStep) : - SetOfInstancesJob(hasTrailingStep), + DummyInstancesJob() : trailingStepDone_(false) { } @@ -189,7 +188,7 @@ { if (HasTrailingStep()) { - trailingStepDone_ = (GetPosition() == GetStepsCount()); + trailingStepDone_ = (GetPosition() == GetCommandsCount()); } else { @@ -861,7 +860,7 @@ job.HasTrailingStep() == unserialized->HasTrailingStep() && job.GetPosition() == unserialized->GetPosition() && job.GetInstancesCount() == unserialized->GetInstancesCount() && - job.GetStepsCount() == unserialized->GetStepsCount()); + job.GetCommandsCount() == unserialized->GetCommandsCount()); } else { @@ -1027,7 +1026,7 @@ // This tests SetOfInstancesJob { - DummyInstancesJob job(false); + DummyInstancesJob job; job.SetDescription("description"); job.AddInstance("hello"); job.AddInstance("nope"); @@ -1605,6 +1604,7 @@ a = job.GetTargetStudyUid(); ASSERT_TRUE(job.LookupTargetSeriesUid(b, series)); + job.AddTrailingStep(); job.Start(); ASSERT_EQ(JobStepCode_Continue, job.Step().GetCode()); ASSERT_EQ(JobStepCode_Success, job.Step().GetCode()); @@ -1663,6 +1663,7 @@ ASSERT_EQ(job.GetTargetStudy(), study); + job.AddTrailingStep(); job.Start(); ASSERT_EQ(JobStepCode_Continue, job.Step().GetCode()); ASSERT_EQ(JobStepCode_Success, job.Step().GetCode()); @@ -1719,8 +1720,8 @@ { Json::Value s; - DummyInstancesJob job(false); - ASSERT_EQ(0, job.GetStepsCount()); + DummyInstancesJob job; + ASSERT_EQ(0, job.GetCommandsCount()); ASSERT_EQ(0, job.GetInstancesCount()); job.Start(); @@ -1748,10 +1749,10 @@ { Json::Value s; - DummyInstancesJob job(false); + DummyInstancesJob job; job.AddInstance("hello"); job.AddInstance("world"); - ASSERT_EQ(2, job.GetStepsCount()); + ASSERT_EQ(2, job.GetCommandsCount()); ASSERT_EQ(2, job.GetInstancesCount()); job.Start(); @@ -1788,11 +1789,14 @@ { Json::Value s; - DummyInstancesJob job(true); - ASSERT_EQ(1, job.GetStepsCount()); + DummyInstancesJob job; ASSERT_EQ(0, job.GetInstancesCount()); + ASSERT_EQ(0, job.GetCommandsCount()); + job.AddTrailingStep(); + ASSERT_EQ(0, job.GetInstancesCount()); + ASSERT_EQ(1, job.GetCommandsCount()); - job.Start(); + job.Start(); // This adds the trailing step ASSERT_EQ(0, job.GetPosition()); ASSERT_TRUE(job.HasTrailingStep()); ASSERT_FALSE(job.IsTrailingStepDone()); @@ -1817,12 +1821,16 @@ { Json::Value s; - DummyInstancesJob job(true); + DummyInstancesJob job; job.AddInstance("hello"); - ASSERT_EQ(2, job.GetStepsCount()); + ASSERT_EQ(1, job.GetInstancesCount()); + ASSERT_EQ(1, job.GetCommandsCount()); + job.AddTrailingStep(); ASSERT_EQ(1, job.GetInstancesCount()); - + ASSERT_EQ(2, job.GetCommandsCount()); + job.Start(); + ASSERT_EQ(2, job.GetCommandsCount()); ASSERT_EQ(0, job.GetPosition()); ASSERT_TRUE(job.HasTrailingStep()); ASSERT_FALSE(job.IsTrailingStepDone());