comparison Sources/Plugin.cpp @ 11:16b9f1ff491d

added configuration option "Preload"
author Sebastien Jodogne <s.jodogne@gmail.com>
date Sun, 18 Jun 2023 15:27:50 +0200
parents 5d5caf89eb5b
children 6115cfbece79
comparison
equal deleted inserted replaced
10:5d5caf89eb5b 11:16b9f1ff491d
40 40
41 41
42 static const std::string METADATA_OHIF = "4202"; 42 static const std::string METADATA_OHIF = "4202";
43 static const char* const KEY_VERSION = "Version"; 43 static const char* const KEY_VERSION = "Version";
44 static const unsigned int MAX_INSTANCES_IN_QUEUE = 10000; 44 static const unsigned int MAX_INSTANCES_IN_QUEUE = 10000;
45
46
47 enum DataSource
48 {
49 DataSource_DicomWeb,
50 DataSource_DicomJson
51 };
52
45 53
46 // Reference: https://v3-docs.ohif.org/configuration/dataSources/dicom-json 54 // Reference: https://v3-docs.ohif.org/configuration/dataSources/dicom-json
47 55
48 enum DataType 56 enum DataType
49 { 57 {
484 } 492 }
485 493
486 494
487 static ResourcesCache cache_; 495 static ResourcesCache cache_;
488 static std::string routerBasename_; 496 static std::string routerBasename_;
489 static bool useDicomWeb_; 497 static DataSource dataSource_;
498 static bool preload_;
490 static boost::thread metadataThread_; 499 static boost::thread metadataThread_;
491 static Orthanc::SharedMessageQueue pendingInstances_; 500 static Orthanc::SharedMessageQueue pendingInstances_;
492 static bool continueThread_; 501 static bool continueThread_;
493 502
494 void ServeFile(OrthancPluginRestOutput* output, 503 void ServeFile(OrthancPluginRestOutput* output,
515 Orthanc::EmbeddedResources::GetFileResource(system, Orthanc::EmbeddedResources::APP_CONFIG_SYSTEM); 524 Orthanc::EmbeddedResources::GetFileResource(system, Orthanc::EmbeddedResources::APP_CONFIG_SYSTEM);
516 Orthanc::EmbeddedResources::GetFileResource(user, Orthanc::EmbeddedResources::APP_CONFIG_USER); 525 Orthanc::EmbeddedResources::GetFileResource(user, Orthanc::EmbeddedResources::APP_CONFIG_USER);
517 526
518 std::map<std::string, std::string> dictionary; 527 std::map<std::string, std::string> dictionary;
519 dictionary["ROUTER_BASENAME"] = routerBasename_; 528 dictionary["ROUTER_BASENAME"] = routerBasename_;
520 dictionary["USE_DICOM_WEB"] = (useDicomWeb_ ? "true" : "false"); 529 dictionary["USE_DICOM_WEB"] = (dataSource_ == DataSource_DicomWeb ? "true" : "false");
521 530
522 system = Orthanc::Toolbox::SubstituteVariables(system, dictionary); 531 system = Orthanc::Toolbox::SubstituteVariables(system, dictionary);
523 532
524 std::string s = (user + "\n" + system); 533 std::string s = (user + "\n" + system);
525 OrthancPluginAnswerBuffer(context, output, s.c_str(), s.size(), "application/json"); 534 OrthancPluginAnswerBuffer(context, output, s.c_str(), s.size(), "application/json");
743 { 752 {
744 case OrthancPluginChangeType_OrthancStarted: 753 case OrthancPluginChangeType_OrthancStarted:
745 { 754 {
746 continueThread_ = true; 755 continueThread_ = true;
747 756
748 if (useDicomWeb_) 757 switch (dataSource_)
749 { 758 {
750 Json::Value info; 759 case DataSource_DicomWeb:
751 if (!OrthancPlugins::RestApiGet(info, "/plugins/dicom-web", false))
752 { 760 {
753 throw Orthanc::OrthancException( 761 Json::Value info;
754 Orthanc::ErrorCode_InternalError, 762 if (!OrthancPlugins::RestApiGet(info, "/plugins/dicom-web", false))
755 "The OHIF plugin requires the DICOMweb plugin to be installed"); 763 {
764 throw Orthanc::OrthancException(
765 Orthanc::ErrorCode_InternalError,
766 "The OHIF plugin requires the DICOMweb plugin to be installed");
767 }
768
769 if (info.type() != Json::objectValue ||
770 !info.isMember("ID") ||
771 !info.isMember("Version") ||
772 info["ID"].type() != Json::stringValue ||
773 info["Version"].type() != Json::stringValue ||
774 info["ID"].asString() != "dicom-web")
775 {
776 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError,
777 "The DICOMweb plugin is required by OHIF, but is not properly installed");
778 }
779
780 break;
756 } 781 }
757 782
758 if (info.type() != Json::objectValue || 783 case DataSource_DicomJson:
759 !info.isMember("ID") ||
760 !info.isMember("Version") ||
761 info["ID"].type() != Json::stringValue ||
762 info["Version"].type() != Json::stringValue ||
763 info["ID"].asString() != "dicom-web")
764 { 784 {
765 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError, 785 if (preload_)
766 "The DICOMweb plugin is required by OHIF, but is not properly installed"); 786 {
787 metadataThread_ = boost::thread(MetadataThread);
788 LOG(INFO) << "Started the OHIF preload thread";
789 }
790 else
791 {
792 LOG(INFO) << "The OHIF preload thread was not started, as indicated in the configuration file";
793 }
794 break;
767 } 795 }
796
797 default:
798 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
768 } 799 }
769 else 800
770 {
771 metadataThread_ = boost::thread(MetadataThread);
772 }
773 break; 801 break;
774 } 802 }
775 803
776 case OrthancPluginChangeType_OrthancStopped: 804 case OrthancPluginChangeType_OrthancStopped:
777 { 805 {
778 continueThread_ = false; 806 continueThread_ = false;
779 807
780 if (metadataThread_.joinable()) 808 if (metadataThread_.joinable())
781 { 809 {
810 LOG(INFO) << "Stopping the OHIF preload thread";
782 metadataThread_.join(); 811 metadataThread_.join();
783 } 812 }
784 break; 813 break;
785 } 814 }
786 815
787 case OrthancPluginChangeType_NewInstance: 816 case OrthancPluginChangeType_NewInstance:
788 { 817 {
789 if (metadataThread_.joinable() && 818 if (metadataThread_.joinable() &&
790 pendingInstances_.GetSize() < MAX_INSTANCES_IN_QUEUE) 819 pendingInstances_.GetSize() < MAX_INSTANCES_IN_QUEUE) /* avoid overwhelming Orthanc */
791 { 820 {
792 pendingInstances_.Enqueue(new Orthanc::SingleValueObject<std::string>(resourceId)); 821 pendingInstances_.Enqueue(new Orthanc::SingleValueObject<std::string>(resourceId));
793 } 822 }
794 823
795 break; 824 break;
832 Orthanc::Logging::InitializePluginContext(context); 861 Orthanc::Logging::InitializePluginContext(context);
833 #else 862 #else
834 Orthanc::Logging::Initialize(context); 863 Orthanc::Logging::Initialize(context);
835 #endif 864 #endif
836 865
837 InitializeOhifTags(); 866 try
838 867 {
839 OrthancPlugins::OrthancConfiguration configuration; 868 InitializeOhifTags();
840 869
841 { 870 OrthancPlugins::OrthancConfiguration configuration;
842 OrthancPlugins::OrthancConfiguration globalConfiguration; 871
843 globalConfiguration.GetSection(configuration, "OHIF"); 872 {
844 } 873 OrthancPlugins::OrthancConfiguration globalConfiguration;
845 874 globalConfiguration.GetSection(configuration, "OHIF");
846 routerBasename_ = configuration.GetStringValue("RouterBasename", "/ohif"); 875 }
847 useDicomWeb_ = configuration.GetBooleanValue("DicomWeb", false); 876
848 877 routerBasename_ = configuration.GetStringValue("RouterBasename", "/ohif");
849 // Make sure that the router basename ends with a trailing slash 878 std::string s = configuration.GetStringValue("DataSource", "dicom-json");
850 if (routerBasename_.empty() || 879 preload_ = configuration.GetBooleanValue("Preload", true);
851 routerBasename_[routerBasename_.size() - 1] != '/') 880
852 { 881 if (s == "dicom-web")
853 routerBasename_ += "/"; 882 {
854 } 883 dataSource_ = DataSource_DicomWeb;
855 884 }
856 OrthancPluginSetDescription(context, "OHIF plugin for Orthanc."); 885 else if (s == "dicom-json")
857 886 {
858 OrthancPlugins::RegisterRestCallback<ServeFile>("/ohif", true); 887 dataSource_ = DataSource_DicomJson;
859 OrthancPlugins::RegisterRestCallback<ServeFile>("/ohif/(.*)", true); 888 }
860 OrthancPlugins::RegisterRestCallback<GetOhifStudy>("/studies/([0-9a-f-]+)/ohif-dicom-json", true); 889 else
861 890 {
862 OrthancPluginRegisterOnChangeCallback(context, OnChangeCallback); 891 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange,
863 892 "Configuration option \"OHIF.DataSource\" must be either "
864 { 893 "\"dicomweb\" or \"dicom-json\", but found: " + s);
865 // Extend the default Orthanc Explorer with custom JavaScript for OHIF 894 }
866 std::string explorer; 895
867 Orthanc::EmbeddedResources::GetFileResource(explorer, Orthanc::EmbeddedResources::ORTHANC_EXPLORER); 896 // Make sure that the router basename ends with a trailing slash
868 897 if (routerBasename_.empty() ||
869 std::map<std::string, std::string> dictionary; 898 routerBasename_[routerBasename_.size() - 1] != '/')
870 dictionary["USE_DICOM_WEB"] = (useDicomWeb_ ? "true" : "false"); 899 {
871 explorer = Orthanc::Toolbox::SubstituteVariables(explorer, dictionary); 900 routerBasename_ += "/";
901 }
902
903 OrthancPluginSetDescription(context, "OHIF plugin for Orthanc.");
904
905 OrthancPlugins::RegisterRestCallback<ServeFile>("/ohif", true);
906 OrthancPlugins::RegisterRestCallback<ServeFile>("/ohif/(.*)", true);
907 OrthancPlugins::RegisterRestCallback<GetOhifStudy>("/studies/([0-9a-f-]+)/ohif-dicom-json", true);
908
909 OrthancPluginRegisterOnChangeCallback(context, OnChangeCallback);
910
911 {
912 // Extend the default Orthanc Explorer with custom JavaScript for OHIF
913 std::string explorer;
914 Orthanc::EmbeddedResources::GetFileResource(explorer, Orthanc::EmbeddedResources::ORTHANC_EXPLORER);
915
916 std::map<std::string, std::string> dictionary;
917 dictionary["USE_DICOM_WEB"] = (dataSource_ == DataSource_DicomWeb ? "true" : "false");
918 explorer = Orthanc::Toolbox::SubstituteVariables(explorer, dictionary);
872 919
873 OrthancPluginExtendOrthancExplorer(context, explorer.c_str()); 920 OrthancPluginExtendOrthancExplorer(context, explorer.c_str());
921 }
922 }
923 catch (Orthanc::OrthancException& e)
924 {
925 return -1;
874 } 926 }
875 927
876 return 0; 928 return 0;
877 } 929 }
878 930