changeset 6265:ac34dce1af7d

allow DicomServer to start without a MetricsRegistry
author Sebastien Jodogne <s.jodogne@gmail.com>
date Mon, 11 Aug 2025 10:22:19 +0200
parents de176f458e35
children 339c4ba0a3a3
files OrthancFramework/Sources/DicomNetworking/DicomServer.cpp OrthancFramework/Sources/DicomNetworking/DicomServer.h OrthancFramework/Sources/MultiThreading/RunnableWorkersPool.cpp OrthancFramework/Sources/MultiThreading/RunnableWorkersPool.h OrthancServer/Plugins/Samples/MultitenantDicom/MultitenantDicomServer.cpp OrthancServer/Sources/main.cpp
diffstat 6 files changed, 85 insertions(+), 42 deletions(-) [+]
line wrap: on
line diff
--- a/OrthancFramework/Sources/DicomNetworking/DicomServer.cpp	Mon Aug 11 09:11:53 2025 +0200
+++ b/OrthancFramework/Sources/DicomNetworking/DicomServer.cpp	Mon Aug 11 10:22:19 2025 +0200
@@ -89,7 +89,7 @@
   }
 
 
-  DicomServer::DicomServer(MetricsRegistry& metricsRegistry) : 
+  DicomServer::DicomServer() :
     pimpl_(new PImpl),
     checkCalledAet_(true),
     aet_("ANY-SCP"),
@@ -105,11 +105,11 @@
     worklistRequestHandlerFactory_(NULL),
     storageCommitmentFactory_(NULL),
     applicationEntityFilter_(NULL),
-    metricsRegistry_(metricsRegistry),
     useDicomTls_(false),
     maximumPduLength_(ASC_DEFAULTMAXPDU),
     remoteCertificateRequired_(true),
-    minimumTlsVersion_(0)
+    minimumTlsVersion_(0),
+    metricsRegistry_(NULL)
   {
   }
 
@@ -433,7 +433,15 @@
 
     CLOG(INFO, DICOM) << "The embedded DICOM server will use " << threadsCount_ << " threads";
 
-    pimpl_->workers_.reset(new RunnableWorkersPool(threadsCount_, "DICOM-", metricsRegistry_, "orthanc_available_dicom_threads"));
+    if (metricsRegistry_ == NULL)
+    {
+      pimpl_->workers_.reset(new RunnableWorkersPool(threadsCount_, "DICOM-"));
+    }
+    else
+    {
+      pimpl_->workers_.reset(new RunnableWorkersPool(threadsCount_, "DICOM-", *metricsRegistry_, "orthanc_available_dicom_threads"));
+    }
+
     pimpl_->thread_ = boost::thread(ServerThread, this, maximumPduLength_, useDicomTls_);
   }
 
@@ -621,4 +629,9 @@
     threadsCount_ = threads;
   }
 
+  void DicomServer::SetMetricsRegistry(MetricsRegistry& registry)
+  {
+    Stop();
+    metricsRegistry_ = &registry;
+  }
 }
--- a/OrthancFramework/Sources/DicomNetworking/DicomServer.h	Mon Aug 11 09:11:53 2025 +0200
+++ b/OrthancFramework/Sources/DicomNetworking/DicomServer.h	Mon Aug 11 10:22:19 2025 +0200
@@ -85,7 +85,6 @@
     IWorklistRequestHandlerFactory* worklistRequestHandlerFactory_;
     IStorageCommitmentRequestHandlerFactory* storageCommitmentFactory_;
     IApplicationEntityFilter* applicationEntityFilter_;
-    MetricsRegistry& metricsRegistry_;
 
     // New in Orthanc 1.9.0 for DICOM TLS
     bool         useDicomTls_;
@@ -96,14 +95,14 @@
     bool         remoteCertificateRequired_;  // New in 1.9.3
     unsigned int minimumTlsVersion_;          // New in 1.12.4
     std::set<std::string> acceptedCiphers_;   // New in 1.12.4
-
+    MetricsRegistry* metricsRegistry_;        // New in 1.12.9
 
     static void ServerThread(DicomServer* server,
                              unsigned int maximumPduLength,
                              bool useDicomTls);
 
   public:
-    explicit DicomServer(MetricsRegistry& metricsRegistry);
+    DicomServer();
 
     ~DicomServer();
 
@@ -178,5 +177,6 @@
 
     void SetThreadsCount(unsigned int threadsCount);
 
+    void SetMetricsRegistry(MetricsRegistry& registry);
   };
 }
--- a/OrthancFramework/Sources/MultiThreading/RunnableWorkersPool.cpp	Mon Aug 11 09:11:53 2025 +0200
+++ b/OrthancFramework/Sources/MultiThreading/RunnableWorkersPool.cpp	Mon Aug 11 10:22:19 2025 +0200
@@ -29,25 +29,24 @@
 #include "../Compatibility.h"
 #include "../OrthancException.h"
 #include "../Logging.h"
-#include "../MetricsRegistry.h"
 
 
 namespace Orthanc
 {
   struct RunnableWorkersPool::PImpl
   {
-    class Worker
+    class Worker : public boost::noncopyable
     {
     private:
       const bool&           continue_;
       SharedMessageQueue&   queue_;
       boost::thread         thread_;
-      std::string           name_;
-      MetricsRegistry::SharedMetrics& availableWorkers_;
+      std::string           threadName_;
+      MetricsRegistry::SharedMetrics* availableWorkers_;
  
       static void WorkerThread(Worker* that)
       {
-        Logging::SetCurrentThreadName(that->name_);
+        Logging::SetCurrentThreadName(that->threadName_);
 
         while (that->continue_)
         {
@@ -57,7 +56,11 @@
             
             if (obj.get() != NULL)
             {
-              MetricsRegistry::AvailableResourcesDecounter counter(that->availableWorkers_);
+              std::unique_ptr<MetricsRegistry::AvailableResourcesDecounter> counter;
+              if (that->availableWorkers_ != NULL)
+              {
+                counter.reset(new MetricsRegistry::AvailableResourcesDecounter(*that->availableWorkers_));
+              }
 
               IRunnableBySteps& runnable = *dynamic_cast<IRunnableBySteps*>(obj.get());
               
@@ -92,11 +95,11 @@
     public:
       Worker(const bool& globalContinue,
              SharedMessageQueue& queue,
-             const std::string& name,
-             MetricsRegistry::SharedMetrics& availableWorkers) : 
+             const std::string& threadName,
+             MetricsRegistry::SharedMetrics* availableWorkers) :
         continue_(globalContinue),
         queue_(queue),
-        name_(name),
+        threadName_(threadName),
         availableWorkers_(availableWorkers)
       {
         thread_ = boost::thread(WorkerThread, this);
@@ -111,28 +114,32 @@
       }
     };
 
-
     bool                  continue_;
     std::vector<Worker*>  workers_;
     SharedMessageQueue    queue_;
-    MetricsRegistry::SharedMetrics  availableWorkers_;
+    std::unique_ptr<MetricsRegistry::SharedMetrics>  availableWorkers_;
 
   public:
-    PImpl(MetricsRegistry& metricsRegistry, const char* availableWorkersMetricsName) :
+    PImpl(MetricsRegistry::SharedMetrics* availableWorkers /* takes ownership */) :
       continue_(false),
-      availableWorkers_(metricsRegistry, availableWorkersMetricsName, MetricsUpdatePolicy_MinOver10Seconds)
+      availableWorkers_(availableWorkers)
     {
     }
   };
 
 
+  void RunnableWorkersPool::Start(size_t countWorkers,
+                                  const std::string& baseThreadName,
+                                  MetricsRegistry::SharedMetrics* availableWorkers)
+  {
+    std::unique_ptr<MetricsRegistry::SharedMetrics> protection(availableWorkers);
 
-  RunnableWorkersPool::RunnableWorkersPool(size_t countWorkers, 
-                                           const std::string& name, 
-                                           MetricsRegistry& metricsRegistry, 
-                                           const char* availableWorkersMetricsName) : 
-    pimpl_(new PImpl(metricsRegistry, availableWorkersMetricsName))
-  {
+    if (pimpl_.get() != NULL)
+    {
+      throw OrthancException(ErrorCode_BadSequenceOfCalls);
+    }
+
+    pimpl_.reset(new PImpl(protection.release()));
     pimpl_->continue_ = true;
 
     if (countWorkers == 0)
@@ -141,17 +148,37 @@
     }
 
     pimpl_->workers_.resize(countWorkers);
-    pimpl_->availableWorkers_.Add(countWorkers); // mark all workers as available
 
     for (size_t i = 0; i < countWorkers; i++)
     {
-      std::string workerName = name + boost::lexical_cast<std::string>(i);
-      pimpl_->workers_[i] = new PImpl::Worker(pimpl_->continue_, pimpl_->queue_, workerName, pimpl_->availableWorkers_);
+      std::string workerName = baseThreadName + boost::lexical_cast<std::string>(i);
+      pimpl_->workers_[i] = new PImpl::Worker(pimpl_->continue_, pimpl_->queue_, workerName, pimpl_->availableWorkers_.get());
     }
   }
 
 
-  void RunnableWorkersPool::Stop()
+  RunnableWorkersPool::RunnableWorkersPool(size_t countWorkers,
+                                           const std::string& baseThreadName)
+  {
+    Start(countWorkers, baseThreadName, NULL);
+  }
+
+
+  RunnableWorkersPool::RunnableWorkersPool(size_t countWorkers,
+                                           const std::string& baseThreadName,
+                                           MetricsRegistry& registry,
+                                           const char* availableWorkersMetricsName)
+  {
+    std::unique_ptr<MetricsRegistry::SharedMetrics> availableWorkers(
+      new MetricsRegistry::SharedMetrics(registry, availableWorkersMetricsName, MetricsUpdatePolicy_MinOver10Seconds));
+
+    availableWorkers->Add(countWorkers); // mark all workers as available
+
+    Start(countWorkers, baseThreadName, availableWorkers.release());
+  }
+
+
+  RunnableWorkersPool::~RunnableWorkersPool()
   {
     if (pimpl_->continue_)
     {
@@ -171,12 +198,6 @@
   }
 
 
-  RunnableWorkersPool::~RunnableWorkersPool()
-  {
-    Stop();
-  }
-
-
   void RunnableWorkersPool::Add(IRunnableBySteps* runnable)
   {
     if (!pimpl_->continue_)
--- a/OrthancFramework/Sources/MultiThreading/RunnableWorkersPool.h	Mon Aug 11 09:11:53 2025 +0200
+++ b/OrthancFramework/Sources/MultiThreading/RunnableWorkersPool.h	Mon Aug 11 10:22:19 2025 +0200
@@ -26,22 +26,30 @@
 
 #include "IRunnableBySteps.h"
 
+#include "../MetricsRegistry.h"
+
 #include <boost/shared_ptr.hpp>
 
 namespace Orthanc
 {
-  class MetricsRegistry;
-
   class RunnableWorkersPool : public boost::noncopyable
   {
   private:
     struct PImpl;
     boost::shared_ptr<PImpl> pimpl_;
 
-    void Stop();
+    void Start(size_t countWorkers,
+               const std::string& baseThreadName,
+               MetricsRegistry::SharedMetrics* availableWorkers /* can be NULL */);
 
   public:
-    explicit RunnableWorkersPool(size_t countWorkers, const std::string& name, MetricsRegistry& metricsRegistry, const char* availableWorkersMetricsName);
+    RunnableWorkersPool(size_t countWorkers,
+                        const std::string& baseThreadName);
+
+    RunnableWorkersPool(size_t countWorkers,
+                        const std::string& name,
+                        MetricsRegistry& registry,
+                        const char* availableWorkersMetricsName);
 
     ~RunnableWorkersPool();
 
--- a/OrthancServer/Plugins/Samples/MultitenantDicom/MultitenantDicomServer.cpp	Mon Aug 11 09:11:53 2025 +0200
+++ b/OrthancServer/Plugins/Samples/MultitenantDicom/MultitenantDicomServer.cpp	Mon Aug 11 10:22:19 2025 +0200
@@ -93,7 +93,7 @@
     labelsStoreLevels_.insert(Orthanc::ResourceType_Instance);
   }
   
-  server_.reset(new Orthanc::DicomServer(dummyMetricsRegistry_));
+  server_.reset(new Orthanc::DicomServer);
 
   {
     OrthancPlugins::OrthancConfiguration globalConfig;
--- a/OrthancServer/Sources/main.cpp	Mon Aug 11 09:11:53 2025 +0200
+++ b/OrthancServer/Sources/main.cpp	Mon Aug 11 10:22:19 2025 +0200
@@ -1298,7 +1298,8 @@
     ModalitiesFromConfiguration modalities;
   
     // Setup the DICOM server  
-    DicomServer dicomServer(context.GetMetricsRegistry());
+    DicomServer dicomServer;
+    dicomServer.SetMetricsRegistry(context.GetMetricsRegistry());
     dicomServer.SetRemoteModalities(modalities);
     dicomServer.SetStoreRequestHandlerFactory(serverFactory);
     dicomServer.SetMoveRequestHandlerFactory(serverFactory);