Mercurial > hg > orthanc
comparison OrthancServer/Sources/Database/StatelessDatabaseOperations.cpp @ 5635:0e16e677fe64
fixed broken /instances/../tags after reconstructing studies when IngestTranscoding has changed
author | Alain Mazy <am@orthanc.team> |
---|---|
date | Tue, 21 May 2024 17:09:57 +0200 |
parents | b2a97dfd719f |
children | f7adfb22e20e |
comparison
equal
deleted
inserted
replaced
5633:5db4ed395d81 | 5635:0e16e677fe64 |
---|---|
3340 } | 3340 } |
3341 | 3341 |
3342 transaction.AddAttachment(instanceId, *it, 0 /* this is the first revision */); | 3342 transaction.AddAttachment(instanceId, *it, 0 /* this is the first revision */); |
3343 } | 3343 } |
3344 | 3344 |
3345 ResourcesContent content(true /* new resource, metadata can be set */); | |
3346 | |
3347 // Attach the user-specified metadata (in case of reconstruction, metadata_ contains all past metadata, including the system ones we want to keep) | |
3348 for (MetadataMap::const_iterator | |
3349 it = metadata_.begin(); it != metadata_.end(); ++it) | |
3350 { | |
3351 switch (it->first.first) | |
3352 { | |
3353 case ResourceType_Patient: | |
3354 content.AddMetadata(status.patientId_, it->first.second, it->second); | |
3355 break; | |
3356 | |
3357 case ResourceType_Study: | |
3358 content.AddMetadata(status.studyId_, it->first.second, it->second); | |
3359 break; | |
3360 | |
3361 case ResourceType_Series: | |
3362 content.AddMetadata(status.seriesId_, it->first.second, it->second); | |
3363 break; | |
3364 | |
3365 case ResourceType_Instance: | |
3366 SetInstanceMetadata(content, instanceMetadata_, instanceId, | |
3367 it->first.second, it->second); | |
3368 break; | |
3369 | |
3370 default: | |
3371 throw OrthancException(ErrorCode_ParameterOutOfRange); | |
3372 } | |
3373 } | |
3374 | |
3345 if (!isReconstruct_) | 3375 if (!isReconstruct_) |
3346 { | 3376 { |
3347 ResourcesContent content(true /* new resource, metadata can be set */); | 3377 // Populate the tags of the newly-created resources |
3348 | 3378 content.AddResource(instanceId, ResourceType_Instance, dicomSummary_); |
3349 // Attach the user-specified metadata (in case of reconstruction, metadata_ contains all past metadata, including the system ones we want to keep) | 3379 SetInstanceMetadata(content, instanceMetadata_, instanceId, MetadataType_MainDicomTagsSignature, DicomMap::GetMainDicomTagsSignature(ResourceType_Instance)); // New in Orthanc 1.11.0 |
3350 for (MetadataMap::const_iterator | 3380 SetMainDicomSequenceMetadata(content, instanceId, dicomSummary_, ResourceType_Instance); // new in Orthanc 1.11.1 |
3351 it = metadata_.begin(); it != metadata_.end(); ++it) | 3381 |
3352 { | 3382 if (status.isNewSeries_) |
3353 switch (it->first.first) | 3383 { |
3384 content.AddResource(status.seriesId_, ResourceType_Series, dicomSummary_); | |
3385 content.AddMetadata(status.seriesId_, MetadataType_MainDicomTagsSignature, DicomMap::GetMainDicomTagsSignature(ResourceType_Series)); // New in Orthanc 1.11.0 | |
3386 SetMainDicomSequenceMetadata(content, status.seriesId_, dicomSummary_, ResourceType_Series); // new in Orthanc 1.11.1 | |
3387 } | |
3388 | |
3389 if (status.isNewStudy_) | |
3390 { | |
3391 content.AddResource(status.studyId_, ResourceType_Study, dicomSummary_); | |
3392 content.AddMetadata(status.studyId_, MetadataType_MainDicomTagsSignature, DicomMap::GetMainDicomTagsSignature(ResourceType_Study)); // New in Orthanc 1.11.0 | |
3393 SetMainDicomSequenceMetadata(content, status.studyId_, dicomSummary_, ResourceType_Study); // new in Orthanc 1.11.1 | |
3394 } | |
3395 | |
3396 if (status.isNewPatient_) | |
3397 { | |
3398 content.AddResource(status.patientId_, ResourceType_Patient, dicomSummary_); | |
3399 content.AddMetadata(status.patientId_, MetadataType_MainDicomTagsSignature, DicomMap::GetMainDicomTagsSignature(ResourceType_Patient)); // New in Orthanc 1.11.0 | |
3400 SetMainDicomSequenceMetadata(content, status.patientId_, dicomSummary_, ResourceType_Patient); // new in Orthanc 1.11.1 | |
3401 } | |
3402 | |
3403 // Attach the auto-computed metadata for the patient/study/series levels | |
3404 std::string now = SystemToolbox::GetNowIsoString(true /* use UTC time (not local time) */); | |
3405 content.AddMetadata(status.seriesId_, MetadataType_LastUpdate, now); | |
3406 content.AddMetadata(status.studyId_, MetadataType_LastUpdate, now); | |
3407 content.AddMetadata(status.patientId_, MetadataType_LastUpdate, now); | |
3408 | |
3409 if (status.isNewSeries_) | |
3410 { | |
3411 if (hasExpectedInstances_) | |
3354 { | 3412 { |
3355 case ResourceType_Patient: | 3413 content.AddMetadata(status.seriesId_, MetadataType_Series_ExpectedNumberOfInstances, |
3356 content.AddMetadata(status.patientId_, it->first.second, it->second); | 3414 boost::lexical_cast<std::string>(expectedInstances_)); |
3357 break; | |
3358 | |
3359 case ResourceType_Study: | |
3360 content.AddMetadata(status.studyId_, it->first.second, it->second); | |
3361 break; | |
3362 | |
3363 case ResourceType_Series: | |
3364 content.AddMetadata(status.seriesId_, it->first.second, it->second); | |
3365 break; | |
3366 | |
3367 case ResourceType_Instance: | |
3368 SetInstanceMetadata(content, instanceMetadata_, instanceId, | |
3369 it->first.second, it->second); | |
3370 break; | |
3371 | |
3372 default: | |
3373 throw OrthancException(ErrorCode_ParameterOutOfRange); | |
3374 } | 3415 } |
3375 } | 3416 |
3376 | 3417 // New in Orthanc 1.9.0 |
3377 if (!isReconstruct_) | 3418 content.AddMetadata(status.seriesId_, MetadataType_RemoteAet, |
3378 { | 3419 origin_.GetRemoteAetC()); |
3379 // Populate the tags of the newly-created resources | 3420 } |
3380 content.AddResource(instanceId, ResourceType_Instance, dicomSummary_); | 3421 // Attach the auto-computed metadata for the instance level, |
3381 SetInstanceMetadata(content, instanceMetadata_, instanceId, MetadataType_MainDicomTagsSignature, DicomMap::GetMainDicomTagsSignature(ResourceType_Instance)); // New in Orthanc 1.11.0 | 3422 // reflecting these additions into the input metadata map |
3382 SetMainDicomSequenceMetadata(content, instanceId, dicomSummary_, ResourceType_Instance); // new in Orthanc 1.11.1 | 3423 SetInstanceMetadata(content, instanceMetadata_, instanceId, |
3383 | 3424 MetadataType_Instance_ReceptionDate, now); |
3384 if (status.isNewSeries_) | 3425 SetInstanceMetadata(content, instanceMetadata_, instanceId, MetadataType_RemoteAet, |
3426 origin_.GetRemoteAetC()); | |
3427 SetInstanceMetadata(content, instanceMetadata_, instanceId, MetadataType_Instance_Origin, | |
3428 EnumerationToString(origin_.GetRequestOrigin())); | |
3429 | |
3430 std::string s; | |
3431 | |
3432 if (origin_.LookupRemoteIp(s)) | |
3433 { | |
3434 // New in Orthanc 1.4.0 | |
3435 SetInstanceMetadata(content, instanceMetadata_, instanceId, | |
3436 MetadataType_Instance_RemoteIp, s); | |
3437 } | |
3438 | |
3439 if (origin_.LookupCalledAet(s)) | |
3440 { | |
3441 // New in Orthanc 1.4.0 | |
3442 SetInstanceMetadata(content, instanceMetadata_, instanceId, | |
3443 MetadataType_Instance_CalledAet, s); | |
3444 } | |
3445 | |
3446 if (origin_.LookupHttpUsername(s)) | |
3447 { | |
3448 // New in Orthanc 1.4.0 | |
3449 SetInstanceMetadata(content, instanceMetadata_, instanceId, | |
3450 MetadataType_Instance_HttpUsername, s); | |
3451 } | |
3452 } | |
3453 | |
3454 // Following metadatas are also updated if reconstructing the instance. | |
3455 // They might be missing since they have been introduced along Orthanc versions. | |
3456 | |
3457 if (hasTransferSyntax_) | |
3458 { | |
3459 // New in Orthanc 1.2.0 | |
3460 SetInstanceMetadata(content, instanceMetadata_, instanceId, | |
3461 MetadataType_Instance_TransferSyntax, | |
3462 GetTransferSyntaxUid(transferSyntax_)); | |
3463 } | |
3464 | |
3465 if (hasPixelDataOffset_) | |
3466 { | |
3467 // New in Orthanc 1.9.1 | |
3468 SetInstanceMetadata(content, instanceMetadata_, instanceId, | |
3469 MetadataType_Instance_PixelDataOffset, | |
3470 boost::lexical_cast<std::string>(pixelDataOffset_)); | |
3471 | |
3472 // New in Orthanc 1.12.1 | |
3473 if (dicomSummary_.GuessPixelDataValueRepresentation(transferSyntax_) != pixelDataVR_) | |
3474 { | |
3475 // Store the VR of pixel data if it doesn't comply with the standard | |
3476 SetInstanceMetadata(content, instanceMetadata_, instanceId, | |
3477 MetadataType_Instance_PixelDataVR, | |
3478 EnumerationToString(pixelDataVR_)); | |
3479 } | |
3480 } | |
3481 | |
3482 const DicomValue* value; | |
3483 if ((value = dicomSummary_.TestAndGetValue(DICOM_TAG_SOP_CLASS_UID)) != NULL && | |
3484 !value->IsNull() && | |
3485 !value->IsBinary()) | |
3486 { | |
3487 SetInstanceMetadata(content, instanceMetadata_, instanceId, | |
3488 MetadataType_Instance_SopClassUid, value->GetContent()); | |
3489 } | |
3490 | |
3491 | |
3492 if ((value = dicomSummary_.TestAndGetValue(DICOM_TAG_INSTANCE_NUMBER)) != NULL || | |
3493 (value = dicomSummary_.TestAndGetValue(DICOM_TAG_IMAGE_INDEX)) != NULL) | |
3494 { | |
3495 if (!value->IsNull() && | |
3496 !value->IsBinary()) | |
3497 { | |
3498 SetInstanceMetadata(content, instanceMetadata_, instanceId, | |
3499 MetadataType_Instance_IndexInSeries, Toolbox::StripSpaces(value->GetContent())); | |
3500 } | |
3501 } | |
3502 | |
3503 | |
3504 transaction.SetResourcesContent(content); | |
3505 | |
3506 | |
3507 if (!isReconstruct_) // a reconstruct shall not trigger any events | |
3508 { | |
3509 // Check whether the series of this new instance is now completed | |
3510 int64_t expectedNumberOfInstances; | |
3511 if (ComputeExpectedNumberOfInstances(expectedNumberOfInstances, dicomSummary_)) | |
3512 { | |
3513 SeriesStatus seriesStatus = transaction.GetSeriesStatus(status.seriesId_, expectedNumberOfInstances); | |
3514 if (seriesStatus == SeriesStatus_Complete) | |
3385 { | 3515 { |
3386 content.AddResource(status.seriesId_, ResourceType_Series, dicomSummary_); | 3516 transaction.LogChange(status.seriesId_, ChangeType_CompletedSeries, ResourceType_Series, hashSeries_); |
3387 content.AddMetadata(status.seriesId_, MetadataType_MainDicomTagsSignature, DicomMap::GetMainDicomTagsSignature(ResourceType_Series)); // New in Orthanc 1.11.0 | |
3388 SetMainDicomSequenceMetadata(content, status.seriesId_, dicomSummary_, ResourceType_Series); // new in Orthanc 1.11.1 | |
3389 } | 3517 } |
3390 | 3518 } |
3391 if (status.isNewStudy_) | 3519 |
3392 { | 3520 transaction.LogChange(status.seriesId_, ChangeType_NewChildInstance, ResourceType_Series, hashSeries_); |
3393 content.AddResource(status.studyId_, ResourceType_Study, dicomSummary_); | 3521 transaction.LogChange(status.studyId_, ChangeType_NewChildInstance, ResourceType_Study, hashStudy_); |
3394 content.AddMetadata(status.studyId_, MetadataType_MainDicomTagsSignature, DicomMap::GetMainDicomTagsSignature(ResourceType_Study)); // New in Orthanc 1.11.0 | 3522 transaction.LogChange(status.patientId_, ChangeType_NewChildInstance, ResourceType_Patient, hashPatient_); |
3395 SetMainDicomSequenceMetadata(content, status.studyId_, dicomSummary_, ResourceType_Study); // new in Orthanc 1.11.1 | 3523 |
3396 } | 3524 // Mark the parent resources of this instance as unstable |
3397 | 3525 transaction.GetTransactionContext().MarkAsUnstable(ResourceType_Series, status.seriesId_, hashSeries_); |
3398 if (status.isNewPatient_) | 3526 transaction.GetTransactionContext().MarkAsUnstable(ResourceType_Study, status.studyId_, hashStudy_); |
3399 { | 3527 transaction.GetTransactionContext().MarkAsUnstable(ResourceType_Patient, status.patientId_, hashPatient_); |
3400 content.AddResource(status.patientId_, ResourceType_Patient, dicomSummary_); | 3528 } |
3401 content.AddMetadata(status.patientId_, MetadataType_MainDicomTagsSignature, DicomMap::GetMainDicomTagsSignature(ResourceType_Patient)); // New in Orthanc 1.11.0 | 3529 |
3402 SetMainDicomSequenceMetadata(content, status.patientId_, dicomSummary_, ResourceType_Patient); // new in Orthanc 1.11.1 | |
3403 } | |
3404 | |
3405 // Attach the auto-computed metadata for the patient/study/series levels | |
3406 std::string now = SystemToolbox::GetNowIsoString(true /* use UTC time (not local time) */); | |
3407 content.AddMetadata(status.seriesId_, MetadataType_LastUpdate, now); | |
3408 content.AddMetadata(status.studyId_, MetadataType_LastUpdate, now); | |
3409 content.AddMetadata(status.patientId_, MetadataType_LastUpdate, now); | |
3410 | |
3411 if (status.isNewSeries_) | |
3412 { | |
3413 if (hasExpectedInstances_) | |
3414 { | |
3415 content.AddMetadata(status.seriesId_, MetadataType_Series_ExpectedNumberOfInstances, | |
3416 boost::lexical_cast<std::string>(expectedInstances_)); | |
3417 } | |
3418 | |
3419 // New in Orthanc 1.9.0 | |
3420 content.AddMetadata(status.seriesId_, MetadataType_RemoteAet, | |
3421 origin_.GetRemoteAetC()); | |
3422 } | |
3423 // Attach the auto-computed metadata for the instance level, | |
3424 // reflecting these additions into the input metadata map | |
3425 SetInstanceMetadata(content, instanceMetadata_, instanceId, | |
3426 MetadataType_Instance_ReceptionDate, now); | |
3427 SetInstanceMetadata(content, instanceMetadata_, instanceId, MetadataType_RemoteAet, | |
3428 origin_.GetRemoteAetC()); | |
3429 SetInstanceMetadata(content, instanceMetadata_, instanceId, MetadataType_Instance_Origin, | |
3430 EnumerationToString(origin_.GetRequestOrigin())); | |
3431 | |
3432 std::string s; | |
3433 | |
3434 if (origin_.LookupRemoteIp(s)) | |
3435 { | |
3436 // New in Orthanc 1.4.0 | |
3437 SetInstanceMetadata(content, instanceMetadata_, instanceId, | |
3438 MetadataType_Instance_RemoteIp, s); | |
3439 } | |
3440 | |
3441 if (origin_.LookupCalledAet(s)) | |
3442 { | |
3443 // New in Orthanc 1.4.0 | |
3444 SetInstanceMetadata(content, instanceMetadata_, instanceId, | |
3445 MetadataType_Instance_CalledAet, s); | |
3446 } | |
3447 | |
3448 if (origin_.LookupHttpUsername(s)) | |
3449 { | |
3450 // New in Orthanc 1.4.0 | |
3451 SetInstanceMetadata(content, instanceMetadata_, instanceId, | |
3452 MetadataType_Instance_HttpUsername, s); | |
3453 } | |
3454 } | |
3455 | |
3456 // Following metadatas are also updated if reconstructing the instance. | |
3457 // They might be missing since they have been introduced along Orthanc versions. | |
3458 | |
3459 if (hasTransferSyntax_) | |
3460 { | |
3461 // New in Orthanc 1.2.0 | |
3462 SetInstanceMetadata(content, instanceMetadata_, instanceId, | |
3463 MetadataType_Instance_TransferSyntax, | |
3464 GetTransferSyntaxUid(transferSyntax_)); | |
3465 } | |
3466 | |
3467 if (hasPixelDataOffset_) | |
3468 { | |
3469 // New in Orthanc 1.9.1 | |
3470 SetInstanceMetadata(content, instanceMetadata_, instanceId, | |
3471 MetadataType_Instance_PixelDataOffset, | |
3472 boost::lexical_cast<std::string>(pixelDataOffset_)); | |
3473 | |
3474 // New in Orthanc 1.12.1 | |
3475 if (dicomSummary_.GuessPixelDataValueRepresentation(transferSyntax_) != pixelDataVR_) | |
3476 { | |
3477 // Store the VR of pixel data if it doesn't comply with the standard | |
3478 SetInstanceMetadata(content, instanceMetadata_, instanceId, | |
3479 MetadataType_Instance_PixelDataVR, | |
3480 EnumerationToString(pixelDataVR_)); | |
3481 } | |
3482 } | |
3483 | |
3484 const DicomValue* value; | |
3485 if ((value = dicomSummary_.TestAndGetValue(DICOM_TAG_SOP_CLASS_UID)) != NULL && | |
3486 !value->IsNull() && | |
3487 !value->IsBinary()) | |
3488 { | |
3489 SetInstanceMetadata(content, instanceMetadata_, instanceId, | |
3490 MetadataType_Instance_SopClassUid, value->GetContent()); | |
3491 } | |
3492 | |
3493 | |
3494 if ((value = dicomSummary_.TestAndGetValue(DICOM_TAG_INSTANCE_NUMBER)) != NULL || | |
3495 (value = dicomSummary_.TestAndGetValue(DICOM_TAG_IMAGE_INDEX)) != NULL) | |
3496 { | |
3497 if (!value->IsNull() && | |
3498 !value->IsBinary()) | |
3499 { | |
3500 SetInstanceMetadata(content, instanceMetadata_, instanceId, | |
3501 MetadataType_Instance_IndexInSeries, Toolbox::StripSpaces(value->GetContent())); | |
3502 } | |
3503 } | |
3504 | |
3505 | |
3506 transaction.SetResourcesContent(content); | |
3507 } | |
3508 | |
3509 | |
3510 // Check whether the series of this new instance is now completed | |
3511 int64_t expectedNumberOfInstances; | |
3512 if (ComputeExpectedNumberOfInstances(expectedNumberOfInstances, dicomSummary_)) | |
3513 { | |
3514 SeriesStatus seriesStatus = transaction.GetSeriesStatus(status.seriesId_, expectedNumberOfInstances); | |
3515 if (seriesStatus == SeriesStatus_Complete) | |
3516 { | |
3517 transaction.LogChange(status.seriesId_, ChangeType_CompletedSeries, ResourceType_Series, hashSeries_); | |
3518 } | |
3519 } | |
3520 | |
3521 transaction.LogChange(status.seriesId_, ChangeType_NewChildInstance, ResourceType_Series, hashSeries_); | |
3522 transaction.LogChange(status.studyId_, ChangeType_NewChildInstance, ResourceType_Study, hashStudy_); | |
3523 transaction.LogChange(status.patientId_, ChangeType_NewChildInstance, ResourceType_Patient, hashPatient_); | |
3524 | |
3525 // Mark the parent resources of this instance as unstable | |
3526 transaction.GetTransactionContext().MarkAsUnstable(ResourceType_Series, status.seriesId_, hashSeries_); | |
3527 transaction.GetTransactionContext().MarkAsUnstable(ResourceType_Study, status.studyId_, hashStudy_); | |
3528 transaction.GetTransactionContext().MarkAsUnstable(ResourceType_Patient, status.patientId_, hashPatient_); | |
3529 transaction.GetTransactionContext().SignalAttachmentsAdded(instanceSize); | 3530 transaction.GetTransactionContext().SignalAttachmentsAdded(instanceSize); |
3530 | 3531 storeStatus_ = StoreStatus_Success; |
3531 storeStatus_ = StoreStatus_Success; | |
3532 } | 3532 } |
3533 }; | 3533 }; |
3534 | 3534 |
3535 | 3535 |
3536 Operations operations(instanceMetadata, dicomSummary, attachments, metadata, origin, overwrite, | 3536 Operations operations(instanceMetadata, dicomSummary, attachments, metadata, origin, overwrite, |