changeset 4185:b289a1234822

giving a try to cross-platform compilation of SyncStorageArea
author Sebastien Jodogne <s.jodogne@gmail.com>
date Mon, 14 Sep 2020 18:09:30 +0200
parents dbd74fa2f446
children e99d1ad11cfe
files NEWS OrthancFramework/Resources/CMake/BoostConfiguration.cmake OrthancFramework/Sources/FileStorage/FilesystemStorage.cpp OrthancFramework/Sources/FileStorage/FilesystemStorage.h OrthancFramework/Sources/SystemToolbox.cpp OrthancFramework/Sources/SystemToolbox.h OrthancServer/Resources/Configuration.json OrthancServer/Sources/OrthancInitialization.cpp
diffstat 8 files changed, 76 insertions(+), 15 deletions(-) [+]
line wrap: on
line diff
--- a/NEWS	Sat Sep 12 16:03:48 2020 +0200
+++ b/NEWS	Mon Sep 14 18:09:30 2020 +0200
@@ -10,6 +10,7 @@
 * When checking DICOM allowed methods, if there are multiple modalities with the same AET, 
   differentiate them from the calling IP
 * Enable the access to raw frames in Philips ELSCINT1 proprietary compression
+* New configuration option "SyncStorageArea"
 
 
 Version 1.7.3 (2020-08-24)
--- a/OrthancFramework/Resources/CMake/BoostConfiguration.cmake	Sat Sep 12 16:03:48 2020 +0200
+++ b/OrthancFramework/Resources/CMake/BoostConfiguration.cmake	Mon Sep 14 18:09:30 2020 +0200
@@ -31,7 +31,7 @@
     list(APPEND ORTHANC_BOOST_COMPONENTS locale)
   endif()
 
-  list(APPEND ORTHANC_BOOST_COMPONENTS filesystem thread system date_time regex)
+  list(APPEND ORTHANC_BOOST_COMPONENTS filesystem thread system date_time regex iostreams)
   find_package(Boost COMPONENTS ${ORTHANC_BOOST_COMPONENTS})
 
   if (NOT Boost_FOUND)
--- a/OrthancFramework/Sources/FileStorage/FilesystemStorage.cpp	Sat Sep 12 16:03:48 2020 +0200
+++ b/OrthancFramework/Sources/FileStorage/FilesystemStorage.cpp	Mon Sep 14 18:09:30 2020 +0200
@@ -68,7 +68,7 @@
     return path;
   }
 
-  FilesystemStorage::FilesystemStorage(std::string root)
+  void FilesystemStorage::Setup(const std::string& root)
   {
     //root_ = boost::filesystem::absolute(root).string();
     root_ = root;
@@ -133,7 +133,7 @@
       }
     }
 
-    SystemToolbox::WriteFile(content, size, path.string());
+    SystemToolbox::WriteFile(content, size, path.string(), fsyncOnWrite_);
   }
 
 
--- a/OrthancFramework/Sources/FileStorage/FilesystemStorage.h	Sat Sep 12 16:03:48 2020 +0200
+++ b/OrthancFramework/Sources/FileStorage/FilesystemStorage.h	Mon Sep 14 18:09:30 2020 +0200
@@ -48,11 +48,25 @@
 
   private:
     boost::filesystem::path root_;
+    bool                    fsyncOnWrite_;
 
     boost::filesystem::path GetPath(const std::string& uuid) const;
 
+    void Setup(const std::string& root);
+    
   public:
-    explicit FilesystemStorage(std::string root);
+    explicit FilesystemStorage(const std::string& root) :
+      fsyncOnWrite_(false)
+    {
+      Setup(root);
+    }
+
+    FilesystemStorage(const std::string& root,
+                      bool fsyncOnWrite) :
+      fsyncOnWrite_(fsyncOnWrite)
+    {
+      Setup(root);
+    }
 
     virtual void Create(const std::string& uuid,
                         const void* content, 
--- a/OrthancFramework/Sources/SystemToolbox.cpp	Sat Sep 12 16:03:48 2020 +0200
+++ b/OrthancFramework/Sources/SystemToolbox.cpp	Mon Sep 14 18:09:30 2020 +0200
@@ -56,6 +56,8 @@
 #include "OrthancException.h"
 #include "Toolbox.h"
 
+#include <boost/iostreams/device/file_descriptor.hpp>
+#include <boost/iostreams/stream.hpp>
 #include <boost/filesystem.hpp>
 #include <boost/filesystem/fstream.hpp>
 #include <boost/date_time/posix_time/posix_time.hpp>
@@ -278,9 +280,12 @@
 
   void SystemToolbox::WriteFile(const void* content,
                                 size_t size,
-                                const std::string& path)
+                                const std::string& path,
+                                bool callFsync)
   {
-    boost::filesystem::ofstream f;
+    //boost::filesystem::ofstream f;
+    boost::iostreams::stream<boost::iostreams::file_descriptor_sink> f;
+    
     f.open(path, std::ofstream::out | std::ofstream::binary);
     if (!f.good())
     {
@@ -298,15 +303,23 @@
       }
     }
 
+    if (callFsync)
+    {
+      // https://stackoverflow.com/a/23826489/881731
+      f.flush();
+      ::fdatasync(f->handle());
+    }
+
     f.close();
   }
 
 
   void SystemToolbox::WriteFile(const std::string& content,
-                                const std::string& path)
+                                const std::string& path,
+                                bool callFsync)
   {
     WriteFile(content.size() > 0 ? content.c_str() : NULL,
-              content.size(), path);
+              content.size(), path, callFsync);
   }
 
 
--- a/OrthancFramework/Sources/SystemToolbox.h	Sat Sep 12 16:03:48 2020 +0200
+++ b/OrthancFramework/Sources/SystemToolbox.h	Mon Sep 14 18:09:30 2020 +0200
@@ -52,7 +52,13 @@
 
     static void ReadFile(std::string& content,
                          const std::string& path,
-                         bool log = true);
+                         bool log);
+
+    static void ReadFile(std::string& content,
+                         const std::string& path)
+    {
+      ReadFile(content, path, true /* log */);
+    }
 
     static bool ReadHeader(std::string& header,
                            const std::string& path,
@@ -60,10 +66,25 @@
 
     static void WriteFile(const void* content,
                           size_t size,
-                          const std::string& path);
+                          const std::string& path,
+                          bool callFsync);
+
+    static void WriteFile(const void* content,
+                          size_t size,
+                          const std::string& path)
+    {
+      WriteFile(content, size, path, false /* don't automatically call fsync */);
+    }
 
     static void WriteFile(const std::string& content,
-                          const std::string& path);
+                          const std::string& path,
+                          bool callFsync);
+
+    static void WriteFile(const std::string& content,
+                          const std::string& path)
+    {
+      WriteFile(content, path, false /* don't automatically call fsync */);
+    }
 
     static void RemoveFile(const std::string& path);
 
--- a/OrthancServer/Resources/Configuration.json	Sat Sep 12 16:03:48 2020 +0200
+++ b/OrthancServer/Resources/Configuration.json	Mon Sep 14 18:09:30 2020 +0200
@@ -575,5 +575,12 @@
 
   // The compression level that is used when transcoding to one of the
   // lossy/JPEG transfer syntaxes (integer between 1 and 100).
-  "DicomLossyTranscodingQuality" : 90
+  "DicomLossyTranscodingQuality" : 90,
+
+  // Whether "fsync()" is called after each write to the storage area
+  // (new in Orthanc 1.7.4). If this option is set to "true", Orthanc
+  // will run more slowly, but the DICOM are guaranteed to be
+  // immediately written to the disk. This option defaults to "false"
+  // in Orthanc <= 1.7.3, and to "true" in Orthanc >= 1.7.4.
+  "SyncStorageArea" : true
 }
--- a/OrthancServer/Sources/OrthancInitialization.cpp	Sat Sep 12 16:03:48 2020 +0200
+++ b/OrthancServer/Sources/OrthancInitialization.cpp	Mon Sep 14 18:09:30 2020 +0200
@@ -314,7 +314,9 @@
       FilesystemStorage storage_;
 
     public:
-      FilesystemStorageWithoutDicom(const std::string& path) : storage_(path)
+      FilesystemStorageWithoutDicom(const std::string& path,
+                                    bool fsyncOnWrite) :
+        storage_(path, fsyncOnWrite)
       {
       }
 
@@ -367,14 +369,17 @@
 
     LOG(WARNING) << "Storage directory: " << storageDirectory;
 
+    // New in Orthanc 1.7.4
+    bool fsyncOnWrite = lock.GetConfiguration().GetBooleanParameter("SyncStorageArea", true);
+
     if (lock.GetConfiguration().GetBooleanParameter("StoreDicom", true))
     {
-      return new FilesystemStorage(storageDirectory.string());
+      return new FilesystemStorage(storageDirectory.string(), fsyncOnWrite);
     }
     else
     {
       LOG(WARNING) << "The DICOM files will not be stored, Orthanc running in index-only mode";
-      return new FilesystemStorageWithoutDicom(storageDirectory.string());
+      return new FilesystemStorageWithoutDicom(storageDirectory.string(), fsyncOnWrite);
     }
   }