Mercurial > hg > orthanc
annotate OrthancFramework/Sources/FileStorage/FilesystemStorage.cpp @ 5736:264d84c1936a
fix
author | Alain Mazy <am@orthanc.team> |
---|---|
date | Tue, 30 Jul 2024 06:06:21 +0200 |
parents | bdbaccc06e98 |
children | 2fe77dfe0466 |
rev | line source |
---|---|
0 | 1 /** |
59 | 2 * Orthanc - A Lightweight, RESTful DICOM Store |
1900 | 3 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics |
1288
6e7e5ed91c2d
upgrade to year 2015
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1250
diff
changeset
|
4 * Department, University Hospital of Liege, Belgium |
5640
f7adfb22e20e
updated copyright, as Orthanc Team now replaces Osimis
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
5485
diff
changeset
|
5 * Copyright (C) 2017-2023 Osimis S.A., Belgium |
f7adfb22e20e
updated copyright, as Orthanc Team now replaces Osimis
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
5485
diff
changeset
|
6 * Copyright (C) 2024-2024 Orthanc Team SRL, Belgium |
5485
48b8dae6dc77
upgrade to year 2024
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
5430
diff
changeset
|
7 * Copyright (C) 2021-2024 Sebastien Jodogne, ICTEAM UCLouvain, Belgium |
0 | 8 * |
9 * This program is free software: you can redistribute it and/or | |
4119
bf7b9edf6b81
re-licensing the OrthancFramework to LGPL, in order to license Stone of Orthanc under LGPL
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4044
diff
changeset
|
10 * modify it under the terms of the GNU Lesser General Public License |
bf7b9edf6b81
re-licensing the OrthancFramework to LGPL, in order to license Stone of Orthanc under LGPL
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4044
diff
changeset
|
11 * as published by the Free Software Foundation, either version 3 of |
bf7b9edf6b81
re-licensing the OrthancFramework to LGPL, in order to license Stone of Orthanc under LGPL
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4044
diff
changeset
|
12 * the License, or (at your option) any later version. |
136 | 13 * |
0 | 14 * This program is distributed in the hope that it will be useful, but |
15 * WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
4119
bf7b9edf6b81
re-licensing the OrthancFramework to LGPL, in order to license Stone of Orthanc under LGPL
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4044
diff
changeset
|
17 * Lesser General Public License for more details. |
0 | 18 * |
4119
bf7b9edf6b81
re-licensing the OrthancFramework to LGPL, in order to license Stone of Orthanc under LGPL
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4044
diff
changeset
|
19 * You should have received a copy of the GNU Lesser General Public |
bf7b9edf6b81
re-licensing the OrthancFramework to LGPL, in order to license Stone of Orthanc under LGPL
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4044
diff
changeset
|
20 * License along with this program. If not, see |
bf7b9edf6b81
re-licensing the OrthancFramework to LGPL, in order to license Stone of Orthanc under LGPL
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4044
diff
changeset
|
21 * <http://www.gnu.org/licenses/>. |
0 | 22 **/ |
23 | |
24 | |
824
a811bdf8b8eb
precompiled headers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
803
diff
changeset
|
25 #include "../PrecompiledHeaders.h" |
1123 | 26 #include "FilesystemStorage.h" |
5729
bdbaccc06e98
Fix extremely rare error when 2 threads are trying to create the same folder in the File Storage at the same time
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
27 #include <boost/thread.hpp> |
0 | 28 |
29 // http://stackoverflow.com/questions/1576272/storing-large-number-of-files-in-file-system | |
30 // http://stackoverflow.com/questions/446358/storing-a-large-number-of-images | |
31 | |
1486
f967bdf8534e
refactoring to Logging.h
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1397
diff
changeset
|
32 #include "../Logging.h" |
234 | 33 #include "../OrthancException.h" |
4484
64f06e7d5fc7
new abstraction IMemoryBuffer to avoid unnecessary copies of std::string buffers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4437
diff
changeset
|
34 #include "../StringMemoryBuffer.h" |
64f06e7d5fc7
new abstraction IMemoryBuffer to avoid unnecessary copies of std::string buffers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4437
diff
changeset
|
35 #include "../SystemToolbox.h" |
234 | 36 #include "../Toolbox.h" |
0 | 37 |
38 #include <boost/filesystem/fstream.hpp> | |
1397 | 39 |
0 | 40 |
110
fd7b0a3e6260
support of boost 1.42 for debian
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
59
diff
changeset
|
41 static std::string ToString(const boost::filesystem::path& p) |
fd7b0a3e6260
support of boost 1.42 for debian
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
59
diff
changeset
|
42 { |
fd7b0a3e6260
support of boost 1.42 for debian
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
59
diff
changeset
|
43 #if BOOST_HAS_FILESYSTEM_V3 == 1 |
fd7b0a3e6260
support of boost 1.42 for debian
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
59
diff
changeset
|
44 return p.filename().string(); |
fd7b0a3e6260
support of boost 1.42 for debian
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
59
diff
changeset
|
45 #else |
fd7b0a3e6260
support of boost 1.42 for debian
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
59
diff
changeset
|
46 return p.filename(); |
fd7b0a3e6260
support of boost 1.42 for debian
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
59
diff
changeset
|
47 #endif |
fd7b0a3e6260
support of boost 1.42 for debian
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
59
diff
changeset
|
48 } |
fd7b0a3e6260
support of boost 1.42 for debian
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
59
diff
changeset
|
49 |
fd7b0a3e6260
support of boost 1.42 for debian
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
59
diff
changeset
|
50 |
59 | 51 namespace Orthanc |
0 | 52 { |
1123 | 53 boost::filesystem::path FilesystemStorage::GetPath(const std::string& uuid) const |
0 | 54 { |
55 namespace fs = boost::filesystem; | |
56 | |
57 if (!Toolbox::IsUuid(uuid)) | |
58 { | |
59 | 59 throw OrthancException(ErrorCode_ParameterOutOfRange); |
0 | 60 } |
61 | |
62 fs::path path = root_; | |
63 | |
64 path /= std::string(&uuid[0], &uuid[2]); | |
65 path /= std::string(&uuid[2], &uuid[4]); | |
66 path /= uuid; | |
110
fd7b0a3e6260
support of boost 1.42 for debian
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
59
diff
changeset
|
67 |
fd7b0a3e6260
support of boost 1.42 for debian
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
59
diff
changeset
|
68 #if BOOST_HAS_FILESYSTEM_V3 == 1 |
0 | 69 path.make_preferred(); |
110
fd7b0a3e6260
support of boost 1.42 for debian
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
59
diff
changeset
|
70 #endif |
0 | 71 |
72 return path; | |
73 } | |
74 | |
4185
b289a1234822
giving a try to cross-platform compilation of SyncStorageArea
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4119
diff
changeset
|
75 void FilesystemStorage::Setup(const std::string& root) |
0 | 76 { |
110
fd7b0a3e6260
support of boost 1.42 for debian
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
59
diff
changeset
|
77 //root_ = boost::filesystem::absolute(root).string(); |
fd7b0a3e6260
support of boost 1.42 for debian
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
59
diff
changeset
|
78 root_ = root; |
0 | 79 |
2140 | 80 SystemToolbox::MakeDirectory(root); |
0 | 81 } |
82 | |
4300 | 83 FilesystemStorage::FilesystemStorage(const std::string &root) : |
84 fsyncOnWrite_(false) | |
85 { | |
86 Setup(root); | |
87 } | |
88 | |
89 FilesystemStorage::FilesystemStorage(const std::string &root, | |
90 bool fsyncOnWrite) : | |
91 fsyncOnWrite_(fsyncOnWrite) | |
92 { | |
93 Setup(root); | |
94 } | |
95 | |
2087
e9e6ffbf0fd5
improved logging in FilesystemStorage
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1911
diff
changeset
|
96 |
e9e6ffbf0fd5
improved logging in FilesystemStorage
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1911
diff
changeset
|
97 |
e9e6ffbf0fd5
improved logging in FilesystemStorage
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1911
diff
changeset
|
98 static const char* GetDescriptionInternal(FileContentType content) |
e9e6ffbf0fd5
improved logging in FilesystemStorage
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1911
diff
changeset
|
99 { |
e9e6ffbf0fd5
improved logging in FilesystemStorage
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1911
diff
changeset
|
100 // This function is for logging only (internal use), a more |
e9e6ffbf0fd5
improved logging in FilesystemStorage
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1911
diff
changeset
|
101 // fully-featured version is available in ServerEnumerations.cpp |
e9e6ffbf0fd5
improved logging in FilesystemStorage
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1911
diff
changeset
|
102 switch (content) |
e9e6ffbf0fd5
improved logging in FilesystemStorage
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1911
diff
changeset
|
103 { |
e9e6ffbf0fd5
improved logging in FilesystemStorage
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1911
diff
changeset
|
104 case FileContentType_Unknown: |
e9e6ffbf0fd5
improved logging in FilesystemStorage
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1911
diff
changeset
|
105 return "Unknown"; |
e9e6ffbf0fd5
improved logging in FilesystemStorage
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1911
diff
changeset
|
106 |
e9e6ffbf0fd5
improved logging in FilesystemStorage
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1911
diff
changeset
|
107 case FileContentType_Dicom: |
e9e6ffbf0fd5
improved logging in FilesystemStorage
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1911
diff
changeset
|
108 return "DICOM"; |
e9e6ffbf0fd5
improved logging in FilesystemStorage
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1911
diff
changeset
|
109 |
e9e6ffbf0fd5
improved logging in FilesystemStorage
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1911
diff
changeset
|
110 case FileContentType_DicomAsJson: |
e9e6ffbf0fd5
improved logging in FilesystemStorage
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1911
diff
changeset
|
111 return "JSON summary of DICOM"; |
e9e6ffbf0fd5
improved logging in FilesystemStorage
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1911
diff
changeset
|
112 |
4512
cff7fdfc83a4
added FileContentType_DicomUntilPixelData
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4495
diff
changeset
|
113 case FileContentType_DicomUntilPixelData: |
cff7fdfc83a4
added FileContentType_DicomUntilPixelData
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4495
diff
changeset
|
114 return "DICOM until pixel data"; |
cff7fdfc83a4
added FileContentType_DicomUntilPixelData
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4495
diff
changeset
|
115 |
2087
e9e6ffbf0fd5
improved logging in FilesystemStorage
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1911
diff
changeset
|
116 default: |
e9e6ffbf0fd5
improved logging in FilesystemStorage
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1911
diff
changeset
|
117 return "User-defined"; |
e9e6ffbf0fd5
improved logging in FilesystemStorage
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1911
diff
changeset
|
118 } |
e9e6ffbf0fd5
improved logging in FilesystemStorage
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1911
diff
changeset
|
119 } |
e9e6ffbf0fd5
improved logging in FilesystemStorage
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1911
diff
changeset
|
120 |
e9e6ffbf0fd5
improved logging in FilesystemStorage
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1911
diff
changeset
|
121 |
1135
67c3c1e4a6e0
index-only mode, and custom storage area with plugins
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1126
diff
changeset
|
122 void FilesystemStorage::Create(const std::string& uuid, |
67c3c1e4a6e0
index-only mode, and custom storage area with plugins
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1126
diff
changeset
|
123 const void* content, |
67c3c1e4a6e0
index-only mode, and custom storage area with plugins
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1126
diff
changeset
|
124 size_t size, |
2087
e9e6ffbf0fd5
improved logging in FilesystemStorage
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1911
diff
changeset
|
125 FileContentType type) |
0 | 126 { |
5430
b83192e7ad10
Now displaying timings when reading from/writing to disk in the verbose logs
Alain Mazy <am@osimis.io>
parents:
5374
diff
changeset
|
127 Toolbox::ElapsedTimer timer; |
b83192e7ad10
Now displaying timings when reading from/writing to disk in the verbose logs
Alain Mazy <am@osimis.io>
parents:
5374
diff
changeset
|
128 LOG(INFO) << "Creating attachment \"" << uuid << "\" of \"" << GetDescriptionInternal(type) |
b83192e7ad10
Now displaying timings when reading from/writing to disk in the verbose logs
Alain Mazy <am@osimis.io>
parents:
5374
diff
changeset
|
129 << "\" type"; |
2087
e9e6ffbf0fd5
improved logging in FilesystemStorage
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1911
diff
changeset
|
130 |
0 | 131 boost::filesystem::path path; |
132 | |
1135
67c3c1e4a6e0
index-only mode, and custom storage area with plugins
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1126
diff
changeset
|
133 path = GetPath(uuid); |
0 | 134 |
1135
67c3c1e4a6e0
index-only mode, and custom storage area with plugins
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1126
diff
changeset
|
135 if (boost::filesystem::exists(path)) |
67c3c1e4a6e0
index-only mode, and custom storage area with plugins
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1126
diff
changeset
|
136 { |
67c3c1e4a6e0
index-only mode, and custom storage area with plugins
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1126
diff
changeset
|
137 // Extremely unlikely case: This Uuid has already been created |
67c3c1e4a6e0
index-only mode, and custom storage area with plugins
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1126
diff
changeset
|
138 // in the past. |
5729
bdbaccc06e98
Fix extremely rare error when 2 threads are trying to create the same folder in the File Storage at the same time
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
139 throw OrthancException(ErrorCode_InternalError, "This file UUID already exists"); |
0 | 140 } |
141 | |
5729
bdbaccc06e98
Fix extremely rare error when 2 threads are trying to create the same folder in the File Storage at the same time
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
142 // In very unlikely case (but we've seen it !), 2 threads might enter this same piece |
bdbaccc06e98
Fix extremely rare error when 2 threads are trying to create the same folder in the File Storage at the same time
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
143 // of code and both try to create the same directory or a thread could be deleting a |
bdbaccc06e98
Fix extremely rare error when 2 threads are trying to create the same folder in the File Storage at the same time
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
144 // directory while another thread needs it -> introduce 3 retries at 1 ms interval |
bdbaccc06e98
Fix extremely rare error when 2 threads are trying to create the same folder in the File Storage at the same time
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
145 int retryCount = 0; |
bdbaccc06e98
Fix extremely rare error when 2 threads are trying to create the same folder in the File Storage at the same time
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
146 const int maxRetryCount = 3; |
bdbaccc06e98
Fix extremely rare error when 2 threads are trying to create the same folder in the File Storage at the same time
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
147 |
bdbaccc06e98
Fix extremely rare error when 2 threads are trying to create the same folder in the File Storage at the same time
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
148 while (retryCount < maxRetryCount) |
0 | 149 { |
5729
bdbaccc06e98
Fix extremely rare error when 2 threads are trying to create the same folder in the File Storage at the same time
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
150 retryCount++; |
bdbaccc06e98
Fix extremely rare error when 2 threads are trying to create the same folder in the File Storage at the same time
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
151 if (retryCount > 1) |
0 | 152 { |
5729
bdbaccc06e98
Fix extremely rare error when 2 threads are trying to create the same folder in the File Storage at the same time
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
153 boost::this_thread::sleep(boost::posix_time::milliseconds(2 * retryCount + (rand() % 10))); |
bdbaccc06e98
Fix extremely rare error when 2 threads are trying to create the same folder in the File Storage at the same time
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
154 LOG(INFO) << "Retrying to create attachment \"" << uuid << "\" of \"" << GetDescriptionInternal(type) |
bdbaccc06e98
Fix extremely rare error when 2 threads are trying to create the same folder in the File Storage at the same time
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
155 << "\" type"; |
bdbaccc06e98
Fix extremely rare error when 2 threads are trying to create the same folder in the File Storage at the same time
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
156 } |
bdbaccc06e98
Fix extremely rare error when 2 threads are trying to create the same folder in the File Storage at the same time
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
157 |
bdbaccc06e98
Fix extremely rare error when 2 threads are trying to create the same folder in the File Storage at the same time
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
158 if (boost::filesystem::exists(path.parent_path())) |
bdbaccc06e98
Fix extremely rare error when 2 threads are trying to create the same folder in the File Storage at the same time
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
159 { |
bdbaccc06e98
Fix extremely rare error when 2 threads are trying to create the same folder in the File Storage at the same time
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
160 if (!boost::filesystem::is_directory(path.parent_path())) |
bdbaccc06e98
Fix extremely rare error when 2 threads are trying to create the same folder in the File Storage at the same time
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
161 { |
bdbaccc06e98
Fix extremely rare error when 2 threads are trying to create the same folder in the File Storage at the same time
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
162 throw OrthancException(ErrorCode_DirectoryOverFile); // no need to retry this error |
bdbaccc06e98
Fix extremely rare error when 2 threads are trying to create the same folder in the File Storage at the same time
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
163 } |
0 | 164 } |
5729
bdbaccc06e98
Fix extremely rare error when 2 threads are trying to create the same folder in the File Storage at the same time
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
165 else |
0 | 166 { |
5729
bdbaccc06e98
Fix extremely rare error when 2 threads are trying to create the same folder in the File Storage at the same time
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
167 if (!boost::filesystem::create_directories(path.parent_path())) |
bdbaccc06e98
Fix extremely rare error when 2 threads are trying to create the same folder in the File Storage at the same time
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
168 { |
bdbaccc06e98
Fix extremely rare error when 2 threads are trying to create the same folder in the File Storage at the same time
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
169 if (retryCount >= maxRetryCount) |
bdbaccc06e98
Fix extremely rare error when 2 threads are trying to create the same folder in the File Storage at the same time
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
170 { |
bdbaccc06e98
Fix extremely rare error when 2 threads are trying to create the same folder in the File Storage at the same time
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
171 throw OrthancException(ErrorCode_FileStorageCannotWrite); |
bdbaccc06e98
Fix extremely rare error when 2 threads are trying to create the same folder in the File Storage at the same time
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
172 } |
bdbaccc06e98
Fix extremely rare error when 2 threads are trying to create the same folder in the File Storage at the same time
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
173 |
bdbaccc06e98
Fix extremely rare error when 2 threads are trying to create the same folder in the File Storage at the same time
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
174 continue; // retry |
bdbaccc06e98
Fix extremely rare error when 2 threads are trying to create the same folder in the File Storage at the same time
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
175 } |
bdbaccc06e98
Fix extremely rare error when 2 threads are trying to create the same folder in the File Storage at the same time
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
176 } |
bdbaccc06e98
Fix extremely rare error when 2 threads are trying to create the same folder in the File Storage at the same time
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
177 |
bdbaccc06e98
Fix extremely rare error when 2 threads are trying to create the same folder in the File Storage at the same time
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
178 try |
bdbaccc06e98
Fix extremely rare error when 2 threads are trying to create the same folder in the File Storage at the same time
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
179 { |
bdbaccc06e98
Fix extremely rare error when 2 threads are trying to create the same folder in the File Storage at the same time
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
180 SystemToolbox::WriteFile(content, size, path.string(), fsyncOnWrite_); |
5736 | 181 |
182 LOG(INFO) << "Created attachment \"" << uuid << "\" (" << timer.GetHumanTransferSpeed(true, size) << ")"; | |
183 return; | |
5729
bdbaccc06e98
Fix extremely rare error when 2 threads are trying to create the same folder in the File Storage at the same time
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
184 } |
bdbaccc06e98
Fix extremely rare error when 2 threads are trying to create the same folder in the File Storage at the same time
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
185 catch (OrthancException& ex) |
bdbaccc06e98
Fix extremely rare error when 2 threads are trying to create the same folder in the File Storage at the same time
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
186 { |
bdbaccc06e98
Fix extremely rare error when 2 threads are trying to create the same folder in the File Storage at the same time
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
187 if (retryCount >= maxRetryCount) |
bdbaccc06e98
Fix extremely rare error when 2 threads are trying to create the same folder in the File Storage at the same time
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
188 { |
bdbaccc06e98
Fix extremely rare error when 2 threads are trying to create the same folder in the File Storage at the same time
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
189 throw ex; |
bdbaccc06e98
Fix extremely rare error when 2 threads are trying to create the same folder in the File Storage at the same time
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
190 } |
0 | 191 } |
192 } | |
193 } | |
194 | |
195 | |
4484
64f06e7d5fc7
new abstraction IMemoryBuffer to avoid unnecessary copies of std::string buffers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4437
diff
changeset
|
196 IMemoryBuffer* FilesystemStorage::Read(const std::string& uuid, |
64f06e7d5fc7
new abstraction IMemoryBuffer to avoid unnecessary copies of std::string buffers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4437
diff
changeset
|
197 FileContentType type) |
0 | 198 { |
5430
b83192e7ad10
Now displaying timings when reading from/writing to disk in the verbose logs
Alain Mazy <am@osimis.io>
parents:
5374
diff
changeset
|
199 Toolbox::ElapsedTimer timer; |
2087
e9e6ffbf0fd5
improved logging in FilesystemStorage
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1911
diff
changeset
|
200 LOG(INFO) << "Reading attachment \"" << uuid << "\" of \"" << GetDescriptionInternal(type) |
e9e6ffbf0fd5
improved logging in FilesystemStorage
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1911
diff
changeset
|
201 << "\" content type"; |
e9e6ffbf0fd5
improved logging in FilesystemStorage
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1911
diff
changeset
|
202 |
4484
64f06e7d5fc7
new abstraction IMemoryBuffer to avoid unnecessary copies of std::string buffers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4437
diff
changeset
|
203 std::string content; |
2140 | 204 SystemToolbox::ReadFile(content, GetPath(uuid).string()); |
4484
64f06e7d5fc7
new abstraction IMemoryBuffer to avoid unnecessary copies of std::string buffers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4437
diff
changeset
|
205 |
5430
b83192e7ad10
Now displaying timings when reading from/writing to disk in the verbose logs
Alain Mazy <am@osimis.io>
parents:
5374
diff
changeset
|
206 LOG(INFO) << "Read attachment \"" << uuid << "\" (" << timer.GetHumanTransferSpeed(true, content.size()) << ")"; |
b83192e7ad10
Now displaying timings when reading from/writing to disk in the verbose logs
Alain Mazy <am@osimis.io>
parents:
5374
diff
changeset
|
207 |
4484
64f06e7d5fc7
new abstraction IMemoryBuffer to avoid unnecessary copies of std::string buffers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4437
diff
changeset
|
208 return StringMemoryBuffer::CreateFromSwap(content); |
0 | 209 } |
210 | |
211 | |
4495
fa2311f94d9f
IStorageArea::ReadRange()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4484
diff
changeset
|
212 IMemoryBuffer* FilesystemStorage::ReadRange(const std::string& uuid, |
fa2311f94d9f
IStorageArea::ReadRange()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4484
diff
changeset
|
213 FileContentType type, |
fa2311f94d9f
IStorageArea::ReadRange()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4484
diff
changeset
|
214 uint64_t start /* inclusive */, |
fa2311f94d9f
IStorageArea::ReadRange()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4484
diff
changeset
|
215 uint64_t end /* exclusive */) |
fa2311f94d9f
IStorageArea::ReadRange()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4484
diff
changeset
|
216 { |
5430
b83192e7ad10
Now displaying timings when reading from/writing to disk in the verbose logs
Alain Mazy <am@osimis.io>
parents:
5374
diff
changeset
|
217 Toolbox::ElapsedTimer timer; |
4495
fa2311f94d9f
IStorageArea::ReadRange()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4484
diff
changeset
|
218 LOG(INFO) << "Reading attachment \"" << uuid << "\" of \"" << GetDescriptionInternal(type) |
fa2311f94d9f
IStorageArea::ReadRange()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4484
diff
changeset
|
219 << "\" content type (range from " << start << " to " << end << ")"; |
fa2311f94d9f
IStorageArea::ReadRange()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4484
diff
changeset
|
220 |
fa2311f94d9f
IStorageArea::ReadRange()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4484
diff
changeset
|
221 std::string content; |
fa2311f94d9f
IStorageArea::ReadRange()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4484
diff
changeset
|
222 SystemToolbox::ReadFileRange( |
fa2311f94d9f
IStorageArea::ReadRange()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4484
diff
changeset
|
223 content, GetPath(uuid).string(), start, end, true /* throw if overflow */); |
fa2311f94d9f
IStorageArea::ReadRange()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4484
diff
changeset
|
224 |
5430
b83192e7ad10
Now displaying timings when reading from/writing to disk in the verbose logs
Alain Mazy <am@osimis.io>
parents:
5374
diff
changeset
|
225 LOG(INFO) << "Read range of attachment \"" << uuid << "\" (" << timer.GetHumanTransferSpeed(true, content.size()) << ")"; |
4495
fa2311f94d9f
IStorageArea::ReadRange()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4484
diff
changeset
|
226 return StringMemoryBuffer::CreateFromSwap(content); |
fa2311f94d9f
IStorageArea::ReadRange()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4484
diff
changeset
|
227 } |
fa2311f94d9f
IStorageArea::ReadRange()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4484
diff
changeset
|
228 |
fa2311f94d9f
IStorageArea::ReadRange()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4484
diff
changeset
|
229 |
4520
f5cb0c0ffbed
added unit test OrthancFramework.SizeOf to dump sizeof all the public classes in the Orthanc framework
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4512
diff
changeset
|
230 bool FilesystemStorage::HasReadRange() const |
f5cb0c0ffbed
added unit test OrthancFramework.SizeOf to dump sizeof all the public classes in the Orthanc framework
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4512
diff
changeset
|
231 { |
f5cb0c0ffbed
added unit test OrthancFramework.SizeOf to dump sizeof all the public classes in the Orthanc framework
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4512
diff
changeset
|
232 return true; |
f5cb0c0ffbed
added unit test OrthancFramework.SizeOf to dump sizeof all the public classes in the Orthanc framework
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4512
diff
changeset
|
233 } |
f5cb0c0ffbed
added unit test OrthancFramework.SizeOf to dump sizeof all the public classes in the Orthanc framework
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4512
diff
changeset
|
234 |
f5cb0c0ffbed
added unit test OrthancFramework.SizeOf to dump sizeof all the public classes in the Orthanc framework
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4512
diff
changeset
|
235 |
1123 | 236 uintmax_t FilesystemStorage::GetSize(const std::string& uuid) const |
0 | 237 { |
238 boost::filesystem::path path = GetPath(uuid); | |
239 return boost::filesystem::file_size(path); | |
240 } | |
241 | |
242 | |
243 | |
1123 | 244 void FilesystemStorage::ListAllFiles(std::set<std::string>& result) const |
0 | 245 { |
246 namespace fs = boost::filesystem; | |
247 | |
248 result.clear(); | |
249 | |
250 if (fs::exists(root_) && fs::is_directory(root_)) | |
251 { | |
252 for (fs::recursive_directory_iterator current(root_), end; current != end ; ++current) | |
253 { | |
2140 | 254 if (SystemToolbox::IsRegularFile(current->path().string())) |
0 | 255 { |
256 try | |
257 { | |
258 fs::path d = current->path(); | |
110
fd7b0a3e6260
support of boost 1.42 for debian
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
59
diff
changeset
|
259 std::string uuid = ToString(d); |
0 | 260 if (Toolbox::IsUuid(uuid)) |
261 { | |
262 fs::path p0 = d.parent_path().parent_path().parent_path(); | |
110
fd7b0a3e6260
support of boost 1.42 for debian
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
59
diff
changeset
|
263 std::string p1 = ToString(d.parent_path().parent_path()); |
fd7b0a3e6260
support of boost 1.42 for debian
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
59
diff
changeset
|
264 std::string p2 = ToString(d.parent_path()); |
0 | 265 if (p1.length() == 2 && |
266 p2.length() == 2 && | |
267 p1 == uuid.substr(0, 2) && | |
268 p2 == uuid.substr(2, 2) && | |
269 p0 == root_) | |
270 { | |
271 result.insert(uuid); | |
272 } | |
273 } | |
274 } | |
2836
7133ad478eea
fix Debian warnings
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2447
diff
changeset
|
275 catch (fs::filesystem_error&) |
0 | 276 { |
277 } | |
278 } | |
279 } | |
280 } | |
281 } | |
282 | |
283 | |
1123 | 284 void FilesystemStorage::Clear() |
0 | 285 { |
286 namespace fs = boost::filesystem; | |
287 typedef std::set<std::string> List; | |
288 | |
289 List result; | |
290 ListAllFiles(result); | |
291 | |
656 | 292 for (List::const_iterator it = result.begin(); it != result.end(); ++it) |
0 | 293 { |
1126
bf67431a7383
handling of file content type in IStorageArea
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1124
diff
changeset
|
294 Remove(*it, FileContentType_Unknown /*ignored in this class*/); |
0 | 295 } |
296 } | |
297 | |
298 | |
1126
bf67431a7383
handling of file content type in IStorageArea
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1124
diff
changeset
|
299 void FilesystemStorage::Remove(const std::string& uuid, |
2129
0c09d1af22f3
"/tools/invalidate-tags" to invalidate the JSON summary of all the DICOM files
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2087
diff
changeset
|
300 FileContentType type) |
0 | 301 { |
2129
0c09d1af22f3
"/tools/invalidate-tags" to invalidate the JSON summary of all the DICOM files
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2087
diff
changeset
|
302 LOG(INFO) << "Deleting attachment \"" << uuid << "\" of type " << static_cast<int>(type); |
1397 | 303 |
0 | 304 namespace fs = boost::filesystem; |
305 | |
306 fs::path p = GetPath(uuid); | |
147 | 307 |
308 try | |
309 { | |
310 fs::remove(p); | |
311 } | |
148 | 312 catch (...) |
147 | 313 { |
314 // Ignore the error | |
315 } | |
0 | 316 |
317 // Remove the two parent directories, ignoring the error code if | |
318 // these directories are not empty | |
110
fd7b0a3e6260
support of boost 1.42 for debian
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
59
diff
changeset
|
319 |
142 | 320 try |
321 { | |
147 | 322 #if BOOST_HAS_FILESYSTEM_V3 == 1 |
323 boost::system::error_code err; | |
324 fs::remove(p.parent_path(), err); | |
325 fs::remove(p.parent_path().parent_path(), err); | |
326 #else | |
327 fs::remove(p.parent_path()); | |
328 fs::remove(p.parent_path().parent_path()); | |
329 #endif | |
142 | 330 } |
148 | 331 catch (...) |
142 | 332 { |
333 // Ignore the error | |
334 } | |
335 } | |
336 | |
337 | |
1123 | 338 uintmax_t FilesystemStorage::GetCapacity() const |
0 | 339 { |
340 return boost::filesystem::space(root_).capacity; | |
341 } | |
342 | |
1123 | 343 uintmax_t FilesystemStorage::GetAvailableSpace() const |
0 | 344 { |
345 return boost::filesystem::space(root_).available; | |
346 } | |
4273
0034f855c023
tuning log categories from command-line, and binary compat with orthanc framework 1.7.2
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4185
diff
changeset
|
347 |
0034f855c023
tuning log categories from command-line, and binary compat with orthanc framework 1.7.2
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4185
diff
changeset
|
348 |
0034f855c023
tuning log categories from command-line, and binary compat with orthanc framework 1.7.2
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4185
diff
changeset
|
349 #if ORTHANC_BUILDING_FRAMEWORK_LIBRARY == 1 |
0034f855c023
tuning log categories from command-line, and binary compat with orthanc framework 1.7.2
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4185
diff
changeset
|
350 FilesystemStorage::FilesystemStorage(std::string root) : |
0034f855c023
tuning log categories from command-line, and binary compat with orthanc framework 1.7.2
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4185
diff
changeset
|
351 fsyncOnWrite_(false) |
0034f855c023
tuning log categories from command-line, and binary compat with orthanc framework 1.7.2
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4185
diff
changeset
|
352 { |
0034f855c023
tuning log categories from command-line, and binary compat with orthanc framework 1.7.2
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4185
diff
changeset
|
353 Setup(root); |
0034f855c023
tuning log categories from command-line, and binary compat with orthanc framework 1.7.2
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4185
diff
changeset
|
354 } |
0034f855c023
tuning log categories from command-line, and binary compat with orthanc framework 1.7.2
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4185
diff
changeset
|
355 #endif |
4484
64f06e7d5fc7
new abstraction IMemoryBuffer to avoid unnecessary copies of std::string buffers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4437
diff
changeset
|
356 |
64f06e7d5fc7
new abstraction IMemoryBuffer to avoid unnecessary copies of std::string buffers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4437
diff
changeset
|
357 |
64f06e7d5fc7
new abstraction IMemoryBuffer to avoid unnecessary copies of std::string buffers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4437
diff
changeset
|
358 #if ORTHANC_BUILDING_FRAMEWORK_LIBRARY == 1 |
64f06e7d5fc7
new abstraction IMemoryBuffer to avoid unnecessary copies of std::string buffers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4437
diff
changeset
|
359 void FilesystemStorage::Read(std::string& content, |
64f06e7d5fc7
new abstraction IMemoryBuffer to avoid unnecessary copies of std::string buffers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4437
diff
changeset
|
360 const std::string& uuid, |
64f06e7d5fc7
new abstraction IMemoryBuffer to avoid unnecessary copies of std::string buffers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4437
diff
changeset
|
361 FileContentType type) |
64f06e7d5fc7
new abstraction IMemoryBuffer to avoid unnecessary copies of std::string buffers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4437
diff
changeset
|
362 { |
64f06e7d5fc7
new abstraction IMemoryBuffer to avoid unnecessary copies of std::string buffers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4437
diff
changeset
|
363 std::unique_ptr<IMemoryBuffer> buffer(Read(uuid, type)); |
64f06e7d5fc7
new abstraction IMemoryBuffer to avoid unnecessary copies of std::string buffers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4437
diff
changeset
|
364 buffer->MoveToString(content); |
64f06e7d5fc7
new abstraction IMemoryBuffer to avoid unnecessary copies of std::string buffers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4437
diff
changeset
|
365 } |
64f06e7d5fc7
new abstraction IMemoryBuffer to avoid unnecessary copies of std::string buffers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4437
diff
changeset
|
366 #endif |
0 | 367 } |