comparison OrthancServer/Plugins/Engine/OrthancPlugins.cpp @ 4484:64f06e7d5fc7

new abstraction IMemoryBuffer to avoid unnecessary copies of std::string buffers
author Sebastien Jodogne <s.jodogne@gmail.com>
date Thu, 28 Jan 2021 19:03:19 +0100
parents a926f8995d0b
children fa2311f94d9f
comparison
equal deleted inserted replaced
4483:a926f8995d0b 4484:64f06e7d5fc7
57 #include "../../../OrthancFramework/Sources/Images/JpegWriter.h" 57 #include "../../../OrthancFramework/Sources/Images/JpegWriter.h"
58 #include "../../../OrthancFramework/Sources/Images/PngReader.h" 58 #include "../../../OrthancFramework/Sources/Images/PngReader.h"
59 #include "../../../OrthancFramework/Sources/Images/PngWriter.h" 59 #include "../../../OrthancFramework/Sources/Images/PngWriter.h"
60 #include "../../../OrthancFramework/Sources/Logging.h" 60 #include "../../../OrthancFramework/Sources/Logging.h"
61 #include "../../../OrthancFramework/Sources/Lua/LuaFunctionCall.h" 61 #include "../../../OrthancFramework/Sources/Lua/LuaFunctionCall.h"
62 #include "../../../OrthancFramework/Sources/MallocMemoryBuffer.h"
62 #include "../../../OrthancFramework/Sources/MetricsRegistry.h" 63 #include "../../../OrthancFramework/Sources/MetricsRegistry.h"
63 #include "../../../OrthancFramework/Sources/OrthancException.h" 64 #include "../../../OrthancFramework/Sources/OrthancException.h"
64 #include "../../../OrthancFramework/Sources/SerializationToolbox.h" 65 #include "../../../OrthancFramework/Sources/SerializationToolbox.h"
65 #include "../../../OrthancFramework/Sources/Toolbox.h" 66 #include "../../../OrthancFramework/Sources/Toolbox.h"
66 #include "../../Sources/OrthancConfiguration.h" 67 #include "../../Sources/OrthancConfiguration.h"
196 } 197 }
197 } 198 }
198 }; 199 };
199 200
200 201
201 class MemoryBuffer64Raii : public boost::noncopyable
202 {
203 private:
204 OrthancPluginMemoryBuffer64 buffer_;
205
206 public:
207 MemoryBuffer64Raii()
208 {
209 buffer_.size = 0;
210 buffer_.data = NULL;
211 }
212
213 ~MemoryBuffer64Raii()
214 {
215 if (buffer_.size != 0)
216 {
217 free(buffer_.data);
218 }
219 }
220
221 OrthancPluginMemoryBuffer64* GetObject()
222 {
223 return &buffer_;
224 }
225
226 void ToString(std::string& target) const
227 {
228 if ((buffer_.data == NULL && buffer_.size != 0) ||
229 (buffer_.data != NULL && buffer_.size == 0))
230 {
231 throw OrthancException(ErrorCode_Plugin);
232 }
233 else
234 {
235 target.resize(buffer_.size);
236
237 if (buffer_.size != 0)
238 {
239 memcpy(&target[0], buffer_.data, buffer_.size);
240 }
241 }
242 }
243 };
244
245
246 class StorageAreaBase : public IStorageArea 202 class StorageAreaBase : public IStorageArea
247 { 203 {
248 private: 204 private:
249 OrthancPluginStorageCreate create_; 205 OrthancPluginStorageCreate create_;
250 OrthancPluginStorageRemove remove_; 206 OrthancPluginStorageRemove remove_;
326 { 282 {
327 throw OrthancException(ErrorCode_Plugin, "Storage area plugin doesn't implement the \"Read\" primitive"); 283 throw OrthancException(ErrorCode_Plugin, "Storage area plugin doesn't implement the \"Read\" primitive");
328 } 284 }
329 } 285 }
330 286
331 virtual void Read(std::string& content, 287 virtual IMemoryBuffer* Read(const std::string& uuid,
332 const std::string& uuid, 288 FileContentType type) ORTHANC_OVERRIDE
333 FileContentType type) ORTHANC_OVERRIDE 289 {
334 { 290 std::unique_ptr<MallocMemoryBuffer> result(new MallocMemoryBuffer);
291
335 void* buffer = NULL; 292 void* buffer = NULL;
336 int64_t size = 0; 293 int64_t size = 0;
337 294
338 OrthancPluginErrorCode error = read_ 295 OrthancPluginErrorCode error = read_
339 (&buffer, &size, uuid.c_str(), Plugins::Convert(type)); 296 (&buffer, &size, uuid.c_str(), Plugins::Convert(type));
340 297
341 if (error != OrthancPluginErrorCode_Success) 298 if (error == OrthancPluginErrorCode_Success)
299 {
300 result->Assign(buffer, size, free_);
301 return result.release();
302 }
303 else
342 { 304 {
343 GetErrorDictionary().LogError(error, true); 305 GetErrorDictionary().LogError(error, true);
344 throw OrthancException(static_cast<ErrorCode>(error)); 306 throw OrthancException(static_cast<ErrorCode>(error));
345 } 307 }
346
347 try
348 {
349 content.resize(static_cast<size_t>(size));
350 }
351 catch (...)
352 {
353 Free(buffer);
354 throw OrthancException(ErrorCode_NotEnoughMemory);
355 }
356
357 if (size > 0)
358 {
359 memcpy(&content[0], buffer, static_cast<size_t>(size));
360 }
361
362 Free(buffer);
363 } 308 }
364 }; 309 };
365 310
366 311
367 // New in Orthanc 1.9.0 312 // New in Orthanc 1.9.0
382 { 327 {
383 throw OrthancException(ErrorCode_Plugin, "Storage area plugin doesn't implement the \"ReadWhole\" primitive"); 328 throw OrthancException(ErrorCode_Plugin, "Storage area plugin doesn't implement the \"ReadWhole\" primitive");
384 } 329 }
385 } 330 }
386 331
387 virtual void Read(std::string& content, 332 virtual IMemoryBuffer* Read(const std::string& uuid,
388 const std::string& uuid, 333 FileContentType type) ORTHANC_OVERRIDE
389 FileContentType type) ORTHANC_OVERRIDE 334 {
390 { 335 std::unique_ptr<MallocMemoryBuffer> result(new MallocMemoryBuffer);
391 MemoryBuffer64Raii buffer; 336
337 OrthancPluginMemoryBuffer64 buffer;
392 338
393 OrthancPluginErrorCode error = readWhole_ 339 OrthancPluginErrorCode error = readWhole_(&buffer, uuid.c_str(), Plugins::Convert(type));
394 (buffer.GetObject(), uuid.c_str(), Plugins::Convert(type)); 340
395 341 if (error == OrthancPluginErrorCode_Success)
396 if (error != OrthancPluginErrorCode_Success) 342 {
343 result->Assign(buffer.data, buffer.size, ::free);
344 return result.release();
345 }
346 else
397 { 347 {
398 GetErrorDictionary().LogError(error, true); 348 GetErrorDictionary().LogError(error, true);
399 throw OrthancException(static_cast<ErrorCode>(error)); 349 throw OrthancException(static_cast<ErrorCode>(error));
400 } 350 }
401
402 buffer.ToString(content);
403 } 351 }
404 }; 352 };
405 353
406 354
407 class StorageAreaFactory : public boost::noncopyable 355 class StorageAreaFactory : public boost::noncopyable
4194 case _OrthancPluginService_StorageAreaRead: 4142 case _OrthancPluginService_StorageAreaRead:
4195 { 4143 {
4196 const _OrthancPluginStorageAreaRead& p = 4144 const _OrthancPluginStorageAreaRead& p =
4197 *reinterpret_cast<const _OrthancPluginStorageAreaRead*>(parameters); 4145 *reinterpret_cast<const _OrthancPluginStorageAreaRead*>(parameters);
4198 IStorageArea& storage = *reinterpret_cast<IStorageArea*>(p.storageArea); 4146 IStorageArea& storage = *reinterpret_cast<IStorageArea*>(p.storageArea);
4199 std::string content; 4147 std::unique_ptr<IMemoryBuffer> content(storage.Read(p.uuid, Plugins::Convert(p.type)));
4200 storage.Read(content, p.uuid, Plugins::Convert(p.type)); 4148 CopyToMemoryBuffer(*p.target, content->GetData(), content->GetSize());
4201 CopyToMemoryBuffer(*p.target, content);
4202 return true; 4149 return true;
4203 } 4150 }
4204 4151
4205 case _OrthancPluginService_StorageAreaRemove: 4152 case _OrthancPluginService_StorageAreaRemove:
4206 { 4153 {