PACS System 0.1.0
PACS DICOM system library
Loading...
Searching...
No Matches
kcenon::pacs::services::n_get_scu Class Reference

#include <n_get_scu.h>

Collaboration diagram for kcenon::pacs::services::n_get_scu:
Collaboration graph

Public Member Functions

 n_get_scu (std::shared_ptr< di::ILogger > logger=nullptr)
 Construct N-GET SCU with default configuration.
 
 n_get_scu (const n_get_scu_config &config, std::shared_ptr< di::ILogger > logger=nullptr)
 Construct N-GET SCU with custom configuration.
 
 ~n_get_scu ()=default
 
 n_get_scu (const n_get_scu &)=delete
 
n_get_scuoperator= (const n_get_scu &)=delete
 
 n_get_scu (n_get_scu &&)=delete
 
n_get_scuoperator= (n_get_scu &&)=delete
 
network::Result< n_get_resultget (network::association &assoc, std::string_view sop_class_uid, std::string_view sop_instance_uid, const std::vector< core::dicom_tag > &attribute_tags={})
 Retrieve attributes from a managed SOP Instance.
 
size_t gets_performed () const noexcept
 Get the number of N-GET operations performed.
 
void reset_statistics () noexcept
 Reset statistics counters to zero.
 

Private Member Functions

uint16_t next_message_id () noexcept
 Get the next message ID for DIMSE operations.
 

Private Attributes

std::shared_ptr< di::ILoggerlogger_
 
n_get_scu_config config_
 
std::atomic< uint16_t > message_id_counter_ {1}
 
std::atomic< size_t > gets_performed_ {0}
 

Detailed Description

Definition at line 126 of file n_get_scu.h.

Constructor & Destructor Documentation

◆ n_get_scu() [1/4]

kcenon::pacs::services::n_get_scu::n_get_scu ( std::shared_ptr< di::ILogger > logger = nullptr)
explicit

Construct N-GET SCU with default configuration.

Parameters
loggerLogger instance (nullptr uses null_logger)

Definition at line 25 of file n_get_scu.cpp.

26 : logger_(logger ? std::move(logger) : di::null_logger()) {}
std::shared_ptr< di::ILogger > logger_
Definition n_get_scu.h:205
std::shared_ptr< ILogger > null_logger()
Get a shared null logger instance.
Definition ilogger.h:271

◆ n_get_scu() [2/4]

kcenon::pacs::services::n_get_scu::n_get_scu ( const n_get_scu_config & config,
std::shared_ptr< di::ILogger > logger = nullptr )
explicit

Construct N-GET SCU with custom configuration.

Parameters
configConfiguration options
loggerLogger instance (nullptr uses null_logger)

Definition at line 28 of file n_get_scu.cpp.

30 : logger_(logger ? std::move(logger) : di::null_logger()),
31 config_(config) {}

◆ ~n_get_scu()

kcenon::pacs::services::n_get_scu::~n_get_scu ( )
default

◆ n_get_scu() [3/4]

kcenon::pacs::services::n_get_scu::n_get_scu ( const n_get_scu & )
delete

◆ n_get_scu() [4/4]

kcenon::pacs::services::n_get_scu::n_get_scu ( n_get_scu && )
delete

Member Function Documentation

◆ get()

network::Result< n_get_result > kcenon::pacs::services::n_get_scu::get ( network::association & assoc,
std::string_view sop_class_uid,
std::string_view sop_instance_uid,
const std::vector< core::dicom_tag > & attribute_tags = {} )
nodiscard

Retrieve attributes from a managed SOP Instance.

Sends an N-GET-RQ and returns the retrieved attributes.

Parameters
assocThe established association to use
sop_class_uidThe SOP Class UID of the instance
sop_instance_uidThe SOP Instance UID to query
attribute_tagsTags to retrieve (empty = all attributes)
Returns
Result containing n_get_result, or error

Definition at line 37 of file n_get_scu.cpp.

41 {
42
43 using namespace network::dimse;
44
45 auto start_time = std::chrono::steady_clock::now();
46
47 // Verify association is established
48 if (!assoc.is_established()) {
51 "Association not established");
52 }
53
54 // Validate UIDs
55 if (sop_class_uid.empty()) {
58 "SOP Class UID is required for N-GET");
59 }
60
61 if (sop_instance_uid.empty()) {
64 "SOP Instance UID is required for N-GET");
65 }
66
67 // Get accepted presentation context
68 auto context_id = assoc.accepted_context_id(sop_class_uid);
69 if (!context_id) {
72 "No accepted presentation context for SOP Class: " +
73 std::string(sop_class_uid));
74 }
75
76 // Build N-GET request using factory function
77 auto request = make_n_get_rq(
78 next_message_id(), sop_class_uid, sop_instance_uid, attribute_tags);
79
80 logger_->debug("Sending N-GET request for instance: " +
81 std::string(sop_instance_uid) +
82 " (attributes: " +
83 (attribute_tags.empty() ? "all" :
84 std::to_string(attribute_tags.size())) + ")");
85
86 // Send the request
87 auto send_result = assoc.send_dimse(*context_id, request);
88 if (send_result.is_err()) {
89 logger_->error("Failed to send N-GET: " + send_result.error().message);
90 return send_result.error();
91 }
92
93 // Receive the response
94 auto recv_result = assoc.receive_dimse(config_.timeout);
95 if (recv_result.is_err()) {
96 logger_->error("Failed to receive N-GET response: " +
97 recv_result.error().message);
98 return recv_result.error();
99 }
100
101 const auto& [recv_context_id, response] = recv_result.value();
102
103 // Verify it's an N-GET response
104 if (response.command() != command_field::n_get_rsp) {
107 "Expected N-GET-RSP but received " +
108 std::string(to_string(response.command())));
109 }
110
111 auto end_time = std::chrono::steady_clock::now();
112 auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
113 end_time - start_time);
114
115 // Build result
116 n_get_result result;
117 result.status = static_cast<uint16_t>(response.status());
118 result.elapsed = elapsed;
119
120 // Extract error comment if present
121 if (response.command_set().contains(tag_error_comment)) {
122 result.error_comment = response.command_set().get_string(
123 tag_error_comment);
124 }
125
126 // Extract dataset (returned attributes) if present
127 if (response.has_dataset()) {
128 auto dataset_result = response.dataset();
129 if (dataset_result.is_ok()) {
130 result.attributes = dataset_result.value().get();
131 }
132 }
133
134 // Update statistics
135 gets_performed_.fetch_add(1, std::memory_order_relaxed);
136
137 if (result.is_success()) {
138 logger_->info("N-GET successful for instance: " +
139 std::string(sop_instance_uid));
140 } else {
141 logger_->warn("N-GET returned status 0x" +
142 std::to_string(result.status) +
143 " for instance: " + std::string(sop_instance_uid));
144 }
145
146 return result;
147}
uint16_t next_message_id() noexcept
Get the next message ID for DIMSE operations.
std::atomic< size_t > gets_performed_
Definition n_get_scu.h:208
constexpr dicom_tag sop_instance_uid
SOP Instance UID.
constexpr dicom_tag sop_class_uid
SOP Class UID.
constexpr int n_get_missing_uid
Definition result.h:194
constexpr int n_get_unexpected_command
Definition result.h:191
constexpr int n_get_context_not_accepted
Definition result.h:193
constexpr int association_not_established
Definition result.h:202
auto to_string(mpps_status status) -> std::string_view
Convert mpps_status to DICOM string representation.
Definition mpps_scp.h:60
Result< T > pacs_error(int code, const std::string &message, const std::string &details="")
Create a PACS error result with module context.
Definition result.h:234
std::chrono::milliseconds timeout
Timeout for receiving DIMSE response.
Definition n_get_scu.h:79

References kcenon::pacs::network::association::accepted_context_id(), kcenon::pacs::error_codes::association_not_established, kcenon::pacs::services::n_get_result::attributes, config_, kcenon::pacs::services::n_get_result::elapsed, kcenon::pacs::services::n_get_result::error_comment, kcenon::pacs::core::dicom_dataset::get(), gets_performed_, kcenon::pacs::network::association::is_established(), kcenon::pacs::services::n_get_result::is_success(), logger_, kcenon::pacs::error_codes::n_get_context_not_accepted, kcenon::pacs::error_codes::n_get_missing_uid, kcenon::pacs::error_codes::n_get_unexpected_command, next_message_id(), kcenon::pacs::pacs_error(), kcenon::pacs::network::association::receive_dimse(), kcenon::pacs::network::association::send_dimse(), kcenon::pacs::services::n_get_result::status, kcenon::pacs::services::n_get_scu_config::timeout, and kcenon::pacs::services::to_string().

Here is the call graph for this function:

◆ gets_performed()

size_t kcenon::pacs::services::n_get_scu::gets_performed ( ) const
nodiscardnoexcept

Get the number of N-GET operations performed.

Definition at line 153 of file n_get_scu.cpp.

153 {
154 return gets_performed_.load(std::memory_order_relaxed);
155}

References gets_performed_.

◆ next_message_id()

uint16_t kcenon::pacs::services::n_get_scu::next_message_id ( )
nodiscardprivatenoexcept

Get the next message ID for DIMSE operations.

Definition at line 165 of file n_get_scu.cpp.

165 {
166 uint16_t id = message_id_counter_.fetch_add(1, std::memory_order_relaxed);
167 if (id == 0) {
168 id = message_id_counter_.fetch_add(1, std::memory_order_relaxed);
169 }
170 return id;
171}
std::atomic< uint16_t > message_id_counter_
Definition n_get_scu.h:207
@ id
Implant Displaced (alternate code)

References message_id_counter_.

Referenced by get().

Here is the caller graph for this function:

◆ operator=() [1/2]

n_get_scu & kcenon::pacs::services::n_get_scu::operator= ( const n_get_scu & )
delete

◆ operator=() [2/2]

n_get_scu & kcenon::pacs::services::n_get_scu::operator= ( n_get_scu && )
delete

◆ reset_statistics()

void kcenon::pacs::services::n_get_scu::reset_statistics ( )
noexcept

Reset statistics counters to zero.

Definition at line 157 of file n_get_scu.cpp.

157 {
158 gets_performed_.store(0, std::memory_order_relaxed);
159}

References gets_performed_.

Member Data Documentation

◆ config_

n_get_scu_config kcenon::pacs::services::n_get_scu::config_
private

Definition at line 206 of file n_get_scu.h.

Referenced by get().

◆ gets_performed_

std::atomic<size_t> kcenon::pacs::services::n_get_scu::gets_performed_ {0}
private

Definition at line 208 of file n_get_scu.h.

208{0};

Referenced by get(), gets_performed(), and reset_statistics().

◆ logger_

std::shared_ptr<di::ILogger> kcenon::pacs::services::n_get_scu::logger_
private

Definition at line 205 of file n_get_scu.h.

Referenced by get().

◆ message_id_counter_

std::atomic<uint16_t> kcenon::pacs::services::n_get_scu::message_id_counter_ {1}
private

Definition at line 207 of file n_get_scu.h.

207{1};

Referenced by next_message_id().


The documentation for this class was generated from the following files: