comparison Core/JobsEngine/JobsRegistry.cpp @ 4025:52bc28f8ac8c

merge
author Alain Mazy <alain@mazy.be>
date Tue, 09 Jun 2020 12:21:03 +0200
parents 1d2b31fc782f
children
comparison
equal deleted inserted replaced
4021:ceba3213cb9e 4025:52bc28f8ac8c
18 * modify file(s) with this exception, you may extend this exception to 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 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 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 21 * version. If you delete this exception statement from all source files
22 * in the program, then also delete it here. 22 * in the program, then also delete it here.
23 * 23 *
24 * This program is distributed in the hope that it will be useful, but 24 * This program is distributed in the hope that it will be useful, but
25 * WITHOUT ANY WARRANTY; without even the implied warranty of 25 * WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
27 * General Public License for more details. 27 * General Public License for more details.
28 * 28 *
48 static const char* JOBS = "Jobs"; 48 static const char* JOBS = "Jobs";
49 static const char* JOBS_REGISTRY = "JobsRegistry"; 49 static const char* JOBS_REGISTRY = "JobsRegistry";
50 static const char* CREATION_TIME = "CreationTime"; 50 static const char* CREATION_TIME = "CreationTime";
51 static const char* LAST_CHANGE_TIME = "LastChangeTime"; 51 static const char* LAST_CHANGE_TIME = "LastChangeTime";
52 static const char* RUNTIME = "Runtime"; 52 static const char* RUNTIME = "Runtime";
53 53
54 54
55 class JobsRegistry::JobHandler : public boost::noncopyable 55 class JobsRegistry::JobHandler : public boost::noncopyable
56 { 56 {
57 private: 57 private:
58 std::string id_; 58 std::string id_;
59 JobState state_; 59 JobState state_;
60 std::string jobType_; 60 std::string jobType_;
61 std::unique_ptr<IJob> job_; 61 std::unique_ptr<IJob> job_;
78 } 78 }
79 79
80 lastStateChangeTime_ = now; 80 lastStateChangeTime_ = now;
81 } 81 }
82 82
83 void SetStateInternal(JobState state) 83 void SetStateInternal(JobState state)
84 { 84 {
85 state_ = state; 85 state_ = state;
86 pauseScheduled_ = false; 86 pauseScheduled_ = false;
87 cancelScheduled_ = false; 87 cancelScheduled_ = false;
88 Touch(); 88 Touch();
137 JobState GetState() const 137 JobState GetState() const
138 { 138 {
139 return state_; 139 return state_;
140 } 140 }
141 141
142 void SetState(JobState state) 142 void SetState(JobState state)
143 { 143 {
144 if (state == JobState_Retry) 144 if (state == JobState_Retry)
145 { 145 {
146 // Use "SetRetryState()" 146 // Use "SetRetryState()"
147 throw OrthancException(ErrorCode_BadSequenceOfCalls); 147 throw OrthancException(ErrorCode_BadSequenceOfCalls);
155 void SetRetryState(unsigned int timeout) 155 void SetRetryState(unsigned int timeout)
156 { 156 {
157 if (state_ == JobState_Running) 157 if (state_ == JobState_Running)
158 { 158 {
159 SetStateInternal(JobState_Retry); 159 SetStateInternal(JobState_Retry);
160 retryTime_ = (boost::posix_time::microsec_clock::universal_time() + 160 retryTime_ = (boost::posix_time::microsec_clock::universal_time() +
161 boost::posix_time::milliseconds(timeout)); 161 boost::posix_time::milliseconds(timeout));
162 } 162 }
163 else 163 else
164 { 164 {
165 // Only valid for running jobs 165 // Only valid for running jobs
273 else 273 else
274 { 274 {
275 ok = false; 275 ok = false;
276 } 276 }
277 } 277 }
278 else 278 else
279 { 279 {
280 ok = job_->Serialize(target[JOB]); 280 ok = job_->Serialize(target[JOB]);
281 } 281 }
282 282
283 if (ok) 283 if (ok)
325 325
326 bool JobsRegistry::PriorityComparator::operator() (JobHandler*& a, 326 bool JobsRegistry::PriorityComparator::operator() (JobHandler*& a,
327 JobHandler*& b) const 327 JobHandler*& b) const
328 { 328 {
329 return a->GetPriority() < b->GetPriority(); 329 return a->GetPriority() < b->GetPriority();
330 } 330 }
331 331
332 332
333 #if defined(NDEBUG) 333 #if defined(NDEBUG)
334 void JobsRegistry::CheckInvariants() const 334 void JobsRegistry::CheckInvariants() const
335 { 335 {
336 } 336 }
337 337
338 #else 338 #else
339 bool JobsRegistry::IsPendingJob(const JobHandler& job) const 339 bool JobsRegistry::IsPendingJob(const JobHandler& job) const
340 { 340 {
341 PendingJobs copy = pendingJobs_; 341 PendingJobs copy = pendingJobs_;
342 while (!copy.empty()) 342 while (!copy.empty())
407 switch (job.GetState()) 407 switch (job.GetState())
408 { 408 {
409 case JobState_Pending: 409 case JobState_Pending:
410 assert(!IsRetryJob(job) && IsPendingJob(job) && !IsCompletedJob(job)); 410 assert(!IsRetryJob(job) && IsPendingJob(job) && !IsCompletedJob(job));
411 break; 411 break;
412 412
413 case JobState_Success: 413 case JobState_Success:
414 case JobState_Failure: 414 case JobState_Failure:
415 assert(!IsRetryJob(job) && !IsPendingJob(job) && IsCompletedJob(job)); 415 assert(!IsRetryJob(job) && !IsPendingJob(job) && IsCompletedJob(job));
416 break; 416 break;
417 417
418 case JobState_Retry: 418 case JobState_Retry:
419 assert(IsRetryJob(job) && !IsPendingJob(job) && !IsCompletedJob(job)); 419 assert(IsRetryJob(job) && !IsPendingJob(job) && !IsCompletedJob(job));
420 break; 420 break;
421 421
422 case JobState_Running: 422 case JobState_Running:
423 case JobState_Paused: 423 case JobState_Paused:
424 assert(!IsRetryJob(job) && !IsPendingJob(job) && !IsCompletedJob(job)); 424 assert(!IsRetryJob(job) && !IsPendingJob(job) && !IsCompletedJob(job));
425 break; 425 break;
426 426
480 break; 480 break;
481 481
482 default: 482 default:
483 throw OrthancException(ErrorCode_InternalError); 483 throw OrthancException(ErrorCode_InternalError);
484 } 484 }
485 485
486 LOG(INFO) << "Job has completed with " << tmp << ": " << job.GetId(); 486 LOG(INFO) << "Job has completed with " << tmp << ": " << job.GetId();
487 487
488 CheckInvariants(); 488 CheckInvariants();
489 489
490 assert(job.GetState() == JobState_Running); 490 assert(job.GetState() == JobState_Running);
558 state = it->second->GetState(); 558 state = it->second->GetState();
559 return true; 559 return true;
560 } 560 }
561 } 561 }
562 562
563 563
564 JobsRegistry::~JobsRegistry() 564 JobsRegistry::~JobsRegistry()
565 { 565 {
566 for (JobsIndex::iterator it = jobsIndex_.begin(); it != jobsIndex_.end(); ++it) 566 for (JobsIndex::iterator it = jobsIndex_.begin(); it != jobsIndex_.end(); ++it)
567 { 567 {
568 assert(it->second != NULL); 568 assert(it->second != NULL);
666 { 666 {
667 if (handler == NULL) 667 if (handler == NULL)
668 { 668 {
669 throw OrthancException(ErrorCode_NullPointer); 669 throw OrthancException(ErrorCode_NullPointer);
670 } 670 }
671 671
672 std::unique_ptr<JobHandler> protection(handler); 672 std::unique_ptr<JobHandler> protection(handler);
673 673
674 { 674 {
675 boost::mutex::scoped_lock lock(mutex_); 675 boost::mutex::scoped_lock lock(mutex_);
676 CheckInvariants(); 676 CheckInvariants();
677 677
678 id = handler->GetId(); 678 id = handler->GetId();
679 int priority = handler->GetPriority(); 679 int priority = handler->GetPriority();
680 680
681 jobsIndex_.insert(std::make_pair(id, protection.release())); 681 jobsIndex_.insert(std::make_pair(id, protection.release()));
682 682
687 case JobState_Running: 687 case JobState_Running:
688 handler->SetState(JobState_Pending); 688 handler->SetState(JobState_Pending);
689 pendingJobs_.push(handler); 689 pendingJobs_.push(handler);
690 pendingJobAvailable_.notify_one(); 690 pendingJobAvailable_.notify_one();
691 break; 691 break;
692 692
693 case JobState_Success: 693 case JobState_Success:
694 SetCompletedJob(*handler, true); 694 SetCompletedJob(*handler, true);
695 break; 695 break;
696 696
697 case JobState_Failure: 697 case JobState_Failure:
698 SetCompletedJob(*handler, false); 698 SetCompletedJob(*handler, false);
699 break; 699 break;
700 700
701 case JobState_Paused: 701 case JobState_Paused:
702 break; 702 break;
703 703
704 default: 704 default:
705 { 705 {
706 std::string details = ("A job should not be loaded from state: " + 706 std::string details = ("A job should not be loaded from state: " +
707 std::string(EnumerationToString(handler->GetState()))); 707 std::string(EnumerationToString(handler->GetState())));
708 throw OrthancException(ErrorCode_InternalError, details); 708 throw OrthancException(ErrorCode_InternalError, details);
796 else 796 else
797 { 797 {
798 const JobStatus& status = it->second->GetLastStatus(); 798 const JobStatus& status = it->second->GetLastStatus();
799 successContent = status.GetPublicContent(); 799 successContent = status.GetPublicContent();
800 } 800 }
801 801
802 return; 802 return;
803 } 803 }
804 else 804 else
805 { 805 {
806 // This job has not finished yet, wait for new completion 806 // This job has not finished yet, wait for new completion
873 873
874 874
875 void JobsRegistry::RemoveRetryJob(JobHandler* handler) 875 void JobsRegistry::RemoveRetryJob(JobHandler* handler)
876 { 876 {
877 RetryJobs::iterator item = retryJobs_.find(handler); 877 RetryJobs::iterator item = retryJobs_.find(handler);
878 assert(item != retryJobs_.end()); 878 assert(item != retryJobs_.end());
879 retryJobs_.erase(item); 879 retryJobs_.erase(item);
880 } 880 }
881 881
882 882
883 bool JobsRegistry::Pause(const std::string& id) 883 bool JobsRegistry::Pause(const std::string& id)
960 960
961 case JobState_Paused: 961 case JobState_Paused:
962 SetCompletedJob(*found->second, false); 962 SetCompletedJob(*found->second, false);
963 found->second->SetLastErrorCode(ErrorCode_CanceledJob); 963 found->second->SetLastErrorCode(ErrorCode_CanceledJob);
964 break; 964 break;
965 965
966 case JobState_Success: 966 case JobState_Success:
967 case JobState_Failure: 967 case JobState_Failure:
968 // Nothing to be done 968 // Nothing to be done
969 break; 969 break;
970 970
1008 { 1008 {
1009 found->second->SetState(JobState_Pending); 1009 found->second->SetState(JobState_Pending);
1010 pendingJobs_.push(found->second); 1010 pendingJobs_.push(found->second);
1011 pendingJobAvailable_.notify_one(); 1011 pendingJobAvailable_.notify_one();
1012 CheckInvariants(); 1012 CheckInvariants();
1013 return true; 1013 return true;
1014 } 1014 }
1015 } 1015 }
1016 1016
1017 1017
1018 bool JobsRegistry::Resubmit(const std::string& id) 1018 bool JobsRegistry::Resubmit(const std::string& id)
1035 return false; 1035 return false;
1036 } 1036 }
1037 else 1037 else
1038 { 1038 {
1039 found->second->GetJob().Reset(); 1039 found->second->GetJob().Reset();
1040 1040
1041 bool ok = false; 1041 bool ok = false;
1042 for (CompletedJobs::iterator it = completedJobs_.begin(); 1042 for (CompletedJobs::iterator it = completedJobs_.begin();
1043 it != completedJobs_.end(); ++it) 1043 it != completedJobs_.end(); ++it)
1044 { 1044 {
1045 if (*it == found->second) 1045 if (*it == found->second)
1046 { 1046 {
1047 ok = true; 1047 ok = true;
1104 { 1104 {
1105 boost::mutex::scoped_lock lock(mutex_); 1105 boost::mutex::scoped_lock lock(mutex_);
1106 observer_ = &observer; 1106 observer_ = &observer;
1107 } 1107 }
1108 1108
1109 1109
1110 void JobsRegistry::ResetObserver() 1110 void JobsRegistry::ResetObserver()
1111 { 1111 {
1112 boost::mutex::scoped_lock lock(mutex_); 1112 boost::mutex::scoped_lock lock(mutex_);
1113 observer_ = NULL; 1113 observer_ = NULL;
1114 } 1114 }
1115 1115
1116 1116
1117 JobsRegistry::RunningJob::RunningJob(JobsRegistry& registry, 1117 JobsRegistry::RunningJob::RunningJob(JobsRegistry& registry,
1118 unsigned int timeout) : 1118 unsigned int timeout) :
1119 registry_(registry), 1119 registry_(registry),
1120 handler_(NULL), 1120 handler_(NULL),
1121 targetState_(JobState_Failure), 1121 targetState_(JobState_Failure),
1154 id_ = handler_->GetId(); 1154 id_ = handler_->GetId();
1155 priority_ = handler_->GetPriority(); 1155 priority_ = handler_->GetPriority();
1156 } 1156 }
1157 } 1157 }
1158 1158
1159 1159
1160 JobsRegistry::RunningJob::~RunningJob() 1160 JobsRegistry::RunningJob::~RunningJob()
1161 { 1161 {
1162 if (IsValid()) 1162 if (IsValid())
1163 { 1163 {
1164 boost::mutex::scoped_lock lock(registry_.mutex_); 1164 boost::mutex::scoped_lock lock(registry_.mutex_);
1174 registry_.MarkRunningAsCompleted(*handler_, CompletedReason_Success); 1174 registry_.MarkRunningAsCompleted(*handler_, CompletedReason_Success);
1175 break; 1175 break;
1176 1176
1177 case JobState_Paused: 1177 case JobState_Paused:
1178 registry_.MarkRunningAsPaused(*handler_); 1178 registry_.MarkRunningAsPaused(*handler_);
1179 break; 1179 break;
1180 1180
1181 case JobState_Retry: 1181 case JobState_Retry:
1182 registry_.MarkRunningAsRetry(*handler_, targetRetryTimeout_); 1182 registry_.MarkRunningAsRetry(*handler_, targetRetryTimeout_);
1183 break; 1183 break;
1184 1184
1185 default: 1185 default:
1186 assert(0); 1186 assert(0);
1187 } 1187 }
1188 } 1188 }
1189 } 1189 }
1190 1190
1191 1191
1192 bool JobsRegistry::RunningJob::IsValid() const 1192 bool JobsRegistry::RunningJob::IsValid() const
1193 { 1193 {
1194 return (handler_ != NULL && 1194 return (handler_ != NULL &&
1195 job_ != NULL); 1195 job_ != NULL);
1196 } 1196 }
1197 1197
1198 1198
1199 const std::string& JobsRegistry::RunningJob::GetId() const 1199 const std::string& JobsRegistry::RunningJob::GetId() const
1200 { 1200 {
1201 if (!IsValid()) 1201 if (!IsValid())
1202 { 1202 {
1203 throw OrthancException(ErrorCode_BadSequenceOfCalls); 1203 throw OrthancException(ErrorCode_BadSequenceOfCalls);
1206 { 1206 {
1207 return id_; 1207 return id_;
1208 } 1208 }
1209 } 1209 }
1210 1210
1211 1211
1212 int JobsRegistry::RunningJob::GetPriority() const 1212 int JobsRegistry::RunningJob::GetPriority() const
1213 { 1213 {
1214 if (!IsValid()) 1214 if (!IsValid())
1215 { 1215 {
1216 throw OrthancException(ErrorCode_BadSequenceOfCalls); 1216 throw OrthancException(ErrorCode_BadSequenceOfCalls);
1218 else 1218 else
1219 { 1219 {
1220 return priority_; 1220 return priority_;
1221 } 1221 }
1222 } 1222 }
1223 1223
1224 1224
1225 IJob& JobsRegistry::RunningJob::GetJob() 1225 IJob& JobsRegistry::RunningJob::GetJob()
1226 { 1226 {
1227 if (!IsValid()) 1227 if (!IsValid())
1228 { 1228 {
1232 { 1232 {
1233 return *job_; 1233 return *job_;
1234 } 1234 }
1235 } 1235 }
1236 1236
1237 1237
1238 bool JobsRegistry::RunningJob::IsPauseScheduled() 1238 bool JobsRegistry::RunningJob::IsPauseScheduled()
1239 { 1239 {
1240 if (!IsValid()) 1240 if (!IsValid())
1241 { 1241 {
1242 throw OrthancException(ErrorCode_BadSequenceOfCalls); 1242 throw OrthancException(ErrorCode_BadSequenceOfCalls);
1244 else 1244 else
1245 { 1245 {
1246 boost::mutex::scoped_lock lock(registry_.mutex_); 1246 boost::mutex::scoped_lock lock(registry_.mutex_);
1247 registry_.CheckInvariants(); 1247 registry_.CheckInvariants();
1248 assert(handler_->GetState() == JobState_Running); 1248 assert(handler_->GetState() == JobState_Running);
1249 1249
1250 return handler_->IsPauseScheduled(); 1250 return handler_->IsPauseScheduled();
1251 } 1251 }
1252 } 1252 }
1253 1253
1254 1254
1255 bool JobsRegistry::RunningJob::IsCancelScheduled() 1255 bool JobsRegistry::RunningJob::IsCancelScheduled()
1256 { 1256 {
1257 if (!IsValid()) 1257 if (!IsValid())
1258 { 1258 {
1259 throw OrthancException(ErrorCode_BadSequenceOfCalls); 1259 throw OrthancException(ErrorCode_BadSequenceOfCalls);
1261 else 1261 else
1262 { 1262 {
1263 boost::mutex::scoped_lock lock(registry_.mutex_); 1263 boost::mutex::scoped_lock lock(registry_.mutex_);
1264 registry_.CheckInvariants(); 1264 registry_.CheckInvariants();
1265 assert(handler_->GetState() == JobState_Running); 1265 assert(handler_->GetState() == JobState_Running);
1266 1266
1267 return handler_->IsCancelScheduled(); 1267 return handler_->IsCancelScheduled();
1268 } 1268 }
1269 } 1269 }
1270 1270
1271 1271
1272 void JobsRegistry::RunningJob::MarkSuccess() 1272 void JobsRegistry::RunningJob::MarkSuccess()
1273 { 1273 {
1274 if (!IsValid()) 1274 if (!IsValid())
1275 { 1275 {
1276 throw OrthancException(ErrorCode_BadSequenceOfCalls); 1276 throw OrthancException(ErrorCode_BadSequenceOfCalls);
1279 { 1279 {
1280 targetState_ = JobState_Success; 1280 targetState_ = JobState_Success;
1281 } 1281 }
1282 } 1282 }
1283 1283
1284 1284
1285 void JobsRegistry::RunningJob::MarkFailure() 1285 void JobsRegistry::RunningJob::MarkFailure()
1286 { 1286 {
1287 if (!IsValid()) 1287 if (!IsValid())
1288 { 1288 {
1289 throw OrthancException(ErrorCode_BadSequenceOfCalls); 1289 throw OrthancException(ErrorCode_BadSequenceOfCalls);
1292 { 1292 {
1293 targetState_ = JobState_Failure; 1293 targetState_ = JobState_Failure;
1294 } 1294 }
1295 } 1295 }
1296 1296
1297 1297
1298 void JobsRegistry::RunningJob::MarkCanceled() 1298 void JobsRegistry::RunningJob::MarkCanceled()
1299 { 1299 {
1300 if (!IsValid()) 1300 if (!IsValid())
1301 { 1301 {
1302 throw OrthancException(ErrorCode_BadSequenceOfCalls); 1302 throw OrthancException(ErrorCode_BadSequenceOfCalls);
1306 targetState_ = JobState_Failure; 1306 targetState_ = JobState_Failure;
1307 canceled_ = true; 1307 canceled_ = true;
1308 } 1308 }
1309 } 1309 }
1310 1310
1311 1311
1312 void JobsRegistry::RunningJob::MarkPause() 1312 void JobsRegistry::RunningJob::MarkPause()
1313 { 1313 {
1314 if (!IsValid()) 1314 if (!IsValid())
1315 { 1315 {
1316 throw OrthancException(ErrorCode_BadSequenceOfCalls); 1316 throw OrthancException(ErrorCode_BadSequenceOfCalls);
1319 { 1319 {
1320 targetState_ = JobState_Paused; 1320 targetState_ = JobState_Paused;
1321 } 1321 }
1322 } 1322 }
1323 1323
1324 1324
1325 void JobsRegistry::RunningJob::MarkRetry(unsigned int timeout) 1325 void JobsRegistry::RunningJob::MarkRetry(unsigned int timeout)
1326 { 1326 {
1327 if (!IsValid()) 1327 if (!IsValid())
1328 { 1328 {
1329 throw OrthancException(ErrorCode_BadSequenceOfCalls); 1329 throw OrthancException(ErrorCode_BadSequenceOfCalls);
1332 { 1332 {
1333 targetState_ = JobState_Retry; 1333 targetState_ = JobState_Retry;
1334 targetRetryTimeout_ = timeout; 1334 targetRetryTimeout_ = timeout;
1335 } 1335 }
1336 } 1336 }
1337 1337
1338 1338
1339 void JobsRegistry::RunningJob::UpdateStatus(ErrorCode code, 1339 void JobsRegistry::RunningJob::UpdateStatus(ErrorCode code,
1340 const std::string& details) 1340 const std::string& details)
1341 { 1341 {
1342 if (!IsValid()) 1342 if (!IsValid())
1344 throw OrthancException(ErrorCode_BadSequenceOfCalls); 1344 throw OrthancException(ErrorCode_BadSequenceOfCalls);
1345 } 1345 }
1346 else 1346 else
1347 { 1347 {
1348 JobStatus status(code, details, *job_); 1348 JobStatus status(code, details, *job_);
1349 1349
1350 boost::mutex::scoped_lock lock(registry_.mutex_); 1350 boost::mutex::scoped_lock lock(registry_.mutex_);
1351 registry_.CheckInvariants(); 1351 registry_.CheckInvariants();
1352 assert(handler_->GetState() == JobState_Running); 1352 assert(handler_->GetState() == JobState_Running);
1353 1353
1354 handler_->SetLastStatus(status); 1354 handler_->SetLastStatus(status);
1355 } 1355 }
1356 } 1356 }
1357 1357
1358 1358
1363 CheckInvariants(); 1363 CheckInvariants();
1364 1364
1365 target = Json::objectValue; 1365 target = Json::objectValue;
1366 target[TYPE] = JOBS_REGISTRY; 1366 target[TYPE] = JOBS_REGISTRY;
1367 target[JOBS] = Json::objectValue; 1367 target[JOBS] = Json::objectValue;
1368 1368
1369 for (JobsIndex::const_iterator it = jobsIndex_.begin(); 1369 for (JobsIndex::const_iterator it = jobsIndex_.begin();
1370 it != jobsIndex_.end(); ++it) 1370 it != jobsIndex_.end(); ++it)
1371 { 1371 {
1372 Json::Value v; 1372 Json::Value v;
1373 if (it->second->Serialize(v)) 1373 if (it->second->Serialize(v))
1374 { 1374 {
1438 1438
1439 pending = 0; 1439 pending = 0;
1440 running = 0; 1440 running = 0;
1441 success = 0; 1441 success = 0;
1442 failed = 0; 1442 failed = 0;
1443 1443
1444 for (JobsIndex::const_iterator it = jobsIndex_.begin(); 1444 for (JobsIndex::const_iterator it = jobsIndex_.begin();
1445 it != jobsIndex_.end(); ++it) 1445 it != jobsIndex_.end(); ++it)
1446 { 1446 {
1447 JobHandler& job = *it->second; 1447 JobHandler& job = *it->second;
1448 1448
1455 1455
1456 case JobState_Paused: 1456 case JobState_Paused:
1457 case JobState_Running: 1457 case JobState_Running:
1458 running ++; 1458 running ++;
1459 break; 1459 break;
1460 1460
1461 case JobState_Success: 1461 case JobState_Success:
1462 success ++; 1462 success ++;
1463 break; 1463 break;
1464 1464
1465 case JobState_Failure: 1465 case JobState_Failure:
1467 break; 1467 break;
1468 1468
1469 default: 1469 default:
1470 throw OrthancException(ErrorCode_InternalError); 1470 throw OrthancException(ErrorCode_InternalError);
1471 } 1471 }
1472 } 1472 }
1473 } 1473 }
1474 } 1474 }