Mercurial > hg > orthanc-object-storage
annotate Common/StoragePlugin.cpp @ 77:80792bb9600e
new HybridMode
author | Alain Mazy <am@osimis.io> |
---|---|
date | Fri, 14 Oct 2022 10:36:02 +0200 |
parents | ba1be668e475 |
children | d7295e8678d7 |
rev | line source |
---|---|
1 | 1 /** |
2 * Cloud storage plugins for Orthanc | |
37
f55b2afdf53d
upgrade to year 2021
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
35
diff
changeset
|
3 * Copyright (C) 2020-2021 Osimis S.A., Belgium |
1 | 4 * |
5 * This program is free software: you can redistribute it and/or | |
6 * modify it under the terms of the GNU Affero General Public License | |
7 * as published by the Free Software Foundation, either version 3 of | |
8 * the License, or (at your option) any later version. | |
9 * | |
10 * This program is distributed in the hope that it will be useful, but | |
11 * WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 * Affero General Public License for more details. | |
14 * | |
15 * You should have received a copy of the GNU Affero General Public License | |
16 * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
17 **/ | |
18 | |
56
b922ae86bbe1
full static linking against AWS SDK
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
43
diff
changeset
|
19 |
1 | 20 #if GOOGLE_STORAGE_PLUGIN==1 |
56
b922ae86bbe1
full static linking against AWS SDK
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
43
diff
changeset
|
21 # include "../Google/GoogleStoragePlugin.h" |
b922ae86bbe1
full static linking against AWS SDK
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
43
diff
changeset
|
22 # define StoragePluginFactory GoogleStoragePluginFactory |
1 | 23 #elif AZURE_STORAGE_PLUGIN==1 |
56
b922ae86bbe1
full static linking against AWS SDK
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
43
diff
changeset
|
24 # include "../Azure/AzureBlobStoragePlugin.h" |
b922ae86bbe1
full static linking against AWS SDK
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
43
diff
changeset
|
25 # define StoragePluginFactory AzureBlobStoragePluginFactory |
1 | 26 #elif AWS_STORAGE_PLUGIN==1 |
56
b922ae86bbe1
full static linking against AWS SDK
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
43
diff
changeset
|
27 # include "../Aws/AwsS3StoragePlugin.h" |
b922ae86bbe1
full static linking against AWS SDK
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
43
diff
changeset
|
28 # define StoragePluginFactory AwsS3StoragePluginFactory |
1 | 29 #else |
56
b922ae86bbe1
full static linking against AWS SDK
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
43
diff
changeset
|
30 # pragma message(error "define a plugin") |
1 | 31 #endif |
32 | |
33 #include <string.h> | |
34 #include <stdio.h> | |
35 #include <string> | |
36 | |
37 #include <iostream> | |
15 | 38 #include <boost/filesystem.hpp> |
39 #include <boost/filesystem/fstream.hpp> | |
40 | |
1 | 41 #include "../Common/EncryptionHelpers.h" |
42 #include "../Common/EncryptionConfigurator.h" | |
77 | 43 #include "../Common/FileSystemStoragePlugin.h" |
35
8a7a5defd5d0
upgrade orthanc framework to 1.8.2 in AWS S3 plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
33
diff
changeset
|
44 |
8a7a5defd5d0
upgrade orthanc framework to 1.8.2 in AWS S3 plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
33
diff
changeset
|
45 #include <Logging.h> |
15 | 46 #include <SystemToolbox.h> |
1 | 47 |
77 | 48 static std::unique_ptr<IStoragePlugin> primaryPlugin; |
49 static std::unique_ptr<IStoragePlugin> secondaryPlugin; | |
1 | 50 |
51 static std::unique_ptr<EncryptionHelpers> crypto; | |
52 static bool cryptoEnabled = false; | |
15 | 53 static std::string fileSystemRootPath; |
20 | 54 static std::string objectsRootPath; |
77 | 55 static std::string hybridModeNameForLogs = ""; |
56 | |
57 typedef enum | |
58 { | |
59 HybridMode_WriteToFileSystem, // write to disk, try to read first from disk and then, from object-storage | |
60 HybridMode_WriteToObjectStorage, // write to object storage, try to read first from object storage and then, from disk | |
61 HybridMode_Disabled // read and write only from/to object-storage | |
62 } HybridMode; | |
63 | |
64 static HybridMode hybridMode = HybridMode_Disabled; | |
65 | |
66 static bool IsReadFromDisk() | |
67 { | |
68 return hybridMode != HybridMode_Disabled; | |
69 } | |
70 | |
71 static bool IsHybridModeEnabled() | |
72 { | |
73 return hybridMode != HybridMode_Disabled; | |
74 } | |
75 | |
76 typedef void LogErrorFunction(const std::string& message); | |
77 | |
1 | 78 |
79 | |
80 static OrthancPluginErrorCode StorageCreate(const char* uuid, | |
81 const void* content, | |
82 int64_t size, | |
83 OrthancPluginContentType type) | |
84 { | |
85 try | |
86 { | |
77 | 87 OrthancPlugins::LogInfo(primaryPlugin->GetNameForLogs() + ": creating attachment " + std::string(uuid) + " of type " + boost::lexical_cast<std::string>(type)); |
88 std::unique_ptr<IStoragePlugin::IWriter> writer(primaryPlugin->GetWriterForObject(uuid, type, cryptoEnabled)); | |
1 | 89 |
90 if (cryptoEnabled) | |
91 { | |
92 std::string encryptedFile; | |
93 | |
94 try | |
95 { | |
96 crypto->Encrypt(encryptedFile, (const char*)content, size); | |
97 } | |
98 catch (EncryptionException& ex) | |
99 { | |
77 | 100 OrthancPlugins::LogError(primaryPlugin->GetNameForLogs() + ": error while encrypting object " + std::string(uuid) + ": " + ex.what()); |
1 | 101 return OrthancPluginErrorCode_StorageAreaPlugin; |
102 } | |
103 | |
104 writer->Write(encryptedFile.data(), encryptedFile.size()); | |
105 } | |
106 else | |
107 { | |
108 writer->Write(reinterpret_cast<const char*>(content), size); | |
109 } | |
110 } | |
111 catch (StoragePluginException& ex) | |
112 { | |
77 | 113 OrthancPlugins::LogError(primaryPlugin->GetNameForLogs() + ": error while creating object " + std::string(uuid) + ": " + ex.what()); |
1 | 114 return OrthancPluginErrorCode_StorageAreaPlugin; |
115 } | |
116 | |
117 return OrthancPluginErrorCode_Success; | |
118 } | |
119 | |
120 | |
77 | 121 static OrthancPluginErrorCode StorageReadRange(IStoragePlugin* plugin, |
122 LogErrorFunction logErrorFunction, | |
123 OrthancPluginMemoryBuffer64* target, // Memory buffer where to store the content of the range. The memory buffer is allocated and freed by Orthanc. The length of the range of interest corresponds to the size of this buffer. | |
39
50d0be413c42
implemented ReadRange (only in Azure plugin right now)
Alain Mazy <am@osimis.io>
parents:
37
diff
changeset
|
124 const char* uuid, |
50d0be413c42
implemented ReadRange (only in Azure plugin right now)
Alain Mazy <am@osimis.io>
parents:
37
diff
changeset
|
125 OrthancPluginContentType type, |
50d0be413c42
implemented ReadRange (only in Azure plugin right now)
Alain Mazy <am@osimis.io>
parents:
37
diff
changeset
|
126 uint64_t rangeStart) |
50d0be413c42
implemented ReadRange (only in Azure plugin right now)
Alain Mazy <am@osimis.io>
parents:
37
diff
changeset
|
127 { |
50d0be413c42
implemented ReadRange (only in Azure plugin right now)
Alain Mazy <am@osimis.io>
parents:
37
diff
changeset
|
128 assert(!cryptoEnabled); |
50d0be413c42
implemented ReadRange (only in Azure plugin right now)
Alain Mazy <am@osimis.io>
parents:
37
diff
changeset
|
129 |
50d0be413c42
implemented ReadRange (only in Azure plugin right now)
Alain Mazy <am@osimis.io>
parents:
37
diff
changeset
|
130 try |
50d0be413c42
implemented ReadRange (only in Azure plugin right now)
Alain Mazy <am@osimis.io>
parents:
37
diff
changeset
|
131 { |
77 | 132 OrthancPlugins::LogInfo(plugin->GetNameForLogs() + ": reading range of attachment " + std::string(uuid) + " of type " + boost::lexical_cast<std::string>(type)); |
133 | |
39
50d0be413c42
implemented ReadRange (only in Azure plugin right now)
Alain Mazy <am@osimis.io>
parents:
37
diff
changeset
|
134 std::unique_ptr<IStoragePlugin::IReader> reader(plugin->GetReaderForObject(uuid, type, cryptoEnabled)); |
50d0be413c42
implemented ReadRange (only in Azure plugin right now)
Alain Mazy <am@osimis.io>
parents:
37
diff
changeset
|
135 reader->ReadRange(reinterpret_cast<char*>(target->data), target->size, rangeStart); |
77 | 136 |
137 return OrthancPluginErrorCode_Success; | |
39
50d0be413c42
implemented ReadRange (only in Azure plugin right now)
Alain Mazy <am@osimis.io>
parents:
37
diff
changeset
|
138 } |
50d0be413c42
implemented ReadRange (only in Azure plugin right now)
Alain Mazy <am@osimis.io>
parents:
37
diff
changeset
|
139 catch (StoragePluginException& ex) |
50d0be413c42
implemented ReadRange (only in Azure plugin right now)
Alain Mazy <am@osimis.io>
parents:
37
diff
changeset
|
140 { |
77 | 141 logErrorFunction(std::string(StoragePluginFactory::GetStoragePluginName()) + ": error while reading object " + std::string(uuid) + ": " + std::string(ex.what())); |
142 return OrthancPluginErrorCode_StorageAreaPlugin; | |
143 } | |
144 } | |
39
50d0be413c42
implemented ReadRange (only in Azure plugin right now)
Alain Mazy <am@osimis.io>
parents:
37
diff
changeset
|
145 |
77 | 146 static OrthancPluginErrorCode StorageReadRange(OrthancPluginMemoryBuffer64* target, // Memory buffer where to store the content of the range. The memory buffer is allocated and freed by Orthanc. The length of the range of interest corresponds to the size of this buffer. |
147 const char* uuid, | |
148 OrthancPluginContentType type, | |
149 uint64_t rangeStart) | |
150 { | |
151 OrthancPluginErrorCode res = StorageReadRange(primaryPlugin.get(), | |
152 (IsHybridModeEnabled() ? OrthancPlugins::LogWarning : OrthancPlugins::LogError), // log errors as warning on first try | |
153 target, | |
154 uuid, | |
155 type, | |
156 rangeStart); | |
39
50d0be413c42
implemented ReadRange (only in Azure plugin right now)
Alain Mazy <am@osimis.io>
parents:
37
diff
changeset
|
157 |
77 | 158 if (res != OrthancPluginErrorCode_Success && IsHybridModeEnabled()) |
159 { | |
160 res = StorageReadRange(secondaryPlugin.get(), | |
161 OrthancPlugins::LogError, // log errors as errors on second try | |
162 target, | |
163 uuid, | |
164 type, | |
165 rangeStart); | |
39
50d0be413c42
implemented ReadRange (only in Azure plugin right now)
Alain Mazy <am@osimis.io>
parents:
37
diff
changeset
|
166 } |
77 | 167 return res; |
39
50d0be413c42
implemented ReadRange (only in Azure plugin right now)
Alain Mazy <am@osimis.io>
parents:
37
diff
changeset
|
168 } |
50d0be413c42
implemented ReadRange (only in Azure plugin right now)
Alain Mazy <am@osimis.io>
parents:
37
diff
changeset
|
169 |
50d0be413c42
implemented ReadRange (only in Azure plugin right now)
Alain Mazy <am@osimis.io>
parents:
37
diff
changeset
|
170 |
77 | 171 |
172 static OrthancPluginErrorCode StorageReadWhole(IStoragePlugin* plugin, | |
173 LogErrorFunction logErrorFunction, | |
174 OrthancPluginMemoryBuffer64* target, // Memory buffer where to store the content of the file. It must be allocated by the plugin using OrthancPluginCreateMemoryBuffer64(). The core of Orthanc will free it. | |
39
50d0be413c42
implemented ReadRange (only in Azure plugin right now)
Alain Mazy <am@osimis.io>
parents:
37
diff
changeset
|
175 const char* uuid, |
50d0be413c42
implemented ReadRange (only in Azure plugin right now)
Alain Mazy <am@osimis.io>
parents:
37
diff
changeset
|
176 OrthancPluginContentType type) |
1 | 177 { |
178 try | |
179 { | |
77 | 180 OrthancPlugins::LogInfo(plugin->GetNameForLogs() + ": reading whole attachment " + std::string(uuid) + " of type " + boost::lexical_cast<std::string>(type)); |
1 | 181 std::unique_ptr<IStoragePlugin::IReader> reader(plugin->GetReaderForObject(uuid, type, cryptoEnabled)); |
182 | |
183 size_t fileSize = reader->GetSize(); | |
39
50d0be413c42
implemented ReadRange (only in Azure plugin right now)
Alain Mazy <am@osimis.io>
parents:
37
diff
changeset
|
184 size_t size; |
1 | 185 |
186 if (cryptoEnabled) | |
187 { | |
39
50d0be413c42
implemented ReadRange (only in Azure plugin right now)
Alain Mazy <am@osimis.io>
parents:
37
diff
changeset
|
188 size = fileSize - crypto->OVERHEAD_SIZE; |
1 | 189 } |
190 else | |
191 { | |
39
50d0be413c42
implemented ReadRange (only in Azure plugin right now)
Alain Mazy <am@osimis.io>
parents:
37
diff
changeset
|
192 size = fileSize; |
1 | 193 } |
194 | |
39
50d0be413c42
implemented ReadRange (only in Azure plugin right now)
Alain Mazy <am@osimis.io>
parents:
37
diff
changeset
|
195 if (size <= 0) |
1 | 196 { |
77 | 197 logErrorFunction(plugin->GetNameForLogs() + ": error while reading object " + std::string(uuid) + ", size of file is too small: " + boost::lexical_cast<std::string>(fileSize) + " bytes"); |
1 | 198 return OrthancPluginErrorCode_StorageAreaPlugin; |
199 } | |
200 | |
39
50d0be413c42
implemented ReadRange (only in Azure plugin right now)
Alain Mazy <am@osimis.io>
parents:
37
diff
changeset
|
201 if (OrthancPluginCreateMemoryBuffer64(OrthancPlugins::GetGlobalContext(), target, size) != OrthancPluginErrorCode_Success) |
1 | 202 { |
77 | 203 logErrorFunction(plugin->GetNameForLogs() + ": error while reading object " + std::string(uuid) + ", cannot allocate memory of size " + boost::lexical_cast<std::string>(size) + " bytes"); |
1 | 204 return OrthancPluginErrorCode_StorageAreaPlugin; |
205 } | |
206 | |
207 if (cryptoEnabled) | |
208 { | |
209 std::vector<char> encrypted(fileSize); | |
39
50d0be413c42
implemented ReadRange (only in Azure plugin right now)
Alain Mazy <am@osimis.io>
parents:
37
diff
changeset
|
210 reader->ReadWhole(encrypted.data(), fileSize); |
1 | 211 |
212 try | |
213 { | |
39
50d0be413c42
implemented ReadRange (only in Azure plugin right now)
Alain Mazy <am@osimis.io>
parents:
37
diff
changeset
|
214 crypto->Decrypt(reinterpret_cast<char*>(target->data), encrypted.data(), fileSize); |
1 | 215 } |
216 catch (EncryptionException& ex) | |
217 { | |
77 | 218 logErrorFunction(plugin->GetNameForLogs() + ": error while decrypting object " + std::string(uuid) + ": " + ex.what()); |
1 | 219 return OrthancPluginErrorCode_StorageAreaPlugin; |
220 } | |
221 } | |
222 else | |
223 { | |
39
50d0be413c42
implemented ReadRange (only in Azure plugin right now)
Alain Mazy <am@osimis.io>
parents:
37
diff
changeset
|
224 reader->ReadWhole(reinterpret_cast<char*>(target->data), fileSize); |
1 | 225 } |
226 } | |
227 catch (StoragePluginException& ex) | |
228 { | |
77 | 229 logErrorFunction(plugin->GetNameForLogs() + ": error while decrypting object " + std::string(uuid) + ": " + ex.what()); |
230 return OrthancPluginErrorCode_StorageAreaPlugin; | |
1 | 231 } |
232 | |
233 return OrthancPluginErrorCode_Success; | |
234 } | |
235 | |
77 | 236 static OrthancPluginErrorCode StorageReadWhole(OrthancPluginMemoryBuffer64* target, // Memory buffer where to store the content of the file. It must be allocated by the plugin using OrthancPluginCreateMemoryBuffer64(). The core of Orthanc will free it. |
237 const char* uuid, | |
238 OrthancPluginContentType type) | |
239 { | |
240 OrthancPluginErrorCode res = StorageReadWhole(primaryPlugin.get(), | |
241 (IsHybridModeEnabled() ? OrthancPlugins::LogWarning : OrthancPlugins::LogError), // log errors as warning on first try | |
242 target, | |
243 uuid, | |
244 type); | |
245 | |
246 if (res != OrthancPluginErrorCode_Success && IsHybridModeEnabled()) | |
247 { | |
248 res = StorageReadWhole(secondaryPlugin.get(), | |
249 OrthancPlugins::LogError, // log errors as errors on second try | |
250 target, | |
251 uuid, | |
252 type); | |
253 } | |
254 return res; | |
255 } | |
256 | |
39
50d0be413c42
implemented ReadRange (only in Azure plugin right now)
Alain Mazy <am@osimis.io>
parents:
37
diff
changeset
|
257 static OrthancPluginErrorCode StorageReadWholeLegacy(void** content, |
50d0be413c42
implemented ReadRange (only in Azure plugin right now)
Alain Mazy <am@osimis.io>
parents:
37
diff
changeset
|
258 int64_t* size, |
50d0be413c42
implemented ReadRange (only in Azure plugin right now)
Alain Mazy <am@osimis.io>
parents:
37
diff
changeset
|
259 const char* uuid, |
50d0be413c42
implemented ReadRange (only in Azure plugin right now)
Alain Mazy <am@osimis.io>
parents:
37
diff
changeset
|
260 OrthancPluginContentType type) |
50d0be413c42
implemented ReadRange (only in Azure plugin right now)
Alain Mazy <am@osimis.io>
parents:
37
diff
changeset
|
261 { |
43
4c71c5e2edce
fix memory handling in legacy read
Alain Mazy <am@osimis.io>
parents:
39
diff
changeset
|
262 OrthancPluginMemoryBuffer64 buffer; |
4c71c5e2edce
fix memory handling in legacy read
Alain Mazy <am@osimis.io>
parents:
39
diff
changeset
|
263 OrthancPluginErrorCode result = StorageReadWhole(&buffer, uuid, type); // will allocate OrthancPluginMemoryBuffer64 |
39
50d0be413c42
implemented ReadRange (only in Azure plugin right now)
Alain Mazy <am@osimis.io>
parents:
37
diff
changeset
|
264 |
43
4c71c5e2edce
fix memory handling in legacy read
Alain Mazy <am@osimis.io>
parents:
39
diff
changeset
|
265 if (result == OrthancPluginErrorCode_Success) |
39
50d0be413c42
implemented ReadRange (only in Azure plugin right now)
Alain Mazy <am@osimis.io>
parents:
37
diff
changeset
|
266 { |
43
4c71c5e2edce
fix memory handling in legacy read
Alain Mazy <am@osimis.io>
parents:
39
diff
changeset
|
267 *size = buffer.size; |
4c71c5e2edce
fix memory handling in legacy read
Alain Mazy <am@osimis.io>
parents:
39
diff
changeset
|
268 *content = buffer.data; // orthanc will free the buffer (we don't have to delete it ourselves) |
39
50d0be413c42
implemented ReadRange (only in Azure plugin right now)
Alain Mazy <am@osimis.io>
parents:
37
diff
changeset
|
269 } |
50d0be413c42
implemented ReadRange (only in Azure plugin right now)
Alain Mazy <am@osimis.io>
parents:
37
diff
changeset
|
270 |
50d0be413c42
implemented ReadRange (only in Azure plugin right now)
Alain Mazy <am@osimis.io>
parents:
37
diff
changeset
|
271 return result; |
50d0be413c42
implemented ReadRange (only in Azure plugin right now)
Alain Mazy <am@osimis.io>
parents:
37
diff
changeset
|
272 } |
50d0be413c42
implemented ReadRange (only in Azure plugin right now)
Alain Mazy <am@osimis.io>
parents:
37
diff
changeset
|
273 |
1 | 274 |
77 | 275 // static bool StorageRemoveFromDisk(const char* uuid, |
276 // OrthancPluginContentType type) | |
277 // { | |
278 // try | |
279 // { | |
280 // namespace fs = boost::filesystem; | |
281 // bool fileExisted = false; | |
282 // fs::path path = BaseStoragePlugin::GetOrthancFileSystemPath(uuid, fileSystemRootPath); | |
283 | |
284 // try | |
285 // { | |
286 // fs::remove(path); | |
287 // fileExisted = true; | |
288 // } | |
289 // catch (...) | |
290 // { | |
291 // // Ignore the error | |
292 // fileExisted = false; | |
293 // } | |
294 | |
295 // // Remove the two parent directories, ignoring the error code if | |
296 // // these directories are not empty | |
297 | |
298 // try | |
299 // { | |
300 // boost::system::error_code err; | |
301 // fs::remove(path.parent_path(), err); | |
302 // fs::remove(path.parent_path().parent_path(), err); | |
303 // } | |
304 // catch (...) | |
305 // { | |
306 // // Ignore the error | |
307 // } | |
308 | |
309 // return fileExisted; | |
310 // } | |
311 // catch(Orthanc::OrthancException& e) | |
312 // { | |
313 // OrthancPlugins::LogError(std::string(StoragePluginFactory::GetStoragePluginName()) + ": error while deleting object " + std::string(uuid) + ": " + std::string(e.What())); | |
314 // return false; | |
315 // } | |
316 | |
317 // } | |
318 | |
319 | |
320 static OrthancPluginErrorCode StorageRemove(IStoragePlugin* plugin, | |
321 LogErrorFunction logErrorFunction, | |
322 const char* uuid, | |
1 | 323 OrthancPluginContentType type) |
324 { | |
325 try | |
326 { | |
77 | 327 OrthancPlugins::LogInfo(plugin->GetNameForLogs() + ": deleting attachment " + std::string(uuid) + " of type " + boost::lexical_cast<std::string>(type)); |
1 | 328 plugin->DeleteObject(uuid, type, cryptoEnabled); |
77 | 329 if ((plugin == primaryPlugin.get()) && IsHybridModeEnabled()) |
330 { | |
331 // not 100% sure the file has been deleted, try the secondary plugin | |
332 return OrthancPluginErrorCode_StorageAreaPlugin; | |
333 } | |
334 | |
335 return OrthancPluginErrorCode_Success; | |
1 | 336 } |
337 catch (StoragePluginException& ex) | |
338 { | |
77 | 339 logErrorFunction(std::string(StoragePluginFactory::GetStoragePluginName()) + ": error while deleting object " + std::string(uuid) + ": " + std::string(ex.what())); |
340 return OrthancPluginErrorCode_StorageAreaPlugin; | |
341 } | |
342 } | |
15 | 343 |
77 | 344 static OrthancPluginErrorCode StorageRemove(const char* uuid, |
345 OrthancPluginContentType type) | |
346 { | |
347 OrthancPluginErrorCode res = StorageRemove(primaryPlugin.get(), | |
348 (IsHybridModeEnabled() ? OrthancPlugins::LogWarning : OrthancPlugins::LogError), // log errors as warning on first try | |
349 uuid, | |
350 type); | |
15 | 351 |
77 | 352 if (res != OrthancPluginErrorCode_Success && IsHybridModeEnabled()) |
353 { | |
354 res = StorageRemove(secondaryPlugin.get(), | |
355 OrthancPlugins::LogError, // log errors as errors on second try | |
356 uuid, | |
357 type); | |
1 | 358 } |
77 | 359 return res; |
1 | 360 } |
361 | |
362 | |
363 extern "C" | |
364 { | |
365 ORTHANC_PLUGINS_API int32_t OrthancPluginInitialize(OrthancPluginContext* context) | |
366 { | |
367 OrthancPlugins::SetGlobalContext(context); | |
368 | |
57
ba1be668e475
fix initialization of the aws static library
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
56
diff
changeset
|
369 Orthanc::InitializeFramework("", false); |
15 | 370 Orthanc::Logging::InitializePluginContext(context); |
371 | |
1 | 372 OrthancPlugins::OrthancConfiguration orthancConfig; |
373 | |
374 OrthancPlugins::LogWarning(std::string(StoragePluginFactory::GetStoragePluginName()) + " plugin is initializing"); | |
375 | |
376 /* Check the version of the Orthanc core */ | |
377 if (OrthancPluginCheckVersion(context) == 0) | |
378 { | |
379 char info[1024]; | |
380 sprintf(info, "Your version of Orthanc (%s) must be above %d.%d.%d to run this plugin", | |
381 context->orthancVersion, | |
382 ORTHANC_PLUGINS_MINIMAL_MAJOR_NUMBER, | |
383 ORTHANC_PLUGINS_MINIMAL_MINOR_NUMBER, | |
384 ORTHANC_PLUGINS_MINIMAL_REVISION_NUMBER); | |
385 OrthancPlugins::LogError(info); | |
386 return -1; | |
387 } | |
388 | |
27
e1f52b851827
Added "VirtualAddressing" configuration option in the AWS S3 plugin (for compatibility with minio)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
20
diff
changeset
|
389 try |
8 | 390 { |
77 | 391 const char* pluginSectionName = StoragePluginFactory::GetConfigurationSectionName(); |
27
e1f52b851827
Added "VirtualAddressing" configuration option in the AWS S3 plugin (for compatibility with minio)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
20
diff
changeset
|
392 static const char* const ENCRYPTION_SECTION = "StorageEncryption"; |
20 | 393 |
27
e1f52b851827
Added "VirtualAddressing" configuration option in the AWS S3 plugin (for compatibility with minio)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
20
diff
changeset
|
394 if (orthancConfig.IsSection(pluginSectionName)) |
15 | 395 { |
27
e1f52b851827
Added "VirtualAddressing" configuration option in the AWS S3 plugin (for compatibility with minio)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
20
diff
changeset
|
396 OrthancPlugins::OrthancConfiguration pluginSection; |
e1f52b851827
Added "VirtualAddressing" configuration option in the AWS S3 plugin (for compatibility with minio)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
20
diff
changeset
|
397 orthancConfig.GetSection(pluginSection, pluginSectionName); |
e1f52b851827
Added "VirtualAddressing" configuration option in the AWS S3 plugin (for compatibility with minio)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
20
diff
changeset
|
398 |
77 | 399 bool migrationFromFileSystemEnabled = pluginSection.GetBooleanValue("MigrationFromFileSystemEnabled", false); |
400 std::string hybridModeString = pluginSection.GetStringValue("HybridMode", "Disabled"); | |
27
e1f52b851827
Added "VirtualAddressing" configuration option in the AWS S3 plugin (for compatibility with minio)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
20
diff
changeset
|
401 |
77 | 402 if (migrationFromFileSystemEnabled && hybridModeString == "Disabled") |
403 { | |
404 hybridMode = HybridMode_WriteToObjectStorage; | |
405 OrthancPlugins::LogWarning(std::string(StoragePluginFactory::GetStoragePluginName()) + ": 'MigrationFromFileSystemEnabled' configuration is deprecated, use 'HybridMode': 'WriteToObjectStorage' instead"); | |
406 } | |
407 else if (hybridModeString == "WriteToObjectStorage") | |
408 { | |
409 hybridMode = HybridMode_WriteToObjectStorage; | |
410 OrthancPlugins::LogWarning(std::string(StoragePluginFactory::GetStoragePluginName()) + ": WriteToObjectStorage HybridMode is enabled: writing to object-storage, try reading first from object-storage and, then, from file system"); | |
411 } | |
412 else if (hybridModeString == "WriteToFileSystem") | |
413 { | |
414 hybridMode = HybridMode_WriteToFileSystem; | |
415 OrthancPlugins::LogWarning(std::string(StoragePluginFactory::GetStoragePluginName()) + ": WriteToFileSystem HybridMode is enabled: writing to file system, try reading first from file system and, then, from object-storage"); | |
416 } | |
417 else | |
418 { | |
419 OrthancPlugins::LogWarning(std::string(StoragePluginFactory::GetStoragePluginName()) + ": HybridMode is disabled enabled: writing to object-storage and reading only from object-storage"); | |
420 } | |
421 | |
422 if (IsReadFromDisk()) | |
27
e1f52b851827
Added "VirtualAddressing" configuration option in the AWS S3 plugin (for compatibility with minio)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
20
diff
changeset
|
423 { |
e1f52b851827
Added "VirtualAddressing" configuration option in the AWS S3 plugin (for compatibility with minio)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
20
diff
changeset
|
424 fileSystemRootPath = orthancConfig.GetStringValue("StorageDirectory", "OrthancStorageNotDefined"); |
77 | 425 OrthancPlugins::LogWarning(std::string(StoragePluginFactory::GetStoragePluginName()) + ": HybridMode: reading from file system is enabled, source: " + fileSystemRootPath); |
27
e1f52b851827
Added "VirtualAddressing" configuration option in the AWS S3 plugin (for compatibility with minio)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
20
diff
changeset
|
426 } |
e1f52b851827
Added "VirtualAddressing" configuration option in the AWS S3 plugin (for compatibility with minio)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
20
diff
changeset
|
427 |
e1f52b851827
Added "VirtualAddressing" configuration option in the AWS S3 plugin (for compatibility with minio)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
20
diff
changeset
|
428 objectsRootPath = pluginSection.GetStringValue("RootPath", std::string()); |
33 | 429 |
430 if (objectsRootPath.size() >= 1 && objectsRootPath[0] == '/') | |
431 { | |
432 OrthancPlugins::LogError(std::string(StoragePluginFactory::GetStoragePluginName()) + ": The RootPath shall not start with a '/': " + objectsRootPath); | |
433 return -1; | |
434 } | |
15 | 435 |
77 | 436 std::string objecstStoragePluginName = StoragePluginFactory::GetStoragePluginName(); |
437 if (hybridMode == HybridMode_WriteToFileSystem) | |
438 { | |
439 objecstStoragePluginName += " (Secondary: object-storage)"; | |
440 } | |
441 else if (hybridMode == HybridMode_WriteToObjectStorage) | |
442 { | |
443 objecstStoragePluginName += " (Primary: object-storage)"; | |
444 } | |
445 | |
446 std::unique_ptr<IStoragePlugin> objectStoragePlugin(StoragePluginFactory::CreateStoragePlugin(objecstStoragePluginName, orthancConfig)); | |
447 | |
448 if (objectStoragePlugin.get() == nullptr) | |
449 { | |
450 return -1; | |
451 } | |
452 | |
453 objectStoragePlugin->SetRootPath(objectsRootPath); | |
454 | |
455 std::unique_ptr<IStoragePlugin> fileSystemStoragePlugin; | |
456 if (IsHybridModeEnabled()) | |
457 { | |
458 bool fsync = orthancConfig.GetBooleanValue("SyncStorageArea", true); | |
459 | |
460 std::string filesystemStoragePluginName = StoragePluginFactory::GetStoragePluginName(); | |
461 if (hybridMode == HybridMode_WriteToFileSystem) | |
462 { | |
463 filesystemStoragePluginName += " (Primary: file-system)"; | |
464 } | |
465 else if (hybridMode == HybridMode_WriteToObjectStorage) | |
466 { | |
467 filesystemStoragePluginName += " (Secondary: file-system)"; | |
468 } | |
469 | |
470 fileSystemStoragePlugin.reset(new FileSystemStoragePlugin(filesystemStoragePluginName, fileSystemRootPath, fsync)); | |
471 } | |
472 | |
473 if (hybridMode == HybridMode_Disabled || hybridMode == HybridMode_WriteToObjectStorage) | |
474 { | |
475 primaryPlugin.reset(objectStoragePlugin.release()); | |
476 | |
477 if (hybridMode == HybridMode_WriteToObjectStorage) | |
478 { | |
479 secondaryPlugin.reset(fileSystemStoragePlugin.release()); | |
480 } | |
481 } | |
482 else if (hybridMode == HybridMode_WriteToFileSystem) | |
483 { | |
484 primaryPlugin.reset(fileSystemStoragePlugin.release()); | |
485 secondaryPlugin.reset(objectStoragePlugin.release()); | |
486 } | |
15 | 487 |
27
e1f52b851827
Added "VirtualAddressing" configuration option in the AWS S3 plugin (for compatibility with minio)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
20
diff
changeset
|
488 if (pluginSection.IsSection(ENCRYPTION_SECTION)) |
e1f52b851827
Added "VirtualAddressing" configuration option in the AWS S3 plugin (for compatibility with minio)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
20
diff
changeset
|
489 { |
e1f52b851827
Added "VirtualAddressing" configuration option in the AWS S3 plugin (for compatibility with minio)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
20
diff
changeset
|
490 OrthancPlugins::OrthancConfiguration cryptoSection; |
e1f52b851827
Added "VirtualAddressing" configuration option in the AWS S3 plugin (for compatibility with minio)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
20
diff
changeset
|
491 pluginSection.GetSection(cryptoSection, ENCRYPTION_SECTION); |
e1f52b851827
Added "VirtualAddressing" configuration option in the AWS S3 plugin (for compatibility with minio)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
20
diff
changeset
|
492 |
e1f52b851827
Added "VirtualAddressing" configuration option in the AWS S3 plugin (for compatibility with minio)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
20
diff
changeset
|
493 crypto.reset(EncryptionConfigurator::CreateEncryptionHelpers(cryptoSection)); |
e1f52b851827
Added "VirtualAddressing" configuration option in the AWS S3 plugin (for compatibility with minio)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
20
diff
changeset
|
494 cryptoEnabled = crypto.get() != nullptr; |
e1f52b851827
Added "VirtualAddressing" configuration option in the AWS S3 plugin (for compatibility with minio)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
20
diff
changeset
|
495 } |
e1f52b851827
Added "VirtualAddressing" configuration option in the AWS S3 plugin (for compatibility with minio)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
20
diff
changeset
|
496 |
e1f52b851827
Added "VirtualAddressing" configuration option in the AWS S3 plugin (for compatibility with minio)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
20
diff
changeset
|
497 if (cryptoEnabled) |
e1f52b851827
Added "VirtualAddressing" configuration option in the AWS S3 plugin (for compatibility with minio)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
20
diff
changeset
|
498 { |
e1f52b851827
Added "VirtualAddressing" configuration option in the AWS S3 plugin (for compatibility with minio)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
20
diff
changeset
|
499 OrthancPlugins::LogWarning(std::string(StoragePluginFactory::GetStoragePluginName()) + ": client-side encryption is enabled"); |
e1f52b851827
Added "VirtualAddressing" configuration option in the AWS S3 plugin (for compatibility with minio)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
20
diff
changeset
|
500 } |
e1f52b851827
Added "VirtualAddressing" configuration option in the AWS S3 plugin (for compatibility with minio)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
20
diff
changeset
|
501 else |
e1f52b851827
Added "VirtualAddressing" configuration option in the AWS S3 plugin (for compatibility with minio)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
20
diff
changeset
|
502 { |
e1f52b851827
Added "VirtualAddressing" configuration option in the AWS S3 plugin (for compatibility with minio)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
20
diff
changeset
|
503 OrthancPlugins::LogWarning(std::string(StoragePluginFactory::GetStoragePluginName()) + ": client-side encryption is disabled"); |
e1f52b851827
Added "VirtualAddressing" configuration option in the AWS S3 plugin (for compatibility with minio)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
20
diff
changeset
|
504 } |
77 | 505 |
506 | |
15 | 507 } |
508 | |
39
50d0be413c42
implemented ReadRange (only in Azure plugin right now)
Alain Mazy <am@osimis.io>
parents:
37
diff
changeset
|
509 if (cryptoEnabled) |
50d0be413c42
implemented ReadRange (only in Azure plugin right now)
Alain Mazy <am@osimis.io>
parents:
37
diff
changeset
|
510 { |
50d0be413c42
implemented ReadRange (only in Azure plugin right now)
Alain Mazy <am@osimis.io>
parents:
37
diff
changeset
|
511 // with encrypted file, we do not want to support ReadRange. Therefore, we register the old interface |
50d0be413c42
implemented ReadRange (only in Azure plugin right now)
Alain Mazy <am@osimis.io>
parents:
37
diff
changeset
|
512 OrthancPluginRegisterStorageArea(context, StorageCreate, StorageReadWholeLegacy, StorageRemove); |
50d0be413c42
implemented ReadRange (only in Azure plugin right now)
Alain Mazy <am@osimis.io>
parents:
37
diff
changeset
|
513 } |
50d0be413c42
implemented ReadRange (only in Azure plugin right now)
Alain Mazy <am@osimis.io>
parents:
37
diff
changeset
|
514 else |
50d0be413c42
implemented ReadRange (only in Azure plugin right now)
Alain Mazy <am@osimis.io>
parents:
37
diff
changeset
|
515 { |
50d0be413c42
implemented ReadRange (only in Azure plugin right now)
Alain Mazy <am@osimis.io>
parents:
37
diff
changeset
|
516 OrthancPluginRegisterStorageArea2(context, StorageCreate, StorageReadWhole, StorageReadRange, StorageRemove); |
50d0be413c42
implemented ReadRange (only in Azure plugin right now)
Alain Mazy <am@osimis.io>
parents:
37
diff
changeset
|
517 } |
1 | 518 } |
27
e1f52b851827
Added "VirtualAddressing" configuration option in the AWS S3 plugin (for compatibility with minio)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
20
diff
changeset
|
519 catch (Orthanc::OrthancException& e) |
e1f52b851827
Added "VirtualAddressing" configuration option in the AWS S3 plugin (for compatibility with minio)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
20
diff
changeset
|
520 { |
e1f52b851827
Added "VirtualAddressing" configuration option in the AWS S3 plugin (for compatibility with minio)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
20
diff
changeset
|
521 LOG(ERROR) << "Exception while creating the object storage plugin: " << e.What(); |
e1f52b851827
Added "VirtualAddressing" configuration option in the AWS S3 plugin (for compatibility with minio)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
20
diff
changeset
|
522 return -1; |
e1f52b851827
Added "VirtualAddressing" configuration option in the AWS S3 plugin (for compatibility with minio)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
20
diff
changeset
|
523 } |
1 | 524 |
525 return 0; | |
526 } | |
527 | |
528 | |
529 ORTHANC_PLUGINS_API void OrthancPluginFinalize() | |
530 { | |
531 OrthancPlugins::LogWarning(std::string(StoragePluginFactory::GetStoragePluginName()) + " plugin is finalizing"); | |
77 | 532 primaryPlugin.reset(); |
533 secondaryPlugin.reset(); | |
57
ba1be668e475
fix initialization of the aws static library
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
56
diff
changeset
|
534 Orthanc::FinalizeFramework(); |
1 | 535 } |
536 | |
537 | |
538 ORTHANC_PLUGINS_API const char* OrthancPluginGetName() | |
539 { | |
540 return StoragePluginFactory::GetStoragePluginName(); | |
541 } | |
542 | |
543 | |
544 ORTHANC_PLUGINS_API const char* OrthancPluginGetVersion() | |
545 { | |
546 return PLUGIN_VERSION; | |
547 } | |
548 } | |
549 |