# HG changeset patch # User Sebastien Jodogne # Date 1407404026 -7200 # Node ID bec1eccf976cb9c24d79d2e9860662f49ae8b1b4 # Parent ce6386b37afd70543c0ddf0743be74f7f21e6d51 Hot restart of Orthanc diff -r ce6386b37afd -r bec1eccf976c Core/EnumerationDictionary.h --- 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 diff -r ce6386b37afd -r bec1eccf976c Core/Toolbox.cpp --- 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); } diff -r ce6386b37afd -r bec1eccf976c Core/Toolbox.h --- 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(); diff -r ce6386b37afd -r bec1eccf976c NEWS --- 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 diff -r ce6386b37afd -r bec1eccf976c OrthancServer/OrthancRestApi/OrthancRestApi.cpp --- 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); } } diff -r ce6386b37afd -r bec1eccf976c OrthancServer/OrthancRestApi/OrthancRestApi.h --- 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(call.GetContext()); diff -r ce6386b37afd -r bec1eccf976c OrthancServer/ServerEnumerations.cpp --- 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"); diff -r ce6386b37afd -r bec1eccf976c OrthancServer/main.cpp --- 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; }