Mercurial > hg > orthanc
comparison OrthancServer/Sources/OrthancRestApi/OrthancRestArchive.cpp @ 4797:4e765c18ace7 storage-cache
enable using multiple threads to load instances when generating zip archive/media
author | Alain Mazy <am@osimis.io> |
---|---|
date | Thu, 07 Oct 2021 13:31:36 +0200 |
parents | b3957ddd88f1 |
children | 70d2a97ca8cb 7053502fbf97 |
comparison
equal
deleted
inserted
replaced
4792:434843934307 | 4797:4e765c18ace7 |
---|---|
49 namespace Orthanc | 49 namespace Orthanc |
50 { | 50 { |
51 static const char* const KEY_RESOURCES = "Resources"; | 51 static const char* const KEY_RESOURCES = "Resources"; |
52 static const char* const KEY_EXTENDED = "Extended"; | 52 static const char* const KEY_EXTENDED = "Extended"; |
53 static const char* const KEY_TRANSCODE = "Transcode"; | 53 static const char* const KEY_TRANSCODE = "Transcode"; |
54 | 54 |
55 static const char* const CONFIG_LOADER_THREADS = "ZipLoaderThreads"; | |
56 | |
55 static void AddResourcesOfInterestFromArray(ArchiveJob& job, | 57 static void AddResourcesOfInterestFromArray(ArchiveJob& job, |
56 const Json::Value& resources) | 58 const Json::Value& resources) |
57 { | 59 { |
58 if (resources.type() != Json::arrayValue) | 60 if (resources.type() != Json::arrayValue) |
59 { | 61 { |
121 static void GetJobParameters(bool& synchronous, /* out */ | 123 static void GetJobParameters(bool& synchronous, /* out */ |
122 bool& extended, /* out */ | 124 bool& extended, /* out */ |
123 bool& transcode, /* out */ | 125 bool& transcode, /* out */ |
124 DicomTransferSyntax& syntax, /* out */ | 126 DicomTransferSyntax& syntax, /* out */ |
125 int& priority, /* out */ | 127 int& priority, /* out */ |
128 unsigned int& loaderThreads, /* out */ | |
126 const Json::Value& body, /* in */ | 129 const Json::Value& body, /* in */ |
127 const bool defaultExtended /* in */) | 130 const bool defaultExtended /* in */) |
128 { | 131 { |
129 synchronous = OrthancRestApi::IsSynchronousJobRequest | 132 synchronous = OrthancRestApi::IsSynchronousJobRequest |
130 (true /* synchronous by default */, body); | 133 (true /* synchronous by default */, body); |
149 } | 152 } |
150 else | 153 else |
151 { | 154 { |
152 transcode = false; | 155 transcode = false; |
153 } | 156 } |
157 | |
158 { | |
159 OrthancConfiguration::ReaderLock lock; | |
160 loaderThreads = lock.GetConfiguration().GetUnsignedIntegerParameter(CONFIG_LOADER_THREADS, 0); // New in Orthanc 1.9.8 | |
161 } | |
162 | |
154 } | 163 } |
155 | 164 |
156 | 165 |
157 namespace | 166 namespace |
158 { | 167 { |
552 if (call.ParseJsonRequest(body)) | 561 if (call.ParseJsonRequest(body)) |
553 { | 562 { |
554 bool synchronous, extended, transcode; | 563 bool synchronous, extended, transcode; |
555 DicomTransferSyntax transferSyntax; | 564 DicomTransferSyntax transferSyntax; |
556 int priority; | 565 int priority; |
566 unsigned int loaderThreads; | |
557 GetJobParameters(synchronous, extended, transcode, transferSyntax, | 567 GetJobParameters(synchronous, extended, transcode, transferSyntax, |
558 priority, body, DEFAULT_IS_EXTENDED); | 568 priority, loaderThreads, body, DEFAULT_IS_EXTENDED); |
559 | 569 |
560 std::unique_ptr<ArchiveJob> job(new ArchiveJob(context, IS_MEDIA, extended)); | 570 std::unique_ptr<ArchiveJob> job(new ArchiveJob(context, IS_MEDIA, extended)); |
561 AddResourcesOfInterest(*job, body); | 571 AddResourcesOfInterest(*job, body); |
562 | 572 |
563 if (transcode) | 573 if (transcode) |
564 { | 574 { |
565 job->SetTranscode(transferSyntax); | 575 job->SetTranscode(transferSyntax); |
566 } | 576 } |
567 | 577 |
578 job->SetLoaderThreads(loaderThreads); | |
579 | |
568 SubmitJob(call.GetOutput(), context, job, priority, synchronous, "Archive.zip"); | 580 SubmitJob(call.GetOutput(), context, job, priority, synchronous, "Archive.zip"); |
569 } | 581 } |
570 else | 582 else |
571 { | 583 { |
572 throw OrthancException(ErrorCode_BadFileFormat, | 584 throw OrthancException(ErrorCode_BadFileFormat, |
576 | 588 |
577 | 589 |
578 template <bool IS_MEDIA> | 590 template <bool IS_MEDIA> |
579 static void CreateSingleGet(RestApiGetCall& call) | 591 static void CreateSingleGet(RestApiGetCall& call) |
580 { | 592 { |
593 static const char* const TRANSCODE = "transcode"; | |
594 | |
581 if (call.IsDocumentation()) | 595 if (call.IsDocumentation()) |
582 { | 596 { |
583 ResourceType t = StringToResourceType(call.GetFullUri()[0].c_str()); | 597 ResourceType t = StringToResourceType(call.GetFullUri()[0].c_str()); |
584 std::string r = GetResourceTypeText(t, false /* plural */, false /* upper case */); | 598 std::string r = GetResourceTypeText(t, false /* plural */, false /* upper case */); |
585 std::string m = (IS_MEDIA ? "DICOMDIR media" : "ZIP archive"); | 599 std::string m = (IS_MEDIA ? "DICOMDIR media" : "ZIP archive"); |
589 .SetDescription("Synchronously create a " + m + " containing the DICOM " + r + | 603 .SetDescription("Synchronously create a " + m + " containing the DICOM " + r + |
590 " whose Orthanc identifier is provided in the URL. This flavor is synchronous, " | 604 " whose Orthanc identifier is provided in the URL. This flavor is synchronous, " |
591 "which might *not* be desirable to archive large amount of data, as it might " | 605 "which might *not* be desirable to archive large amount of data, as it might " |
592 "lead to network timeouts. Prefer the asynchronous version using `POST` method.") | 606 "lead to network timeouts. Prefer the asynchronous version using `POST` method.") |
593 .SetUriArgument("id", "Orthanc identifier of the " + r + " of interest") | 607 .SetUriArgument("id", "Orthanc identifier of the " + r + " of interest") |
594 .SetHttpGetArgument("transcode", RestApiCallDocumentation::Type_String, | 608 .SetHttpGetArgument(TRANSCODE, RestApiCallDocumentation::Type_String, |
595 "If present, the DICOM files in the archive will be transcoded to the provided " | 609 "If present, the DICOM files in the archive will be transcoded to the provided " |
596 "transfer syntax: https://book.orthanc-server.com/faq/transcoding.html", false) | 610 "transfer syntax: https://book.orthanc-server.com/faq/transcoding.html", false) |
597 .AddAnswerType(MimeType_Zip, "ZIP file containing the archive"); | 611 .AddAnswerType(MimeType_Zip, "ZIP file containing the archive"); |
598 if (IS_MEDIA) | 612 if (IS_MEDIA) |
599 { | 613 { |
619 } | 633 } |
620 | 634 |
621 std::unique_ptr<ArchiveJob> job(new ArchiveJob(context, IS_MEDIA, extended)); | 635 std::unique_ptr<ArchiveJob> job(new ArchiveJob(context, IS_MEDIA, extended)); |
622 job->AddResource(id); | 636 job->AddResource(id); |
623 | 637 |
624 static const char* const TRANSCODE = "transcode"; | |
625 if (call.HasArgument(TRANSCODE)) | 638 if (call.HasArgument(TRANSCODE)) |
626 { | 639 { |
627 job->SetTranscode(GetTransferSyntax(call.GetArgument(TRANSCODE, ""))); | 640 job->SetTranscode(GetTransferSyntax(call.GetArgument(TRANSCODE, ""))); |
641 } | |
642 | |
643 { | |
644 OrthancConfiguration::ReaderLock lock; | |
645 unsigned int loaderThreads = lock.GetConfiguration().GetUnsignedIntegerParameter(CONFIG_LOADER_THREADS, 0); // New in Orthanc 1.9.8 | |
646 job->SetLoaderThreads(loaderThreads); | |
628 } | 647 } |
629 | 648 |
630 SubmitJob(call.GetOutput(), context, job, 0 /* priority */, | 649 SubmitJob(call.GetOutput(), context, job, 0 /* priority */, |
631 true /* synchronous */, id + ".zip"); | 650 true /* synchronous */, id + ".zip"); |
632 } | 651 } |
658 if (call.ParseJsonRequest(body)) | 677 if (call.ParseJsonRequest(body)) |
659 { | 678 { |
660 bool synchronous, extended, transcode; | 679 bool synchronous, extended, transcode; |
661 DicomTransferSyntax transferSyntax; | 680 DicomTransferSyntax transferSyntax; |
662 int priority; | 681 int priority; |
682 unsigned int loaderThreads; | |
663 GetJobParameters(synchronous, extended, transcode, transferSyntax, | 683 GetJobParameters(synchronous, extended, transcode, transferSyntax, |
664 priority, body, false /* by default, not extented */); | 684 priority, loaderThreads, body, false /* by default, not extented */); |
665 | 685 |
666 std::unique_ptr<ArchiveJob> job(new ArchiveJob(context, IS_MEDIA, extended)); | 686 std::unique_ptr<ArchiveJob> job(new ArchiveJob(context, IS_MEDIA, extended)); |
667 job->AddResource(id); | 687 job->AddResource(id); |
668 | 688 |
669 if (transcode) | 689 if (transcode) |
670 { | 690 { |
671 job->SetTranscode(transferSyntax); | 691 job->SetTranscode(transferSyntax); |
672 } | 692 } |
693 | |
694 job->SetLoaderThreads(loaderThreads); | |
673 | 695 |
674 SubmitJob(call.GetOutput(), context, job, priority, synchronous, id + ".zip"); | 696 SubmitJob(call.GetOutput(), context, job, priority, synchronous, id + ".zip"); |
675 } | 697 } |
676 else | 698 else |
677 { | 699 { |