changeset 1103:bec1eccf976c

Hot restart of Orthanc
author Sebastien Jodogne <s.jodogne@gmail.com>
date Thu, 07 Aug 2014 11:33:46 +0200
parents ce6386b37afd
children 354dfbd1898b b53e058c2b08
files Core/EnumerationDictionary.h Core/Toolbox.cpp Core/Toolbox.h NEWS OrthancServer/OrthancRestApi/OrthancRestApi.cpp OrthancServer/OrthancRestApi/OrthancRestApi.h OrthancServer/ServerEnumerations.cpp OrthancServer/main.cpp
diffstat 8 files changed, 177 insertions(+), 121 deletions(-) [+]
line wrap: on
line diff
--- a/Core/EnumerationDictionary.h	Thu Aug 07 10:51:35 2014 +0200
+++ b/Core/EnumerationDictionary.h	Thu Aug 07 11:33:46 2014 +0200
@@ -54,6 +54,12 @@
       StringToEnumeration stringToEnumeration_;
 
     public:
+      void Clear()
+      {
+        enumerationToString_.clear();
+        stringToEnumeration_.clear();
+      }
+
       void Add(Enumeration value, const std::string& str)
       {
         // Check if these values are free
--- a/Core/Toolbox.cpp	Thu Aug 07 10:51:35 2014 +0200
+++ b/Core/Toolbox.cpp	Thu Aug 07 11:33:46 2014 +0200
@@ -124,7 +124,7 @@
   }
 
 
-  static void ServerBarrierInternal(bool* stopFlag)
+  static void ServerBarrierInternal(const bool* stopFlag)
   {
 #if defined(_WIN32)
     SetConsoleCtrlHandler(ConsoleControlHandler, true);
@@ -151,14 +151,14 @@
   }
 
 
-  void Toolbox::ServerBarrier(bool& stopFlag)
+  void Toolbox::ServerBarrier(const bool& stopFlag)
   {
     ServerBarrierInternal(&stopFlag);
   }
 
   void Toolbox::ServerBarrier()
   {
-    bool stopFlag = false;
+    const bool stopFlag = false;
     ServerBarrierInternal(&stopFlag);
   }
 
--- a/Core/Toolbox.h	Thu Aug 07 10:51:35 2014 +0200
+++ b/Core/Toolbox.h	Thu Aug 07 11:33:46 2014 +0200
@@ -49,7 +49,7 @@
 
   namespace Toolbox
   {
-    void ServerBarrier(bool& stopFlag);
+    void ServerBarrier(const bool& stopFlag);
 
     void ServerBarrier();
 
--- a/NEWS	Thu Aug 07 10:51:35 2014 +0200
+++ b/NEWS	Thu Aug 07 11:33:46 2014 +0200
@@ -1,8 +1,9 @@
 Pending changes in the mainline
 ===============================
 
+* Support of the standard text encodings
+* Hot restart of Orthanc by posting to "/tools/reset"
 * More fault-tolerant commands in Lua scripts
-* Support of the standard text encodings
 * Parameter to set the default encoding for DICOM files without SpecificCharacterSet
 * Fix of issue #14 (support of XCode 5.1)
 * Upgrade to Google Test 1.7.0
--- a/OrthancServer/OrthancRestApi/OrthancRestApi.cpp	Thu Aug 07 10:51:35 2014 +0200
+++ b/OrthancServer/OrthancRestApi/OrthancRestApi.cpp	Thu Aug 07 11:33:46 2014 +0200
@@ -56,6 +56,15 @@
   }
 
 
+  void OrthancRestApi::ResetOrthanc(RestApiPostCall& call)
+  {
+    OrthancRestApi::GetApi(call).resetRequestReceived_ = true;
+    call.GetOutput().AnswerBuffer("{}", "application/json");
+  }
+
+
+
+
 
   // Upload of DICOM files through HTTP ---------------------------------------
 
@@ -85,7 +94,8 @@
   // Registration of the various REST handlers --------------------------------
 
   OrthancRestApi::OrthancRestApi(ServerContext& context) : 
-    context_(context)
+    context_(context),
+    resetRequestReceived_(false)
   {
     RegisterSystem();
 
@@ -99,6 +109,7 @@
 
     // Auto-generated directories
     Register("/tools", RestApi::AutoListChildren);
+    Register("/tools/reset", ResetOrthanc);
     Register("/instances/{id}/frames/{frame}", RestApi::AutoListChildren);
   }
 }
--- a/OrthancServer/OrthancRestApi/OrthancRestApi.h	Thu Aug 07 10:51:35 2014 +0200
+++ b/OrthancServer/OrthancRestApi/OrthancRestApi.h	Thu Aug 07 11:33:46 2014 +0200
@@ -47,6 +47,7 @@
 
   private:
     ServerContext& context_;
+    bool resetRequestReceived_;
 
     void RegisterSystem();
 
@@ -60,9 +61,16 @@
 
     void RegisterArchive();
 
+    static void ResetOrthanc(RestApiPostCall& call);
+
   public:
     OrthancRestApi(ServerContext& context);
 
+    const bool& ResetRequestReceivedFlag() const
+    {
+      return resetRequestReceived_;
+    }
+
     static OrthancRestApi& GetApi(RestApiCall& call)
     {
       return dynamic_cast<OrthancRestApi&>(call.GetContext());
--- a/OrthancServer/ServerEnumerations.cpp	Thu Aug 07 10:51:35 2014 +0200
+++ b/OrthancServer/ServerEnumerations.cpp	Thu Aug 07 11:33:46 2014 +0200
@@ -48,6 +48,9 @@
   void InitializeServerEnumerations()
   {
     boost::mutex::scoped_lock lock(enumerationsMutex_);
+
+    dictMetadataType_.Clear();
+    dictContentType_.Clear();
     
     dictMetadataType_.Add(MetadataType_Instance_IndexInSeries, "IndexInSeries");
     dictMetadataType_.Add(MetadataType_Instance_ReceptionDate, "ReceptionDate");
--- a/OrthancServer/main.cpp	Thu Aug 07 10:51:35 2014 +0200
+++ b/OrthancServer/main.cpp	Thu Aug 07 11:33:46 2014 +0200
@@ -314,6 +314,140 @@
 
 
 
+static bool StartOrthanc()
+{
+  std::string storageDirectoryStr = Configuration::GetGlobalStringParameter("StorageDirectory", "OrthancStorage");
+  boost::filesystem::path storageDirectory = Configuration::InterpretStringParameterAsPath(storageDirectoryStr);
+  boost::filesystem::path indexDirectory = Configuration::InterpretStringParameterAsPath(
+    Configuration::GetGlobalStringParameter("IndexDirectory", storageDirectoryStr));
+  ServerContext context(storageDirectory, indexDirectory);
+
+  LOG(WARNING) << "Storage directory: " << storageDirectory;
+  LOG(WARNING) << "Index directory: " << indexDirectory;
+
+  context.SetCompressionEnabled(Configuration::GetGlobalBoolParameter("StorageCompression", false));
+  context.SetStoreMD5ForAttachments(Configuration::GetGlobalBoolParameter("StoreMD5ForAttachments", true));
+
+  LoadLuaScripts(context);
+
+  try
+  {
+    context.GetIndex().SetMaximumPatientCount(Configuration::GetGlobalIntegerParameter("MaximumPatientCount", 0));
+  }
+  catch (...)
+  {
+    context.GetIndex().SetMaximumPatientCount(0);
+  }
+
+  try
+  {
+    uint64_t size = Configuration::GetGlobalIntegerParameter("MaximumStorageSize", 0);
+    context.GetIndex().SetMaximumStorageSize(size * 1024 * 1024);
+  }
+  catch (...)
+  {
+    context.GetIndex().SetMaximumStorageSize(0);
+  }
+
+  MyDicomServerFactory serverFactory(context);
+  bool isReset = false;
+    
+  {
+    // DICOM server
+    DicomServer dicomServer;
+    OrthancApplicationEntityFilter dicomFilter;
+    dicomServer.SetCalledApplicationEntityTitleCheck(Configuration::GetGlobalBoolParameter("DicomCheckCalledAet", false));
+    dicomServer.SetStoreRequestHandlerFactory(serverFactory);
+    dicomServer.SetMoveRequestHandlerFactory(serverFactory);
+    dicomServer.SetFindRequestHandlerFactory(serverFactory);
+    dicomServer.SetPortNumber(Configuration::GetGlobalIntegerParameter("DicomPort", 4242));
+    dicomServer.SetApplicationEntityTitle(Configuration::GetGlobalStringParameter("DicomAet", "ORTHANC"));
+    dicomServer.SetApplicationEntityFilter(dicomFilter);
+
+    // HTTP server
+    MyIncomingHttpRequestFilter httpFilter(context);
+    MongooseServer httpServer;
+    httpServer.SetPortNumber(Configuration::GetGlobalIntegerParameter("HttpPort", 8042));
+    httpServer.SetRemoteAccessAllowed(Configuration::GetGlobalBoolParameter("RemoteAccessAllowed", false));
+    httpServer.SetIncomingHttpRequestFilter(httpFilter);
+
+    httpServer.SetAuthenticationEnabled(Configuration::GetGlobalBoolParameter("AuthenticationEnabled", false));
+    Configuration::SetupRegisteredUsers(httpServer);
+
+    if (Configuration::GetGlobalBoolParameter("SslEnabled", false))
+    {
+      std::string certificate = Configuration::InterpretStringParameterAsPath(
+        Configuration::GetGlobalStringParameter("SslCertificate", "certificate.pem"));
+      httpServer.SetSslEnabled(true);
+      httpServer.SetSslCertificate(certificate.c_str());
+    }
+    else
+    {
+      httpServer.SetSslEnabled(false);
+    }
+
+    OrthancRestApi restApi(context);
+
+#if ORTHANC_STANDALONE == 1
+    EmbeddedResourceHttpHandler staticResources("/app", EmbeddedResources::ORTHANC_EXPLORER);
+#else
+    FilesystemHttpHandler staticResources("/app", ORTHANC_PATH "/OrthancExplorer");
+#endif
+
+    PluginsHttpHandler httpPlugins(context);
+    httpPlugins.SetOrthancRestApi(restApi);
+
+    PluginsManager pluginsManager;
+    pluginsManager.RegisterServiceProvider(httpPlugins);
+    LoadPlugins(pluginsManager);
+
+    httpServer.RegisterHandler(httpPlugins);
+    httpServer.RegisterHandler(staticResources);
+    httpServer.RegisterHandler(restApi);
+    httpPlugins.SetOrthancRestApi(restApi);
+    context.SetPluginsHttpHandler(httpPlugins);
+
+    // GO !!! Start the requested servers
+    if (Configuration::GetGlobalBoolParameter("HttpServerEnabled", true))
+    {
+      httpServer.Start();
+      LOG(WARNING) << "HTTP server listening on port: " << httpServer.GetPortNumber();
+    }
+    else
+    {
+      LOG(WARNING) << "The HTTP server is disabled";
+    }
+
+    if (Configuration::GetGlobalBoolParameter("DicomServerEnabled", true))
+    {
+      dicomServer.Start();
+      LOG(WARNING) << "DICOM server listening on port: " << dicomServer.GetPortNumber();
+    }
+    else
+    {
+      LOG(WARNING) << "The DICOM server is disabled";
+    }
+
+    LOG(WARNING) << "Orthanc has started";
+    Toolbox::ServerBarrier(restApi.ResetRequestReceivedFlag());
+    isReset = restApi.ResetRequestReceivedFlag();
+
+    if (isReset)
+    {
+      LOG(WARNING) << "Reset request received, restarting Orthanc";
+    }
+
+    // We're done
+    LOG(WARNING) << "Orthanc is stopping";
+  }
+
+  serverFactory.Done();
+
+  return isReset;
+}
+
+
+
 
 int main(int argc, char* argv[]) 
 {
@@ -388,136 +522,29 @@
   int status = 0;
   try
   {
-    OrthancInitialize(configurationFile);
-
-    std::string storageDirectoryStr = Configuration::GetGlobalStringParameter("StorageDirectory", "OrthancStorage");
-    boost::filesystem::path storageDirectory = Configuration::InterpretStringParameterAsPath(storageDirectoryStr);
-    boost::filesystem::path indexDirectory = Configuration::InterpretStringParameterAsPath(
-        Configuration::GetGlobalStringParameter("IndexDirectory", storageDirectoryStr));
-    ServerContext context(storageDirectory, indexDirectory);
-
-    LOG(WARNING) << "Storage directory: " << storageDirectory;
-    LOG(WARNING) << "Index directory: " << indexDirectory;
-
-    context.SetCompressionEnabled(Configuration::GetGlobalBoolParameter("StorageCompression", false));
-    context.SetStoreMD5ForAttachments(Configuration::GetGlobalBoolParameter("StoreMD5ForAttachments", true));
-
-    LoadLuaScripts(context);
-
-    try
-    {
-      context.GetIndex().SetMaximumPatientCount(Configuration::GetGlobalIntegerParameter("MaximumPatientCount", 0));
-    }
-    catch (...)
-    {
-      context.GetIndex().SetMaximumPatientCount(0);
-    }
-
-    try
-    {
-      uint64_t size = Configuration::GetGlobalIntegerParameter("MaximumStorageSize", 0);
-      context.GetIndex().SetMaximumStorageSize(size * 1024 * 1024);
-    }
-    catch (...)
+    for (;;)
     {
-      context.GetIndex().SetMaximumStorageSize(0);
-    }
-
-    MyDicomServerFactory serverFactory(context);
-    
-    {
-      // DICOM server
-      DicomServer dicomServer;
-      OrthancApplicationEntityFilter dicomFilter;
-      dicomServer.SetCalledApplicationEntityTitleCheck(Configuration::GetGlobalBoolParameter("DicomCheckCalledAet", false));
-      dicomServer.SetStoreRequestHandlerFactory(serverFactory);
-      dicomServer.SetMoveRequestHandlerFactory(serverFactory);
-      dicomServer.SetFindRequestHandlerFactory(serverFactory);
-      dicomServer.SetPortNumber(Configuration::GetGlobalIntegerParameter("DicomPort", 4242));
-      dicomServer.SetApplicationEntityTitle(Configuration::GetGlobalStringParameter("DicomAet", "ORTHANC"));
-      dicomServer.SetApplicationEntityFilter(dicomFilter);
+      OrthancInitialize(configurationFile);
 
-      // HTTP server
-      MyIncomingHttpRequestFilter httpFilter(context);
-      MongooseServer httpServer;
-      httpServer.SetPortNumber(Configuration::GetGlobalIntegerParameter("HttpPort", 8042));
-      httpServer.SetRemoteAccessAllowed(Configuration::GetGlobalBoolParameter("RemoteAccessAllowed", false));
-      httpServer.SetIncomingHttpRequestFilter(httpFilter);
-
-      httpServer.SetAuthenticationEnabled(Configuration::GetGlobalBoolParameter("AuthenticationEnabled", false));
-      Configuration::SetupRegisteredUsers(httpServer);
-
-      if (Configuration::GetGlobalBoolParameter("SslEnabled", false))
+      bool reset = StartOrthanc();
+      if (reset)
       {
-        std::string certificate = Configuration::InterpretStringParameterAsPath(
-          Configuration::GetGlobalStringParameter("SslCertificate", "certificate.pem"));
-        httpServer.SetSslEnabled(true);
-        httpServer.SetSslCertificate(certificate.c_str());
+        OrthancFinalize();
       }
       else
       {
-        httpServer.SetSslEnabled(false);
+        break;
       }
-
-      OrthancRestApi restApi(context);
-
-#if ORTHANC_STANDALONE == 1
-      EmbeddedResourceHttpHandler staticResources("/app", EmbeddedResources::ORTHANC_EXPLORER);
-#else
-      FilesystemHttpHandler staticResources("/app", ORTHANC_PATH "/OrthancExplorer");
-#endif
-
-      PluginsHttpHandler httpPlugins(context);
-      httpPlugins.SetOrthancRestApi(restApi);
-
-      PluginsManager pluginsManager;
-      pluginsManager.RegisterServiceProvider(httpPlugins);
-      LoadPlugins(pluginsManager);
-
-      httpServer.RegisterHandler(httpPlugins);
-      httpServer.RegisterHandler(staticResources);
-      httpServer.RegisterHandler(restApi);
-      httpPlugins.SetOrthancRestApi(restApi);
-      context.SetPluginsHttpHandler(httpPlugins);
-
-      // GO !!! Start the requested servers
-      if (Configuration::GetGlobalBoolParameter("HttpServerEnabled", true))
-      {
-        httpServer.Start();
-        LOG(WARNING) << "HTTP server listening on port: " << httpServer.GetPortNumber();
-      }
-      else
-      {
-        LOG(WARNING) << "The HTTP server is disabled";
-      }
-
-      if (Configuration::GetGlobalBoolParameter("DicomServerEnabled", true))
-      {
-        dicomServer.Start();
-        LOG(WARNING) << "DICOM server listening on port: " << dicomServer.GetPortNumber();
-      }
-      else
-      {
-        LOG(WARNING) << "The DICOM server is disabled";
-      }
-
-      LOG(WARNING) << "Orthanc has started";
-      Toolbox::ServerBarrier();
-
-      // We're done
-      LOG(WARNING) << "Orthanc is stopping";
     }
-
-    serverFactory.Done();
   }
   catch (OrthancException& e)
   {
-    LOG(ERROR) << "EXCEPTION [" << e.What() << "]";
+    LOG(ERROR) << "Uncaught exception, stopping now: [" << e.What() << "]";
     status = -1;
   }
   catch (...)
   {
-    LOG(ERROR) << "NATIVE EXCEPTION";
+    LOG(ERROR) << "Native exception, stopping now";
     status = -1;
   }