comparison Plugins/Engine/OrthancPlugins.cpp @ 1999:364cc624eb65

New URI "/modalities/.../move" to issue C-Move SCU requests
author Sebastien Jodogne <s.jodogne@gmail.com>
date Thu, 26 May 2016 14:24:56 +0200
parents f0acfa753973
children 39329372b667
comparison
equal deleted inserted replaced
1998:9b61701c35f2 1999:364cc624eb65
314 OnStoredCallbacks onStoredCallbacks_; 314 OnStoredCallbacks onStoredCallbacks_;
315 OnChangeCallbacks onChangeCallbacks_; 315 OnChangeCallbacks onChangeCallbacks_;
316 OrthancPluginFindCallback findCallback_; 316 OrthancPluginFindCallback findCallback_;
317 OrthancPluginWorklistCallback worklistCallback_; 317 OrthancPluginWorklistCallback worklistCallback_;
318 OrthancPluginDecodeImageCallback decodeImageCallback_; 318 OrthancPluginDecodeImageCallback decodeImageCallback_;
319 _OrthancPluginMoveCallback moveCallbacks_;
319 IncomingHttpRequestFilters incomingHttpRequestFilters_; 320 IncomingHttpRequestFilters incomingHttpRequestFilters_;
320 std::auto_ptr<StorageAreaFactory> storageArea_; 321 std::auto_ptr<StorageAreaFactory> storageArea_;
321 boost::recursive_mutex restCallbackMutex_; 322 boost::recursive_mutex restCallbackMutex_;
322 boost::recursive_mutex storedCallbackMutex_; 323 boost::recursive_mutex storedCallbackMutex_;
323 boost::recursive_mutex changeCallbackMutex_; 324 boost::recursive_mutex changeCallbackMutex_;
324 boost::mutex findCallbackMutex_; 325 boost::mutex findCallbackMutex_;
326 boost::mutex moveCallbackMutex_;
325 boost::mutex worklistCallbackMutex_; 327 boost::mutex worklistCallbackMutex_;
326 boost::mutex decodeImageCallbackMutex_; 328 boost::mutex decodeImageCallbackMutex_;
327 boost::recursive_mutex invokeServiceMutex_; 329 boost::recursive_mutex invokeServiceMutex_;
328 Properties properties_; 330 Properties properties_;
329 int argc_; 331 int argc_;
337 worklistCallback_(NULL), 339 worklistCallback_(NULL),
338 decodeImageCallback_(NULL), 340 decodeImageCallback_(NULL),
339 argc_(1), 341 argc_(1),
340 argv_(NULL) 342 argv_(NULL)
341 { 343 {
344 memset(&moveCallbacks_, 0, sizeof(moveCallbacks_));
342 } 345 }
343 }; 346 };
344 347
345 348
346 349
533 } 536 }
534 537
535 default: 538 default:
536 throw OrthancException(ErrorCode_InternalError); 539 throw OrthancException(ErrorCode_InternalError);
537 } 540 }
541 }
542 };
543
544
545
546 class OrthancPlugins::MoveHandler : public IMoveRequestHandler
547 {
548 private:
549 class Driver : public IMoveRequestIterator
550 {
551 private:
552 void* driver_;
553 unsigned int count_;
554 unsigned int pos_;
555 OrthancPluginApplyMove apply_;
556 OrthancPluginFreeMove free_;
557
558 public:
559 Driver(void* driver,
560 unsigned int count,
561 OrthancPluginApplyMove apply,
562 OrthancPluginFreeMove free) :
563 driver_(driver),
564 count_(count),
565 pos_(0),
566 apply_(apply),
567 free_(free)
568 {
569 if (driver_ == NULL)
570 {
571 throw OrthancException(ErrorCode_Plugin);
572 }
573 }
574
575 virtual ~Driver()
576 {
577 if (driver_ != NULL)
578 {
579 free_(driver_);
580 driver_ = NULL;
581 }
582 }
583
584 virtual unsigned int GetSubOperationCount() const
585 {
586 return count_;
587 }
588
589 virtual Status DoNext()
590 {
591 if (pos_ >= count_)
592 {
593 throw OrthancException(ErrorCode_BadSequenceOfCalls);
594 }
595 else
596 {
597 OrthancPluginErrorCode error = apply_(driver_);
598 if (error != OrthancPluginErrorCode_Success)
599 {
600 LOG(ERROR) << "Error while doing C-Move from plugin: " << EnumerationToString(static_cast<ErrorCode>(error));
601 return Status_Failure;
602 }
603 else
604 {
605 pos_++;
606 return Status_Success;
607 }
608 }
609 }
610 };
611
612
613 _OrthancPluginMoveCallback params_;
614
615
616 static std::string ReadTag(const DicomMap& input,
617 const DicomTag& tag)
618 {
619 const DicomValue* value = input.TestAndGetValue(tag);
620 if (value != NULL &&
621 !value->IsBinary() &&
622 !value->IsNull())
623 {
624 return value->GetContent();
625 }
626 else
627 {
628 return std::string();
629 }
630 }
631
632
633
634 public:
635 MoveHandler(OrthancPlugins& that)
636 {
637 boost::mutex::scoped_lock lock(that.pimpl_->moveCallbackMutex_);
638 params_ = that.pimpl_->moveCallbacks_;
639
640 if (params_.callback == NULL ||
641 params_.getMoveSize == NULL ||
642 params_.applyMove == NULL ||
643 params_.freeMove == NULL)
644 {
645 throw OrthancException(ErrorCode_Plugin);
646 }
647 }
648
649 virtual IMoveRequestIterator* Handle(const std::string& targetAet,
650 const DicomMap& input,
651 const std::string& remoteIp,
652 const std::string& remoteAet,
653 const std::string& calledAet,
654 uint16_t messageId)
655 {
656 std::string levelString = ReadTag(input, DICOM_TAG_QUERY_RETRIEVE_LEVEL);
657 std::string patientId = ReadTag(input, DICOM_TAG_PATIENT_ID);
658 std::string accessionNumber = ReadTag(input, DICOM_TAG_ACCESSION_NUMBER);
659 std::string studyInstanceUid = ReadTag(input, DICOM_TAG_STUDY_INSTANCE_UID);
660 std::string seriesInstanceUid = ReadTag(input, DICOM_TAG_SERIES_INSTANCE_UID);
661 std::string sopInstanceUid = ReadTag(input, DICOM_TAG_SOP_INSTANCE_UID);
662
663 OrthancPluginResourceType level = OrthancPluginResourceType_None;
664
665 if (!levelString.empty())
666 {
667 level = Plugins::Convert(StringToResourceType(levelString.c_str()));
668 }
669
670 void* driver = params_.callback(level,
671 patientId.empty() ? NULL : patientId.c_str(),
672 accessionNumber.empty() ? NULL : accessionNumber.c_str(),
673 studyInstanceUid.empty() ? NULL : studyInstanceUid.c_str(),
674 seriesInstanceUid.empty() ? NULL : seriesInstanceUid.c_str(),
675 sopInstanceUid.empty() ? NULL : sopInstanceUid.c_str(),
676 remoteAet.c_str(),
677 calledAet.c_str(),
678 targetAet.c_str(),
679 messageId);
680
681 if (driver == NULL)
682 {
683 LOG(ERROR) << "Plugin cannot create a driver for an incoming C-MOVE request";
684 throw OrthancException(ErrorCode_Plugin);
685 }
686
687 unsigned int size = params_.getMoveSize(driver);
688
689 return new Driver(driver, size, params_.applyMove, params_.freeMove);
538 } 690 }
539 }; 691 };
540 692
541 693
542 694
879 pimpl_->findCallback_ = p.callback; 1031 pimpl_->findCallback_ = p.callback;
880 } 1032 }
881 } 1033 }
882 1034
883 1035
1036 void OrthancPlugins::RegisterMoveCallback(const void* parameters)
1037 {
1038 const _OrthancPluginMoveCallback& p =
1039 *reinterpret_cast<const _OrthancPluginMoveCallback*>(parameters);
1040
1041 boost::mutex::scoped_lock lock(pimpl_->moveCallbackMutex_);
1042
1043 if (pimpl_->moveCallbacks_.callback != NULL)
1044 {
1045 LOG(ERROR) << "Can only register one plugin to handle C-MOVE requests";
1046 throw OrthancException(ErrorCode_Plugin);
1047 }
1048 else
1049 {
1050 LOG(INFO) << "Plugin has registered a callback to handle C-MOVE requests";
1051 pimpl_->moveCallbacks_ = p;
1052 }
1053 }
1054
1055
884 void OrthancPlugins::RegisterDecodeImageCallback(const void* parameters) 1056 void OrthancPlugins::RegisterDecodeImageCallback(const void* parameters)
885 { 1057 {
886 const _OrthancPluginDecodeImageCallback& p = 1058 const _OrthancPluginDecodeImageCallback& p =
887 *reinterpret_cast<const _OrthancPluginDecodeImageCallback*>(parameters); 1059 *reinterpret_cast<const _OrthancPluginDecodeImageCallback*>(parameters);
888 1060
1980 2152
1981 case _OrthancPluginService_RegisterFindCallback: 2153 case _OrthancPluginService_RegisterFindCallback:
1982 RegisterFindCallback(parameters); 2154 RegisterFindCallback(parameters);
1983 return true; 2155 return true;
1984 2156
2157 case _OrthancPluginService_RegisterMoveCallback:
2158 RegisterMoveCallback(parameters);
2159 return true;
2160
1985 case _OrthancPluginService_RegisterDecodeImageCallback: 2161 case _OrthancPluginService_RegisterDecodeImageCallback:
1986 RegisterDecodeImageCallback(parameters); 2162 RegisterDecodeImageCallback(parameters);
1987 return true; 2163 return true;
1988 2164
1989 case _OrthancPluginService_RegisterIncomingHttpRequestFilter: 2165 case _OrthancPluginService_RegisterIncomingHttpRequestFilter:
2664 boost::mutex::scoped_lock lock(pimpl_->findCallbackMutex_); 2840 boost::mutex::scoped_lock lock(pimpl_->findCallbackMutex_);
2665 return pimpl_->findCallback_ != NULL; 2841 return pimpl_->findCallback_ != NULL;
2666 } 2842 }
2667 2843
2668 2844
2845 IMoveRequestHandler* OrthancPlugins::ConstructMoveRequestHandler()
2846 {
2847 if (HasMoveHandler())
2848 {
2849 return new MoveHandler(*this);
2850 }
2851 else
2852 {
2853 return NULL;
2854 }
2855 }
2856
2857
2858 bool OrthancPlugins::HasMoveHandler()
2859 {
2860 boost::mutex::scoped_lock lock(pimpl_->moveCallbackMutex_);
2861 return pimpl_->moveCallbacks_.callback != NULL;
2862 }
2863
2864
2669 bool OrthancPlugins::HasCustomImageDecoder() 2865 bool OrthancPlugins::HasCustomImageDecoder()
2670 { 2866 {
2671 boost::mutex::scoped_lock lock(pimpl_->decodeImageCallbackMutex_); 2867 boost::mutex::scoped_lock lock(pimpl_->decodeImageCallbackMutex_);
2672 return (pimpl_->decodeImageCallback_ != NULL); 2868 return (pimpl_->decodeImageCallback_ != NULL);
2673 } 2869 }