comparison Core/DicomNetworking/DicomUserConnection.cpp @ 3657:115f82775c46 storage-commitment

handling of storage commitment failure reasons
author Sebastien Jodogne <s.jodogne@gmail.com>
date Mon, 10 Feb 2020 14:53:36 +0100
parents f6a73611ec5c
children 736907ecb626
comparison
equal deleted inserted replaced
3656:cccd97333e3d 3657:115f82775c46
1385 } 1385 }
1386 1386
1387 1387
1388 static void FillSopSequence(DcmDataset& dataset, 1388 static void FillSopSequence(DcmDataset& dataset,
1389 const DcmTagKey& tag, 1389 const DcmTagKey& tag,
1390 const std::list<std::string>& sopClassUids, 1390 const std::vector<std::string>& sopClassUids,
1391 const std::list<std::string>& sopInstanceUids, 1391 const std::vector<std::string>& sopInstanceUids,
1392 bool hasFailureReason, 1392 const std::vector<StorageCommitmentFailureReason>& failureReasons,
1393 Uint16 failureReason) 1393 bool hasFailureReasons)
1394 { 1394 {
1395 assert(sopClassUids.size() == sopInstanceUids.size()); 1395 assert(sopClassUids.size() == sopInstanceUids.size() &&
1396 (hasFailureReasons ?
1397 failureReasons.size() == sopClassUids.size() :
1398 failureReasons.empty()));
1396 1399
1397 if (sopInstanceUids.empty()) 1400 if (sopInstanceUids.empty())
1398 { 1401 {
1399 // Add an empty sequence 1402 // Add an empty sequence
1400 if (!dataset.insertEmptyElement(tag).good()) 1403 if (!dataset.insertEmptyElement(tag).good())
1402 throw OrthancException(ErrorCode_InternalError); 1405 throw OrthancException(ErrorCode_InternalError);
1403 } 1406 }
1404 } 1407 }
1405 else 1408 else
1406 { 1409 {
1407 std::list<std::string>::const_iterator currentClass = sopClassUids.begin(); 1410 for (size_t i = 0; i < sopClassUids.size(); i++)
1408 std::list<std::string>::const_iterator currentInstance = sopInstanceUids.begin();
1409
1410 while (currentClass != sopClassUids.end())
1411 { 1411 {
1412 std::auto_ptr<DcmItem> item(new DcmItem); 1412 std::auto_ptr<DcmItem> item(new DcmItem);
1413 if (!item->putAndInsertString(DCM_ReferencedSOPClassUID, currentClass->c_str()).good() || 1413 if (!item->putAndInsertString(DCM_ReferencedSOPClassUID, sopClassUids[i].c_str()).good() ||
1414 !item->putAndInsertString(DCM_ReferencedSOPInstanceUID, currentInstance->c_str()).good() || 1414 !item->putAndInsertString(DCM_ReferencedSOPInstanceUID, sopInstanceUids[i].c_str()).good() ||
1415 (hasFailureReason && 1415 (hasFailureReasons &&
1416 !item->putAndInsertUint16(DCM_FailureReason, failureReason).good()) || 1416 !item->putAndInsertUint16(DCM_FailureReason, failureReasons[i]).good()) ||
1417 !dataset.insertSequenceItem(tag, item.release()).good()) 1417 !dataset.insertSequenceItem(tag, item.release()).good())
1418 { 1418 {
1419 throw OrthancException(ErrorCode_InternalError); 1419 throw OrthancException(ErrorCode_InternalError);
1420 } 1420 }
1421
1422 ++currentClass;
1423 ++currentInstance;
1424 }
1425
1426 for (size_t i = 0; i < sopClassUids.size(); i++)
1427 {
1428 } 1421 }
1429 } 1422 }
1430 } 1423 }
1431 1424
1432 1425
1433 1426
1434 1427
1435 void DicomUserConnection::ReportStorageCommitment( 1428 void DicomUserConnection::ReportStorageCommitment(
1436 const std::string& transactionUid, 1429 const std::string& transactionUid,
1437 const std::list<std::string>& successSopClassUids, 1430 const std::vector<std::string>& sopClassUids,
1438 const std::list<std::string>& successSopInstanceUids, 1431 const std::vector<std::string>& sopInstanceUids,
1439 const std::list<std::string>& failureSopClassUids, 1432 const std::vector<StorageCommitmentFailureReason>& failureReasons)
1440 const std::list<std::string>& failureSopInstanceUids) 1433 {
1441 { 1434 if (sopClassUids.size() != sopInstanceUids.size() ||
1442 if (successSopClassUids.size() != successSopInstanceUids.size() || 1435 sopClassUids.size() != failureReasons.size())
1443 failureSopClassUids.size() != failureSopInstanceUids.size())
1444 { 1436 {
1445 throw OrthancException(ErrorCode_ParameterOutOfRange); 1437 throw OrthancException(ErrorCode_ParameterOutOfRange);
1446 } 1438 }
1447 1439
1448 if (IsOpen()) 1440 if (IsOpen())
1449 { 1441 {
1450 Close(); 1442 Close();
1451 } 1443 }
1452 1444
1445 std::vector<std::string> successSopClassUids, successSopInstanceUids, failedSopClassUids, failedSopInstanceUids;
1446 std::vector<StorageCommitmentFailureReason> failedReasons;
1447
1448 successSopClassUids.reserve(sopClassUids.size());
1449 successSopInstanceUids.reserve(sopClassUids.size());
1450 failedSopClassUids.reserve(sopClassUids.size());
1451 failedSopInstanceUids.reserve(sopClassUids.size());
1452 failedReasons.reserve(sopClassUids.size());
1453
1454 for (size_t i = 0; i < sopClassUids.size(); i++)
1455 {
1456 switch (failureReasons[i])
1457 {
1458 case StorageCommitmentFailureReason_Success:
1459 successSopClassUids.push_back(sopClassUids[i]);
1460 successSopInstanceUids.push_back(sopInstanceUids[i]);
1461 break;
1462
1463 case StorageCommitmentFailureReason_ProcessingFailure:
1464 case StorageCommitmentFailureReason_NoSuchObjectInstance:
1465 case StorageCommitmentFailureReason_ResourceLimitation:
1466 case StorageCommitmentFailureReason_ReferencedSOPClassNotSupported:
1467 case StorageCommitmentFailureReason_ClassInstanceConflict:
1468 case StorageCommitmentFailureReason_DuplicateTransactionUID:
1469 failedSopClassUids.push_back(sopClassUids[i]);
1470 failedSopInstanceUids.push_back(sopInstanceUids[i]);
1471 failedReasons.push_back(failureReasons[i]);
1472 break;
1473
1474 default:
1475 {
1476 char buf[16];
1477 sprintf(buf, "%04xH", failureReasons[i]);
1478 throw OrthancException(ErrorCode_ParameterOutOfRange,
1479 "Unsupported failure reason for storage commitment: " + std::string(buf));
1480 }
1481 }
1482 }
1483
1453 try 1484 try
1454 { 1485 {
1455 OpenInternal(Mode_ReportStorageCommitment); 1486 OpenInternal(Mode_ReportStorageCommitment);
1456 1487
1457 /** 1488 /**
1468 **/ 1499 **/
1469 1500
1470 LOG(INFO) << "Reporting modality \"" << remoteAet_ 1501 LOG(INFO) << "Reporting modality \"" << remoteAet_
1471 << "\" about storage commitment transaction: " << transactionUid 1502 << "\" about storage commitment transaction: " << transactionUid
1472 << " (" << successSopClassUids.size() << " successes, " 1503 << " (" << successSopClassUids.size() << " successes, "
1473 << failureSopClassUids.size() << " failures)"; 1504 << failedSopClassUids.size() << " failures)";
1474 const DIC_US messageId = pimpl_->assoc_->nextMsgID++; 1505 const DIC_US messageId = pimpl_->assoc_->nextMsgID++;
1475 1506
1476 { 1507 {
1477 T_DIMSE_Message message; 1508 T_DIMSE_Message message;
1478 memset(&message, 0, sizeof(message)); 1509 memset(&message, 0, sizeof(message));
1488 if (!dataset.putAndInsertString(DCM_TransactionUID, transactionUid.c_str()).good()) 1519 if (!dataset.putAndInsertString(DCM_TransactionUID, transactionUid.c_str()).good())
1489 { 1520 {
1490 throw OrthancException(ErrorCode_InternalError); 1521 throw OrthancException(ErrorCode_InternalError);
1491 } 1522 }
1492 1523
1493 FillSopSequence(dataset, DCM_ReferencedSOPSequence, successSopClassUids, 1524 {
1494 successSopInstanceUids, false, 0); 1525 std::vector<StorageCommitmentFailureReason> empty;
1526 FillSopSequence(dataset, DCM_ReferencedSOPSequence, successSopClassUids,
1527 successSopInstanceUids, empty, false);
1528 }
1495 1529
1496 // http://dicom.nema.org/medical/dicom/2019a/output/chtml/part04/sect_J.3.3.html 1530 // http://dicom.nema.org/medical/dicom/2019a/output/chtml/part04/sect_J.3.3.html
1497 if (failureSopClassUids.empty()) 1531 if (failedSopClassUids.empty())
1498 { 1532 {
1499 content.EventTypeID = 1; // "Storage Commitment Request Successful" 1533 content.EventTypeID = 1; // "Storage Commitment Request Successful"
1500 } 1534 }
1501 else 1535 else
1502 { 1536 {
1503 content.EventTypeID = 2; // "Storage Commitment Request Complete - Failures Exist" 1537 content.EventTypeID = 2; // "Storage Commitment Request Complete - Failures Exist"
1504 1538
1505 // Failure reason 1539 // Failure reason
1506 // http://dicom.nema.org/medical/dicom/2019a/output/chtml/part03/sect_C.14.html#sect_C.14.1.1 1540 // http://dicom.nema.org/medical/dicom/2019a/output/chtml/part03/sect_C.14.html#sect_C.14.1.1
1507 FillSopSequence(dataset, DCM_FailedSOPSequence, failureSopClassUids, 1541 FillSopSequence(dataset, DCM_FailedSOPSequence, failedSopClassUids,
1508 failureSopInstanceUids, true, 0x0112 /* No such object instance == 274 */); 1542 failedSopInstanceUids, failedReasons, true);
1509 } 1543 }
1510 1544
1511 int presID = ASC_findAcceptedPresentationContextID( 1545 int presID = ASC_findAcceptedPresentationContextID(
1512 pimpl_->assoc_, UID_StorageCommitmentPushModelSOPClass); 1546 pimpl_->assoc_, UID_StorageCommitmentPushModelSOPClass);
1513 if (presID == 0) 1547 if (presID == 0)
1572 1606
1573 1607
1574 1608
1575 void DicomUserConnection::RequestStorageCommitment( 1609 void DicomUserConnection::RequestStorageCommitment(
1576 const std::string& transactionUid, 1610 const std::string& transactionUid,
1577 const std::list<std::string>& sopClassUids, 1611 const std::vector<std::string>& sopClassUids,
1578 const std::list<std::string>& sopInstanceUids) 1612 const std::vector<std::string>& sopInstanceUids)
1579 { 1613 {
1580 if (sopClassUids.size() != sopInstanceUids.size()) 1614 if (sopClassUids.size() != sopInstanceUids.size())
1581 { 1615 {
1582 throw OrthancException(ErrorCode_ParameterOutOfRange); 1616 throw OrthancException(ErrorCode_ParameterOutOfRange);
1583 } 1617 }
1631 if (!dataset.putAndInsertString(DCM_TransactionUID, transactionUid.c_str()).good()) 1665 if (!dataset.putAndInsertString(DCM_TransactionUID, transactionUid.c_str()).good())
1632 { 1666 {
1633 throw OrthancException(ErrorCode_InternalError); 1667 throw OrthancException(ErrorCode_InternalError);
1634 } 1668 }
1635 1669
1636 FillSopSequence(dataset, DCM_ReferencedSOPSequence, sopClassUids, sopInstanceUids, false, 0); 1670 {
1637 1671 std::vector<StorageCommitmentFailureReason> empty;
1672 FillSopSequence(dataset, DCM_ReferencedSOPSequence, sopClassUids, sopInstanceUids, empty, false);
1673 }
1674
1638 int presID = ASC_findAcceptedPresentationContextID( 1675 int presID = ASC_findAcceptedPresentationContextID(
1639 pimpl_->assoc_, UID_StorageCommitmentPushModelSOPClass); 1676 pimpl_->assoc_, UID_StorageCommitmentPushModelSOPClass);
1640 if (presID == 0) 1677 if (presID == 0)
1641 { 1678 {
1642 throw OrthancException(ErrorCode_NetworkProtocol, "Storage commitment - " 1679 throw OrthancException(ErrorCode_NetworkProtocol, "Storage commitment - "