comparison OrthancServer/Sources/Database/StatelessDatabaseOperations.cpp @ 5663:3765085693e5 large-queries

merge default -> large-queries
author Alain Mazy <am@orthanc.team>
date Thu, 04 Jul 2024 07:40:58 +0200
parents 28cc06e4859a f7adfb22e20e
children 5463c3ae3235
comparison
equal deleted inserted replaced
5553:28cc06e4859a 5663:3765085693e5
1 /** 1 /**
2 * Orthanc - A Lightweight, RESTful DICOM Store 2 * Orthanc - A Lightweight, RESTful DICOM Store
3 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics 3 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
4 * Department, University Hospital of Liege, Belgium 4 * Department, University Hospital of Liege, Belgium
5 * Copyright (C) 2017-2024 Osimis S.A., Belgium 5 * Copyright (C) 2017-2023 Osimis S.A., Belgium
6 * Copyright (C) 2024-2024 Orthanc Team SRL, Belgium
6 * Copyright (C) 2021-2024 Sebastien Jodogne, ICTEAM UCLouvain, Belgium 7 * Copyright (C) 2021-2024 Sebastien Jodogne, ICTEAM UCLouvain, Belgium
7 * 8 *
8 * This program is free software: you can redistribute it and/or 9 * This program is free software: you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as 10 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation, either version 3 of the 11 * published by the Free Software Foundation, either version 3 of the
964 965
965 if (type == ResourceType_Patient || 966 if (type == ResourceType_Patient ||
966 type == ResourceType_Study || 967 type == ResourceType_Study ||
967 type == ResourceType_Series) 968 type == ResourceType_Series)
968 { 969 {
969 target.isStable_ = !transaction.GetTransactionContext().IsUnstableResource(internalId); 970 target.isStable_ = !transaction.GetTransactionContext().IsUnstableResource(type, internalId);
970 971
971 if (LookupStringMetadata(tmp, target.metadata_, MetadataType_LastUpdate)) 972 if (LookupStringMetadata(tmp, target.metadata_, MetadataType_LastUpdate))
972 { 973 {
973 target.lastUpdate_ = tmp; 974 target.lastUpdate_ = tmp;
974 } 975 }
2795 Toolbox::WriteFastJson(result, jsonMetadata); 2796 Toolbox::WriteFastJson(result, jsonMetadata);
2796 } 2797 }
2797 } 2798 }
2798 2799
2799 2800
2800 void StatelessDatabaseOperations::ReconstructInstance(const ParsedDicomFile& dicom) 2801 void StatelessDatabaseOperations::ReconstructInstance(const ParsedDicomFile& dicom, bool limitToThisLevelDicomTags, ResourceType limitToLevel)
2801 { 2802 {
2802 class Operations : public IReadWriteOperations 2803 class Operations : public IReadWriteOperations
2803 { 2804 {
2804 private: 2805 private:
2805 DicomMap summary_; 2806 DicomMap summary_;
2806 std::unique_ptr<DicomInstanceHasher> hasher_; 2807 std::unique_ptr<DicomInstanceHasher> hasher_;
2808 bool limitToThisLevelDicomTags_;
2809 ResourceType limitToLevel_;
2807 bool hasTransferSyntax_; 2810 bool hasTransferSyntax_;
2808 DicomTransferSyntax transferSyntax_; 2811 DicomTransferSyntax transferSyntax_;
2809 2812
2810 static void ReplaceMetadata(ReadWriteTransaction& transaction, 2813 static void ReplaceMetadata(ReadWriteTransaction& transaction,
2811 int64_t instance, 2814 int64_t instance,
2843 } 2846 }
2844 2847
2845 } 2848 }
2846 2849
2847 public: 2850 public:
2848 explicit Operations(const ParsedDicomFile& dicom) 2851 explicit Operations(const ParsedDicomFile& dicom, bool limitToThisLevelDicomTags, ResourceType limitToLevel)
2852 : limitToThisLevelDicomTags_(limitToThisLevelDicomTags),
2853 limitToLevel_(limitToLevel)
2849 { 2854 {
2850 OrthancConfiguration::DefaultExtractDicomSummary(summary_, dicom); 2855 OrthancConfiguration::DefaultExtractDicomSummary(summary_, dicom);
2851 hasher_.reset(new DicomInstanceHasher(summary_)); 2856 hasher_.reset(new DicomInstanceHasher(summary_));
2852 hasTransferSyntax_ = dicom.LookupTransferSyntax(transferSyntax_); 2857 hasTransferSyntax_ = dicom.LookupTransferSyntax(transferSyntax_);
2853 } 2858 }
2871 instance == -1) 2876 instance == -1)
2872 { 2877 {
2873 throw OrthancException(ErrorCode_InternalError); 2878 throw OrthancException(ErrorCode_InternalError);
2874 } 2879 }
2875 2880
2876 transaction.ClearMainDicomTags(patient); 2881 if (limitToThisLevelDicomTags_)
2877 transaction.ClearMainDicomTags(study);
2878 transaction.ClearMainDicomTags(series);
2879 transaction.ClearMainDicomTags(instance);
2880
2881 { 2882 {
2882 ResourcesContent content(false /* prevent the setting of metadata */); 2883 ResourcesContent content(false /* prevent the setting of metadata */);
2883 content.AddResource(patient, ResourceType_Patient, summary_); 2884 int64_t resource = -1;
2884 content.AddResource(study, ResourceType_Study, summary_); 2885 if (limitToLevel_ == ResourceType_Patient)
2885 content.AddResource(series, ResourceType_Series, summary_); 2886 {
2886 content.AddResource(instance, ResourceType_Instance, summary_); 2887 resource = patient;
2887 2888 }
2889 else if (limitToLevel_ == ResourceType_Study)
2890 {
2891 resource = study;
2892 }
2893 else if (limitToLevel_ == ResourceType_Series)
2894 {
2895 resource = series;
2896 }
2897 else if (limitToLevel_ == ResourceType_Instance)
2898 {
2899 resource = instance;
2900 }
2901
2902 transaction.ClearMainDicomTags(resource);
2903 content.AddResource(resource, limitToLevel_, summary_);
2888 transaction.SetResourcesContent(content); 2904 transaction.SetResourcesContent(content);
2889 2905 ReplaceMetadata(transaction, resource, MetadataType_MainDicomTagsSignature, DicomMap::GetMainDicomTagsSignature(limitToLevel_));
2890 ReplaceMetadata(transaction, patient, MetadataType_MainDicomTagsSignature, DicomMap::GetMainDicomTagsSignature(ResourceType_Patient)); // New in Orthanc 1.11.0 2906 }
2891 ReplaceMetadata(transaction, study, MetadataType_MainDicomTagsSignature, DicomMap::GetMainDicomTagsSignature(ResourceType_Study)); // New in Orthanc 1.11.0 2907 else
2892 ReplaceMetadata(transaction, series, MetadataType_MainDicomTagsSignature, DicomMap::GetMainDicomTagsSignature(ResourceType_Series)); // New in Orthanc 1.11.0 2908 {
2893 ReplaceMetadata(transaction, instance, MetadataType_MainDicomTagsSignature, DicomMap::GetMainDicomTagsSignature(ResourceType_Instance)); // New in Orthanc 1.11.0 2909 transaction.ClearMainDicomTags(patient);
2894 2910 transaction.ClearMainDicomTags(study);
2895 SetMainDicomSequenceMetadata(transaction, patient, summary_, ResourceType_Patient); 2911 transaction.ClearMainDicomTags(series);
2896 SetMainDicomSequenceMetadata(transaction, study, summary_, ResourceType_Study); 2912 transaction.ClearMainDicomTags(instance);
2897 SetMainDicomSequenceMetadata(transaction, series, summary_, ResourceType_Series); 2913
2898 SetMainDicomSequenceMetadata(transaction, instance, summary_, ResourceType_Instance); 2914 {
2899 } 2915 ResourcesContent content(false /* prevent the setting of metadata */);
2900 2916 content.AddResource(patient, ResourceType_Patient, summary_);
2901 if (hasTransferSyntax_) 2917 content.AddResource(study, ResourceType_Study, summary_);
2902 { 2918 content.AddResource(series, ResourceType_Series, summary_);
2903 ReplaceMetadata(transaction, instance, MetadataType_Instance_TransferSyntax, GetTransferSyntaxUid(transferSyntax_)); 2919 content.AddResource(instance, ResourceType_Instance, summary_);
2904 } 2920
2905 2921 transaction.SetResourcesContent(content);
2906 const DicomValue* value; 2922
2907 if ((value = summary_.TestAndGetValue(DICOM_TAG_SOP_CLASS_UID)) != NULL && 2923 ReplaceMetadata(transaction, patient, MetadataType_MainDicomTagsSignature, DicomMap::GetMainDicomTagsSignature(ResourceType_Patient)); // New in Orthanc 1.11.0
2908 !value->IsNull() && 2924 ReplaceMetadata(transaction, study, MetadataType_MainDicomTagsSignature, DicomMap::GetMainDicomTagsSignature(ResourceType_Study)); // New in Orthanc 1.11.0
2909 !value->IsBinary()) 2925 ReplaceMetadata(transaction, series, MetadataType_MainDicomTagsSignature, DicomMap::GetMainDicomTagsSignature(ResourceType_Series)); // New in Orthanc 1.11.0
2910 { 2926 ReplaceMetadata(transaction, instance, MetadataType_MainDicomTagsSignature, DicomMap::GetMainDicomTagsSignature(ResourceType_Instance)); // New in Orthanc 1.11.0
2911 ReplaceMetadata(transaction, instance, MetadataType_Instance_SopClassUid, value->GetContent()); 2927
2912 } 2928 SetMainDicomSequenceMetadata(transaction, patient, summary_, ResourceType_Patient);
2913 2929 SetMainDicomSequenceMetadata(transaction, study, summary_, ResourceType_Study);
2914 } 2930 SetMainDicomSequenceMetadata(transaction, series, summary_, ResourceType_Series);
2915 }; 2931 SetMainDicomSequenceMetadata(transaction, instance, summary_, ResourceType_Instance);
2916 2932 }
2917 Operations operations(dicom); 2933
2934 if (hasTransferSyntax_)
2935 {
2936 ReplaceMetadata(transaction, instance, MetadataType_Instance_TransferSyntax, GetTransferSyntaxUid(transferSyntax_));
2937 }
2938
2939 const DicomValue* value;
2940 if ((value = summary_.TestAndGetValue(DICOM_TAG_SOP_CLASS_UID)) != NULL &&
2941 !value->IsNull() &&
2942 !value->IsBinary())
2943 {
2944 ReplaceMetadata(transaction, instance, MetadataType_Instance_SopClassUid, value->GetContent());
2945 }
2946 }
2947 }
2948 };
2949
2950 Operations operations(dicom, limitToThisLevelDicomTags, limitToLevel);
2918 Apply(operations); 2951 Apply(operations);
2919 } 2952 }
2920 2953
2921 2954
2922 bool StatelessDatabaseOperations::ReadWriteTransaction::HasReachedMaxStorageSize(uint64_t maximumStorageSize, 2955 bool StatelessDatabaseOperations::ReadWriteTransaction::HasReachedMaxStorageSize(uint64_t maximumStorageSize,
3341 } 3374 }
3342 3375
3343 transaction.AddAttachment(instanceId, *it, 0 /* this is the first revision */); 3376 transaction.AddAttachment(instanceId, *it, 0 /* this is the first revision */);
3344 } 3377 }
3345 3378
3379 ResourcesContent content(true /* new resource, metadata can be set */);
3380
3381 // Attach the user-specified metadata (in case of reconstruction, metadata_ contains all past metadata, including the system ones we want to keep)
3382 for (MetadataMap::const_iterator
3383 it = metadata_.begin(); it != metadata_.end(); ++it)
3384 {
3385 switch (it->first.first)
3386 {
3387 case ResourceType_Patient:
3388 content.AddMetadata(status.patientId_, it->first.second, it->second);
3389 break;
3390
3391 case ResourceType_Study:
3392 content.AddMetadata(status.studyId_, it->first.second, it->second);
3393 break;
3394
3395 case ResourceType_Series:
3396 content.AddMetadata(status.seriesId_, it->first.second, it->second);
3397 break;
3398
3399 case ResourceType_Instance:
3400 SetInstanceMetadata(content, instanceMetadata_, instanceId,
3401 it->first.second, it->second);
3402 break;
3403
3404 default:
3405 throw OrthancException(ErrorCode_ParameterOutOfRange);
3406 }
3407 }
3408
3346 if (!isReconstruct_) 3409 if (!isReconstruct_)
3347 { 3410 {
3348 ResourcesContent content(true /* new resource, metadata can be set */); 3411 // Populate the tags of the newly-created resources
3349 3412 content.AddResource(instanceId, ResourceType_Instance, dicomSummary_);
3350 // Attach the user-specified metadata (in case of reconstruction, metadata_ contains all past metadata, including the system ones we want to keep) 3413 SetInstanceMetadata(content, instanceMetadata_, instanceId, MetadataType_MainDicomTagsSignature, DicomMap::GetMainDicomTagsSignature(ResourceType_Instance)); // New in Orthanc 1.11.0
3351 for (MetadataMap::const_iterator 3414 SetMainDicomSequenceMetadata(content, instanceId, dicomSummary_, ResourceType_Instance); // new in Orthanc 1.11.1
3352 it = metadata_.begin(); it != metadata_.end(); ++it) 3415
3353 { 3416 if (status.isNewSeries_)
3354 switch (it->first.first) 3417 {
3418 content.AddResource(status.seriesId_, ResourceType_Series, dicomSummary_);
3419 content.AddMetadata(status.seriesId_, MetadataType_MainDicomTagsSignature, DicomMap::GetMainDicomTagsSignature(ResourceType_Series)); // New in Orthanc 1.11.0
3420 SetMainDicomSequenceMetadata(content, status.seriesId_, dicomSummary_, ResourceType_Series); // new in Orthanc 1.11.1
3421 }
3422
3423 if (status.isNewStudy_)
3424 {
3425 content.AddResource(status.studyId_, ResourceType_Study, dicomSummary_);
3426 content.AddMetadata(status.studyId_, MetadataType_MainDicomTagsSignature, DicomMap::GetMainDicomTagsSignature(ResourceType_Study)); // New in Orthanc 1.11.0
3427 SetMainDicomSequenceMetadata(content, status.studyId_, dicomSummary_, ResourceType_Study); // new in Orthanc 1.11.1
3428 }
3429
3430 if (status.isNewPatient_)
3431 {
3432 content.AddResource(status.patientId_, ResourceType_Patient, dicomSummary_);
3433 content.AddMetadata(status.patientId_, MetadataType_MainDicomTagsSignature, DicomMap::GetMainDicomTagsSignature(ResourceType_Patient)); // New in Orthanc 1.11.0
3434 SetMainDicomSequenceMetadata(content, status.patientId_, dicomSummary_, ResourceType_Patient); // new in Orthanc 1.11.1
3435 }
3436
3437 // Attach the auto-computed metadata for the patient/study/series levels
3438 std::string now = SystemToolbox::GetNowIsoString(true /* use UTC time (not local time) */);
3439 content.AddMetadata(status.seriesId_, MetadataType_LastUpdate, now);
3440 content.AddMetadata(status.studyId_, MetadataType_LastUpdate, now);
3441 content.AddMetadata(status.patientId_, MetadataType_LastUpdate, now);
3442
3443 if (status.isNewSeries_)
3444 {
3445 if (hasExpectedInstances_)
3355 { 3446 {
3356 case ResourceType_Patient: 3447 content.AddMetadata(status.seriesId_, MetadataType_Series_ExpectedNumberOfInstances,
3357 content.AddMetadata(status.patientId_, it->first.second, it->second); 3448 boost::lexical_cast<std::string>(expectedInstances_));
3358 break;
3359
3360 case ResourceType_Study:
3361 content.AddMetadata(status.studyId_, it->first.second, it->second);
3362 break;
3363
3364 case ResourceType_Series:
3365 content.AddMetadata(status.seriesId_, it->first.second, it->second);
3366 break;
3367
3368 case ResourceType_Instance:
3369 SetInstanceMetadata(content, instanceMetadata_, instanceId,
3370 it->first.second, it->second);
3371 break;
3372
3373 default:
3374 throw OrthancException(ErrorCode_ParameterOutOfRange);
3375 } 3449 }
3376 } 3450
3377 3451 // New in Orthanc 1.9.0
3378 if (!isReconstruct_) 3452 content.AddMetadata(status.seriesId_, MetadataType_RemoteAet,
3379 { 3453 origin_.GetRemoteAetC());
3380 // Populate the tags of the newly-created resources 3454 }
3381 content.AddResource(instanceId, ResourceType_Instance, dicomSummary_); 3455 // Attach the auto-computed metadata for the instance level,
3382 SetInstanceMetadata(content, instanceMetadata_, instanceId, MetadataType_MainDicomTagsSignature, DicomMap::GetMainDicomTagsSignature(ResourceType_Instance)); // New in Orthanc 1.11.0 3456 // reflecting these additions into the input metadata map
3383 SetMainDicomSequenceMetadata(content, instanceId, dicomSummary_, ResourceType_Instance); // new in Orthanc 1.11.1 3457 SetInstanceMetadata(content, instanceMetadata_, instanceId,
3384 3458 MetadataType_Instance_ReceptionDate, now);
3385 if (status.isNewSeries_) 3459 SetInstanceMetadata(content, instanceMetadata_, instanceId, MetadataType_RemoteAet,
3460 origin_.GetRemoteAetC());
3461 SetInstanceMetadata(content, instanceMetadata_, instanceId, MetadataType_Instance_Origin,
3462 EnumerationToString(origin_.GetRequestOrigin()));
3463
3464 std::string s;
3465
3466 if (origin_.LookupRemoteIp(s))
3467 {
3468 // New in Orthanc 1.4.0
3469 SetInstanceMetadata(content, instanceMetadata_, instanceId,
3470 MetadataType_Instance_RemoteIp, s);
3471 }
3472
3473 if (origin_.LookupCalledAet(s))
3474 {
3475 // New in Orthanc 1.4.0
3476 SetInstanceMetadata(content, instanceMetadata_, instanceId,
3477 MetadataType_Instance_CalledAet, s);
3478 }
3479
3480 if (origin_.LookupHttpUsername(s))
3481 {
3482 // New in Orthanc 1.4.0
3483 SetInstanceMetadata(content, instanceMetadata_, instanceId,
3484 MetadataType_Instance_HttpUsername, s);
3485 }
3486 }
3487
3488 // Following metadatas are also updated if reconstructing the instance.
3489 // They might be missing since they have been introduced along Orthanc versions.
3490
3491 if (hasTransferSyntax_)
3492 {
3493 // New in Orthanc 1.2.0
3494 SetInstanceMetadata(content, instanceMetadata_, instanceId,
3495 MetadataType_Instance_TransferSyntax,
3496 GetTransferSyntaxUid(transferSyntax_));
3497 }
3498
3499 if (hasPixelDataOffset_)
3500 {
3501 // New in Orthanc 1.9.1
3502 SetInstanceMetadata(content, instanceMetadata_, instanceId,
3503 MetadataType_Instance_PixelDataOffset,
3504 boost::lexical_cast<std::string>(pixelDataOffset_));
3505
3506 // New in Orthanc 1.12.1
3507 if (dicomSummary_.GuessPixelDataValueRepresentation(transferSyntax_) != pixelDataVR_)
3508 {
3509 // Store the VR of pixel data if it doesn't comply with the standard
3510 SetInstanceMetadata(content, instanceMetadata_, instanceId,
3511 MetadataType_Instance_PixelDataVR,
3512 EnumerationToString(pixelDataVR_));
3513 }
3514 }
3515
3516 const DicomValue* value;
3517 if ((value = dicomSummary_.TestAndGetValue(DICOM_TAG_SOP_CLASS_UID)) != NULL &&
3518 !value->IsNull() &&
3519 !value->IsBinary())
3520 {
3521 SetInstanceMetadata(content, instanceMetadata_, instanceId,
3522 MetadataType_Instance_SopClassUid, value->GetContent());
3523 }
3524
3525
3526 if ((value = dicomSummary_.TestAndGetValue(DICOM_TAG_INSTANCE_NUMBER)) != NULL ||
3527 (value = dicomSummary_.TestAndGetValue(DICOM_TAG_IMAGE_INDEX)) != NULL)
3528 {
3529 if (!value->IsNull() &&
3530 !value->IsBinary())
3531 {
3532 SetInstanceMetadata(content, instanceMetadata_, instanceId,
3533 MetadataType_Instance_IndexInSeries, Toolbox::StripSpaces(value->GetContent()));
3534 }
3535 }
3536
3537
3538 transaction.SetResourcesContent(content);
3539
3540
3541 if (!isReconstruct_) // a reconstruct shall not trigger any events
3542 {
3543 // Check whether the series of this new instance is now completed
3544 int64_t expectedNumberOfInstances;
3545 if (ComputeExpectedNumberOfInstances(expectedNumberOfInstances, dicomSummary_))
3546 {
3547 SeriesStatus seriesStatus = transaction.GetSeriesStatus(status.seriesId_, expectedNumberOfInstances);
3548 if (seriesStatus == SeriesStatus_Complete)
3386 { 3549 {
3387 content.AddResource(status.seriesId_, ResourceType_Series, dicomSummary_); 3550 transaction.LogChange(status.seriesId_, ChangeType_CompletedSeries, ResourceType_Series, hashSeries_);
3388 content.AddMetadata(status.seriesId_, MetadataType_MainDicomTagsSignature, DicomMap::GetMainDicomTagsSignature(ResourceType_Series)); // New in Orthanc 1.11.0
3389 SetMainDicomSequenceMetadata(content, status.seriesId_, dicomSummary_, ResourceType_Series); // new in Orthanc 1.11.1
3390 } 3551 }
3391 3552 }
3392 if (status.isNewStudy_) 3553
3393 { 3554 transaction.LogChange(status.seriesId_, ChangeType_NewChildInstance, ResourceType_Series, hashSeries_);
3394 content.AddResource(status.studyId_, ResourceType_Study, dicomSummary_); 3555 transaction.LogChange(status.studyId_, ChangeType_NewChildInstance, ResourceType_Study, hashStudy_);
3395 content.AddMetadata(status.studyId_, MetadataType_MainDicomTagsSignature, DicomMap::GetMainDicomTagsSignature(ResourceType_Study)); // New in Orthanc 1.11.0 3556 transaction.LogChange(status.patientId_, ChangeType_NewChildInstance, ResourceType_Patient, hashPatient_);
3396 SetMainDicomSequenceMetadata(content, status.studyId_, dicomSummary_, ResourceType_Study); // new in Orthanc 1.11.1 3557
3397 } 3558 // Mark the parent resources of this instance as unstable
3398 3559 transaction.GetTransactionContext().MarkAsUnstable(ResourceType_Series, status.seriesId_, hashSeries_);
3399 if (status.isNewPatient_) 3560 transaction.GetTransactionContext().MarkAsUnstable(ResourceType_Study, status.studyId_, hashStudy_);
3400 { 3561 transaction.GetTransactionContext().MarkAsUnstable(ResourceType_Patient, status.patientId_, hashPatient_);
3401 content.AddResource(status.patientId_, ResourceType_Patient, dicomSummary_); 3562 }
3402 content.AddMetadata(status.patientId_, MetadataType_MainDicomTagsSignature, DicomMap::GetMainDicomTagsSignature(ResourceType_Patient)); // New in Orthanc 1.11.0 3563
3403 SetMainDicomSequenceMetadata(content, status.patientId_, dicomSummary_, ResourceType_Patient); // new in Orthanc 1.11.1
3404 }
3405
3406 // Attach the auto-computed metadata for the patient/study/series levels
3407 std::string now = SystemToolbox::GetNowIsoString(true /* use UTC time (not local time) */);
3408 content.AddMetadata(status.seriesId_, MetadataType_LastUpdate, now);
3409 content.AddMetadata(status.studyId_, MetadataType_LastUpdate, now);
3410 content.AddMetadata(status.patientId_, MetadataType_LastUpdate, now);
3411
3412 if (status.isNewSeries_)
3413 {
3414 if (hasExpectedInstances_)
3415 {
3416 content.AddMetadata(status.seriesId_, MetadataType_Series_ExpectedNumberOfInstances,
3417 boost::lexical_cast<std::string>(expectedInstances_));
3418 }
3419
3420 // New in Orthanc 1.9.0
3421 content.AddMetadata(status.seriesId_, MetadataType_RemoteAet,
3422 origin_.GetRemoteAetC());
3423 }
3424 // Attach the auto-computed metadata for the instance level,
3425 // reflecting these additions into the input metadata map
3426 SetInstanceMetadata(content, instanceMetadata_, instanceId,
3427 MetadataType_Instance_ReceptionDate, now);
3428 SetInstanceMetadata(content, instanceMetadata_, instanceId, MetadataType_RemoteAet,
3429 origin_.GetRemoteAetC());
3430 SetInstanceMetadata(content, instanceMetadata_, instanceId, MetadataType_Instance_Origin,
3431 EnumerationToString(origin_.GetRequestOrigin()));
3432
3433 std::string s;
3434
3435 if (origin_.LookupRemoteIp(s))
3436 {
3437 // New in Orthanc 1.4.0
3438 SetInstanceMetadata(content, instanceMetadata_, instanceId,
3439 MetadataType_Instance_RemoteIp, s);
3440 }
3441
3442 if (origin_.LookupCalledAet(s))
3443 {
3444 // New in Orthanc 1.4.0
3445 SetInstanceMetadata(content, instanceMetadata_, instanceId,
3446 MetadataType_Instance_CalledAet, s);
3447 }
3448
3449 if (origin_.LookupHttpUsername(s))
3450 {
3451 // New in Orthanc 1.4.0
3452 SetInstanceMetadata(content, instanceMetadata_, instanceId,
3453 MetadataType_Instance_HttpUsername, s);
3454 }
3455 }
3456
3457 // Following metadatas are also updated if reconstructing the instance.
3458 // They might be missing since they have been introduced along Orthanc versions.
3459
3460 if (hasTransferSyntax_)
3461 {
3462 // New in Orthanc 1.2.0
3463 SetInstanceMetadata(content, instanceMetadata_, instanceId,
3464 MetadataType_Instance_TransferSyntax,
3465 GetTransferSyntaxUid(transferSyntax_));
3466 }
3467
3468 if (hasPixelDataOffset_)
3469 {
3470 // New in Orthanc 1.9.1
3471 SetInstanceMetadata(content, instanceMetadata_, instanceId,
3472 MetadataType_Instance_PixelDataOffset,
3473 boost::lexical_cast<std::string>(pixelDataOffset_));
3474
3475 // New in Orthanc 1.12.1
3476 if (dicomSummary_.GuessPixelDataValueRepresentation(transferSyntax_) != pixelDataVR_)
3477 {
3478 // Store the VR of pixel data if it doesn't comply with the standard
3479 SetInstanceMetadata(content, instanceMetadata_, instanceId,
3480 MetadataType_Instance_PixelDataVR,
3481 EnumerationToString(pixelDataVR_));
3482 }
3483 }
3484
3485 const DicomValue* value;
3486 if ((value = dicomSummary_.TestAndGetValue(DICOM_TAG_SOP_CLASS_UID)) != NULL &&
3487 !value->IsNull() &&
3488 !value->IsBinary())
3489 {
3490 SetInstanceMetadata(content, instanceMetadata_, instanceId,
3491 MetadataType_Instance_SopClassUid, value->GetContent());
3492 }
3493
3494
3495 if ((value = dicomSummary_.TestAndGetValue(DICOM_TAG_INSTANCE_NUMBER)) != NULL ||
3496 (value = dicomSummary_.TestAndGetValue(DICOM_TAG_IMAGE_INDEX)) != NULL)
3497 {
3498 if (!value->IsNull() &&
3499 !value->IsBinary())
3500 {
3501 SetInstanceMetadata(content, instanceMetadata_, instanceId,
3502 MetadataType_Instance_IndexInSeries, Toolbox::StripSpaces(value->GetContent()));
3503 }
3504 }
3505
3506
3507 transaction.SetResourcesContent(content);
3508 }
3509
3510
3511 // Check whether the series of this new instance is now completed
3512 int64_t expectedNumberOfInstances;
3513 if (ComputeExpectedNumberOfInstances(expectedNumberOfInstances, dicomSummary_))
3514 {
3515 SeriesStatus seriesStatus = transaction.GetSeriesStatus(status.seriesId_, expectedNumberOfInstances);
3516 if (seriesStatus == SeriesStatus_Complete)
3517 {
3518 transaction.LogChange(status.seriesId_, ChangeType_CompletedSeries, ResourceType_Series, hashSeries_);
3519 }
3520 }
3521
3522 transaction.LogChange(status.seriesId_, ChangeType_NewChildInstance, ResourceType_Series, hashSeries_);
3523 transaction.LogChange(status.studyId_, ChangeType_NewChildInstance, ResourceType_Study, hashStudy_);
3524 transaction.LogChange(status.patientId_, ChangeType_NewChildInstance, ResourceType_Patient, hashPatient_);
3525
3526 // Mark the parent resources of this instance as unstable
3527 transaction.GetTransactionContext().MarkAsUnstable(status.seriesId_, ResourceType_Series, hashSeries_);
3528 transaction.GetTransactionContext().MarkAsUnstable(status.studyId_, ResourceType_Study, hashStudy_);
3529 transaction.GetTransactionContext().MarkAsUnstable(status.patientId_, ResourceType_Patient, hashPatient_);
3530 transaction.GetTransactionContext().SignalAttachmentsAdded(instanceSize); 3564 transaction.GetTransactionContext().SignalAttachmentsAdded(instanceSize);
3531 3565 storeStatus_ = StoreStatus_Success;
3532 storeStatus_ = StoreStatus_Success;
3533 } 3566 }
3534 }; 3567 };
3535 3568
3536 3569
3537 Operations operations(instanceMetadata, dicomSummary, attachments, metadata, origin, overwrite, 3570 Operations operations(instanceMetadata, dicomSummary, attachments, metadata, origin, overwrite,