# HG changeset patch # User Sebastien Jodogne # Date 1546687050 -3600 # Node ID 31244604f617b73d3bfd23538431b0bb29df4153 # Parent fb8ee0786b1e84e0a93a24adda21ddf7c5d07fce starting optimization of SeriesIndex::GetSeriesStatus() diff -r fb8ee0786b1e -r 31244604f617 OrthancServer/ServerIndex.cpp --- a/OrthancServer/ServerIndex.cpp Sat Jan 05 11:39:31 2019 +0100 +++ b/OrthancServer/ServerIndex.cpp Sat Jan 05 12:17:30 2019 +0100 @@ -499,8 +499,7 @@ } - static void ComputeExpectedNumberOfInstances(ResourcesContent& target, - int64_t series, + static bool ComputeExpectedNumberOfInstances(int64_t& target, const DicomMap& dicomSummary) { try @@ -509,28 +508,39 @@ const DicomValue* value2; if ((value = dicomSummary.TestAndGetValue(DICOM_TAG_IMAGES_IN_ACQUISITION)) != NULL && - (value2 = dicomSummary.TestAndGetValue(DICOM_TAG_NUMBER_OF_TEMPORAL_POSITIONS)) != NULL) + !value->IsNull() && + !value->IsBinary() && + (value2 = dicomSummary.TestAndGetValue(DICOM_TAG_NUMBER_OF_TEMPORAL_POSITIONS)) != NULL && + !value2->IsNull() && + !value2->IsBinary()) { // Patch for series with temporal positions thanks to Will Ryder int64_t imagesInAcquisition = boost::lexical_cast(value->GetContent()); int64_t countTemporalPositions = boost::lexical_cast(value2->GetContent()); - std::string expected = boost::lexical_cast(imagesInAcquisition * countTemporalPositions); - target.AddMetadata(series, MetadataType_Series_ExpectedNumberOfInstances, expected); + target = imagesInAcquisition * countTemporalPositions; + return (target > 0); } else if ((value = dicomSummary.TestAndGetValue(DICOM_TAG_NUMBER_OF_SLICES)) != NULL && - (value2 = dicomSummary.TestAndGetValue(DICOM_TAG_NUMBER_OF_TIME_SLICES)) != NULL) + !value->IsNull() && + !value->IsBinary() && + (value2 = dicomSummary.TestAndGetValue(DICOM_TAG_NUMBER_OF_TIME_SLICES)) != NULL && + !value2->IsBinary() && + !value2->IsNull()) { // Support of Cardio-PET images int64_t numberOfSlices = boost::lexical_cast(value->GetContent()); int64_t numberOfTimeSlices = boost::lexical_cast(value2->GetContent()); - std::string expected = boost::lexical_cast(numberOfSlices * numberOfTimeSlices); - target.AddMetadata(series, MetadataType_Series_ExpectedNumberOfInstances, expected); + target = numberOfSlices * numberOfTimeSlices; + return (target > 0); } - else if ((value = dicomSummary.TestAndGetValue(DICOM_TAG_CARDIAC_NUMBER_OF_IMAGES)) != NULL) + else if ((value = dicomSummary.TestAndGetValue(DICOM_TAG_CARDIAC_NUMBER_OF_IMAGES)) != NULL && + !value->IsNull() && + !value->IsBinary()) { - target.AddMetadata(series, MetadataType_Series_ExpectedNumberOfInstances, value->GetContent()); + target = boost::lexical_cast(value->GetContent()); + return (target > 0); } } catch (OrthancException&) @@ -539,6 +549,8 @@ catch (boost::bad_lexical_cast&) { } + + return false; } @@ -704,6 +716,10 @@ const DicomMap& dicomSummary = instanceToStore.GetSummary(); const ServerIndex::MetadataMap& metadata = instanceToStore.GetMetadata(); + int64_t expectedInstances; + const bool hasExpectedInstances = + ComputeExpectedNumberOfInstances(expectedInstances, dicomSummary); + instanceMetadata.clear(); const std::string hashPatient = instanceToStore.GetHasher().HashPatient(); @@ -746,7 +762,14 @@ } - // Warn about the creation of new resources. The order must be from instance to patient. + // Warn about the creation of new resources. The order must be + // from instance to patient. + + // NB: In theory, could be sped up by grouping the underlying + // calls to "db_.LogChange()". However, this would only have an + // impact when new patient/study/series get created, which + // occurs far less often that creating new instances. The + // positive impact looks marginal in practice. SignalNewResource(ChangeType_NewInstance, ResourceType_Instance, hashInstance, instanceId); if (status.isNewSeries_) @@ -843,7 +866,14 @@ content.AddMetadata(status.studyId_, MetadataType_LastUpdate, now); content.AddMetadata(status.patientId_, MetadataType_LastUpdate, now); - + if (status.isNewSeries_ && + hasExpectedInstances) + { + content.AddMetadata(status.seriesId_, MetadataType_Series_ExpectedNumberOfInstances, + boost::lexical_cast(expectedInstances)); + } + + // Attach the auto-computed metadata for the instance level, // reflecting these additions into the input metadata map SetInstanceMetadata(content, instanceMetadata, instanceId, @@ -909,17 +939,11 @@ } - // Check whether the series of this new instance is now completed - if (status.isNewSeries_) - { - ComputeExpectedNumberOfInstances(content, status.seriesId_, dicomSummary); - } - - db_.SetResourcesContent(content); } - + + // Check whether the series of this new instance is now completed // TODO - SPEED THIS UP SeriesStatus seriesStatus = GetSeriesStatus(status.seriesId_); if (seriesStatus == SeriesStatus_Complete) @@ -965,16 +989,10 @@ } - - SeriesStatus ServerIndex::GetSeriesStatus(int64_t id) + + SeriesStatus ServerIndex::GetSeriesStatus(int64_t id, + int64_t expectedNumberOfInstances) { - // Get the expected number of instances in this series (from the metadata) - int64_t expected; - if (!GetMetadataAsInteger(expected, id, MetadataType_Series_ExpectedNumberOfInstances)) - { - return SeriesStatus_Unknown; - } - // Loop over the instances of this series std::list children; db_.GetChildrenInternalId(children, id); @@ -990,7 +1008,7 @@ return SeriesStatus_Unknown; } - if (!(index > 0 && index <= expected)) + if (!(index > 0 && index <= expectedNumberOfInstances)) { // Out-of-range instance index return SeriesStatus_Inconsistent; @@ -1005,7 +1023,7 @@ instances.insert(index); } - if (static_cast(instances.size()) == expected) + if (static_cast(instances.size()) == expectedNumberOfInstances) { return SeriesStatus_Complete; } @@ -1016,6 +1034,21 @@ } + SeriesStatus ServerIndex::GetSeriesStatus(int64_t id) + { + // Get the expected number of instances in this series (from the metadata) + int64_t expected; + if (!GetMetadataAsInteger(expected, id, MetadataType_Series_ExpectedNumberOfInstances)) + { + return SeriesStatus_Unknown; + } + else + { + return GetSeriesStatus(id, expected); + } + } + + void ServerIndex::MainDicomTagsToJson(Json::Value& target, int64_t resourceId, ResourceType resourceType) @@ -1042,6 +1075,7 @@ } } + bool ServerIndex::LookupResource(Json::Value& result, const std::string& publicId, ResourceType expectedType) @@ -1140,9 +1174,13 @@ int64_t i; if (GetMetadataAsInteger(i, id, MetadataType_Series_ExpectedNumberOfInstances)) + { result["ExpectedNumberOfInstances"] = static_cast(i); + } else + { result["ExpectedNumberOfInstances"] = Json::nullValue; + } break; } diff -r fb8ee0786b1e -r 31244604f617 OrthancServer/ServerIndex.h --- a/OrthancServer/ServerIndex.h Sat Jan 05 11:39:31 2019 +0100 +++ b/OrthancServer/ServerIndex.h Sat Jan 05 12:17:30 2019 +0100 @@ -127,6 +127,9 @@ const DatabaseLookup& source, ResourceType level) const; + SeriesStatus GetSeriesStatus(int64_t id, + int64_t expectedNumberOfInstances); + public: ServerIndex(ServerContext& context, IDatabaseWrapper& database,