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

#include <retrieve_scp.h>

Inheritance diagram for kcenon::pacs::services::retrieve_scp:
Inheritance graph
Collaboration diagram for kcenon::pacs::services::retrieve_scp:
Collaboration graph

Public Member Functions

 retrieve_scp (std::shared_ptr< di::ILogger > logger=nullptr)
 Construct a Retrieve SCP with optional logger.
 
 ~retrieve_scp () override=default
 
void set_retrieve_handler (retrieve_handler handler)
 Set the retrieve handler function.
 
void set_destination_resolver (destination_resolver resolver)
 Set the destination resolver function.
 
void set_store_sub_operation (store_sub_operation handler)
 Set the store sub-operation handler.
 
void set_cancel_check (retrieve_cancel_check check)
 Set the cancel check function.
 
std::vector< std::string > supported_sop_classes () const override
 Get supported SOP Class UIDs.
 
network::Result< std::monostate > handle_message (network::association &assoc, uint8_t context_id, const network::dimse::dimse_message &request) override
 Handle an incoming DIMSE message (C-MOVE-RQ or C-GET-RQ)
 
std::string_view service_name () const noexcept override
 Get the service name.
 
size_t move_operations () const noexcept
 Get total number of C-MOVE operations processed.
 
size_t get_operations () const noexcept
 Get total number of C-GET operations processed.
 
size_t images_transferred () const noexcept
 Get total number of images transferred.
 
void reset_statistics () noexcept
 Reset statistics counters.
 
- Public Member Functions inherited from kcenon::pacs::services::scp_service
 scp_service (std::shared_ptr< di::ILogger > logger=nullptr)
 Construct SCP service with optional logger.
 
virtual ~scp_service ()=default
 
 scp_service (const scp_service &)=delete
 
scp_serviceoperator= (const scp_service &)=delete
 
 scp_service (scp_service &&)=default
 
scp_serviceoperator= (scp_service &&)=default
 
void set_logger (std::shared_ptr< di::ILogger > logger)
 Set the logger instance.
 
const std::shared_ptr< di::ILogger > & logger () const noexcept
 Get the current logger instance.
 
bool supports_sop_class (std::string_view sop_class_uid) const
 Check if this service supports a specific SOP Class.
 

Private Member Functions

network::Result< std::monostate > handle_c_move (network::association &assoc, uint8_t context_id, const network::dimse::dimse_message &request)
 Handle a C-MOVE request.
 
network::Result< std::monostate > handle_c_get (network::association &assoc, uint8_t context_id, const network::dimse::dimse_message &request)
 Handle a C-GET request.
 
network::Result< std::monostate > send_pending_response (network::association &assoc, uint8_t context_id, uint16_t message_id, std::string_view sop_class_uid, bool is_move, const sub_operation_stats &stats)
 Send a pending response with progress information.
 
network::Result< std::monostate > send_final_response (network::association &assoc, uint8_t context_id, uint16_t message_id, std::string_view sop_class_uid, bool is_move, const sub_operation_stats &stats, bool was_cancelled)
 Send a final response with completion status.
 
std::string get_move_destination (const network::dimse::dimse_message &request) const
 Get the Move Destination AE title from the request.
 

Private Attributes

retrieve_handler retrieve_handler_
 
destination_resolver destination_resolver_
 
store_sub_operation store_handler_
 
retrieve_cancel_check cancel_check_
 
std::atomic< size_t > move_operations_ {0}
 
std::atomic< size_t > get_operations_ {0}
 
std::atomic< size_t > images_transferred_ {0}
 

Additional Inherited Members

- Protected Attributes inherited from kcenon::pacs::services::scp_service
std::shared_ptr< di::ILoggerlogger_
 Logger instance for service logging.
 

Detailed Description

Definition at line 230 of file retrieve_scp.h.

Constructor & Destructor Documentation

◆ retrieve_scp()

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

Construct a Retrieve SCP with optional logger.

Parameters
loggerLogger instance for service logging (nullptr uses null_logger)

Definition at line 26 of file retrieve_scp.cpp.

27 : scp_service(std::move(logger)) {}
const std::shared_ptr< di::ILogger > & logger() const noexcept
Get the current logger instance.
Definition scp_service.h:93
scp_service(std::shared_ptr< di::ILogger > logger=nullptr)
Construct SCP service with optional logger.
Definition scp_service.h:64

◆ ~retrieve_scp()

kcenon::pacs::services::retrieve_scp::~retrieve_scp ( )
overridedefault

Member Function Documentation

◆ get_move_destination()

std::string kcenon::pacs::services::retrieve_scp::get_move_destination ( const network::dimse::dimse_message & request) const
nodiscardprivate

Get the Move Destination AE title from the request.

Parameters
requestThe C-MOVE-RQ message
Returns
Move Destination AE title, or empty string if not present

Definition at line 528 of file retrieve_scp.cpp.

529 {
530
531 // Move Destination is in the command set at tag (0000,0600)
532 return request.command_set().get_string(network::dimse::tag_move_destination);
533}
constexpr core::dicom_tag tag_move_destination
Move Destination (0000,0600) - AE.

References kcenon::pacs::network::dimse::dimse_message::command_set(), and kcenon::pacs::network::dimse::tag_move_destination.

Referenced by handle_c_move().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_operations()

size_t kcenon::pacs::services::retrieve_scp::get_operations ( ) const
nodiscardnoexcept

Get total number of C-GET operations processed.

Returns
Number of C-GET requests handled

Definition at line 97 of file retrieve_scp.cpp.

97 {
98 return get_operations_.load();
99}
std::atomic< size_t > get_operations_

References get_operations_.

◆ handle_c_get()

network::Result< std::monostate > kcenon::pacs::services::retrieve_scp::handle_c_get ( network::association & assoc,
uint8_t context_id,
const network::dimse::dimse_message & request )
nodiscardprivate

Handle a C-GET request.

Parameters
assocThe association
context_idThe presentation context ID
requestThe C-GET-RQ message
Returns
Success or error

Definition at line 278 of file retrieve_scp.cpp.

281 {
282
283 using namespace network::dimse;
284
285 // Verify we have a retrieve handler
286 if (!retrieve_handler_) {
289 "No retrieve handler configured");
290 }
291
292 auto sop_class_uid = request.affected_sop_class_uid();
293 auto message_id = request.message_id();
294
295 // Verify we have a dataset (query keys)
296 if (!request.has_dataset()) {
297 sub_operation_stats stats;
298 return send_final_response(
299 assoc, context_id, message_id,
300 sop_class_uid, false, stats, false);
301 }
302
303 // Get calling AE for logging
304 std::string calling_ae{assoc.calling_ae()};
305
306 // Retrieve matching files
307 const auto& query_keys = request.dataset().value().get();
308 auto files = retrieve_handler_(query_keys);
309 auto start_time = std::chrono::steady_clock::now();
310
311 // Get study UID for event
312 std::string study_uid = query_keys.get_string(core::tags::study_instance_uid);
313
314 // Publish retrieve started event (C-GET has no destination AE)
315 kcenon::common::get_event_bus().publish(
318 calling_ae,
319 "", // No destination for C-GET
320 study_uid,
321 static_cast<uint16_t>(files.size())
322 }
323 );
324
325 // Initialize sub-operation statistics
326 sub_operation_stats stats;
327 stats.remaining = static_cast<uint16_t>(files.size());
328 bool was_cancelled = false;
329
330 // Process each file (C-STORE sub-operations on same association)
331 for (const auto& file : files) {
332 // Check for cancel request
333 if (cancel_check_ && cancel_check_()) {
334 was_cancelled = true;
335 break;
336 }
337
338 // Send pending response with current progress
339 auto pending_result = send_pending_response(
340 assoc, context_id, message_id,
341 sop_class_uid, false, stats);
342
343 if (pending_result.is_err()) {
344 return pending_result;
345 }
346
347 // Perform C-STORE sub-operation on the same association
348 // For C-GET, images are sent back on the same association
349 status_code store_status = status_success;
350
351 if (store_handler_) {
352 // Use custom store handler
353 store_status = store_handler_(
354 assoc, context_id, file,
355 calling_ae, message_id);
356 } else {
357 // Default implementation: build and send C-STORE-RQ
358 // Get the SOP Class and Instance UIDs from the file
359 auto file_sop_class = file.sop_class_uid();
360 auto file_sop_instance = file.sop_instance_uid();
361
362 // Create C-STORE request
363 dimse_message store_rq{command_field::c_store_rq, message_id};
364 store_rq.set_affected_sop_class_uid(file_sop_class);
365 store_rq.set_affected_sop_instance_uid(file_sop_instance);
366 store_rq.set_priority(priority_medium);
367
368 // For C-GET, include Move Originator information
369 // (0000,1030) Move Originator Application Entity Title
370 // (0000,1031) Move Originator Message ID
371 store_rq.command_set().set_string(
372 tag_move_originator_aet,
374 calling_ae);
375 store_rq.command_set().set_numeric<uint16_t>(
378 message_id);
379
380 // Attach the dataset
381 store_rq.set_dataset(file.dataset());
382
383 // Find the presentation context for the SOP Class
384 auto store_context_id = assoc.accepted_context_id(file_sop_class);
385 if (!store_context_id.has_value()) {
386 // No accepted context for this SOP Class
387 stats.remaining--;
388 stats.failed++;
389 continue;
390 }
391
392 // Send the C-STORE request
393 auto send_result = assoc.send_dimse(store_context_id.value(), store_rq);
394 if (send_result.is_err()) {
395 stats.remaining--;
396 stats.failed++;
397 continue;
398 }
399
400 // Wait for C-STORE response
401 auto recv_result = assoc.receive_dimse();
402 if (recv_result.is_err()) {
403 stats.remaining--;
404 stats.failed++;
405 continue;
406 }
407
408 auto& [recv_ctx, store_rsp] = recv_result.value();
409 store_status = store_rsp.status();
410 }
411
412 // Update statistics based on store result
413 stats.remaining--;
414 if (is_success(store_status)) {
415 stats.completed++;
417 } else if (is_warning(store_status)) {
418 stats.warning++;
420 } else {
421 stats.failed++;
422 }
423 }
424
425 // Update operation count
427
428 // Calculate duration and publish completed event
429 auto end_time = std::chrono::steady_clock::now();
430 auto duration_ms = std::chrono::duration_cast<std::chrono::milliseconds>(
431 end_time - start_time).count();
432
433 kcenon::common::get_event_bus().publish(
436 calling_ae,
437 "", // No destination for C-GET
438 stats.completed,
439 stats.failed,
440 stats.warning,
441 static_cast<uint64_t>(duration_ms)
442 }
443 );
444
445 // Send final response
446 return send_final_response(
447 assoc, context_id, message_id,
448 sop_class_uid, false, stats, was_cancelled);
449}
network::Result< std::monostate > send_pending_response(network::association &assoc, uint8_t context_id, uint16_t message_id, std::string_view sop_class_uid, bool is_move, const sub_operation_stats &stats)
Send a pending response with progress information.
retrieve_cancel_check cancel_check_
std::atomic< size_t > images_transferred_
network::Result< std::monostate > send_final_response(network::association &assoc, uint8_t context_id, uint16_t message_id, std::string_view sop_class_uid, bool is_move, const sub_operation_stats &stats, bool was_cancelled)
Send a final response with completion status.
constexpr dicom_tag message_id
Message ID.
constexpr dicom_tag study_instance_uid
Study Instance UID.
constexpr dicom_tag sop_class_uid
SOP Class UID.
@ US
Unsigned Short (2 bytes)
@ AE
Application Entity (16 chars max)
constexpr int retrieve_handler_not_set
Definition result.h:161
constexpr core::dicom_tag tag_move_originator_message_id
Move Originator Message ID (0000,1031) - US.
constexpr bool is_success(storage_status status) noexcept
Check if the status indicates success.
constexpr bool is_warning(storage_status status) noexcept
Check if the status indicates a warning.
VoidResult pacs_void_error(int code, const std::string &message, const std::string &details="")
Create a PACS void error result.
Definition result.h:249
Event published when a retrieve operation completes.
Definition events.h:271
Event published when a retrieve operation (C-MOVE/C-GET) starts.
Definition events.h:247

References kcenon::pacs::network::association::accepted_context_id(), kcenon::pacs::encoding::AE, kcenon::pacs::network::dimse::dimse_message::affected_sop_class_uid(), kcenon::pacs::events::c_get, kcenon::pacs::network::association::calling_ae(), cancel_check_, kcenon::pacs::network::dimse::dimse_message::dataset(), get_operations_, kcenon::pacs::network::dimse::dimse_message::has_dataset(), images_transferred_, kcenon::pacs::services::is_success(), kcenon::pacs::services::is_warning(), kcenon::pacs::network::dimse::dimse_message::message_id(), kcenon::pacs::pacs_void_error(), kcenon::pacs::network::association::receive_dimse(), retrieve_handler_, kcenon::pacs::error_codes::retrieve_handler_not_set, kcenon::pacs::network::association::send_dimse(), send_final_response(), send_pending_response(), store_handler_, kcenon::pacs::core::tags::study_instance_uid, and kcenon::pacs::encoding::US.

Referenced by handle_message().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ handle_c_move()

network::Result< std::monostate > kcenon::pacs::services::retrieve_scp::handle_c_move ( network::association & assoc,
uint8_t context_id,
const network::dimse::dimse_message & request )
nodiscardprivate

Handle a C-MOVE request.

Parameters
assocThe association
context_idThe presentation context ID
requestThe C-MOVE-RQ message
Returns
Success or error

Definition at line 115 of file retrieve_scp.cpp.

118 {
119
120 using namespace network::dimse;
121
122 // Verify we have a retrieve handler
123 if (!retrieve_handler_) {
126 "No retrieve handler configured");
127 }
128
129 // Verify we have a destination resolver for C-MOVE
133 "No destination resolver configured for C-MOVE");
134 }
135
136 auto sop_class_uid = request.affected_sop_class_uid();
137 auto message_id = request.message_id();
138
139 // Verify we have a dataset (query keys)
140 if (!request.has_dataset()) {
141 sub_operation_stats stats;
142 return send_final_response(
143 assoc, context_id, message_id,
144 sop_class_uid, true, stats, false);
145 }
146
147 // Get move destination AE title
148 auto dest_ae = get_move_destination(request);
149 if (dest_ae.empty()) {
150 // Missing Move Destination - return error status
152
153 dimse_message response{command_field::c_move_rsp, 0};
154 response.set_affected_sop_class_uid(sop_class_uid);
155 response.set_message_id_responded_to(message_id);
156 response.set_status(status_refused_move_destination_unknown);
157
158 return assoc.send_dimse(context_id, response);
159 }
160
161 // Resolve destination to network address
162 auto dest_addr = destination_resolver_(dest_ae);
163 if (!dest_addr.has_value()) {
164 // Unknown destination AE - return error status
166
167 dimse_message response{command_field::c_move_rsp, 0};
168 response.set_affected_sop_class_uid(sop_class_uid);
169 response.set_message_id_responded_to(message_id);
170 response.set_status(status_refused_move_destination_unknown);
171
172 return assoc.send_dimse(context_id, response);
173 }
174
175 // Get calling AE for move originator information
176 std::string calling_ae{assoc.calling_ae()};
177
178 // Retrieve matching files
179 const auto& query_keys = request.dataset().value().get();
180 auto files = retrieve_handler_(query_keys);
181 auto start_time = std::chrono::steady_clock::now();
182
183 // Get study UID for event
184 std::string study_uid = query_keys.get_string(core::tags::study_instance_uid);
185
186 // Publish retrieve started event
187 kcenon::common::get_event_bus().publish(
190 calling_ae,
191 dest_ae,
192 study_uid,
193 static_cast<uint16_t>(files.size())
194 }
195 );
196
197 // Initialize sub-operation statistics
198 sub_operation_stats stats;
199 stats.remaining = static_cast<uint16_t>(files.size());
200 bool was_cancelled = false;
201
202 // Process each file (C-STORE sub-operations)
203 for (const auto& file : files) {
204 // Check for cancel request
205 if (cancel_check_ && cancel_check_()) {
206 was_cancelled = true;
207 break;
208 }
209
210 // Send pending response with current progress
211 auto pending_result = send_pending_response(
212 assoc, context_id, message_id,
213 sop_class_uid, true, stats);
214
215 if (pending_result.is_err()) {
216 return pending_result;
217 }
218
219 // Perform C-STORE sub-operation
220 // Note: In a full implementation, this would establish a sub-association
221 // to the destination and perform C-STORE. For now, we simulate success
222 // or use the provided store handler.
223 status_code store_status = status_success;
224
225 if (store_handler_) {
226 // Use custom store handler
227 // The handler should establish connection to dest_addr and perform C-STORE
228 // For now, we pass the current association (which isn't correct for C-MOVE)
229 // A real implementation would create a separate association to destination
230 store_status = store_handler_(
231 assoc, context_id, file,
232 calling_ae, message_id);
233 }
234
235 // Update statistics based on store result
236 stats.remaining--;
237 if (is_success(store_status)) {
238 stats.completed++;
240 } else if (is_warning(store_status)) {
241 stats.warning++;
243 } else {
244 stats.failed++;
245 }
246 }
247
248 // Update operation count
250
251 // Calculate duration and publish completed event
252 auto end_time = std::chrono::steady_clock::now();
253 auto duration_ms = std::chrono::duration_cast<std::chrono::milliseconds>(
254 end_time - start_time).count();
255
256 kcenon::common::get_event_bus().publish(
259 calling_ae,
260 dest_ae,
261 stats.completed,
262 stats.failed,
263 stats.warning,
264 static_cast<uint64_t>(duration_ms)
265 }
266 );
267
268 // Send final response
269 return send_final_response(
270 assoc, context_id, message_id,
271 sop_class_uid, true, stats, was_cancelled);
272}
std::string get_move_destination(const network::dimse::dimse_message &request) const
Get the Move Destination AE title from the request.
destination_resolver destination_resolver_
std::atomic< size_t > move_operations_
constexpr int retrieve_missing_destination
Definition result.h:162

References kcenon::pacs::network::dimse::dimse_message::affected_sop_class_uid(), kcenon::pacs::events::c_move, kcenon::pacs::network::association::calling_ae(), cancel_check_, kcenon::pacs::network::dimse::dimse_message::dataset(), destination_resolver_, get_move_destination(), kcenon::pacs::network::dimse::dimse_message::has_dataset(), images_transferred_, kcenon::pacs::services::is_success(), kcenon::pacs::services::is_warning(), kcenon::pacs::network::dimse::dimse_message::message_id(), move_operations_, kcenon::pacs::pacs_void_error(), retrieve_handler_, kcenon::pacs::error_codes::retrieve_handler_not_set, kcenon::pacs::error_codes::retrieve_missing_destination, kcenon::pacs::network::association::send_dimse(), send_final_response(), send_pending_response(), store_handler_, and kcenon::pacs::core::tags::study_instance_uid.

Referenced by handle_message().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ handle_message()

network::Result< std::monostate > kcenon::pacs::services::retrieve_scp::handle_message ( network::association & assoc,
uint8_t context_id,
const network::dimse::dimse_message & request )
nodiscardoverridevirtual

Handle an incoming DIMSE message (C-MOVE-RQ or C-GET-RQ)

Processes the retrieve request:

  1. Validates the message type (C-MOVE-RQ or C-GET-RQ)
  2. Extracts query keys from the dataset
  3. Retrieves matching files via the retrieve handler
  4. For C-MOVE: resolves destination and establishes sub-association
  5. Performs C-STORE sub-operations for each file
  6. Sends pending responses with progress updates
  7. Sends final response with operation statistics
Parameters
assocThe association on which the message was received
context_idThe presentation context ID for the message
requestThe incoming C-MOVE-RQ or C-GET-RQ message
Returns
Success or error

Implements kcenon::pacs::services::scp_service.

Definition at line 62 of file retrieve_scp.cpp.

65 {
66
67 using namespace network::dimse;
68
69 // Route to appropriate handler based on command type
70 switch (request.command()) {
71 case command_field::c_move_rq:
72 return handle_c_move(assoc, context_id, request);
73
74 case command_field::c_get_rq:
75 return handle_c_get(assoc, context_id, request);
76
77 default:
80 "Expected C-MOVE-RQ or C-GET-RQ but received " +
81 std::string(to_string(request.command())));
82 }
83}
network::Result< std::monostate > handle_c_get(network::association &assoc, uint8_t context_id, const network::dimse::dimse_message &request)
Handle a C-GET request.
network::Result< std::monostate > handle_c_move(network::association &assoc, uint8_t context_id, const network::dimse::dimse_message &request)
Handle a C-MOVE request.
constexpr int retrieve_unexpected_command
Definition result.h:165
auto to_string(mpps_status status) -> std::string_view
Convert mpps_status to DICOM string representation.
Definition mpps_scp.h:60

References kcenon::pacs::network::dimse::dimse_message::command(), handle_c_get(), handle_c_move(), kcenon::pacs::pacs_void_error(), kcenon::pacs::error_codes::retrieve_unexpected_command, and kcenon::pacs::services::to_string().

Here is the call graph for this function:

◆ images_transferred()

size_t kcenon::pacs::services::retrieve_scp::images_transferred ( ) const
nodiscardnoexcept

Get total number of images transferred.

Returns
Number of images sent via C-STORE sub-operations

Definition at line 101 of file retrieve_scp.cpp.

101 {
102 return images_transferred_.load();
103}

References images_transferred_.

◆ move_operations()

size_t kcenon::pacs::services::retrieve_scp::move_operations ( ) const
nodiscardnoexcept

Get total number of C-MOVE operations processed.

Returns
Number of C-MOVE requests handled

Definition at line 93 of file retrieve_scp.cpp.

93 {
94 return move_operations_.load();
95}

References move_operations_.

◆ reset_statistics()

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

Reset statistics counters.

Definition at line 105 of file retrieve_scp.cpp.

105 {
107 get_operations_ = 0;
109}

References get_operations_, images_transferred_, and move_operations_.

◆ send_final_response()

network::Result< std::monostate > kcenon::pacs::services::retrieve_scp::send_final_response ( network::association & assoc,
uint8_t context_id,
uint16_t message_id,
std::string_view sop_class_uid,
bool is_move,
const sub_operation_stats & stats,
bool was_cancelled )
nodiscardprivate

Send a final response with completion status.

Parameters
assocThe association
context_idThe presentation context ID
message_idThe original request message ID
sop_class_uidThe SOP Class UID
is_movetrue for C-MOVE-RSP, false for C-GET-RSP
statsFinal sub-operation statistics
was_cancelledtrue if operation was cancelled
Returns
Success or error

Definition at line 483 of file retrieve_scp.cpp.

490 {
491
492 using namespace network::dimse;
493
494 // Create response message
495 auto cmd = is_move ? command_field::c_move_rsp : command_field::c_get_rsp;
496 dimse_message response{cmd, 0};
497
498 response.set_affected_sop_class_uid(sop_class_uid);
499 response.set_message_id_responded_to(message_id);
500
501 // Determine final status
502 status_code final_status;
503 if (was_cancelled) {
504 final_status = status_cancel;
505 } else if (stats.failed > 0 && stats.completed == 0 && stats.warning == 0) {
506 // All sub-operations failed
507 final_status = status_refused_out_of_resources_subops;
508 } else if (stats.failed > 0 || stats.warning > 0) {
509 // Some sub-operations had issues
511 } else {
512 // All successful
513 final_status = status_success;
514 }
515
516 response.set_status(final_status);
517
518 // Set final sub-operation counts
519 response.set_remaining_subops(stats.remaining);
520 response.set_completed_subops(stats.completed);
521 response.set_failed_subops(stats.failed);
522 response.set_warning_subops(stats.warning);
523
524 // Send the response
525 return assoc.send_dimse(context_id, response);
526}
constexpr status_code status_warning_subops_complete_failures
Warning: Sub-operations complete with failures.

References kcenon::pacs::network::association::send_dimse().

Referenced by handle_c_get(), and handle_c_move().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ send_pending_response()

network::Result< std::monostate > kcenon::pacs::services::retrieve_scp::send_pending_response ( network::association & assoc,
uint8_t context_id,
uint16_t message_id,
std::string_view sop_class_uid,
bool is_move,
const sub_operation_stats & stats )
nodiscardprivate

Send a pending response with progress information.

Parameters
assocThe association
context_idThe presentation context ID
message_idThe original request message ID
sop_class_uidThe SOP Class UID
is_movetrue for C-MOVE-RSP, false for C-GET-RSP
statsCurrent sub-operation statistics
Returns
Success or error

Definition at line 455 of file retrieve_scp.cpp.

461 {
462
463 using namespace network::dimse;
464
465 // Create response message
466 auto cmd = is_move ? command_field::c_move_rsp : command_field::c_get_rsp;
467 dimse_message response{cmd, 0};
468
469 response.set_affected_sop_class_uid(sop_class_uid);
470 response.set_message_id_responded_to(message_id);
471 response.set_status(status_pending);
472
473 // Set sub-operation counts
474 response.set_remaining_subops(stats.remaining);
475 response.set_completed_subops(stats.completed);
476 response.set_failed_subops(stats.failed);
477 response.set_warning_subops(stats.warning);
478
479 // Send the response
480 return assoc.send_dimse(context_id, response);
481}

References kcenon::pacs::network::association::send_dimse().

Referenced by handle_c_get(), and handle_c_move().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ service_name()

std::string_view kcenon::pacs::services::retrieve_scp::service_name ( ) const
nodiscardoverridevirtualnoexcept

Get the service name.

Returns
"Retrieve SCP"

Implements kcenon::pacs::services::scp_service.

Definition at line 85 of file retrieve_scp.cpp.

85 {
86 return "Retrieve SCP";
87}

◆ set_cancel_check()

void kcenon::pacs::services::retrieve_scp::set_cancel_check ( retrieve_cancel_check check)

Set the cancel check function.

The cancel check is called periodically during retrieve processing to check if a C-CANCEL has been received.

Parameters
checkThe cancel check function

Definition at line 45 of file retrieve_scp.cpp.

45 {
46 cancel_check_ = std::move(check);
47}

References cancel_check_.

◆ set_destination_resolver()

void kcenon::pacs::services::retrieve_scp::set_destination_resolver ( destination_resolver resolver)

Set the destination resolver function.

The resolver maps AE titles to network addresses for C-MOVE operations.

Parameters
resolverThe destination resolver function

Definition at line 37 of file retrieve_scp.cpp.

37 {
38 destination_resolver_ = std::move(resolver);
39}

References destination_resolver_.

◆ set_retrieve_handler()

void kcenon::pacs::services::retrieve_scp::set_retrieve_handler ( retrieve_handler handler)

Set the retrieve handler function.

The handler is called for each retrieve request to find matching DICOM files in storage.

Parameters
handlerThe retrieve handler function

Definition at line 33 of file retrieve_scp.cpp.

33 {
34 retrieve_handler_ = std::move(handler);
35}

References retrieve_handler_.

◆ set_store_sub_operation()

void kcenon::pacs::services::retrieve_scp::set_store_sub_operation ( store_sub_operation handler)

Set the store sub-operation handler.

The store handler performs C-STORE sub-operations during C-MOVE/C-GET. If not set, a default implementation using the association's send_dimse will be used.

Parameters
handlerThe store sub-operation handler

Definition at line 41 of file retrieve_scp.cpp.

41 {
42 store_handler_ = std::move(handler);
43}

References store_handler_.

◆ supported_sop_classes()

std::vector< std::string > kcenon::pacs::services::retrieve_scp::supported_sop_classes ( ) const
nodiscardoverridevirtual

Get supported SOP Class UIDs.

Returns
Vector containing Patient Root and Study Root Move/Get SOP Classes

Implements kcenon::pacs::services::scp_service.

Definition at line 53 of file retrieve_scp.cpp.

53 {
54 return {
59 };
60}
constexpr std::string_view study_root_move_sop_class_uid
Study Root Query/Retrieve Information Model - MOVE.
constexpr std::string_view study_root_get_sop_class_uid
Study Root Query/Retrieve Information Model - GET.
constexpr std::string_view patient_root_move_sop_class_uid
Patient Root Query/Retrieve Information Model - MOVE.
constexpr std::string_view patient_root_get_sop_class_uid
Patient Root Query/Retrieve Information Model - GET.

References kcenon::pacs::services::patient_root_get_sop_class_uid, kcenon::pacs::services::patient_root_move_sop_class_uid, kcenon::pacs::services::study_root_get_sop_class_uid, and kcenon::pacs::services::study_root_move_sop_class_uid.

Member Data Documentation

◆ cancel_check_

retrieve_cancel_check kcenon::pacs::services::retrieve_scp::cancel_check_
private

Definition at line 442 of file retrieve_scp.h.

Referenced by handle_c_get(), handle_c_move(), and set_cancel_check().

◆ destination_resolver_

destination_resolver kcenon::pacs::services::retrieve_scp::destination_resolver_
private

Definition at line 440 of file retrieve_scp.h.

Referenced by handle_c_move(), and set_destination_resolver().

◆ get_operations_

std::atomic<size_t> kcenon::pacs::services::retrieve_scp::get_operations_ {0}
private

Definition at line 445 of file retrieve_scp.h.

445{0};

Referenced by get_operations(), handle_c_get(), and reset_statistics().

◆ images_transferred_

std::atomic<size_t> kcenon::pacs::services::retrieve_scp::images_transferred_ {0}
private

Definition at line 446 of file retrieve_scp.h.

446{0};

Referenced by handle_c_get(), handle_c_move(), images_transferred(), and reset_statistics().

◆ move_operations_

std::atomic<size_t> kcenon::pacs::services::retrieve_scp::move_operations_ {0}
private

Definition at line 444 of file retrieve_scp.h.

444{0};

Referenced by handle_c_move(), move_operations(), and reset_statistics().

◆ retrieve_handler_

retrieve_handler kcenon::pacs::services::retrieve_scp::retrieve_handler_
private

Definition at line 439 of file retrieve_scp.h.

Referenced by handle_c_get(), handle_c_move(), and set_retrieve_handler().

◆ store_handler_

store_sub_operation kcenon::pacs::services::retrieve_scp::store_handler_
private

Definition at line 441 of file retrieve_scp.h.

Referenced by handle_c_get(), handle_c_move(), and set_store_sub_operation().


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