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

UPS Query SCP service for handling workitem C-FIND requests. More...

#include <ups_query_scp.h>

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

Public Member Functions

 ups_query_scp (std::shared_ptr< di::ILogger > logger=nullptr)
 Construct UPS Query SCP with optional logger.
 
 ~ups_query_scp () override=default
 
void set_handler (ups_query_handler handler)
 
void set_max_results (size_t max) noexcept
 
size_t max_results () const noexcept
 
void set_cancel_check (ups_query_cancel_check check)
 
std::vector< std::string > supported_sop_classes () const override
 Get the list of SOP Class UIDs supported by this service.
 
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.
 
std::string_view service_name () const noexcept override
 Get the service name for logging/debugging.
 
size_t queries_processed () const noexcept
 
size_t items_returned () const noexcept
 
void reset_statistics () noexcept
 
- 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 > send_pending_response (network::association &assoc, uint8_t context_id, uint16_t message_id, const core::dicom_dataset &result)
 
network::Result< std::monostate > send_final_response (network::association &assoc, uint8_t context_id, uint16_t message_id, network::dimse::status_code status)
 

Private Attributes

ups_query_handler handler_
 
ups_query_cancel_check cancel_check_
 
size_t max_results_ {0}
 
std::atomic< size_t > queries_processed_ {0}
 
std::atomic< size_t > items_returned_ {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

UPS Query SCP service for handling workitem C-FIND requests.

The UPS Query SCP (Service Class Provider) responds to C-FIND requests to search for UPS workitems. It follows the same pending/final response pattern as the Modality Worklist SCP.

UPS C-FIND Message Flow

SCU (Scheduler/Performer) UPS Query SCP
| |
| C-FIND-RQ |
| +-------------------------------+ |
| | SOPClass: ...34.6.4 | |
| | ProcedureStepState: SCHEDULED | |
| | Priority: HIGH | |
| +-------------------------------+ |
|------------------------------------>|
| |
| C-FIND-RSP (Pending, 0xFF00) |
| +-------------------------------+ |
| | WorkitemUID: 1.2.3.4... | |
| | Label: "AI Analysis" | |
| | State: SCHEDULED | |
| +-------------------------------+ |
|<------------------------------------|
| |
| ... (repeat for each match) |
| |
| C-FIND-RSP (Success, 0x0000) |
| (No dataset) |
|<------------------------------------|

Definition at line 106 of file ups_query_scp.h.

Constructor & Destructor Documentation

◆ ups_query_scp()

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

Construct UPS Query SCP with optional logger.

Parameters
loggerLogger instance (nullptr uses null_logger)

Definition at line 19 of file ups_query_scp.cpp.

20 : 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

◆ ~ups_query_scp()

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

Member Function Documentation

◆ handle_message()

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

Handle an incoming DIMSE message.

Processes the request and sends appropriate response(s) via the association.

Parameters
assocThe association on which the message was received
context_idThe presentation context ID for the message
requestThe incoming DIMSE request message
Returns
Success or error result

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

Definition at line 52 of file ups_query_scp.cpp.

55 {
56
57 using namespace network::dimse;
58
59 // Verify the message is a C-FIND request
60 if (request.command() != command_field::c_find_rq) {
63 "Expected C-FIND-RQ but received " +
64 std::string(to_string(request.command())));
65 }
66
67 // Verify we have a handler
68 if (!handler_) {
71 "No UPS query handler configured");
72 }
73
74 // Get the SOP Class UID from the request
75 auto sop_class_uid = request.affected_sop_class_uid();
76
77 // Verify the SOP Class is UPS Query FIND
78 if (sop_class_uid != ups_query_find_sop_class_uid) {
80 assoc, context_id, request.message_id(),
81 status_refused_sop_class_not_supported);
82 }
83
84 // Verify we have a dataset (query keys)
85 if (!request.has_dataset()) {
87 assoc, context_id, request.message_id(),
88 status_error_cannot_understand);
89 }
90
91 // Get the query keys from the request
92 const auto& query_keys = request.dataset().value().get();
93
94 // Get calling AE for logging and access control
95 std::string calling_ae{assoc.calling_ae()};
96
97 logger_->debug("Processing UPS C-FIND query from " + calling_ae);
98
99 // Call the handler to get matching workitems
100 auto results = handler_(query_keys, calling_ae);
101
102 // Apply max results limit if configured
103 if (max_results_ > 0 && results.size() > max_results_) {
104 results.resize(max_results_);
105 }
106
107 // Send pending responses for each result
108 for (const auto& result : results) {
109 // Check for cancel request
110 if (cancel_check_ && cancel_check_()) {
112
113 return send_final_response(
114 assoc, context_id, request.message_id(),
115 status_cancel);
116 }
117
118 // Send pending response with matching workitem
119 auto send_result = send_pending_response(
120 assoc, context_id, request.message_id(),
121 result);
122
123 if (send_result.is_err()) {
124 return send_result;
125 }
126
128 }
129
130 // Increment statistics
132
133 logger_->info("UPS C-FIND completed: " + std::to_string(results.size()) +
134 " workitems matched");
135
136 // Send final success response (no dataset)
137 return send_final_response(
138 assoc, context_id, request.message_id(),
139 status_success);
140}
std::shared_ptr< di::ILogger > logger_
Logger instance for service logging.
network::Result< std::monostate > send_pending_response(network::association &assoc, uint8_t context_id, uint16_t message_id, const core::dicom_dataset &result)
network::Result< std::monostate > send_final_response(network::association &assoc, uint8_t context_id, uint16_t message_id, network::dimse::status_code status)
std::atomic< size_t > queries_processed_
constexpr dicom_tag sop_class_uid
SOP Class UID.
constexpr int ups_unexpected_command
Definition result.h:210
constexpr int ups_handler_not_set
Definition result.h:209
auto to_string(mpps_status status) -> std::string_view
Convert mpps_status to DICOM string representation.
Definition mpps_scp.h:60
constexpr std::string_view ups_query_find_sop_class_uid
UPS Query Information Model - FIND SOP Class UID (PS3.4 Table CC.2-1)
VoidResult pacs_void_error(int code, const std::string &message, const std::string &details="")
Create a PACS void error result.
Definition result.h:249

References kcenon::pacs::network::dimse::dimse_message::affected_sop_class_uid(), kcenon::pacs::network::association::calling_ae(), cancel_check_, kcenon::pacs::network::dimse::dimse_message::command(), kcenon::pacs::network::dimse::dimse_message::dataset(), handler_, kcenon::pacs::network::dimse::dimse_message::has_dataset(), items_returned_, kcenon::pacs::services::scp_service::logger_, max_results_, kcenon::pacs::network::dimse::dimse_message::message_id(), kcenon::pacs::pacs_void_error(), queries_processed_, send_final_response(), send_pending_response(), kcenon::pacs::services::to_string(), kcenon::pacs::error_codes::ups_handler_not_set, kcenon::pacs::services::ups_query_find_sop_class_uid, and kcenon::pacs::error_codes::ups_unexpected_command.

Here is the call graph for this function:

◆ items_returned()

size_t kcenon::pacs::services::ups_query_scp::items_returned ( ) const
nodiscardnoexcept

Definition at line 154 of file ups_query_scp.cpp.

154 {
155 return items_returned_.load();
156}

References items_returned_.

◆ max_results()

size_t kcenon::pacs::services::ups_query_scp::max_results ( ) const
nodiscardnoexcept

Definition at line 34 of file ups_query_scp.cpp.

34 {
35 return max_results_;
36}

References max_results_.

◆ queries_processed()

size_t kcenon::pacs::services::ups_query_scp::queries_processed ( ) const
nodiscardnoexcept

Definition at line 150 of file ups_query_scp.cpp.

150 {
151 return queries_processed_.load();
152}

References queries_processed_.

◆ reset_statistics()

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

Definition at line 158 of file ups_query_scp.cpp.

158 {
160 items_returned_ = 0;
161}

References items_returned_, and queries_processed_.

◆ send_final_response()

network::Result< std::monostate > kcenon::pacs::services::ups_query_scp::send_final_response ( network::association & assoc,
uint8_t context_id,
uint16_t message_id,
network::dimse::status_code status )
nodiscardprivate

Definition at line 186 of file ups_query_scp.cpp.

190 {
191
192 using namespace network::dimse;
193
194 auto response = make_c_find_rsp(
195 message_id,
197 status
198 );
199
200 return assoc.send_dimse(context_id, response);
201}

References kcenon::pacs::network::association::send_dimse(), and kcenon::pacs::services::ups_query_find_sop_class_uid.

Referenced by handle_message().

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::ups_query_scp::send_pending_response ( network::association & assoc,
uint8_t context_id,
uint16_t message_id,
const core::dicom_dataset & result )
nodiscardprivate

Definition at line 167 of file ups_query_scp.cpp.

171 {
172
173 using namespace network::dimse;
174
175 auto response = make_c_find_rsp(
176 message_id,
178 status_pending
179 );
180
181 response.set_dataset(result);
182
183 return assoc.send_dimse(context_id, response);
184}

References kcenon::pacs::network::association::send_dimse(), and kcenon::pacs::services::ups_query_find_sop_class_uid.

Referenced by handle_message().

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

◆ service_name()

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

Get the service name for logging/debugging.

Returns
Human-readable service name

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

Definition at line 142 of file ups_query_scp.cpp.

142 {
143 return "UPS Query SCP";
144}

◆ set_cancel_check()

void kcenon::pacs::services::ups_query_scp::set_cancel_check ( ups_query_cancel_check check)

Definition at line 38 of file ups_query_scp.cpp.

38 {
39 cancel_check_ = std::move(check);
40}

References cancel_check_.

◆ set_handler()

void kcenon::pacs::services::ups_query_scp::set_handler ( ups_query_handler handler)

Definition at line 26 of file ups_query_scp.cpp.

26 {
27 handler_ = std::move(handler);
28}

References handler_.

◆ set_max_results()

void kcenon::pacs::services::ups_query_scp::set_max_results ( size_t max)
noexcept

Definition at line 30 of file ups_query_scp.cpp.

30 {
31 max_results_ = max;
32}

◆ supported_sop_classes()

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

Get the list of SOP Class UIDs supported by this service.

Returns
Vector of SOP Class UIDs that this service can handle

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

Definition at line 46 of file ups_query_scp.cpp.

46 {
47 return {
49 };
50}

References kcenon::pacs::services::ups_query_find_sop_class_uid.

Member Data Documentation

◆ cancel_check_

ups_query_cancel_check kcenon::pacs::services::ups_query_scp::cancel_check_
private

Definition at line 174 of file ups_query_scp.h.

Referenced by handle_message(), and set_cancel_check().

◆ handler_

ups_query_handler kcenon::pacs::services::ups_query_scp::handler_
private

Definition at line 173 of file ups_query_scp.h.

Referenced by handle_message(), and set_handler().

◆ items_returned_

std::atomic<size_t> kcenon::pacs::services::ups_query_scp::items_returned_ {0}
private

Definition at line 177 of file ups_query_scp.h.

177{0};

Referenced by handle_message(), items_returned(), and reset_statistics().

◆ max_results_

size_t kcenon::pacs::services::ups_query_scp::max_results_ {0}
private

Definition at line 175 of file ups_query_scp.h.

175{0}; // 0 = unlimited

Referenced by handle_message(), and max_results().

◆ queries_processed_

std::atomic<size_t> kcenon::pacs::services::ups_query_scp::queries_processed_ {0}
private

Definition at line 176 of file ups_query_scp.h.

176{0};

Referenced by handle_message(), queries_processed(), and reset_statistics().


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