Mercurial > hg > orthanc
annotate Core/JobsEngine/JobsRegistry.cpp @ 2630:00327e989458 jobs
creating archives/medias is now a job
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Fri, 25 May 2018 16:09:59 +0200 |
parents | 1232922c8793 |
children | e1893d31652a |
rev | line source |
---|---|
2569 | 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-2018 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 "JobsRegistry.h" | |
36 | |
37 #include "../Logging.h" | |
38 #include "../OrthancException.h" | |
39 #include "../Toolbox.h" | |
40 | |
41 namespace Orthanc | |
42 { | |
43 class JobsRegistry::JobHandler : public boost::noncopyable | |
44 { | |
45 private: | |
46 std::string id_; | |
47 JobState state_; | |
48 std::auto_ptr<IJob> job_; | |
49 int priority_; // "+inf()" means highest priority | |
50 boost::posix_time::ptime creationTime_; | |
51 boost::posix_time::ptime lastStateChangeTime_; | |
52 boost::posix_time::time_duration runtime_; | |
53 boost::posix_time::ptime retryTime_; | |
54 bool pauseScheduled_; | |
2581
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
55 bool cancelScheduled_; |
2569 | 56 JobStatus lastStatus_; |
57 | |
58 void Touch() | |
59 { | |
60 const boost::posix_time::ptime now = boost::posix_time::microsec_clock::universal_time(); | |
61 | |
62 if (state_ == JobState_Running) | |
63 { | |
64 runtime_ += (now - lastStateChangeTime_); | |
65 } | |
66 | |
67 lastStateChangeTime_ = now; | |
68 } | |
69 | |
70 void SetStateInternal(JobState state) | |
71 { | |
72 state_ = state; | |
73 pauseScheduled_ = false; | |
2581
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
74 cancelScheduled_ = false; |
2569 | 75 Touch(); |
76 } | |
77 | |
78 public: | |
79 JobHandler(IJob* job, | |
80 int priority) : | |
81 id_(Toolbox::GenerateUuid()), | |
82 state_(JobState_Pending), | |
83 job_(job), | |
84 priority_(priority), | |
85 creationTime_(boost::posix_time::microsec_clock::universal_time()), | |
86 lastStateChangeTime_(creationTime_), | |
87 runtime_(boost::posix_time::milliseconds(0)), | |
88 retryTime_(creationTime_), | |
2581
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
89 pauseScheduled_(false), |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
90 cancelScheduled_(false) |
2569 | 91 { |
92 if (job == NULL) | |
93 { | |
94 throw OrthancException(ErrorCode_NullPointer); | |
95 } | |
96 | |
2630
00327e989458
creating archives/medias is now a job
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2620
diff
changeset
|
97 job->Start(); |
00327e989458
creating archives/medias is now a job
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2620
diff
changeset
|
98 |
2569 | 99 lastStatus_ = JobStatus(ErrorCode_Success, *job); |
100 } | |
101 | |
102 const std::string& GetId() const | |
103 { | |
104 return id_; | |
105 } | |
106 | |
107 IJob& GetJob() const | |
108 { | |
109 assert(job_.get() != NULL); | |
110 return *job_; | |
111 } | |
112 | |
113 void SetPriority(int priority) | |
114 { | |
115 priority_ = priority; | |
116 } | |
117 | |
118 int GetPriority() const | |
119 { | |
120 return priority_; | |
121 } | |
122 | |
123 JobState GetState() const | |
124 { | |
125 return state_; | |
126 } | |
127 | |
128 void SetState(JobState state) | |
129 { | |
130 if (state == JobState_Retry) | |
131 { | |
132 // Use "SetRetryState()" | |
133 throw OrthancException(ErrorCode_BadSequenceOfCalls); | |
134 } | |
135 else | |
136 { | |
137 SetStateInternal(state); | |
138 } | |
139 } | |
140 | |
141 void SetRetryState(unsigned int timeout) | |
142 { | |
143 if (state_ == JobState_Running) | |
144 { | |
145 SetStateInternal(JobState_Retry); | |
146 retryTime_ = (boost::posix_time::microsec_clock::universal_time() + | |
147 boost::posix_time::milliseconds(timeout)); | |
148 } | |
149 else | |
150 { | |
151 // Only valid for running jobs | |
152 throw OrthancException(ErrorCode_BadSequenceOfCalls); | |
153 } | |
154 } | |
155 | |
156 void SchedulePause() | |
157 { | |
158 if (state_ == JobState_Running) | |
159 { | |
160 pauseScheduled_ = true; | |
161 } | |
162 else | |
163 { | |
164 // Only valid for running jobs | |
165 throw OrthancException(ErrorCode_BadSequenceOfCalls); | |
166 } | |
167 } | |
168 | |
2581
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
169 void ScheduleCancel() |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
170 { |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
171 if (state_ == JobState_Running) |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
172 { |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
173 cancelScheduled_ = true; |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
174 } |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
175 else |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
176 { |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
177 // Only valid for running jobs |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
178 throw OrthancException(ErrorCode_BadSequenceOfCalls); |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
179 } |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
180 } |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
181 |
2569 | 182 bool IsPauseScheduled() |
183 { | |
184 return pauseScheduled_; | |
185 } | |
186 | |
2581
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
187 bool IsCancelScheduled() |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
188 { |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
189 return cancelScheduled_; |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
190 } |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
191 |
2569 | 192 bool IsRetryReady(const boost::posix_time::ptime& now) const |
193 { | |
194 if (state_ != JobState_Retry) | |
195 { | |
196 throw OrthancException(ErrorCode_BadSequenceOfCalls); | |
197 } | |
198 else | |
199 { | |
200 return retryTime_ <= now; | |
201 } | |
202 } | |
203 | |
204 const boost::posix_time::ptime& GetCreationTime() const | |
205 { | |
206 return creationTime_; | |
207 } | |
208 | |
209 const boost::posix_time::ptime& GetLastStateChangeTime() const | |
210 { | |
211 return lastStateChangeTime_; | |
212 } | |
213 | |
214 const boost::posix_time::time_duration& GetRuntime() const | |
215 { | |
216 return runtime_; | |
217 } | |
218 | |
219 const JobStatus& GetLastStatus() const | |
220 { | |
221 return lastStatus_; | |
222 } | |
223 | |
224 void SetLastStatus(const JobStatus& status) | |
225 { | |
226 lastStatus_ = status; | |
227 Touch(); | |
228 } | |
2581
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
229 |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
230 void SetLastErrorCode(ErrorCode code) |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
231 { |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
232 lastStatus_.SetErrorCode(code); |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
233 } |
2569 | 234 }; |
235 | |
236 | |
237 bool JobsRegistry::PriorityComparator::operator() (JobHandler*& a, | |
238 JobHandler*& b) const | |
239 { | |
240 return a->GetPriority() < b->GetPriority(); | |
241 } | |
242 | |
243 | |
244 #if defined(NDEBUG) | |
245 void JobsRegistry::CheckInvariants() const | |
246 { | |
247 } | |
248 | |
249 #else | |
250 bool JobsRegistry::IsPendingJob(const JobHandler& job) const | |
251 { | |
252 PendingJobs copy = pendingJobs_; | |
253 while (!copy.empty()) | |
254 { | |
255 if (copy.top() == &job) | |
256 { | |
257 return true; | |
258 } | |
259 | |
260 copy.pop(); | |
261 } | |
262 | |
263 return false; | |
264 } | |
265 | |
266 bool JobsRegistry::IsCompletedJob(JobHandler& job) const | |
267 { | |
268 for (CompletedJobs::const_iterator it = completedJobs_.begin(); | |
269 it != completedJobs_.end(); ++it) | |
270 { | |
271 if (*it == &job) | |
272 { | |
273 return true; | |
274 } | |
275 } | |
276 | |
277 return false; | |
278 } | |
279 | |
280 bool JobsRegistry::IsRetryJob(JobHandler& job) const | |
281 { | |
282 return retryJobs_.find(&job) != retryJobs_.end(); | |
283 } | |
284 | |
285 void JobsRegistry::CheckInvariants() const | |
286 { | |
287 { | |
288 PendingJobs copy = pendingJobs_; | |
289 while (!copy.empty()) | |
290 { | |
291 assert(copy.top()->GetState() == JobState_Pending); | |
292 copy.pop(); | |
293 } | |
294 } | |
295 | |
296 assert(completedJobs_.size() <= maxCompletedJobs_); | |
297 | |
298 for (CompletedJobs::const_iterator it = completedJobs_.begin(); | |
299 it != completedJobs_.end(); ++it) | |
300 { | |
301 assert((*it)->GetState() == JobState_Success || | |
302 (*it)->GetState() == JobState_Failure); | |
303 } | |
304 | |
305 for (RetryJobs::const_iterator it = retryJobs_.begin(); | |
306 it != retryJobs_.end(); ++it) | |
307 { | |
308 assert((*it)->GetState() == JobState_Retry); | |
309 } | |
310 | |
311 for (JobsIndex::const_iterator it = jobsIndex_.begin(); | |
312 it != jobsIndex_.end(); ++it) | |
313 { | |
314 JobHandler& job = *it->second; | |
315 | |
316 assert(job.GetId() == it->first); | |
317 | |
318 switch (job.GetState()) | |
319 { | |
320 case JobState_Pending: | |
321 assert(!IsRetryJob(job) && IsPendingJob(job) && !IsCompletedJob(job)); | |
322 break; | |
323 | |
324 case JobState_Success: | |
325 case JobState_Failure: | |
326 assert(!IsRetryJob(job) && !IsPendingJob(job) && IsCompletedJob(job)); | |
327 break; | |
328 | |
329 case JobState_Retry: | |
330 assert(IsRetryJob(job) && !IsPendingJob(job) && !IsCompletedJob(job)); | |
331 break; | |
332 | |
333 case JobState_Running: | |
334 case JobState_Paused: | |
335 assert(!IsRetryJob(job) && !IsPendingJob(job) && !IsCompletedJob(job)); | |
336 break; | |
337 | |
338 default: | |
339 throw OrthancException(ErrorCode_InternalError); | |
340 } | |
341 } | |
342 } | |
343 #endif | |
344 | |
345 | |
346 void JobsRegistry::ForgetOldCompletedJobs() | |
347 { | |
348 if (maxCompletedJobs_ != 0) | |
349 { | |
350 while (completedJobs_.size() > maxCompletedJobs_) | |
351 { | |
352 assert(completedJobs_.front() != NULL); | |
353 | |
354 std::string id = completedJobs_.front()->GetId(); | |
355 assert(jobsIndex_.find(id) != jobsIndex_.end()); | |
356 | |
357 jobsIndex_.erase(id); | |
358 delete(completedJobs_.front()); | |
359 completedJobs_.pop_front(); | |
360 } | |
361 } | |
362 } | |
363 | |
364 | |
2581
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
365 void JobsRegistry::SetCompletedJob(JobHandler& job, |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
366 bool success) |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
367 { |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
368 job.SetState(success ? JobState_Success : JobState_Failure); |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
369 |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
370 completedJobs_.push_back(&job); |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
371 ForgetOldCompletedJobs(); |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
372 |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
373 someJobComplete_.notify_all(); |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
374 } |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
375 |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
376 |
2569 | 377 void JobsRegistry::MarkRunningAsCompleted(JobHandler& job, |
378 bool success) | |
379 { | |
380 LOG(INFO) << "Job has completed with " << (success ? "success" : "failure") | |
381 << ": " << job.GetId(); | |
382 | |
383 CheckInvariants(); | |
2581
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
384 |
2569 | 385 assert(job.GetState() == JobState_Running); |
2581
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
386 SetCompletedJob(job, success); |
2570
2e879c796ec7
JobsRegistry::SubmitAndWait(), StoreScuJob
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2569
diff
changeset
|
387 |
2569 | 388 CheckInvariants(); |
389 } | |
390 | |
391 | |
392 void JobsRegistry::MarkRunningAsRetry(JobHandler& job, | |
393 unsigned int timeout) | |
394 { | |
395 LOG(INFO) << "Job scheduled for retry in " << timeout << "ms: " << job.GetId(); | |
396 | |
397 CheckInvariants(); | |
398 | |
399 assert(job.GetState() == JobState_Running && | |
400 retryJobs_.find(&job) == retryJobs_.end()); | |
401 | |
402 retryJobs_.insert(&job); | |
403 job.SetRetryState(timeout); | |
404 | |
405 CheckInvariants(); | |
406 } | |
407 | |
408 | |
409 void JobsRegistry::MarkRunningAsPaused(JobHandler& job) | |
410 { | |
411 LOG(INFO) << "Job paused: " << job.GetId(); | |
412 | |
413 CheckInvariants(); | |
414 assert(job.GetState() == JobState_Running); | |
415 | |
416 job.SetState(JobState_Paused); | |
417 | |
418 CheckInvariants(); | |
419 } | |
420 | |
421 | |
2570
2e879c796ec7
JobsRegistry::SubmitAndWait(), StoreScuJob
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2569
diff
changeset
|
422 bool JobsRegistry::GetStateInternal(JobState& state, |
2e879c796ec7
JobsRegistry::SubmitAndWait(), StoreScuJob
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2569
diff
changeset
|
423 const std::string& id) |
2e879c796ec7
JobsRegistry::SubmitAndWait(), StoreScuJob
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2569
diff
changeset
|
424 { |
2e879c796ec7
JobsRegistry::SubmitAndWait(), StoreScuJob
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2569
diff
changeset
|
425 CheckInvariants(); |
2e879c796ec7
JobsRegistry::SubmitAndWait(), StoreScuJob
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2569
diff
changeset
|
426 |
2e879c796ec7
JobsRegistry::SubmitAndWait(), StoreScuJob
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2569
diff
changeset
|
427 JobsIndex::const_iterator it = jobsIndex_.find(id); |
2e879c796ec7
JobsRegistry::SubmitAndWait(), StoreScuJob
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2569
diff
changeset
|
428 if (it == jobsIndex_.end()) |
2e879c796ec7
JobsRegistry::SubmitAndWait(), StoreScuJob
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2569
diff
changeset
|
429 { |
2e879c796ec7
JobsRegistry::SubmitAndWait(), StoreScuJob
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2569
diff
changeset
|
430 return false; |
2e879c796ec7
JobsRegistry::SubmitAndWait(), StoreScuJob
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2569
diff
changeset
|
431 } |
2e879c796ec7
JobsRegistry::SubmitAndWait(), StoreScuJob
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2569
diff
changeset
|
432 else |
2e879c796ec7
JobsRegistry::SubmitAndWait(), StoreScuJob
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2569
diff
changeset
|
433 { |
2e879c796ec7
JobsRegistry::SubmitAndWait(), StoreScuJob
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2569
diff
changeset
|
434 state = it->second->GetState(); |
2e879c796ec7
JobsRegistry::SubmitAndWait(), StoreScuJob
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2569
diff
changeset
|
435 return true; |
2e879c796ec7
JobsRegistry::SubmitAndWait(), StoreScuJob
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2569
diff
changeset
|
436 } |
2e879c796ec7
JobsRegistry::SubmitAndWait(), StoreScuJob
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2569
diff
changeset
|
437 } |
2e879c796ec7
JobsRegistry::SubmitAndWait(), StoreScuJob
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2569
diff
changeset
|
438 |
2e879c796ec7
JobsRegistry::SubmitAndWait(), StoreScuJob
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2569
diff
changeset
|
439 |
2569 | 440 JobsRegistry::~JobsRegistry() |
441 { | |
442 for (JobsIndex::iterator it = jobsIndex_.begin(); it != jobsIndex_.end(); ++it) | |
443 { | |
444 assert(it->second != NULL); | |
445 delete it->second; | |
446 } | |
447 } | |
448 | |
449 | |
2620
1232922c8793
speeding up shutdown if Lua script is in trailing phase
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2600
diff
changeset
|
450 void JobsRegistry::SetMaxCompletedJobs(size_t n) |
2569 | 451 { |
452 boost::mutex::scoped_lock lock(mutex_); | |
453 CheckInvariants(); | |
454 | |
2620
1232922c8793
speeding up shutdown if Lua script is in trailing phase
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2600
diff
changeset
|
455 LOG(INFO) << "The size of the history of the jobs engine is set to: " << n << " job(s)"; |
1232922c8793
speeding up shutdown if Lua script is in trailing phase
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2600
diff
changeset
|
456 |
1232922c8793
speeding up shutdown if Lua script is in trailing phase
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2600
diff
changeset
|
457 maxCompletedJobs_ = n; |
2569 | 458 ForgetOldCompletedJobs(); |
459 | |
460 CheckInvariants(); | |
461 } | |
462 | |
463 | |
464 void JobsRegistry::ListJobs(std::set<std::string>& target) | |
465 { | |
466 boost::mutex::scoped_lock lock(mutex_); | |
467 CheckInvariants(); | |
468 | |
469 for (JobsIndex::const_iterator it = jobsIndex_.begin(); | |
470 it != jobsIndex_.end(); ++it) | |
471 { | |
472 target.insert(it->first); | |
473 } | |
474 } | |
475 | |
476 | |
477 bool JobsRegistry::GetJobInfo(JobInfo& target, | |
478 const std::string& id) | |
479 { | |
480 boost::mutex::scoped_lock lock(mutex_); | |
481 CheckInvariants(); | |
482 | |
483 JobsIndex::const_iterator found = jobsIndex_.find(id); | |
484 | |
485 if (found == jobsIndex_.end()) | |
486 { | |
487 return false; | |
488 } | |
489 else | |
490 { | |
491 const JobHandler& handler = *found->second; | |
492 target = JobInfo(handler.GetId(), | |
493 handler.GetPriority(), | |
494 handler.GetState(), | |
495 handler.GetLastStatus(), | |
496 handler.GetCreationTime(), | |
497 handler.GetLastStateChangeTime(), | |
498 handler.GetRuntime()); | |
499 return true; | |
500 } | |
501 } | |
502 | |
503 | |
504 void JobsRegistry::Submit(std::string& id, | |
505 IJob* job, // Takes ownership | |
506 int priority) | |
507 { | |
508 std::auto_ptr<JobHandler> handler(new JobHandler(job, priority)); | |
509 | |
510 boost::mutex::scoped_lock lock(mutex_); | |
511 CheckInvariants(); | |
512 | |
513 id = handler->GetId(); | |
514 | |
515 pendingJobs_.push(handler.get()); | |
516 pendingJobAvailable_.notify_one(); | |
517 | |
518 jobsIndex_.insert(std::make_pair(id, handler.release())); | |
519 | |
520 LOG(INFO) << "New job submitted with priority " << priority << ": " << id; | |
521 | |
522 CheckInvariants(); | |
523 } | |
524 | |
525 | |
526 void JobsRegistry::Submit(IJob* job, // Takes ownership | |
527 int priority) | |
528 { | |
529 std::string id; | |
530 Submit(id, job, priority); | |
531 } | |
532 | |
533 | |
2570
2e879c796ec7
JobsRegistry::SubmitAndWait(), StoreScuJob
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2569
diff
changeset
|
534 bool JobsRegistry::SubmitAndWait(IJob* job, // Takes ownership |
2e879c796ec7
JobsRegistry::SubmitAndWait(), StoreScuJob
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2569
diff
changeset
|
535 int priority) |
2e879c796ec7
JobsRegistry::SubmitAndWait(), StoreScuJob
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2569
diff
changeset
|
536 { |
2e879c796ec7
JobsRegistry::SubmitAndWait(), StoreScuJob
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2569
diff
changeset
|
537 std::string id; |
2e879c796ec7
JobsRegistry::SubmitAndWait(), StoreScuJob
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2569
diff
changeset
|
538 Submit(id, job, priority); |
2e879c796ec7
JobsRegistry::SubmitAndWait(), StoreScuJob
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2569
diff
changeset
|
539 |
2e879c796ec7
JobsRegistry::SubmitAndWait(), StoreScuJob
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2569
diff
changeset
|
540 JobState state; |
2e879c796ec7
JobsRegistry::SubmitAndWait(), StoreScuJob
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2569
diff
changeset
|
541 |
2e879c796ec7
JobsRegistry::SubmitAndWait(), StoreScuJob
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2569
diff
changeset
|
542 { |
2e879c796ec7
JobsRegistry::SubmitAndWait(), StoreScuJob
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2569
diff
changeset
|
543 boost::mutex::scoped_lock lock(mutex_); |
2e879c796ec7
JobsRegistry::SubmitAndWait(), StoreScuJob
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2569
diff
changeset
|
544 |
2e879c796ec7
JobsRegistry::SubmitAndWait(), StoreScuJob
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2569
diff
changeset
|
545 while (GetStateInternal(state, id) && |
2e879c796ec7
JobsRegistry::SubmitAndWait(), StoreScuJob
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2569
diff
changeset
|
546 state != JobState_Success && |
2e879c796ec7
JobsRegistry::SubmitAndWait(), StoreScuJob
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2569
diff
changeset
|
547 state != JobState_Failure) |
2e879c796ec7
JobsRegistry::SubmitAndWait(), StoreScuJob
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2569
diff
changeset
|
548 { |
2e879c796ec7
JobsRegistry::SubmitAndWait(), StoreScuJob
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2569
diff
changeset
|
549 someJobComplete_.wait(lock); |
2e879c796ec7
JobsRegistry::SubmitAndWait(), StoreScuJob
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2569
diff
changeset
|
550 } |
2e879c796ec7
JobsRegistry::SubmitAndWait(), StoreScuJob
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2569
diff
changeset
|
551 } |
2e879c796ec7
JobsRegistry::SubmitAndWait(), StoreScuJob
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2569
diff
changeset
|
552 |
2e879c796ec7
JobsRegistry::SubmitAndWait(), StoreScuJob
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2569
diff
changeset
|
553 return (state == JobState_Success); |
2e879c796ec7
JobsRegistry::SubmitAndWait(), StoreScuJob
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2569
diff
changeset
|
554 } |
2e879c796ec7
JobsRegistry::SubmitAndWait(), StoreScuJob
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2569
diff
changeset
|
555 |
2e879c796ec7
JobsRegistry::SubmitAndWait(), StoreScuJob
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2569
diff
changeset
|
556 |
2573
3372c5255333
StoreScuJob, Orthanc Explorer for jobs
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2570
diff
changeset
|
557 bool JobsRegistry::SetPriority(const std::string& id, |
2569 | 558 int priority) |
559 { | |
560 LOG(INFO) << "Changing priority to " << priority << " for job: " << id; | |
561 | |
562 boost::mutex::scoped_lock lock(mutex_); | |
563 CheckInvariants(); | |
564 | |
565 JobsIndex::iterator found = jobsIndex_.find(id); | |
566 | |
567 if (found == jobsIndex_.end()) | |
568 { | |
569 LOG(WARNING) << "Unknown job: " << id; | |
2573
3372c5255333
StoreScuJob, Orthanc Explorer for jobs
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2570
diff
changeset
|
570 return false; |
2569 | 571 } |
572 else | |
573 { | |
574 found->second->SetPriority(priority); | |
575 | |
576 if (found->second->GetState() == JobState_Pending) | |
577 { | |
578 // If the job is pending, we need to reconstruct the | |
579 // priority queue, as the heap condition has changed | |
580 | |
581 PendingJobs copy; | |
582 std::swap(copy, pendingJobs_); | |
583 | |
584 assert(pendingJobs_.empty()); | |
585 while (!copy.empty()) | |
586 { | |
587 pendingJobs_.push(copy.top()); | |
588 copy.pop(); | |
589 } | |
590 } | |
2573
3372c5255333
StoreScuJob, Orthanc Explorer for jobs
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2570
diff
changeset
|
591 |
3372c5255333
StoreScuJob, Orthanc Explorer for jobs
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2570
diff
changeset
|
592 CheckInvariants(); |
3372c5255333
StoreScuJob, Orthanc Explorer for jobs
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2570
diff
changeset
|
593 return true; |
2569 | 594 } |
595 } | |
596 | |
597 | |
2581
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
598 void JobsRegistry::RemovePendingJob(const std::string& id) |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
599 { |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
600 // If the job is pending, we need to reconstruct the priority |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
601 // queue to remove it |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
602 PendingJobs copy; |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
603 std::swap(copy, pendingJobs_); |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
604 |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
605 assert(pendingJobs_.empty()); |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
606 while (!copy.empty()) |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
607 { |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
608 if (copy.top()->GetId() != id) |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
609 { |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
610 pendingJobs_.push(copy.top()); |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
611 } |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
612 |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
613 copy.pop(); |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
614 } |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
615 } |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
616 |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
617 |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
618 void JobsRegistry::RemoveRetryJob(JobHandler* handler) |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
619 { |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
620 RetryJobs::iterator item = retryJobs_.find(handler); |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
621 assert(item != retryJobs_.end()); |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
622 retryJobs_.erase(item); |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
623 } |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
624 |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
625 |
2573
3372c5255333
StoreScuJob, Orthanc Explorer for jobs
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2570
diff
changeset
|
626 bool JobsRegistry::Pause(const std::string& id) |
2569 | 627 { |
628 LOG(INFO) << "Pausing job: " << id; | |
629 | |
630 boost::mutex::scoped_lock lock(mutex_); | |
631 CheckInvariants(); | |
632 | |
633 JobsIndex::iterator found = jobsIndex_.find(id); | |
634 | |
635 if (found == jobsIndex_.end()) | |
636 { | |
637 LOG(WARNING) << "Unknown job: " << id; | |
2573
3372c5255333
StoreScuJob, Orthanc Explorer for jobs
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2570
diff
changeset
|
638 return false; |
2569 | 639 } |
640 else | |
641 { | |
642 switch (found->second->GetState()) | |
643 { | |
644 case JobState_Pending: | |
2581
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
645 RemovePendingJob(id); |
2569 | 646 found->second->SetState(JobState_Paused); |
647 break; | |
648 | |
649 case JobState_Retry: | |
2581
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
650 RemoveRetryJob(found->second); |
2569 | 651 found->second->SetState(JobState_Paused); |
652 break; | |
653 | |
654 case JobState_Paused: | |
655 case JobState_Success: | |
656 case JobState_Failure: | |
657 // Nothing to be done | |
658 break; | |
659 | |
660 case JobState_Running: | |
661 found->second->SchedulePause(); | |
662 break; | |
663 | |
664 default: | |
665 throw OrthancException(ErrorCode_InternalError); | |
666 } | |
2573
3372c5255333
StoreScuJob, Orthanc Explorer for jobs
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2570
diff
changeset
|
667 |
3372c5255333
StoreScuJob, Orthanc Explorer for jobs
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2570
diff
changeset
|
668 CheckInvariants(); |
3372c5255333
StoreScuJob, Orthanc Explorer for jobs
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2570
diff
changeset
|
669 return true; |
2569 | 670 } |
671 } | |
672 | |
673 | |
2581
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
674 bool JobsRegistry::Cancel(const std::string& id) |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
675 { |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
676 LOG(INFO) << "Canceling job: " << id; |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
677 |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
678 boost::mutex::scoped_lock lock(mutex_); |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
679 CheckInvariants(); |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
680 |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
681 JobsIndex::iterator found = jobsIndex_.find(id); |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
682 |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
683 if (found == jobsIndex_.end()) |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
684 { |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
685 LOG(WARNING) << "Unknown job: " << id; |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
686 return false; |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
687 } |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
688 else |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
689 { |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
690 switch (found->second->GetState()) |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
691 { |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
692 case JobState_Pending: |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
693 RemovePendingJob(id); |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
694 SetCompletedJob(*found->second, false); |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
695 found->second->SetLastErrorCode(ErrorCode_CanceledJob); |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
696 break; |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
697 |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
698 case JobState_Retry: |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
699 RemoveRetryJob(found->second); |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
700 SetCompletedJob(*found->second, false); |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
701 found->second->SetLastErrorCode(ErrorCode_CanceledJob); |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
702 break; |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
703 |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
704 case JobState_Paused: |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
705 SetCompletedJob(*found->second, false); |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
706 found->second->SetLastErrorCode(ErrorCode_CanceledJob); |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
707 break; |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
708 |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
709 case JobState_Success: |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
710 case JobState_Failure: |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
711 // Nothing to be done |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
712 break; |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
713 |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
714 case JobState_Running: |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
715 found->second->ScheduleCancel(); |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
716 break; |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
717 |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
718 default: |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
719 throw OrthancException(ErrorCode_InternalError); |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
720 } |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
721 |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
722 CheckInvariants(); |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
723 return true; |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
724 } |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
725 } |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
726 |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
727 |
2573
3372c5255333
StoreScuJob, Orthanc Explorer for jobs
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2570
diff
changeset
|
728 bool JobsRegistry::Resume(const std::string& id) |
2569 | 729 { |
730 LOG(INFO) << "Resuming job: " << id; | |
731 | |
732 boost::mutex::scoped_lock lock(mutex_); | |
733 CheckInvariants(); | |
734 | |
735 JobsIndex::iterator found = jobsIndex_.find(id); | |
736 | |
737 if (found == jobsIndex_.end()) | |
738 { | |
739 LOG(WARNING) << "Unknown job: " << id; | |
2573
3372c5255333
StoreScuJob, Orthanc Explorer for jobs
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2570
diff
changeset
|
740 return false; |
2569 | 741 } |
742 else if (found->second->GetState() != JobState_Paused) | |
743 { | |
744 LOG(WARNING) << "Cannot resume a job that is not paused: " << id; | |
2573
3372c5255333
StoreScuJob, Orthanc Explorer for jobs
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2570
diff
changeset
|
745 return false; |
2569 | 746 } |
747 else | |
748 { | |
749 found->second->SetState(JobState_Pending); | |
750 pendingJobs_.push(found->second); | |
751 pendingJobAvailable_.notify_one(); | |
2573
3372c5255333
StoreScuJob, Orthanc Explorer for jobs
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2570
diff
changeset
|
752 CheckInvariants(); |
3372c5255333
StoreScuJob, Orthanc Explorer for jobs
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2570
diff
changeset
|
753 return true; |
2569 | 754 } |
755 } | |
756 | |
757 | |
2573
3372c5255333
StoreScuJob, Orthanc Explorer for jobs
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2570
diff
changeset
|
758 bool JobsRegistry::Resubmit(const std::string& id) |
2569 | 759 { |
760 LOG(INFO) << "Resubmitting failed job: " << id; | |
761 | |
762 boost::mutex::scoped_lock lock(mutex_); | |
763 CheckInvariants(); | |
764 | |
765 JobsIndex::iterator found = jobsIndex_.find(id); | |
766 | |
767 if (found == jobsIndex_.end()) | |
768 { | |
769 LOG(WARNING) << "Unknown job: " << id; | |
2573
3372c5255333
StoreScuJob, Orthanc Explorer for jobs
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2570
diff
changeset
|
770 return false; |
2569 | 771 } |
772 else if (found->second->GetState() != JobState_Failure) | |
773 { | |
2600
140a539b4eba
SequenceOfOperationsJob
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2583
diff
changeset
|
774 printf("%s\n", EnumerationToString(found->second->GetState())); |
2569 | 775 LOG(WARNING) << "Cannot resubmit a job that has not failed: " << id; |
2573
3372c5255333
StoreScuJob, Orthanc Explorer for jobs
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2570
diff
changeset
|
776 return false; |
2569 | 777 } |
778 else | |
779 { | |
2583
1b6a6d80b6f2
OrthancPeerStoreJob
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2581
diff
changeset
|
780 found->second->GetJob().SignalResubmit(); |
1b6a6d80b6f2
OrthancPeerStoreJob
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2581
diff
changeset
|
781 |
2569 | 782 bool ok = false; |
783 for (CompletedJobs::iterator it = completedJobs_.begin(); | |
784 it != completedJobs_.end(); ++it) | |
785 { | |
786 if (*it == found->second) | |
787 { | |
788 ok = true; | |
789 completedJobs_.erase(it); | |
790 break; | |
791 } | |
792 } | |
793 | |
794 assert(ok); | |
795 | |
796 found->second->SetState(JobState_Pending); | |
797 pendingJobs_.push(found->second); | |
798 pendingJobAvailable_.notify_one(); | |
2573
3372c5255333
StoreScuJob, Orthanc Explorer for jobs
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2570
diff
changeset
|
799 |
3372c5255333
StoreScuJob, Orthanc Explorer for jobs
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2570
diff
changeset
|
800 CheckInvariants(); |
3372c5255333
StoreScuJob, Orthanc Explorer for jobs
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2570
diff
changeset
|
801 return true; |
2569 | 802 } |
803 } | |
804 | |
805 | |
806 void JobsRegistry::ScheduleRetries() | |
807 { | |
808 boost::mutex::scoped_lock lock(mutex_); | |
809 CheckInvariants(); | |
810 | |
811 RetryJobs copy; | |
812 std::swap(copy, retryJobs_); | |
813 | |
814 const boost::posix_time::ptime now = boost::posix_time::microsec_clock::universal_time(); | |
815 | |
816 assert(retryJobs_.empty()); | |
817 for (RetryJobs::iterator it = copy.begin(); it != copy.end(); ++it) | |
818 { | |
819 if ((*it)->IsRetryReady(now)) | |
820 { | |
821 LOG(INFO) << "Retrying job: " << (*it)->GetId(); | |
822 (*it)->SetState(JobState_Pending); | |
823 pendingJobs_.push(*it); | |
824 pendingJobAvailable_.notify_one(); | |
825 } | |
826 else | |
827 { | |
828 retryJobs_.insert(*it); | |
829 } | |
830 } | |
831 | |
832 CheckInvariants(); | |
833 } | |
834 | |
835 | |
836 bool JobsRegistry::GetState(JobState& state, | |
837 const std::string& id) | |
838 { | |
839 boost::mutex::scoped_lock lock(mutex_); | |
2570
2e879c796ec7
JobsRegistry::SubmitAndWait(), StoreScuJob
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2569
diff
changeset
|
840 return GetStateInternal(state, id); |
2569 | 841 } |
842 | |
843 | |
844 JobsRegistry::RunningJob::RunningJob(JobsRegistry& registry, | |
845 unsigned int timeout) : | |
846 registry_(registry), | |
847 handler_(NULL), | |
848 targetState_(JobState_Failure), | |
2581
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
849 targetRetryTimeout_(0), |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
850 canceled_(false) |
2569 | 851 { |
852 { | |
853 boost::mutex::scoped_lock lock(registry_.mutex_); | |
854 | |
855 while (registry_.pendingJobs_.empty()) | |
856 { | |
857 if (timeout == 0) | |
858 { | |
859 registry_.pendingJobAvailable_.wait(lock); | |
860 } | |
861 else | |
862 { | |
863 bool success = registry_.pendingJobAvailable_.timed_wait | |
864 (lock, boost::posix_time::milliseconds(timeout)); | |
865 if (!success) | |
866 { | |
867 // No pending job | |
868 return; | |
869 } | |
870 } | |
871 } | |
872 | |
873 handler_ = registry_.pendingJobs_.top(); | |
874 registry_.pendingJobs_.pop(); | |
875 | |
876 assert(handler_->GetState() == JobState_Pending); | |
877 handler_->SetState(JobState_Running); | |
2581
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
878 handler_->SetLastErrorCode(ErrorCode_Success); |
2569 | 879 |
880 job_ = &handler_->GetJob(); | |
881 id_ = handler_->GetId(); | |
882 priority_ = handler_->GetPriority(); | |
883 } | |
884 } | |
885 | |
886 | |
887 JobsRegistry::RunningJob::~RunningJob() | |
888 { | |
889 if (IsValid()) | |
890 { | |
891 boost::mutex::scoped_lock lock(registry_.mutex_); | |
892 | |
893 switch (targetState_) | |
894 { | |
895 case JobState_Failure: | |
896 registry_.MarkRunningAsCompleted(*handler_, false); | |
2581
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
897 |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
898 if (canceled_) |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
899 { |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
900 handler_->SetLastErrorCode(ErrorCode_CanceledJob); |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
901 } |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
902 |
2569 | 903 break; |
904 | |
905 case JobState_Success: | |
906 registry_.MarkRunningAsCompleted(*handler_, true); | |
907 break; | |
908 | |
909 case JobState_Paused: | |
910 registry_.MarkRunningAsPaused(*handler_); | |
911 break; | |
912 | |
913 case JobState_Retry: | |
914 registry_.MarkRunningAsRetry(*handler_, targetRetryTimeout_); | |
915 break; | |
916 | |
917 default: | |
918 assert(0); | |
919 } | |
920 } | |
921 } | |
922 | |
923 | |
924 bool JobsRegistry::RunningJob::IsValid() const | |
925 { | |
926 return (handler_ != NULL && | |
927 job_ != NULL); | |
928 } | |
929 | |
930 | |
931 const std::string& JobsRegistry::RunningJob::GetId() const | |
932 { | |
933 if (!IsValid()) | |
934 { | |
935 throw OrthancException(ErrorCode_BadSequenceOfCalls); | |
936 } | |
937 else | |
938 { | |
939 return id_; | |
940 } | |
941 } | |
942 | |
943 | |
944 int JobsRegistry::RunningJob::GetPriority() const | |
945 { | |
946 if (!IsValid()) | |
947 { | |
948 throw OrthancException(ErrorCode_BadSequenceOfCalls); | |
949 } | |
950 else | |
951 { | |
952 return priority_; | |
953 } | |
954 } | |
955 | |
956 | |
957 IJob& JobsRegistry::RunningJob::GetJob() | |
958 { | |
959 if (!IsValid()) | |
960 { | |
961 throw OrthancException(ErrorCode_BadSequenceOfCalls); | |
962 } | |
963 else | |
964 { | |
965 return *job_; | |
966 } | |
967 } | |
968 | |
969 | |
970 bool JobsRegistry::RunningJob::IsPauseScheduled() | |
971 { | |
972 if (!IsValid()) | |
973 { | |
974 throw OrthancException(ErrorCode_BadSequenceOfCalls); | |
975 } | |
976 else | |
977 { | |
978 boost::mutex::scoped_lock lock(registry_.mutex_); | |
979 registry_.CheckInvariants(); | |
980 assert(handler_->GetState() == JobState_Running); | |
981 | |
982 return handler_->IsPauseScheduled(); | |
983 } | |
984 } | |
985 | |
986 | |
2581
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
987 bool JobsRegistry::RunningJob::IsCancelScheduled() |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
988 { |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
989 if (!IsValid()) |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
990 { |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
991 throw OrthancException(ErrorCode_BadSequenceOfCalls); |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
992 } |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
993 else |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
994 { |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
995 boost::mutex::scoped_lock lock(registry_.mutex_); |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
996 registry_.CheckInvariants(); |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
997 assert(handler_->GetState() == JobState_Running); |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
998 |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
999 return handler_->IsCancelScheduled(); |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
1000 } |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
1001 } |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
1002 |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
1003 |
2569 | 1004 void JobsRegistry::RunningJob::MarkSuccess() |
1005 { | |
1006 if (!IsValid()) | |
1007 { | |
1008 throw OrthancException(ErrorCode_BadSequenceOfCalls); | |
1009 } | |
1010 else | |
1011 { | |
1012 targetState_ = JobState_Success; | |
1013 } | |
1014 } | |
1015 | |
1016 | |
1017 void JobsRegistry::RunningJob::MarkFailure() | |
1018 { | |
1019 if (!IsValid()) | |
1020 { | |
1021 throw OrthancException(ErrorCode_BadSequenceOfCalls); | |
1022 } | |
1023 else | |
1024 { | |
1025 targetState_ = JobState_Failure; | |
1026 } | |
1027 } | |
1028 | |
1029 | |
2581
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
1030 void JobsRegistry::RunningJob::MarkCanceled() |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
1031 { |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
1032 if (!IsValid()) |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
1033 { |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
1034 throw OrthancException(ErrorCode_BadSequenceOfCalls); |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
1035 } |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
1036 else |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
1037 { |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
1038 targetState_ = JobState_Failure; |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
1039 canceled_ = true; |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
1040 } |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
1041 } |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
1042 |
8da2cffc2378
JobsRegistry::Cancel()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2573
diff
changeset
|
1043 |
2569 | 1044 void JobsRegistry::RunningJob::MarkPause() |
1045 { | |
1046 if (!IsValid()) | |
1047 { | |
1048 throw OrthancException(ErrorCode_BadSequenceOfCalls); | |
1049 } | |
1050 else | |
1051 { | |
1052 targetState_ = JobState_Paused; | |
1053 } | |
1054 } | |
1055 | |
1056 | |
1057 void JobsRegistry::RunningJob::MarkRetry(unsigned int timeout) | |
1058 { | |
1059 if (!IsValid()) | |
1060 { | |
1061 throw OrthancException(ErrorCode_BadSequenceOfCalls); | |
1062 } | |
1063 else | |
1064 { | |
1065 targetState_ = JobState_Retry; | |
1066 targetRetryTimeout_ = timeout; | |
1067 } | |
1068 } | |
1069 | |
1070 | |
1071 void JobsRegistry::RunningJob::UpdateStatus(ErrorCode code) | |
1072 { | |
1073 if (!IsValid()) | |
1074 { | |
1075 throw OrthancException(ErrorCode_BadSequenceOfCalls); | |
1076 } | |
1077 else | |
1078 { | |
1079 JobStatus status(code, *job_); | |
1080 | |
1081 boost::mutex::scoped_lock lock(registry_.mutex_); | |
1082 registry_.CheckInvariants(); | |
1083 assert(handler_->GetState() == JobState_Running); | |
1084 | |
1085 handler_->SetLastStatus(status); | |
1086 } | |
1087 } | |
1088 } |