Mercurial > hg > orthanc
comparison OrthancServer/ServerIndex.cpp @ 3080:1a75595d8e44 db-changes
started refactoring of ServerIndex::Store()
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Thu, 03 Jan 2019 18:21:22 +0100 |
parents | ead8576a02ef |
children | 847a0ed92654 |
comparison
equal
deleted
inserted
replaced
3079:65e2bfa953ef | 3080:1a75595d8e44 |
---|---|
610 } | 610 } |
611 } | 611 } |
612 | 612 |
613 | 613 |
614 | 614 |
615 int64_t ServerIndex::CreateResource(const std::string& publicId, | |
616 ResourceType type) | |
617 { | |
618 int64_t id = db_.CreateResource(publicId, type); | |
619 | |
620 ChangeType changeType; | |
621 switch (type) | |
622 { | |
623 case ResourceType_Patient: | |
624 changeType = ChangeType_NewPatient; | |
625 break; | |
626 | |
627 case ResourceType_Study: | |
628 changeType = ChangeType_NewStudy; | |
629 break; | |
630 | |
631 case ResourceType_Series: | |
632 changeType = ChangeType_NewSeries; | |
633 break; | |
634 | |
635 case ResourceType_Instance: | |
636 changeType = ChangeType_NewInstance; | |
637 break; | |
638 | |
639 default: | |
640 throw OrthancException(ErrorCode_InternalError); | |
641 } | |
642 | |
643 ServerIndexChange change(changeType, type, publicId); | |
644 db_.LogChange(id, change); | |
645 | |
646 assert(listener_.get() != NULL); | |
647 listener_->SignalChange(change); | |
648 | |
649 return id; | |
650 } | |
651 | |
652 | |
653 ServerIndex::ServerIndex(ServerContext& context, | 615 ServerIndex::ServerIndex(ServerContext& context, |
654 IDatabaseWrapper& db, | 616 IDatabaseWrapper& db, |
655 unsigned int threadSleep) : | 617 unsigned int threadSleep) : |
656 done_(false), | 618 done_(false), |
657 db_(db), | 619 db_(db), |
718 db_.SetMetadata(instance, metadata, value); | 680 db_.SetMetadata(instance, metadata, value); |
719 instanceMetadata[metadata] = value; | 681 instanceMetadata[metadata] = value; |
720 } | 682 } |
721 | 683 |
722 | 684 |
723 | 685 void ServerIndex::SignalNewResource(ChangeType changeType, |
686 ResourceType level, | |
687 const std::string& publicId, | |
688 int64_t internalId) | |
689 { | |
690 ServerIndexChange change(changeType, level, publicId); | |
691 db_.LogChange(internalId, change); | |
692 | |
693 assert(listener_.get() != NULL); | |
694 listener_->SignalChange(change); | |
695 } | |
696 | |
697 | |
724 StoreStatus ServerIndex::Store(std::map<MetadataType, std::string>& instanceMetadata, | 698 StoreStatus ServerIndex::Store(std::map<MetadataType, std::string>& instanceMetadata, |
725 DicomInstanceToStore& instanceToStore, | 699 DicomInstanceToStore& instanceToStore, |
726 const Attachments& attachments) | 700 const Attachments& attachments) |
727 { | 701 { |
728 boost::mutex::scoped_lock lock(mutex_); | 702 boost::mutex::scoped_lock lock(mutex_); |
730 const DicomMap& dicomSummary = instanceToStore.GetSummary(); | 704 const DicomMap& dicomSummary = instanceToStore.GetSummary(); |
731 const ServerIndex::MetadataMap& metadata = instanceToStore.GetMetadata(); | 705 const ServerIndex::MetadataMap& metadata = instanceToStore.GetMetadata(); |
732 | 706 |
733 instanceMetadata.clear(); | 707 instanceMetadata.clear(); |
734 | 708 |
709 const std::string hashPatient = instanceToStore.GetHasher().HashPatient(); | |
710 const std::string hashStudy = instanceToStore.GetHasher().HashStudy(); | |
711 const std::string hashSeries = instanceToStore.GetHasher().HashSeries(); | |
712 const std::string hashInstance = instanceToStore.GetHasher().HashInstance(); | |
713 | |
735 try | 714 try |
736 { | 715 { |
737 Transaction t(*this); | 716 Transaction t(*this); |
738 | 717 |
718 IDatabaseWrapper::CreateInstanceResult status; | |
719 int64_t instanceId; | |
720 | |
739 // Check whether this instance is already stored | 721 // Check whether this instance is already stored |
740 { | 722 if (!db_.CreateInstance(status, instanceId, hashPatient, |
741 ResourceType type; | 723 hashStudy, hashSeries, hashInstance, overwrite_)) |
742 int64_t tmp; | 724 { |
743 if (db_.LookupResource(tmp, type, instanceToStore.GetHasher().HashInstance())) | 725 // Do nothing if the instance already exists and overwriting is disabled |
744 { | 726 db_.GetAllMetadata(instanceMetadata, instanceId); |
745 assert(type == ResourceType_Instance); | 727 return StoreStatus_AlreadyStored; |
746 | 728 } |
747 if (overwrite_) | 729 |
748 { | 730 |
749 // Overwrite the old instance | 731 // Warn about the creation of new resources. The order must be from instance to patient. |
750 LOG(INFO) << "Overwriting instance: " << instanceToStore.GetHasher().HashInstance(); | 732 SignalNewResource(ChangeType_NewInstance, ResourceType_Instance, hashInstance, instanceId); |
751 db_.DeleteResource(tmp); | 733 |
752 } | 734 if (status.isNewSeries_) |
753 else | 735 { |
754 { | 736 SignalNewResource(ChangeType_NewSeries, ResourceType_Series, hashSeries, status.seriesId_); |
755 // Do nothing if the instance already exists | 737 } |
756 db_.GetAllMetadata(instanceMetadata, tmp); | 738 |
757 return StoreStatus_AlreadyStored; | 739 if (status.isNewStudy_) |
758 } | 740 { |
759 } | 741 SignalNewResource(ChangeType_NewStudy, ResourceType_Study, hashStudy, status.studyId_); |
760 } | 742 } |
761 | 743 |
744 if (status.isNewPatient_) | |
745 { | |
746 SignalNewResource(ChangeType_NewPatient, ResourceType_Patient, hashPatient, status.patientId_); | |
747 } | |
748 | |
749 | |
762 // Ensure there is enough room in the storage for the new instance | 750 // Ensure there is enough room in the storage for the new instance |
763 uint64_t instanceSize = 0; | 751 uint64_t instanceSize = 0; |
764 for (Attachments::const_iterator it = attachments.begin(); | 752 for (Attachments::const_iterator it = attachments.begin(); |
765 it != attachments.end(); ++it) | 753 it != attachments.end(); ++it) |
766 { | 754 { |
767 instanceSize += it->GetCompressedSize(); | 755 instanceSize += it->GetCompressedSize(); |
768 } | 756 } |
769 | 757 |
770 Recycle(instanceSize, instanceToStore.GetHasher().HashPatient()); | 758 Recycle(instanceSize, hashPatient /* don't consider the current patient for recycling */); |
771 | 759 |
772 // Create the instance | 760 |
773 int64_t instance = CreateResource(instanceToStore.GetHasher().HashInstance(), ResourceType_Instance); | 761 // Populate the newly-created resources |
774 ServerToolbox::StoreMainDicomTags(db_, instance, ResourceType_Instance, dicomSummary); | 762 // TODO - GROUP THIS |
775 | 763 |
776 // Detect up to which level the patient/study/series/instance | 764 ServerToolbox::StoreMainDicomTags(db_, instanceId, ResourceType_Instance, dicomSummary); |
777 // hierarchy must be created | 765 |
778 int64_t patient = -1, study = -1, series = -1; | 766 if (status.isNewSeries_) |
779 bool isNewPatient = false; | 767 { |
780 bool isNewStudy = false; | 768 ServerToolbox::StoreMainDicomTags(db_, status.seriesId_, ResourceType_Series, dicomSummary); |
781 bool isNewSeries = false; | 769 } |
782 | 770 |
783 { | 771 if (status.isNewStudy_) |
784 ResourceType dummy; | 772 { |
785 | 773 ServerToolbox::StoreMainDicomTags(db_, status.studyId_, ResourceType_Study, dicomSummary); |
786 if (db_.LookupResource(series, dummy, instanceToStore.GetHasher().HashSeries())) | 774 } |
787 { | 775 |
788 assert(dummy == ResourceType_Series); | 776 if (status.isNewPatient_) |
789 // The patient, the study and the series already exist | 777 { |
790 | 778 ServerToolbox::StoreMainDicomTags(db_, status.patientId_, ResourceType_Patient, dicomSummary); |
791 bool ok = (db_.LookupResource(patient, dummy, instanceToStore.GetHasher().HashPatient()) && | 779 } |
792 db_.LookupResource(study, dummy, instanceToStore.GetHasher().HashStudy())); | 780 |
793 assert(ok); | 781 |
794 } | |
795 else if (db_.LookupResource(study, dummy, instanceToStore.GetHasher().HashStudy())) | |
796 { | |
797 assert(dummy == ResourceType_Study); | |
798 | |
799 // New series: The patient and the study already exist | |
800 isNewSeries = true; | |
801 | |
802 bool ok = db_.LookupResource(patient, dummy, instanceToStore.GetHasher().HashPatient()); | |
803 assert(ok); | |
804 } | |
805 else if (db_.LookupResource(patient, dummy, instanceToStore.GetHasher().HashPatient())) | |
806 { | |
807 assert(dummy == ResourceType_Patient); | |
808 | |
809 // New study and series: The patient already exist | |
810 isNewStudy = true; | |
811 isNewSeries = true; | |
812 } | |
813 else | |
814 { | |
815 // New patient, study and series: Nothing exists | |
816 isNewPatient = true; | |
817 isNewStudy = true; | |
818 isNewSeries = true; | |
819 } | |
820 } | |
821 | |
822 // Create the series if needed | |
823 if (isNewSeries) | |
824 { | |
825 series = CreateResource(instanceToStore.GetHasher().HashSeries(), ResourceType_Series); | |
826 ServerToolbox::StoreMainDicomTags(db_, series, ResourceType_Series, dicomSummary); | |
827 } | |
828 | |
829 // Create the study if needed | |
830 if (isNewStudy) | |
831 { | |
832 study = CreateResource(instanceToStore.GetHasher().HashStudy(), ResourceType_Study); | |
833 ServerToolbox::StoreMainDicomTags(db_, study, ResourceType_Study, dicomSummary); | |
834 } | |
835 | |
836 // Create the patient if needed | |
837 if (isNewPatient) | |
838 { | |
839 patient = CreateResource(instanceToStore.GetHasher().HashPatient(), ResourceType_Patient); | |
840 ServerToolbox::StoreMainDicomTags(db_, patient, ResourceType_Patient, dicomSummary); | |
841 } | |
842 | |
843 // Create the parent-to-child links | |
844 db_.AttachChild(series, instance); | |
845 | |
846 if (isNewSeries) | |
847 { | |
848 db_.AttachChild(study, series); | |
849 } | |
850 | |
851 if (isNewStudy) | |
852 { | |
853 db_.AttachChild(patient, study); | |
854 } | |
855 | |
856 // Sanity checks | |
857 assert(patient != -1); | |
858 assert(study != -1); | |
859 assert(series != -1); | |
860 assert(instance != -1); | |
861 | |
862 // Attach the files to the newly created instance | 782 // Attach the files to the newly created instance |
863 for (Attachments::const_iterator it = attachments.begin(); | 783 for (Attachments::const_iterator it = attachments.begin(); |
864 it != attachments.end(); ++it) | 784 it != attachments.end(); ++it) |
865 { | 785 { |
866 db_.AddAttachment(instance, *it); | 786 db_.AddAttachment(instanceId, *it); |
867 } | 787 } |
788 | |
868 | 789 |
869 // Attach the user-specified metadata | 790 // Attach the user-specified metadata |
791 // TODO - GROUP THIS | |
870 for (MetadataMap::const_iterator | 792 for (MetadataMap::const_iterator |
871 it = metadata.begin(); it != metadata.end(); ++it) | 793 it = metadata.begin(); it != metadata.end(); ++it) |
872 { | 794 { |
873 switch (it->first.first) | 795 switch (it->first.first) |
874 { | 796 { |
875 case ResourceType_Patient: | 797 case ResourceType_Patient: |
876 db_.SetMetadata(patient, it->first.second, it->second); | 798 db_.SetMetadata(status.patientId_, it->first.second, it->second); |
877 break; | 799 break; |
878 | 800 |
879 case ResourceType_Study: | 801 case ResourceType_Study: |
880 db_.SetMetadata(study, it->first.second, it->second); | 802 db_.SetMetadata(status.studyId_, it->first.second, it->second); |
881 break; | 803 break; |
882 | 804 |
883 case ResourceType_Series: | 805 case ResourceType_Series: |
884 db_.SetMetadata(series, it->first.second, it->second); | 806 db_.SetMetadata(status.seriesId_, it->first.second, it->second); |
885 break; | 807 break; |
886 | 808 |
887 case ResourceType_Instance: | 809 case ResourceType_Instance: |
888 SetInstanceMetadata(instanceMetadata, instance, it->first.second, it->second); | 810 SetInstanceMetadata(instanceMetadata, instanceId, it->first.second, it->second); |
889 break; | 811 break; |
890 | 812 |
891 default: | 813 default: |
892 throw OrthancException(ErrorCode_ParameterOutOfRange); | 814 throw OrthancException(ErrorCode_ParameterOutOfRange); |
893 } | 815 } |
894 } | 816 } |
895 | 817 |
896 // Attach the auto-computed metadata for the patient/study/series levels | 818 // Attach the auto-computed metadata for the patient/study/series levels |
897 std::string now = SystemToolbox::GetNowIsoString(true /* use UTC time (not local time) */); | 819 std::string now = SystemToolbox::GetNowIsoString(true /* use UTC time (not local time) */); |
898 db_.SetMetadata(series, MetadataType_LastUpdate, now); | 820 db_.SetMetadata(status.seriesId_, MetadataType_LastUpdate, now); |
899 db_.SetMetadata(study, MetadataType_LastUpdate, now); | 821 db_.SetMetadata(status.studyId_, MetadataType_LastUpdate, now); |
900 db_.SetMetadata(patient, MetadataType_LastUpdate, now); | 822 db_.SetMetadata(status.patientId_, MetadataType_LastUpdate, now); |
901 | 823 |
902 // Attach the auto-computed metadata for the instance level, | 824 // Attach the auto-computed metadata for the instance level, |
903 // reflecting these additions into the input metadata map | 825 // reflecting these additions into the input metadata map |
904 SetInstanceMetadata(instanceMetadata, instance, MetadataType_Instance_ReceptionDate, now); | 826 SetInstanceMetadata(instanceMetadata, instanceId, MetadataType_Instance_ReceptionDate, now); |
905 SetInstanceMetadata(instanceMetadata, instance, MetadataType_Instance_RemoteAet, | 827 SetInstanceMetadata(instanceMetadata, instanceId, MetadataType_Instance_RemoteAet, |
906 instanceToStore.GetOrigin().GetRemoteAetC()); | 828 instanceToStore.GetOrigin().GetRemoteAetC()); |
907 SetInstanceMetadata(instanceMetadata, instance, MetadataType_Instance_Origin, | 829 SetInstanceMetadata(instanceMetadata, instanceId, MetadataType_Instance_Origin, |
908 EnumerationToString(instanceToStore.GetOrigin().GetRequestOrigin())); | 830 EnumerationToString(instanceToStore.GetOrigin().GetRequestOrigin())); |
909 | 831 |
910 { | 832 { |
911 std::string s; | 833 std::string s; |
912 | 834 |
913 if (instanceToStore.LookupTransferSyntax(s)) | 835 if (instanceToStore.LookupTransferSyntax(s)) |
914 { | 836 { |
915 // New in Orthanc 1.2.0 | 837 // New in Orthanc 1.2.0 |
916 SetInstanceMetadata(instanceMetadata, instance, MetadataType_Instance_TransferSyntax, s); | 838 SetInstanceMetadata(instanceMetadata, instanceId, MetadataType_Instance_TransferSyntax, s); |
917 } | 839 } |
918 | 840 |
919 if (instanceToStore.GetOrigin().LookupRemoteIp(s)) | 841 if (instanceToStore.GetOrigin().LookupRemoteIp(s)) |
920 { | 842 { |
921 // New in Orthanc 1.4.0 | 843 // New in Orthanc 1.4.0 |
922 SetInstanceMetadata(instanceMetadata, instance, MetadataType_Instance_RemoteIp, s); | 844 SetInstanceMetadata(instanceMetadata, instanceId, MetadataType_Instance_RemoteIp, s); |
923 } | 845 } |
924 | 846 |
925 if (instanceToStore.GetOrigin().LookupCalledAet(s)) | 847 if (instanceToStore.GetOrigin().LookupCalledAet(s)) |
926 { | 848 { |
927 // New in Orthanc 1.4.0 | 849 // New in Orthanc 1.4.0 |
928 SetInstanceMetadata(instanceMetadata, instance, MetadataType_Instance_CalledAet, s); | 850 SetInstanceMetadata(instanceMetadata, instanceId, MetadataType_Instance_CalledAet, s); |
929 } | 851 } |
930 | 852 |
931 if (instanceToStore.GetOrigin().LookupHttpUsername(s)) | 853 if (instanceToStore.GetOrigin().LookupHttpUsername(s)) |
932 { | 854 { |
933 // New in Orthanc 1.4.0 | 855 // New in Orthanc 1.4.0 |
934 SetInstanceMetadata(instanceMetadata, instance, MetadataType_Instance_HttpUsername, s); | 856 SetInstanceMetadata(instanceMetadata, instanceId, MetadataType_Instance_HttpUsername, s); |
935 } | 857 } |
936 } | 858 } |
937 | 859 |
938 const DicomValue* value; | 860 const DicomValue* value; |
939 if ((value = dicomSummary.TestAndGetValue(DICOM_TAG_SOP_CLASS_UID)) != NULL && | 861 if ((value = dicomSummary.TestAndGetValue(DICOM_TAG_SOP_CLASS_UID)) != NULL && |
940 !value->IsNull() && | 862 !value->IsNull() && |
941 !value->IsBinary()) | 863 !value->IsBinary()) |
942 { | 864 { |
943 SetInstanceMetadata(instanceMetadata, instance, MetadataType_Instance_SopClassUid, value->GetContent()); | 865 SetInstanceMetadata(instanceMetadata, instanceId, MetadataType_Instance_SopClassUid, value->GetContent()); |
944 } | 866 } |
945 | 867 |
946 if ((value = dicomSummary.TestAndGetValue(DICOM_TAG_INSTANCE_NUMBER)) != NULL || | 868 if ((value = dicomSummary.TestAndGetValue(DICOM_TAG_INSTANCE_NUMBER)) != NULL || |
947 (value = dicomSummary.TestAndGetValue(DICOM_TAG_IMAGE_INDEX)) != NULL) | 869 (value = dicomSummary.TestAndGetValue(DICOM_TAG_IMAGE_INDEX)) != NULL) |
948 { | 870 { |
949 if (!value->IsNull() && | 871 if (!value->IsNull() && |
950 !value->IsBinary()) | 872 !value->IsBinary()) |
951 { | 873 { |
952 SetInstanceMetadata(instanceMetadata, instance, MetadataType_Instance_IndexInSeries, value->GetContent()); | 874 SetInstanceMetadata(instanceMetadata, instanceId, MetadataType_Instance_IndexInSeries, value->GetContent()); |
953 } | 875 } |
954 } | 876 } |
955 | 877 |
956 // Check whether the series of this new instance is now completed | 878 // Check whether the series of this new instance is now completed |
957 if (isNewSeries) | 879 if (status.isNewSeries_) |
958 { | 880 { |
959 ComputeExpectedNumberOfInstances(db_, series, dicomSummary); | 881 ComputeExpectedNumberOfInstances(db_, status.seriesId_, dicomSummary); |
960 } | 882 } |
961 | 883 |
962 SeriesStatus seriesStatus = GetSeriesStatus(series); | 884 SeriesStatus seriesStatus = GetSeriesStatus(status.seriesId_); |
963 if (seriesStatus == SeriesStatus_Complete) | 885 if (seriesStatus == SeriesStatus_Complete) |
964 { | 886 { |
965 LogChange(series, ChangeType_CompletedSeries, ResourceType_Series, instanceToStore.GetHasher().HashSeries()); | 887 LogChange(status.seriesId_, ChangeType_CompletedSeries, ResourceType_Series, hashSeries); |
966 } | 888 } |
967 | 889 |
968 // Mark the parent resources of this instance as unstable | 890 // Mark the parent resources of this instance as unstable |
969 MarkAsUnstable(series, ResourceType_Series, instanceToStore.GetHasher().HashSeries()); | 891 MarkAsUnstable(status.seriesId_, ResourceType_Series, hashSeries); |
970 MarkAsUnstable(study, ResourceType_Study, instanceToStore.GetHasher().HashStudy()); | 892 MarkAsUnstable(status.studyId_, ResourceType_Study, hashStudy); |
971 MarkAsUnstable(patient, ResourceType_Patient, instanceToStore.GetHasher().HashPatient()); | 893 MarkAsUnstable(status.patientId_, ResourceType_Patient, hashPatient); |
972 | 894 |
973 t.Commit(instanceSize); | 895 t.Commit(instanceSize); |
974 | 896 |
975 return StoreStatus_Success; | 897 return StoreStatus_Success; |
976 } | 898 } |