comparison OrthancFramework/Sources/JobsEngine/SetOfCommandsJob.cpp @ 4044:d25f4c0fa160 framework

splitting code into OrthancFramework and OrthancServer
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 10 Jun 2020 20:30:34 +0200
parents Core/JobsEngine/SetOfCommandsJob.cpp@56f2397f027a
children bf7b9edf6b81
comparison
equal deleted inserted replaced
4043:6c6239aec462 4044:d25f4c0fa160
1 /**
2 * Orthanc - A Lightweight, RESTful DICOM Store
3 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
4 * Department, University Hospital of Liege, Belgium
5 * Copyright (C) 2017-2020 Osimis S.A., Belgium
6 *
7 * This program is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation, either version 3 of the
10 * License, or (at your option) any later version.
11 *
12 * In addition, as a special exception, the copyright holders of this
13 * program give permission to link the code of its release with the
14 * OpenSSL project's "OpenSSL" library (or with modified versions of it
15 * that use the same license as the "OpenSSL" library), and distribute
16 * the linked executables. You must obey the GNU General Public License
17 * in all respects for all of the code used other than "OpenSSL". If you
18 * modify file(s) with this exception, you may extend this exception to
19 * your version of the file(s), but you are not obligated to do so. If
20 * you do not wish to do so, delete this exception statement from your
21 * version. If you delete this exception statement from all source files
22 * in the program, then also delete it here.
23 *
24 * This program is distributed in the hope that it will be useful, but
25 * WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
27 * General Public License for more details.
28 *
29 * You should have received a copy of the GNU General Public License
30 * along with this program. If not, see <http://www.gnu.org/licenses/>.
31 **/
32
33
34 #include "../PrecompiledHeaders.h"
35 #include "SetOfCommandsJob.h"
36
37 #include "../Logging.h"
38 #include "../OrthancException.h"
39 #include "../SerializationToolbox.h"
40
41 #include <cassert>
42 #include <memory>
43
44 namespace Orthanc
45 {
46 SetOfCommandsJob::SetOfCommandsJob() :
47 started_(false),
48 permissive_(false),
49 position_(0)
50 {
51 }
52
53
54 SetOfCommandsJob::~SetOfCommandsJob()
55 {
56 for (size_t i = 0; i < commands_.size(); i++)
57 {
58 assert(commands_[i] != NULL);
59 delete commands_[i];
60 }
61 }
62
63
64 void SetOfCommandsJob::Reserve(size_t size)
65 {
66 if (started_)
67 {
68 throw OrthancException(ErrorCode_BadSequenceOfCalls);
69 }
70 else
71 {
72 commands_.reserve(size);
73 }
74 }
75
76
77 void SetOfCommandsJob::AddCommand(ICommand* command)
78 {
79 if (command == NULL)
80 {
81 throw OrthancException(ErrorCode_NullPointer);
82 }
83 else if (started_)
84 {
85 throw OrthancException(ErrorCode_BadSequenceOfCalls);
86 }
87 else
88 {
89 commands_.push_back(command);
90 }
91 }
92
93
94 void SetOfCommandsJob::SetPermissive(bool permissive)
95 {
96 if (started_)
97 {
98 throw OrthancException(ErrorCode_BadSequenceOfCalls);
99 }
100 else
101 {
102 permissive_ = permissive;
103 }
104 }
105
106
107 void SetOfCommandsJob::Reset()
108 {
109 if (started_)
110 {
111 position_ = 0;
112 }
113 else
114 {
115 throw OrthancException(ErrorCode_BadSequenceOfCalls);
116 }
117 }
118
119
120 float SetOfCommandsJob::GetProgress()
121 {
122 if (commands_.empty())
123 {
124 return 1;
125 }
126 else
127 {
128 return (static_cast<float>(position_) /
129 static_cast<float>(commands_.size()));
130 }
131 }
132
133
134 const SetOfCommandsJob::ICommand& SetOfCommandsJob::GetCommand(size_t index) const
135 {
136 if (index >= commands_.size())
137 {
138 throw OrthancException(ErrorCode_ParameterOutOfRange);
139 }
140 else
141 {
142 assert(commands_[index] != NULL);
143 return *commands_[index];
144 }
145 }
146
147
148 JobStepResult SetOfCommandsJob::Step(const std::string& jobId)
149 {
150 if (!started_)
151 {
152 throw OrthancException(ErrorCode_InternalError);
153 }
154
155 if (commands_.empty() &&
156 position_ == 0)
157 {
158 // No command to handle: We're done
159 position_ = 1;
160 return JobStepResult::Success();
161 }
162
163 if (position_ >= commands_.size())
164 {
165 // Already done
166 throw OrthancException(ErrorCode_BadSequenceOfCalls);
167 }
168
169 try
170 {
171 // Not at the trailing step: Handle the current command
172 if (!commands_[position_]->Execute(jobId))
173 {
174 // Error
175 if (!permissive_)
176 {
177 return JobStepResult::Failure(ErrorCode_InternalError, NULL);
178 }
179 }
180 }
181 catch (OrthancException& e)
182 {
183 if (permissive_)
184 {
185 LOG(WARNING) << "Ignoring an error in a permissive job: " << e.What();
186 }
187 else
188 {
189 return JobStepResult::Failure(e);
190 }
191 }
192
193 position_ += 1;
194
195 if (position_ == commands_.size())
196 {
197 // We're done
198 return JobStepResult::Success();
199 }
200 else
201 {
202 return JobStepResult::Continue();
203 }
204 }
205
206
207
208 static const char* KEY_DESCRIPTION = "Description";
209 static const char* KEY_PERMISSIVE = "Permissive";
210 static const char* KEY_POSITION = "Position";
211 static const char* KEY_TYPE = "Type";
212 static const char* KEY_COMMANDS = "Commands";
213
214
215 void SetOfCommandsJob::GetPublicContent(Json::Value& value)
216 {
217 value[KEY_DESCRIPTION] = GetDescription();
218 }
219
220
221 bool SetOfCommandsJob::Serialize(Json::Value& target)
222 {
223 target = Json::objectValue;
224
225 std::string type;
226 GetJobType(type);
227 target[KEY_TYPE] = type;
228
229 target[KEY_PERMISSIVE] = permissive_;
230 target[KEY_POSITION] = static_cast<unsigned int>(position_);
231 target[KEY_DESCRIPTION] = description_;
232
233 target[KEY_COMMANDS] = Json::arrayValue;
234 Json::Value& tmp = target[KEY_COMMANDS];
235
236 for (size_t i = 0; i < commands_.size(); i++)
237 {
238 assert(commands_[i] != NULL);
239
240 Json::Value command;
241 commands_[i]->Serialize(command);
242 tmp.append(command);
243 }
244
245 return true;
246 }
247
248
249 SetOfCommandsJob::SetOfCommandsJob(ICommandUnserializer* unserializer,
250 const Json::Value& source) :
251 started_(false)
252 {
253 std::unique_ptr<ICommandUnserializer> raii(unserializer);
254
255 permissive_ = SerializationToolbox::ReadBoolean(source, KEY_PERMISSIVE);
256 position_ = SerializationToolbox::ReadUnsignedInteger(source, KEY_POSITION);
257 description_ = SerializationToolbox::ReadString(source, KEY_DESCRIPTION);
258
259 if (!source.isMember(KEY_COMMANDS) ||
260 source[KEY_COMMANDS].type() != Json::arrayValue)
261 {
262 throw OrthancException(ErrorCode_BadFileFormat);
263 }
264 else
265 {
266 const Json::Value& tmp = source[KEY_COMMANDS];
267 commands_.resize(tmp.size());
268
269 for (Json::Value::ArrayIndex i = 0; i < tmp.size(); i++)
270 {
271 try
272 {
273 commands_[i] = unserializer->Unserialize(tmp[i]);
274 }
275 catch (OrthancException&)
276 {
277 }
278
279 if (commands_[i] == NULL)
280 {
281 for (size_t j = 0; j < i; j++)
282 {
283 delete commands_[j];
284 }
285
286 throw OrthancException(ErrorCode_BadFileFormat);
287 }
288 }
289 }
290
291 if (commands_.empty())
292 {
293 if (position_ > 1)
294 {
295 throw OrthancException(ErrorCode_BadFileFormat);
296 }
297 }
298 else if (position_ > commands_.size())
299 {
300 throw OrthancException(ErrorCode_BadFileFormat);
301 }
302 }
303 }