comparison UnitTestsSources/MultiThreadingTests.cpp @ 2566:c09ce3c038fc jobs

improved handling of eta
author Sebastien Jodogne <s.jodogne@gmail.com>
date Mon, 07 May 2018 13:51:23 +0200
parents 0f06b4d5b3d0
children 3caca43371f5
comparison
equal deleted inserted replaced
2565:0f06b4d5b3d0 2566:c09ce3c038fc
391 float progress_; 391 float progress_;
392 Json::Value description_; 392 Json::Value description_;
393 393
394 public: 394 public:
395 JobStatus() : 395 JobStatus() :
396 errorCode_(ErrorCode_Success), 396 errorCode_(ErrorCode_InternalError),
397 progress_(0), 397 progress_(0),
398 description_(Json::objectValue) 398 description_(Json::objectValue)
399 { 399 {
400 } 400 }
401 401
440 std::string id_; 440 std::string id_;
441 int priority_; 441 int priority_;
442 JobState state_; 442 JobState state_;
443 boost::posix_time::ptime timestamp_; 443 boost::posix_time::ptime timestamp_;
444 boost::posix_time::ptime creationTime_; 444 boost::posix_time::ptime creationTime_;
445 boost::posix_time::ptime lastStateChangeTime_;
445 boost::posix_time::time_duration runtime_; 446 boost::posix_time::time_duration runtime_;
447 bool hasEta_;
446 boost::posix_time::ptime eta_; 448 boost::posix_time::ptime eta_;
447 JobStatus status_; 449 JobStatus status_;
448 450
449 public: 451 public:
450 JobInfo(const std::string& id, 452 JobInfo(const std::string& id,
451 int priority, 453 int priority,
452 JobState state, 454 JobState state,
453 const JobStatus& status, 455 const JobStatus& status,
454 const boost::posix_time::ptime& creationTime, 456 const boost::posix_time::ptime& creationTime,
457 const boost::posix_time::ptime& lastStateChangeTime,
455 const boost::posix_time::time_duration& runtime) : 458 const boost::posix_time::time_duration& runtime) :
456 id_(id), 459 id_(id),
457 priority_(priority), 460 priority_(priority),
458 state_(state), 461 state_(state),
459 timestamp_(boost::posix_time::microsec_clock::universal_time()), 462 timestamp_(boost::posix_time::microsec_clock::universal_time()),
460 creationTime_(creationTime), 463 creationTime_(creationTime),
464 lastStateChangeTime_(lastStateChangeTime),
461 runtime_(runtime), 465 runtime_(runtime),
466 hasEta_(false),
462 status_(status) 467 status_(status)
463 { 468 {
464 float ms = static_cast<float>(runtime_.total_milliseconds()); 469 if (state_ == JobState_Running)
465 float remaining = boost::math::llround(1.0f - status_.GetProgress()) * ms; 470 {
466 eta_ = timestamp_ + boost::posix_time::milliseconds(remaining); 471 float ms = static_cast<float>(runtime_.total_milliseconds());
472
473 if (status_.GetProgress() > 0.01f &&
474 ms > 0.01f)
475 {
476 float remaining = boost::math::llround(1.0f - status_.GetProgress()) * ms;
477 eta_ = timestamp_ + boost::posix_time::milliseconds(remaining);
478 hasEta_ = true;
479 }
480 }
467 } 481 }
468 482
469 JobInfo() : 483 JobInfo() :
470 priority_(0), 484 priority_(0),
471 state_(JobState_Failure), 485 state_(JobState_Failure),
472 timestamp_(boost::posix_time::microsec_clock::universal_time()), 486 timestamp_(boost::posix_time::microsec_clock::universal_time()),
473 creationTime_(timestamp_), 487 creationTime_(timestamp_),
488 lastStateChangeTime_(timestamp_),
474 runtime_(boost::posix_time::milliseconds(0)), 489 runtime_(boost::posix_time::milliseconds(0)),
475 eta_(timestamp_) 490 hasEta_(false)
476 { 491 {
477 } 492 }
478 493
479 const std::string& GetIdentifier() const 494 const std::string& GetIdentifier() const
480 { 495 {
504 const boost::posix_time::time_duration& GetRuntime() const 519 const boost::posix_time::time_duration& GetRuntime() const
505 { 520 {
506 return runtime_; 521 return runtime_;
507 } 522 }
508 523
524 bool HasEstimatedTimeOfArrival() const
525 {
526 return hasEta_;
527 }
528
529 bool HasCompletionTime() const
530 {
531 return (state_ == JobState_Success ||
532 state_ == JobState_Failure);
533 }
534
509 const boost::posix_time::ptime& GetEstimatedTimeOfArrival() const 535 const boost::posix_time::ptime& GetEstimatedTimeOfArrival() const
510 { 536 {
511 return eta_; 537 if (hasEta_)
538 {
539 return eta_;
540 }
541 else
542 {
543 throw OrthancException(ErrorCode_BadSequenceOfCalls);
544 }
545 }
546
547 const boost::posix_time::ptime& GetCompletionTime() const
548 {
549 if (HasCompletionTime())
550 {
551 return lastStateChangeTime_;
552 }
553 else
554 {
555 throw OrthancException(ErrorCode_BadSequenceOfCalls);
556 }
512 } 557 }
513 558
514 const JobStatus& GetStatus() const 559 const JobStatus& GetStatus() const
515 { 560 {
516 return status_; 561 return status_;
524 void Format(Json::Value& target) const 569 void Format(Json::Value& target) const
525 { 570 {
526 target = Json::objectValue; 571 target = Json::objectValue;
527 target["ID"] = id_; 572 target["ID"] = id_;
528 target["Priority"] = priority_; 573 target["Priority"] = priority_;
529 target["ErrorCode"] = EnumerationToString(status_.GetErrorCode()); 574 target["ErrorCode"] = static_cast<int>(status_.GetErrorCode());
575 target["ErrorDescription"] = EnumerationToString(status_.GetErrorCode());
530 target["State"] = EnumerationToString(state_); 576 target["State"] = EnumerationToString(state_);
531 target["Timestamp"] = boost::posix_time::to_iso_string(timestamp_); 577 target["Timestamp"] = boost::posix_time::to_iso_string(timestamp_);
532 target["CreationTime"] = boost::posix_time::to_iso_string(creationTime_); 578 target["CreationTime"] = boost::posix_time::to_iso_string(creationTime_);
533 target["Runtime"] = static_cast<uint32_t>(runtime_.total_milliseconds()); 579 target["Runtime"] = static_cast<uint32_t>(runtime_.total_milliseconds());
534 target["EstimatedTimeOfArrival"] = boost::posix_time::to_iso_string(eta_);
535 target["Progress"] = boost::math::iround(status_.GetProgress() * 100.0f); 580 target["Progress"] = boost::math::iround(status_.GetProgress() * 100.0f);
536 target["Description"] = status_.GetDescription(); 581 target["Description"] = status_.GetDescription();
582
583 if (HasEstimatedTimeOfArrival())
584 {
585 target["EstimatedTimeOfArrival"] = boost::posix_time::to_iso_string(GetEstimatedTimeOfArrival());
586 }
587
588 if (HasCompletionTime())
589 {
590 target["CompletionTime"] = boost::posix_time::to_iso_string(GetCompletionTime());
591 }
537 } 592 }
538 }; 593 };
539 594
540 595
541 class JobHandler : public boost::noncopyable 596 class JobHandler : public boost::noncopyable
550 boost::posix_time::time_duration runtime_; 605 boost::posix_time::time_duration runtime_;
551 boost::posix_time::ptime retryTime_; 606 boost::posix_time::ptime retryTime_;
552 bool pauseScheduled_; 607 bool pauseScheduled_;
553 JobStatus lastStatus_; 608 JobStatus lastStatus_;
554 609
610 void Touch()
611 {
612 const boost::posix_time::ptime now = boost::posix_time::microsec_clock::universal_time();
613
614 if (state_ == JobState_Running)
615 {
616 runtime_ += (now - lastStateChangeTime_);
617 }
618
619 lastStateChangeTime_ = now;
620 }
621
555 void SetStateInternal(JobState state) 622 void SetStateInternal(JobState state)
556 { 623 {
557 const boost::posix_time::ptime now = boost::posix_time::microsec_clock::universal_time();
558
559 if (state_ == JobState_Running)
560 {
561 runtime_ += (now - lastStateChangeTime_);
562 }
563
564 state_ = state; 624 state_ = state;
565 lastStateChangeTime_ = now;
566 pauseScheduled_ = false; 625 pauseScheduled_ = false;
626 Touch();
567 } 627 }
568 628
569 public: 629 public:
570 JobHandler(IJob* job, 630 JobHandler(IJob* job,
571 int priority) : 631 int priority) :
581 { 641 {
582 if (job == NULL) 642 if (job == NULL)
583 { 643 {
584 throw OrthancException(ErrorCode_NullPointer); 644 throw OrthancException(ErrorCode_NullPointer);
585 } 645 }
646
647 lastStatus_ = JobStatus(ErrorCode_Success, *job);
586 } 648 }
587 649
588 const std::string& GetId() const 650 const std::string& GetId() const
589 { 651 {
590 return id_; 652 return id_;
672 const boost::posix_time::ptime& GetCreationTime() const 734 const boost::posix_time::ptime& GetCreationTime() const
673 { 735 {
674 return creationTime_; 736 return creationTime_;
675 } 737 }
676 738
739 const boost::posix_time::ptime& GetLastStateChangeTime() const
740 {
741 return lastStateChangeTime_;
742 }
743
677 const boost::posix_time::time_duration& GetRuntime() const 744 const boost::posix_time::time_duration& GetRuntime() const
678 { 745 {
679 return runtime_; 746 return runtime_;
680 } 747 }
681 748
685 } 752 }
686 753
687 void SetLastStatus(const JobStatus& status) 754 void SetLastStatus(const JobStatus& status)
688 { 755 {
689 lastStatus_ = status; 756 lastStatus_ = status;
757 Touch();
690 } 758 }
691 }; 759 };
692 760
693 761
694 class JobsRegistry : public boost::noncopyable 762 class JobsRegistry : public boost::noncopyable
941 target[it->first] = JobInfo(handler.GetId(), 1009 target[it->first] = JobInfo(handler.GetId(),
942 handler.GetPriority(), 1010 handler.GetPriority(),
943 handler.GetState(), 1011 handler.GetState(),
944 handler.GetLastStatus(), 1012 handler.GetLastStatus(),
945 handler.GetCreationTime(), 1013 handler.GetCreationTime(),
1014 handler.GetLastStateChangeTime(),
946 handler.GetRuntime()); 1015 handler.GetRuntime());
947 } 1016 }
948 } 1017 }
949 1018
950 1019
2033 engine.GetRegistry().Submit(s, new DummyJob(), rand() % 10); 2102 engine.GetRegistry().Submit(s, new DummyJob(), rand() % 10);
2034 2103
2035 engine.SetWorkersCount(3); 2104 engine.SetWorkersCount(3);
2036 engine.Start(); 2105 engine.Start();
2037 2106
2038 boost::this_thread::sleep(boost::posix_time::milliseconds(200)); 2107 boost::this_thread::sleep(boost::posix_time::milliseconds(100));
2108
2109 {
2110 typedef std::map<std::string, JobInfo> Jobs;
2111
2112 Jobs jobs;
2113 engine.GetRegistry().GetJobsInfo(jobs);
2114
2115 Json::Value v;
2116 for (Jobs::const_iterator it = jobs.begin(); it != jobs.end(); ++it)
2117 {
2118 Json::Value vv;
2119 it->second.Format(vv);
2120 v[it->first] = vv;
2121 }
2122
2123 std::cout << v << std::endl;
2124 }
2125 std::cout << "====================================================" << std::endl;
2126
2127 boost::this_thread::sleep(boost::posix_time::milliseconds(100));
2039 2128
2040 engine.Stop(); 2129 engine.Stop();
2041 2130
2042 typedef std::map<std::string, JobInfo> Jobs; 2131
2043 2132 {
2044 Jobs jobs; 2133 typedef std::map<std::string, JobInfo> Jobs;
2045 engine.GetRegistry().GetJobsInfo(jobs); 2134
2046 2135 Jobs jobs;
2047 Json::Value v; 2136 engine.GetRegistry().GetJobsInfo(jobs);
2048 for (Jobs::const_iterator it = jobs.begin(); it != jobs.end(); ++it) 2137
2049 { 2138 Json::Value v;
2050 Json::Value vv; 2139 for (Jobs::const_iterator it = jobs.begin(); it != jobs.end(); ++it)
2051 it->second.Format(vv); 2140 {
2052 v[it->first] = vv; 2141 Json::Value vv;
2053 } 2142 it->second.Format(vv);
2054 2143 v[it->first] = vv;
2055 std::cout << v << std::endl; 2144 }
2145
2146 std::cout << v << std::endl;
2147 }
2056 } 2148 }