comparison Common/StoragePlugin.cpp @ 152:d62f52be1943

use Orthanc frameworking for logging
author Sebastien Jodogne <s.jodogne@gmail.com>
date Fri, 21 Jun 2024 11:22:57 +0200
parents 00cd1f01dd5d
children 99c14487f96b
comparison
equal deleted inserted replaced
151:00cd1f01dd5d 152:d62f52be1943
79 return hybridMode != HybridMode_Disabled; 79 return hybridMode != HybridMode_Disabled;
80 } 80 }
81 81
82 typedef void LogErrorFunction(const std::string& message); 82 typedef void LogErrorFunction(const std::string& message);
83 83
84 static void LogErrorAsWarning(const std::string& message)
85 {
86 LOG(WARNING) << message;
87 }
88
89 static void LogErrorAsError(const std::string& message)
90 {
91 LOG(ERROR) << message;
92 }
93
84 94
85 95
86 static OrthancPluginErrorCode StorageCreate(const char* uuid, 96 static OrthancPluginErrorCode StorageCreate(const char* uuid,
87 const void* content, 97 const void* content,
88 int64_t size, 98 int64_t size,
89 OrthancPluginContentType type) 99 OrthancPluginContentType type)
90 { 100 {
91 try 101 try
92 { 102 {
93 Orthanc::Toolbox::ElapsedTimer timer; 103 Orthanc::Toolbox::ElapsedTimer timer;
94 OrthancPlugins::LogInfo(primaryStorage->GetNameForLogs() + ": creating attachment " + std::string(uuid) + " of type " + boost::lexical_cast<std::string>(type)); 104 LOG(INFO) << primaryStorage->GetNameForLogs() << ": creating attachment " << uuid
105 << " of type " << boost::lexical_cast<std::string>(type);
95 std::unique_ptr<IStorage::IWriter> writer(primaryStorage->GetWriterForObject(uuid, type, cryptoEnabled)); 106 std::unique_ptr<IStorage::IWriter> writer(primaryStorage->GetWriterForObject(uuid, type, cryptoEnabled));
96 107
97 if (cryptoEnabled) 108 if (cryptoEnabled)
98 { 109 {
99 std::string encryptedFile; 110 std::string encryptedFile;
102 { 113 {
103 crypto->Encrypt(encryptedFile, (const char*)content, size); 114 crypto->Encrypt(encryptedFile, (const char*)content, size);
104 } 115 }
105 catch (EncryptionException& ex) 116 catch (EncryptionException& ex)
106 { 117 {
107 OrthancPlugins::LogError(primaryStorage->GetNameForLogs() + ": error while encrypting object " + std::string(uuid) + ": " + ex.what()); 118 LOG(ERROR) << primaryStorage->GetNameForLogs() << ": error while encrypting object " << uuid << ": " << ex.what();
108 return OrthancPluginErrorCode_StorageAreaPlugin; 119 return OrthancPluginErrorCode_StorageAreaPlugin;
109 } 120 }
110 121
111 writer->Write(encryptedFile.data(), encryptedFile.size()); 122 writer->Write(encryptedFile.data(), encryptedFile.size());
112 } 123 }
113 else 124 else
114 { 125 {
115 writer->Write(reinterpret_cast<const char*>(content), size); 126 writer->Write(reinterpret_cast<const char*>(content), size);
116 } 127 }
117 OrthancPlugins::LogInfo(primaryStorage->GetNameForLogs() + ": created attachment " + std::string(uuid) + " (" + timer.GetHumanTransferSpeed(true, size) + ")"); 128 LOG(INFO) << primaryStorage->GetNameForLogs() << ": created attachment " << uuid
129 << " (" << timer.GetHumanTransferSpeed(true, size) << ")";
118 } 130 }
119 catch (StoragePluginException& ex) 131 catch (StoragePluginException& ex)
120 { 132 {
121 OrthancPlugins::LogError(primaryStorage->GetNameForLogs() + ": error while creating object " + std::string(uuid) + ": " + ex.what()); 133 LOG(ERROR) << primaryStorage->GetNameForLogs() << ": error while creating object " << uuid << ": " << ex.what();
122 return OrthancPluginErrorCode_StorageAreaPlugin; 134 return OrthancPluginErrorCode_StorageAreaPlugin;
123 } 135 }
124 136
125 return OrthancPluginErrorCode_Success; 137 return OrthancPluginErrorCode_Success;
126 } 138 }
136 assert(!cryptoEnabled); 148 assert(!cryptoEnabled);
137 149
138 try 150 try
139 { 151 {
140 Orthanc::Toolbox::ElapsedTimer timer; 152 Orthanc::Toolbox::ElapsedTimer timer;
141 OrthancPlugins::LogInfo(storage->GetNameForLogs() + ": reading range of attachment " + std::string(uuid) + " of type " + boost::lexical_cast<std::string>(type)); 153 LOG(INFO) << storage->GetNameForLogs() << ": reading range of attachment " << uuid
154 << " of type " << boost::lexical_cast<std::string>(type);
142 155
143 std::unique_ptr<IStorage::IReader> reader(storage->GetReaderForObject(uuid, type, cryptoEnabled)); 156 std::unique_ptr<IStorage::IReader> reader(storage->GetReaderForObject(uuid, type, cryptoEnabled));
144 reader->ReadRange(reinterpret_cast<char*>(target->data), target->size, rangeStart); 157 reader->ReadRange(reinterpret_cast<char*>(target->data), target->size, rangeStart);
145 158
146 OrthancPlugins::LogInfo(storage->GetNameForLogs() + ": read range of attachment " + std::string(uuid) + " (" + timer.GetHumanTransferSpeed(true, target->size) + ")"); 159 LOG(INFO) << storage->GetNameForLogs() << ": read range of attachment " << uuid
160 << " (" << timer.GetHumanTransferSpeed(true, target->size) << ")";
147 return OrthancPluginErrorCode_Success; 161 return OrthancPluginErrorCode_Success;
148 } 162 }
149 catch (StoragePluginException& ex) 163 catch (StoragePluginException& ex)
150 { 164 {
151 logErrorFunction(std::string(StoragePluginFactory::GetStoragePluginName()) + ": error while reading object " + std::string(uuid) + ": " + std::string(ex.what())); 165 logErrorFunction(std::string(StoragePluginFactory::GetStoragePluginName()) + ": error while reading object " + std::string(uuid) + ": " + std::string(ex.what()));
157 const char* uuid, 171 const char* uuid,
158 OrthancPluginContentType type, 172 OrthancPluginContentType type,
159 uint64_t rangeStart) 173 uint64_t rangeStart)
160 { 174 {
161 OrthancPluginErrorCode res = StorageReadRange(primaryStorage.get(), 175 OrthancPluginErrorCode res = StorageReadRange(primaryStorage.get(),
162 (IsHybridModeEnabled() ? OrthancPlugins::LogWarning : OrthancPlugins::LogError), // log errors as warning on first try 176 (IsHybridModeEnabled() ? LogErrorAsWarning : LogErrorAsError), // log errors as warning on first try
163 target, 177 target,
164 uuid, 178 uuid,
165 type, 179 type,
166 rangeStart); 180 rangeStart);
167 181
168 if (res != OrthancPluginErrorCode_Success && IsHybridModeEnabled()) 182 if (res != OrthancPluginErrorCode_Success && IsHybridModeEnabled())
169 { 183 {
170 res = StorageReadRange(secondaryStorage.get(), 184 res = StorageReadRange(secondaryStorage.get(),
171 OrthancPlugins::LogError, // log errors as errors on second try 185 LogErrorAsError, // log errors as errors on second try
172 target, 186 target,
173 uuid, 187 uuid,
174 type, 188 type,
175 rangeStart); 189 rangeStart);
176 } 190 }
186 OrthancPluginContentType type) 200 OrthancPluginContentType type)
187 { 201 {
188 try 202 try
189 { 203 {
190 Orthanc::Toolbox::ElapsedTimer timer; 204 Orthanc::Toolbox::ElapsedTimer timer;
191 OrthancPlugins::LogInfo(storage->GetNameForLogs() + ": reading whole attachment " + std::string(uuid) + " of type " + boost::lexical_cast<std::string>(type)); 205 LOG(INFO) << storage->GetNameForLogs() << ": reading whole attachment " << uuid
206 << " of type " << boost::lexical_cast<std::string>(type);
192 std::unique_ptr<IStorage::IReader> reader(storage->GetReaderForObject(uuid, type, cryptoEnabled)); 207 std::unique_ptr<IStorage::IReader> reader(storage->GetReaderForObject(uuid, type, cryptoEnabled));
193 208
194 size_t fileSize = reader->GetSize(); 209 size_t fileSize = reader->GetSize();
195 size_t size; 210 size_t size;
196 211
233 else 248 else
234 { 249 {
235 reader->ReadWhole(reinterpret_cast<char*>(target->data), fileSize); 250 reader->ReadWhole(reinterpret_cast<char*>(target->data), fileSize);
236 } 251 }
237 252
238 OrthancPlugins::LogInfo(storage->GetNameForLogs() + ": read whole attachment " + std::string(uuid) + " (" + timer.GetHumanTransferSpeed(true, fileSize) + ")"); 253 LOG(INFO) << storage->GetNameForLogs() << ": read whole attachment " << uuid
254 << " (" << timer.GetHumanTransferSpeed(true, fileSize) << ")";
239 } 255 }
240 catch (StoragePluginException& ex) 256 catch (StoragePluginException& ex)
241 { 257 {
242 logErrorFunction(storage->GetNameForLogs() + ": error while reading object " + std::string(uuid) + ": " + ex.what()); 258 logErrorFunction(storage->GetNameForLogs() + ": error while reading object " + std::string(uuid) + ": " + ex.what());
243 return OrthancPluginErrorCode_StorageAreaPlugin; 259 return OrthancPluginErrorCode_StorageAreaPlugin;
249 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. 265 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.
250 const char* uuid, 266 const char* uuid,
251 OrthancPluginContentType type) 267 OrthancPluginContentType type)
252 { 268 {
253 OrthancPluginErrorCode res = StorageReadWhole(primaryStorage.get(), 269 OrthancPluginErrorCode res = StorageReadWhole(primaryStorage.get(),
254 (IsHybridModeEnabled() ? OrthancPlugins::LogWarning : OrthancPlugins::LogError), // log errors as warning on first try 270 (IsHybridModeEnabled() ? LogErrorAsWarning : LogErrorAsError), // log errors as warning on first try
255 target, 271 target,
256 uuid, 272 uuid,
257 type); 273 type);
258 274
259 if (res != OrthancPluginErrorCode_Success && IsHybridModeEnabled()) 275 if (res != OrthancPluginErrorCode_Success && IsHybridModeEnabled())
260 { 276 {
261 res = StorageReadWhole(secondaryStorage.get(), 277 res = StorageReadWhole(secondaryStorage.get(),
262 OrthancPlugins::LogError, // log errors as errors on second try 278 LogErrorAsError, // log errors as errors on second try
263 target, 279 target,
264 uuid, 280 uuid,
265 type); 281 type);
266 } 282 }
267 return res; 283 return res;
290 const char* uuid, 306 const char* uuid,
291 OrthancPluginContentType type) 307 OrthancPluginContentType type)
292 { 308 {
293 try 309 try
294 { 310 {
295 OrthancPlugins::LogInfo(storage->GetNameForLogs() + ": deleting attachment " + std::string(uuid) + " of type " + boost::lexical_cast<std::string>(type)); 311 LOG(INFO) << storage->GetNameForLogs() << ": deleting attachment " << uuid
312 << " of type " << boost::lexical_cast<std::string>(type);
296 storage->DeleteObject(uuid, type, cryptoEnabled); 313 storage->DeleteObject(uuid, type, cryptoEnabled);
297 if ((storage == primaryStorage.get()) && IsHybridModeEnabled()) 314 if ((storage == primaryStorage.get()) && IsHybridModeEnabled())
298 { 315 {
299 // not 100% sure the file has been deleted, try the secondary plugin 316 // not 100% sure the file has been deleted, try the secondary plugin
300 return OrthancPluginErrorCode_StorageAreaPlugin; 317 return OrthancPluginErrorCode_StorageAreaPlugin;
311 328
312 static OrthancPluginErrorCode StorageRemove(const char* uuid, 329 static OrthancPluginErrorCode StorageRemove(const char* uuid,
313 OrthancPluginContentType type) 330 OrthancPluginContentType type)
314 { 331 {
315 OrthancPluginErrorCode res = StorageRemove(primaryStorage.get(), 332 OrthancPluginErrorCode res = StorageRemove(primaryStorage.get(),
316 (IsHybridModeEnabled() ? OrthancPlugins::LogWarning : OrthancPlugins::LogError), // log errors as warning on first try 333 (IsHybridModeEnabled() ? LogErrorAsWarning : LogErrorAsError), // log errors as warning on first try
317 uuid, 334 uuid,
318 type); 335 type);
319 336
320 if (res != OrthancPluginErrorCode_Success && IsHybridModeEnabled()) 337 if (res != OrthancPluginErrorCode_Success && IsHybridModeEnabled())
321 { 338 {
322 res = StorageRemove(secondaryStorage.get(), 339 res = StorageRemove(secondaryStorage.get(),
323 OrthancPlugins::LogError, // log errors as errors on second try 340 LogErrorAsError, // log errors as errors on second try
324 uuid, 341 uuid,
325 type); 342 type);
326 } 343 }
327 return res; 344 return res;
328 } 345 }
450 { 467 {
451 throw Orthanc::OrthancException(Orthanc::ErrorCode_UnknownResource); 468 throw Orthanc::OrthancException(Orthanc::ErrorCode_UnknownResource);
452 } 469 }
453 } 470 }
454 471
455 OrthancPlugins::LogInfo("Moving " + boost::lexical_cast<std::string>(instances.size()) + " instances to " + targetStorage); 472 LOG(INFO) << "Moving " << instances.size() << " instances to " << targetStorage;
456 473
457 std::unique_ptr<MoveStorageJob> job(CreateMoveStorageJob(targetStorage, instances, resourcesForJobContent)); 474 std::unique_ptr<MoveStorageJob> job(CreateMoveStorageJob(targetStorage, instances, resourcesForJobContent));
458 475
459 OrthancPlugins::OrthancJob::SubmitFromRestApiPost(output, requestPayload, job.release()); 476 OrthancPlugins::OrthancJob::SubmitFromRestApiPost(output, requestPayload, job.release());
460 } 477 }
545 sprintf(info, "Your version of Orthanc (%s) must be above %d.%d.%d to run this plugin", 562 sprintf(info, "Your version of Orthanc (%s) must be above %d.%d.%d to run this plugin",
546 context->orthancVersion, 563 context->orthancVersion,
547 ORTHANC_PLUGINS_MINIMAL_MAJOR_NUMBER, 564 ORTHANC_PLUGINS_MINIMAL_MAJOR_NUMBER,
548 ORTHANC_PLUGINS_MINIMAL_MINOR_NUMBER, 565 ORTHANC_PLUGINS_MINIMAL_MINOR_NUMBER,
549 ORTHANC_PLUGINS_MINIMAL_REVISION_NUMBER); 566 ORTHANC_PLUGINS_MINIMAL_REVISION_NUMBER);
550 OrthancPlugins::LogError(info); 567 LOG(ERROR) << info;
551 return -1; 568 return -1;
552 } 569 }
553 570
554 Orthanc::InitializeFramework("", false); 571 Orthanc::InitializeFramework("", false);
555 572
556 OrthancPlugins::OrthancConfiguration orthancConfig; 573 OrthancPlugins::OrthancConfiguration orthancConfig;
557 574
558 OrthancPlugins::LogWarning(std::string(StoragePluginFactory::GetStoragePluginName()) + " plugin is initializing"); 575 LOG(WARNING) << StoragePluginFactory::GetStoragePluginName() << " plugin is initializing";
559 OrthancPlugins::SetDescription(StoragePluginFactory::GetStoragePluginName(), StoragePluginFactory::GetStorageDescription()); 576 OrthancPlugins::SetDescription(StoragePluginFactory::GetStoragePluginName(), StoragePluginFactory::GetStorageDescription());
560 577
561 try 578 try
562 { 579 {
563 const char* pluginSectionName = StoragePluginFactory::GetConfigurationSectionName(); 580 const char* pluginSectionName = StoragePluginFactory::GetConfigurationSectionName();
564 static const char* const ENCRYPTION_SECTION = "StorageEncryption"; 581 static const char* const ENCRYPTION_SECTION = "StorageEncryption";
565 582
566 if (!orthancConfig.IsSection(pluginSectionName)) 583 if (!orthancConfig.IsSection(pluginSectionName))
567 { 584 {
568 OrthancPlugins::LogWarning(std::string(StoragePluginFactory::GetStoragePluginName()) + ": no \"" + pluginSectionName + "\" section found in configuration, plugin is disabled"); 585 LOG(WARNING) << StoragePluginFactory::GetStoragePluginName() << ": no \"" << pluginSectionName
586 << "\" section found in configuration, plugin is disabled";
569 return 0; 587 return 0;
570 } 588 }
571 589
572 OrthancPlugins::OrthancConfiguration pluginSection; 590 OrthancPlugins::OrthancConfiguration pluginSection;
573 orthancConfig.GetSection(pluginSection, pluginSectionName); 591 orthancConfig.GetSection(pluginSection, pluginSectionName);
576 std::string hybridModeString = pluginSection.GetStringValue("HybridMode", "Disabled"); 594 std::string hybridModeString = pluginSection.GetStringValue("HybridMode", "Disabled");
577 595
578 if (migrationFromFileSystemEnabled && hybridModeString == "Disabled") 596 if (migrationFromFileSystemEnabled && hybridModeString == "Disabled")
579 { 597 {
580 hybridMode = HybridMode_WriteToObjectStorage; 598 hybridMode = HybridMode_WriteToObjectStorage;
581 OrthancPlugins::LogWarning(std::string(StoragePluginFactory::GetStoragePluginName()) + ": 'MigrationFromFileSystemEnabled' configuration is deprecated, use 'HybridMode': 'WriteToObjectStorage' instead"); 599 LOG(WARNING) << StoragePluginFactory::GetStoragePluginName() << ": 'MigrationFromFileSystemEnabled' configuration is deprecated, use 'HybridMode': 'WriteToObjectStorage' instead";
582 } 600 }
583 else if (hybridModeString == "WriteToObjectStorage") 601 else if (hybridModeString == "WriteToObjectStorage")
584 { 602 {
585 hybridMode = HybridMode_WriteToObjectStorage; 603 hybridMode = HybridMode_WriteToObjectStorage;
586 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"); 604 LOG(WARNING) << StoragePluginFactory::GetStoragePluginName() << ": WriteToObjectStorage HybridMode is enabled: writing to object-storage, try reading first from object-storage and, then, from file system";
587 } 605 }
588 else if (hybridModeString == "WriteToFileSystem") 606 else if (hybridModeString == "WriteToFileSystem")
589 { 607 {
590 hybridMode = HybridMode_WriteToFileSystem; 608 hybridMode = HybridMode_WriteToFileSystem;
591 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"); 609 LOG(WARNING) << StoragePluginFactory::GetStoragePluginName() << ": WriteToFileSystem HybridMode is enabled: writing to file system, try reading first from file system and, then, from object-storage";
592 } 610 }
593 else 611 else
594 { 612 {
595 OrthancPlugins::LogWarning(std::string(StoragePluginFactory::GetStoragePluginName()) + ": HybridMode is disabled: writing to object-storage and reading only from object-storage"); 613 LOG(WARNING) << StoragePluginFactory::GetStoragePluginName() << ": HybridMode is disabled: writing to object-storage and reading only from object-storage";
596 } 614 }
597 615
598 if (IsReadFromDisk()) 616 if (IsReadFromDisk())
599 { 617 {
600 fileSystemRootPath = orthancConfig.GetStringValue("StorageDirectory", "OrthancStorageNotDefined"); 618 fileSystemRootPath = orthancConfig.GetStringValue("StorageDirectory", "OrthancStorageNotDefined");
601 OrthancPlugins::LogWarning(std::string(StoragePluginFactory::GetStoragePluginName()) + ": HybridMode: reading from file system is enabled, source: " + fileSystemRootPath); 619 LOG(WARNING) << StoragePluginFactory::GetStoragePluginName() << ": HybridMode: reading from file system is enabled, source: " << fileSystemRootPath;
602 } 620 }
603 621
604 objectsRootPath = pluginSection.GetStringValue("RootPath", std::string()); 622 objectsRootPath = pluginSection.GetStringValue("RootPath", std::string());
605 623
606 if (objectsRootPath.size() >= 1 && objectsRootPath[0] == '/') 624 if (objectsRootPath.size() >= 1 && objectsRootPath[0] == '/')
607 { 625 {
608 OrthancPlugins::LogError(std::string(StoragePluginFactory::GetStoragePluginName()) + ": The RootPath shall not start with a '/': " + objectsRootPath); 626 LOG(ERROR) << StoragePluginFactory::GetStoragePluginName() << ": The RootPath shall not start with a '/': " << objectsRootPath;
609 return -1; 627 return -1;
610 } 628 }
611 629
612 std::string objecstStoragePluginName = StoragePluginFactory::GetStoragePluginName(); 630 std::string objecstStoragePluginName = StoragePluginFactory::GetStoragePluginName();
613 if (hybridMode == HybridMode_WriteToFileSystem) 631 if (hybridMode == HybridMode_WriteToFileSystem)
670 cryptoEnabled = crypto.get() != nullptr; 688 cryptoEnabled = crypto.get() != nullptr;
671 } 689 }
672 690
673 if (cryptoEnabled) 691 if (cryptoEnabled)
674 { 692 {
675 OrthancPlugins::LogWarning(std::string(StoragePluginFactory::GetStoragePluginName()) + ": client-side encryption is enabled"); 693 LOG(WARNING) << StoragePluginFactory::GetStoragePluginName() << ": client-side encryption is enabled";
676 } 694 }
677 else 695 else
678 { 696 {
679 OrthancPlugins::LogWarning(std::string(StoragePluginFactory::GetStoragePluginName()) + ": client-side encryption is disabled"); 697 LOG(WARNING) << StoragePluginFactory::GetStoragePluginName() << ": client-side encryption is disabled";
680 } 698 }
681 699
682 700
683 if (IsHybridModeEnabled()) 701 if (IsHybridModeEnabled())
684 { 702 {
706 } 724 }
707 725
708 726
709 ORTHANC_PLUGINS_API void OrthancPluginFinalize() 727 ORTHANC_PLUGINS_API void OrthancPluginFinalize()
710 { 728 {
711 OrthancPlugins::LogWarning(std::string(StoragePluginFactory::GetStoragePluginName()) + " plugin is finalizing"); 729 LOG(WARNING) << StoragePluginFactory::GetStoragePluginName() << " plugin is finalizing";
712 primaryStorage.reset(); 730 primaryStorage.reset();
713 secondaryStorage.reset(); 731 secondaryStorage.reset();
714 Orthanc::FinalizeFramework(); 732 Orthanc::FinalizeFramework();
715 } 733 }
716 734