Mercurial > hg > orthanc
comparison OrthancServer/Sources/ServerIndex.cpp @ 4580:49f6b9a2b9f5 db-changes
remove the only use of GlobalProperty_FlushSleep
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Tue, 09 Mar 2021 14:49:39 +0100 |
parents | 5ee9a4f8a0f0 |
children | bb3c82b8f373 |
comparison
equal
deleted
inserted
replaced
4579:5ee9a4f8a0f0 | 4580:49f6b9a2b9f5 |
---|---|
451 } | 451 } |
452 }; | 452 }; |
453 | 453 |
454 | 454 |
455 void ServerIndex::FlushThread(ServerIndex* that, | 455 void ServerIndex::FlushThread(ServerIndex* that, |
456 unsigned int threadSleep) | 456 unsigned int threadSleepGranularityMilliseconds) |
457 { | 457 { |
458 // By default, wait for 10 seconds before flushing | 458 // By default, wait for 10 seconds before flushing |
459 unsigned int sleep = 10; | 459 static const unsigned int SLEEP_SECONDS = 10; |
460 | 460 |
461 // TODO - REMOVE THIS | 461 if (threadSleepGranularityMilliseconds > 1000) |
462 try | 462 { |
463 { | 463 throw OrthancException(ErrorCode_ParameterOutOfRange); |
464 boost::mutex::scoped_lock lock(that->monitoringMutex_); | 464 } |
465 std::string sleepString; | 465 |
466 | 466 LOG(INFO) << "Starting the database flushing thread (sleep = " << SLEEP_SECONDS << " seconds)"; |
467 if (that->db_.LookupGlobalProperty(sleepString, GlobalProperty_FlushSleep) && | |
468 Toolbox::IsInteger(sleepString)) | |
469 { | |
470 sleep = boost::lexical_cast<unsigned int>(sleepString); | |
471 } | |
472 } | |
473 catch (boost::bad_lexical_cast&) | |
474 { | |
475 } | |
476 | |
477 LOG(INFO) << "Starting the database flushing thread (sleep = " << sleep << ")"; | |
478 | 467 |
479 unsigned int count = 0; | 468 unsigned int count = 0; |
469 unsigned int countThreshold = (1000 * SLEEP_SECONDS) / threadSleepGranularityMilliseconds; | |
480 | 470 |
481 while (!that->done_) | 471 while (!that->done_) |
482 { | 472 { |
483 boost::this_thread::sleep(boost::posix_time::milliseconds(threadSleep)); | 473 boost::this_thread::sleep(boost::posix_time::milliseconds(threadSleepGranularityMilliseconds)); |
484 count++; | 474 count++; |
485 if (count < sleep) | 475 |
486 { | 476 if (count >= countThreshold) |
487 continue; | 477 { |
488 } | 478 Logging::Flush(); |
489 | 479 |
490 Logging::Flush(); | 480 boost::mutex::scoped_lock lock(that->monitoringMutex_); |
491 | 481 |
492 boost::mutex::scoped_lock lock(that->monitoringMutex_); | 482 try |
493 | 483 { |
494 try | 484 that->db_.FlushToDisk(); |
495 { | 485 } |
496 that->db_.FlushToDisk(); | 486 catch (OrthancException&) |
497 } | 487 { |
498 catch (OrthancException&) | 488 LOG(ERROR) << "Cannot flush the SQLite database to the disk (is your filesystem full?)"; |
499 { | 489 } |
500 LOG(ERROR) << "Cannot flush the SQLite database to the disk (is your filesystem full?)"; | 490 |
501 } | 491 count = 0; |
502 | 492 } |
503 count = 0; | |
504 } | 493 } |
505 | 494 |
506 LOG(INFO) << "Stopping the database flushing thread"; | 495 LOG(INFO) << "Stopping the database flushing thread"; |
507 } | |
508 | |
509 | |
510 static bool ComputeExpectedNumberOfInstances(int64_t& target, | |
511 const DicomMap& dicomSummary) | |
512 { | |
513 try | |
514 { | |
515 const DicomValue* value; | |
516 const DicomValue* value2; | |
517 | |
518 if ((value = dicomSummary.TestAndGetValue(DICOM_TAG_IMAGES_IN_ACQUISITION)) != NULL && | |
519 !value->IsNull() && | |
520 !value->IsBinary() && | |
521 (value2 = dicomSummary.TestAndGetValue(DICOM_TAG_NUMBER_OF_TEMPORAL_POSITIONS)) != NULL && | |
522 !value2->IsNull() && | |
523 !value2->IsBinary()) | |
524 { | |
525 // Patch for series with temporal positions thanks to Will Ryder | |
526 int64_t imagesInAcquisition = boost::lexical_cast<int64_t>(value->GetContent()); | |
527 int64_t countTemporalPositions = boost::lexical_cast<int64_t>(value2->GetContent()); | |
528 target = imagesInAcquisition * countTemporalPositions; | |
529 return (target > 0); | |
530 } | |
531 | |
532 else if ((value = dicomSummary.TestAndGetValue(DICOM_TAG_NUMBER_OF_SLICES)) != NULL && | |
533 !value->IsNull() && | |
534 !value->IsBinary() && | |
535 (value2 = dicomSummary.TestAndGetValue(DICOM_TAG_NUMBER_OF_TIME_SLICES)) != NULL && | |
536 !value2->IsBinary() && | |
537 !value2->IsNull()) | |
538 { | |
539 // Support of Cardio-PET images | |
540 int64_t numberOfSlices = boost::lexical_cast<int64_t>(value->GetContent()); | |
541 int64_t numberOfTimeSlices = boost::lexical_cast<int64_t>(value2->GetContent()); | |
542 target = numberOfSlices * numberOfTimeSlices; | |
543 return (target > 0); | |
544 } | |
545 | |
546 else if ((value = dicomSummary.TestAndGetValue(DICOM_TAG_CARDIAC_NUMBER_OF_IMAGES)) != NULL && | |
547 !value->IsNull() && | |
548 !value->IsBinary()) | |
549 { | |
550 target = boost::lexical_cast<int64_t>(value->GetContent()); | |
551 return (target > 0); | |
552 } | |
553 } | |
554 catch (OrthancException&) | |
555 { | |
556 } | |
557 catch (boost::bad_lexical_cast&) | |
558 { | |
559 } | |
560 | |
561 return false; | |
562 } | |
563 | |
564 | |
565 | |
566 | |
567 static bool LookupStringMetadata(std::string& result, | |
568 const std::map<MetadataType, std::string>& metadata, | |
569 MetadataType type) | |
570 { | |
571 std::map<MetadataType, std::string>::const_iterator found = metadata.find(type); | |
572 | |
573 if (found == metadata.end()) | |
574 { | |
575 return false; | |
576 } | |
577 else | |
578 { | |
579 result = found->second; | |
580 return true; | |
581 } | |
582 } | |
583 | |
584 | |
585 static bool LookupIntegerMetadata(int64_t& result, | |
586 const std::map<MetadataType, std::string>& metadata, | |
587 MetadataType type) | |
588 { | |
589 std::string s; | |
590 if (!LookupStringMetadata(s, metadata, type)) | |
591 { | |
592 return false; | |
593 } | |
594 | |
595 try | |
596 { | |
597 result = boost::lexical_cast<int64_t>(s); | |
598 return true; | |
599 } | |
600 catch (boost::bad_lexical_cast&) | |
601 { | |
602 return false; | |
603 } | |
604 } | 496 } |
605 | 497 |
606 | 498 |
607 void ServerIndex::LogChange(int64_t internalId, | 499 void ServerIndex::LogChange(int64_t internalId, |
608 ChangeType changeType, | 500 ChangeType changeType, |
627 } | 519 } |
628 | 520 |
629 | 521 |
630 ServerIndex::ServerIndex(ServerContext& context, | 522 ServerIndex::ServerIndex(ServerContext& context, |
631 IDatabaseWrapper& db, | 523 IDatabaseWrapper& db, |
632 unsigned int threadSleep) : | 524 unsigned int threadSleepGranularityMilliseconds) : |
633 done_(false), | 525 done_(false), |
634 db_(db), | 526 db_(db), |
635 maximumStorageSize_(0), | 527 maximumStorageSize_(0), |
636 maximumPatients_(0), | 528 maximumPatients_(0), |
637 mainDicomTagsRegistry_(new MainDicomTagsRegistry), | 529 mainDicomTagsRegistry_(new MainDicomTagsRegistry), |
644 // execution of Orthanc | 536 // execution of Orthanc |
645 StandaloneRecycling(maximumStorageSize_, maximumPatients_); | 537 StandaloneRecycling(maximumStorageSize_, maximumPatients_); |
646 | 538 |
647 if (db.HasFlushToDisk()) | 539 if (db.HasFlushToDisk()) |
648 { | 540 { |
649 flushThread_ = boost::thread(FlushThread, this, threadSleep); | 541 flushThread_ = boost::thread(FlushThread, this, threadSleepGranularityMilliseconds); |
650 } | 542 } |
651 | 543 |
652 unstableResourcesMonitorThread_ = boost::thread | 544 unstableResourcesMonitorThread_ = boost::thread |
653 (UnstableResourcesMonitorThread, this, threadSleep); | 545 (UnstableResourcesMonitorThread, this, threadSleepGranularityMilliseconds); |
654 } | 546 } |
655 | 547 |
656 | 548 |
657 | 549 |
658 ServerIndex::~ServerIndex() | 550 ServerIndex::~ServerIndex() |
839 StandaloneRecycling(maximumStorageSize_, maximumPatients_); | 731 StandaloneRecycling(maximumStorageSize_, maximumPatients_); |
840 } | 732 } |
841 | 733 |
842 | 734 |
843 void ServerIndex::UnstableResourcesMonitorThread(ServerIndex* that, | 735 void ServerIndex::UnstableResourcesMonitorThread(ServerIndex* that, |
844 unsigned int threadSleep) | 736 unsigned int threadSleepGranularityMilliseconds) |
845 { | 737 { |
846 int stableAge; | 738 int stableAge; |
847 | 739 |
848 { | 740 { |
849 OrthancConfiguration::ReaderLock lock; | 741 OrthancConfiguration::ReaderLock lock; |
858 LOG(INFO) << "Starting the monitor for stable resources (stable age = " << stableAge << ")"; | 750 LOG(INFO) << "Starting the monitor for stable resources (stable age = " << stableAge << ")"; |
859 | 751 |
860 while (!that->done_) | 752 while (!that->done_) |
861 { | 753 { |
862 // Check for stable resources each few seconds | 754 // Check for stable resources each few seconds |
863 boost::this_thread::sleep(boost::posix_time::milliseconds(threadSleep)); | 755 boost::this_thread::sleep(boost::posix_time::milliseconds(threadSleepGranularityMilliseconds)); |
864 | 756 |
865 boost::mutex::scoped_lock lock(that->monitoringMutex_); | 757 boost::mutex::scoped_lock lock(that->monitoringMutex_); |
866 | 758 |
867 while (!that->unstableResources_.IsEmpty() && | 759 while (!that->unstableResources_.IsEmpty() && |
868 that->unstableResources_.GetOldestPayload().GetAge() > static_cast<unsigned int>(stableAge)) | 760 that->unstableResources_.GetOldestPayload().GetAge() > static_cast<unsigned int>(stableAge)) |
1260 { | 1152 { |
1261 class Operations : public ReadOnlyOperationsT4<bool&, Json::Value&, const std::string&, ResourceType> | 1153 class Operations : public ReadOnlyOperationsT4<bool&, Json::Value&, const std::string&, ResourceType> |
1262 { | 1154 { |
1263 private: | 1155 private: |
1264 ServerIndex& index_; // TODO - REMOVE | 1156 ServerIndex& index_; // TODO - REMOVE |
1157 | |
1158 static bool LookupStringMetadata(std::string& result, | |
1159 const std::map<MetadataType, std::string>& metadata, | |
1160 MetadataType type) | |
1161 { | |
1162 std::map<MetadataType, std::string>::const_iterator found = metadata.find(type); | |
1163 | |
1164 if (found == metadata.end()) | |
1165 { | |
1166 return false; | |
1167 } | |
1168 else | |
1169 { | |
1170 result = found->second; | |
1171 return true; | |
1172 } | |
1173 } | |
1174 | |
1175 | |
1176 static bool LookupIntegerMetadata(int64_t& result, | |
1177 const std::map<MetadataType, std::string>& metadata, | |
1178 MetadataType type) | |
1179 { | |
1180 std::string s; | |
1181 if (!LookupStringMetadata(s, metadata, type)) | |
1182 { | |
1183 return false; | |
1184 } | |
1185 | |
1186 try | |
1187 { | |
1188 result = boost::lexical_cast<int64_t>(s); | |
1189 return true; | |
1190 } | |
1191 catch (boost::bad_lexical_cast&) | |
1192 { | |
1193 return false; | |
1194 } | |
1195 } | |
1196 | |
1265 | 1197 |
1266 public: | 1198 public: |
1267 explicit Operations(ServerIndex& index) : | 1199 explicit Operations(ServerIndex& index) : |
1268 index_(index) | 1200 index_(index) |
1269 { | 1201 { |
3215 std::string hashPatient_; | 3147 std::string hashPatient_; |
3216 std::string hashStudy_; | 3148 std::string hashStudy_; |
3217 std::string hashSeries_; | 3149 std::string hashSeries_; |
3218 std::string hashInstance_; | 3150 std::string hashInstance_; |
3219 | 3151 |
3152 static bool ComputeExpectedNumberOfInstances(int64_t& target, | |
3153 const DicomMap& dicomSummary) | |
3154 { | |
3155 try | |
3156 { | |
3157 const DicomValue* value; | |
3158 const DicomValue* value2; | |
3159 | |
3160 if ((value = dicomSummary.TestAndGetValue(DICOM_TAG_IMAGES_IN_ACQUISITION)) != NULL && | |
3161 !value->IsNull() && | |
3162 !value->IsBinary() && | |
3163 (value2 = dicomSummary.TestAndGetValue(DICOM_TAG_NUMBER_OF_TEMPORAL_POSITIONS)) != NULL && | |
3164 !value2->IsNull() && | |
3165 !value2->IsBinary()) | |
3166 { | |
3167 // Patch for series with temporal positions thanks to Will Ryder | |
3168 int64_t imagesInAcquisition = boost::lexical_cast<int64_t>(value->GetContent()); | |
3169 int64_t countTemporalPositions = boost::lexical_cast<int64_t>(value2->GetContent()); | |
3170 target = imagesInAcquisition * countTemporalPositions; | |
3171 return (target > 0); | |
3172 } | |
3173 | |
3174 else if ((value = dicomSummary.TestAndGetValue(DICOM_TAG_NUMBER_OF_SLICES)) != NULL && | |
3175 !value->IsNull() && | |
3176 !value->IsBinary() && | |
3177 (value2 = dicomSummary.TestAndGetValue(DICOM_TAG_NUMBER_OF_TIME_SLICES)) != NULL && | |
3178 !value2->IsBinary() && | |
3179 !value2->IsNull()) | |
3180 { | |
3181 // Support of Cardio-PET images | |
3182 int64_t numberOfSlices = boost::lexical_cast<int64_t>(value->GetContent()); | |
3183 int64_t numberOfTimeSlices = boost::lexical_cast<int64_t>(value2->GetContent()); | |
3184 target = numberOfSlices * numberOfTimeSlices; | |
3185 return (target > 0); | |
3186 } | |
3187 | |
3188 else if ((value = dicomSummary.TestAndGetValue(DICOM_TAG_CARDIAC_NUMBER_OF_IMAGES)) != NULL && | |
3189 !value->IsNull() && | |
3190 !value->IsBinary()) | |
3191 { | |
3192 target = boost::lexical_cast<int64_t>(value->GetContent()); | |
3193 return (target > 0); | |
3194 } | |
3195 } | |
3196 catch (OrthancException&) | |
3197 { | |
3198 } | |
3199 catch (boost::bad_lexical_cast&) | |
3200 { | |
3201 } | |
3202 | |
3203 return false; | |
3204 } | |
3205 | |
3220 public: | 3206 public: |
3221 Operations(std::map<MetadataType, std::string>& instanceMetadata, | 3207 Operations(std::map<MetadataType, std::string>& instanceMetadata, |
3222 ServerIndex& index, | 3208 ServerIndex& index, |
3223 const DicomMap& dicomSummary, | 3209 const DicomMap& dicomSummary, |
3224 const Attachments& attachments, | 3210 const Attachments& attachments, |