PACS System 0.1.0
PACS DICOM system library
Loading...
Searching...
No Matches
kcenon::pacs::network::pipeline::dimse_process_job Class Reference

Job for processing DIMSE messages. More...

#include <dimse_process_job.h>

Inheritance diagram for kcenon::pacs::network::pipeline::dimse_process_job:
Inheritance graph
Collaboration diagram for kcenon::pacs::network::pipeline::dimse_process_job:
Collaboration graph

Public Types

using request_callback = std::function<void(const dimse_request& request)>
 Callback type for processed request.
 
using association_callback
 Callback type for association handling.
 
using error_callback
 Callback type for processing errors.
 

Public Member Functions

 dimse_process_job (decoded_pdu pdu, request_callback on_request=nullptr, association_callback on_association=nullptr, error_callback on_error=nullptr)
 Construct a DIMSE process job from decoded PDU.
 
 ~dimse_process_job () override=default
 
 dimse_process_job (const dimse_process_job &)=delete
 
dimse_process_joboperator= (const dimse_process_job &)=delete
 
 dimse_process_job (dimse_process_job &&)=default
 
dimse_process_joboperator= (dimse_process_job &&)=default
 
auto execute (pipeline_coordinator &coordinator) -> VoidResult override
 Execute the DIMSE process job.
 
auto get_context () const noexcept -> const job_context &override
 Get the job context.
 
auto get_context () noexcept -> job_context &override
 Get the job context (mutable)
 
auto get_name () const -> std::string override
 Get the job name.
 
auto get_pdu () const noexcept -> const decoded_pdu &
 Get the decoded PDU.
 
- Public Member Functions inherited from kcenon::pacs::network::pipeline::pipeline_job_base
virtual ~pipeline_job_base ()=default
 Virtual destructor.
 

Private Member Functions

auto process_p_data () -> Result< dimse_request >
 Process P-DATA-TF PDU.
 
auto process_association_pdu () -> VoidResult
 Process association PDUs (A-ASSOCIATE, A-RELEASE, A-ABORT)
 

Private Attributes

job_context context_
 
decoded_pdu pdu_
 
request_callback on_request_
 
association_callback on_association_
 
error_callback on_error_
 

Additional Inherited Members

- Protected Member Functions inherited from kcenon::pacs::network::pipeline::pipeline_job_base
 pipeline_job_base ()=default
 
 pipeline_job_base (const pipeline_job_base &)=delete
 
pipeline_job_baseoperator= (const pipeline_job_base &)=delete
 
 pipeline_job_base (pipeline_job_base &&)=default
 
pipeline_job_baseoperator= (pipeline_job_base &&)=default
 

Detailed Description

Job for processing DIMSE messages.

Stage 3 of the pipeline. Processes DIMSE messages and routes them to the storage/query execution stage.

Definition at line 108 of file dimse_process_job.h.

Member Typedef Documentation

◆ association_callback

Initial value:
std::function<void(uint64_t session_id,
const std::vector<uint8_t>& data)>
pdu_type
PDU (Protocol Data Unit) types as defined in DICOM PS3.8.
Definition pdu_types.h:25

Callback type for association handling.

Examples
/home/runner/work/pacs_system/pacs_system/include/kcenon/pacs/network/pipeline/jobs/dimse_process_job.h.

Definition at line 114 of file dimse_process_job.h.

◆ error_callback

Initial value:
std::function<void(uint64_t session_id,
const std::string& error)>

Callback type for processing errors.

Examples
/home/runner/work/pacs_system/pacs_system/include/kcenon/pacs/network/pipeline/jobs/dimse_process_job.h.

Definition at line 119 of file dimse_process_job.h.

◆ request_callback

Constructor & Destructor Documentation

◆ dimse_process_job() [1/3]

kcenon::pacs::network::pipeline::dimse_process_job::dimse_process_job ( decoded_pdu pdu,
request_callback on_request = nullptr,
association_callback on_association = nullptr,
error_callback on_error = nullptr )

Construct a DIMSE process job from decoded PDU.

Parameters
pduThe decoded PDU to process
on_requestCallback for DIMSE requests
on_associationCallback for association messages
on_errorCallback for errors
Examples
/home/runner/work/pacs_system/pacs_system/include/kcenon/pacs/network/pipeline/jobs/dimse_process_job.h.

Definition at line 20 of file dimse_process_job.cpp.

24 : pdu_(std::move(pdu))
25 , on_request_(std::move(on_request))
26 , on_association_(std::move(on_association))
27 , on_error_(std::move(on_error)) {
28
32 context_.enqueue_time_ns = static_cast<uint64_t>(
33 std::chrono::duration_cast<std::chrono::nanoseconds>(
34 std::chrono::steady_clock::now().time_since_epoch()
35 ).count()
36 );
37}
@ dimse_process
Stage 3: Process DIMSE messages and route requests.
std::variant< associate_rq, associate_ac, associate_rj, p_data_tf_pdu, release_rq_pdu, release_rp_pdu, abort_pdu > pdu
Variant type that can hold any PDU.
Definition pdu_decoder.h:62
uint64_t session_id
Session this PDU belongs to.
pipeline_stage stage
Current pipeline stage.
job_category category
Job category for metrics.
uint64_t enqueue_time_ns
Timestamp when job entered the pipeline (nanoseconds since epoch)
uint64_t session_id
Session/association identifier.

References kcenon::pacs::network::pipeline::job_context::category, context_, kcenon::pacs::network::pipeline::dimse_process, kcenon::pacs::network::pipeline::job_context::enqueue_time_ns, kcenon::pacs::network::pipeline::other, pdu_, kcenon::pacs::network::pipeline::decoded_pdu::session_id, kcenon::pacs::network::pipeline::job_context::session_id, and kcenon::pacs::network::pipeline::job_context::stage.

◆ ~dimse_process_job()

kcenon::pacs::network::pipeline::dimse_process_job::~dimse_process_job ( )
overridedefault

◆ dimse_process_job() [2/3]

kcenon::pacs::network::pipeline::dimse_process_job::dimse_process_job ( const dimse_process_job & )
delete

◆ dimse_process_job() [3/3]

kcenon::pacs::network::pipeline::dimse_process_job::dimse_process_job ( dimse_process_job && )
default

Member Function Documentation

◆ execute()

auto kcenon::pacs::network::pipeline::dimse_process_job::execute ( pipeline_coordinator & coordinator) -> VoidResult
nodiscardoverridevirtual

Execute the DIMSE process job.

Processes the PDU and routes to appropriate handler.

Parameters
coordinatorPipeline coordinator for stage submission
Returns
VoidResult indicating success or error

Implements kcenon::pacs::network::pipeline::pipeline_job_base.

Examples
/home/runner/work/pacs_system/pacs_system/include/kcenon/pacs/network/pipeline/jobs/dimse_process_job.h.

Definition at line 39 of file dimse_process_job.cpp.

39 {
40 // Handle association PDUs differently
43 }
44
45 // Process P-DATA-TF (DIMSE message)
46 auto request_result = process_p_data();
47 if (!request_result.is_ok()) {
48 if (on_error_) {
49 auto err = request_result.error();
50 on_error_(context_.session_id, err.message);
51 }
52 return VoidResult(request_result.error());
53 }
54
55 auto request = request_result.value();
56
57 // Update context with message ID and category
58 context_.message_id = request.message_id;
59
60 // Determine category from command type
61 switch (request.command_type) {
65 break;
69 break;
73 break;
77 break;
81 break;
82 default:
84 break;
85 }
86
87 // Invoke callback if set
88 if (on_request_) {
89 on_request_(request);
90 }
91
92 // For response messages, skip execution stage
93 uint16_t cmd_type = static_cast<uint16_t>(request.command_type);
94 if (cmd_type & 0x8000) {
95 // This is a response, not a request - don't submit to execution
96 return ok();
97 }
98
99 // Create execution job for request
100 // Note: The actual service handler would be set by the adapter layer
101 auto exec_job = std::make_unique<storage_query_exec_job>(
102 std::move(request),
103 nullptr // Handler will be set by adapter
104 );
105
106 // Copy context to execution job
107 exec_job->get_context() = context_;
108 exec_job->get_context().stage = pipeline_stage::storage_query_exec;
109
110 return coordinator.submit_to_stage(
112 std::move(exec_job)
113 );
114}
auto process_association_pdu() -> VoidResult
Process association PDUs (A-ASSOCIATE, A-RELEASE, A-ABORT)
auto process_p_data() -> Result< dimse_request >
Process P-DATA-TF PDU.
@ move
C-MOVE move request/response.
@ store
C-STORE storage request/response.
@ get
C-GET retrieve request/response.
@ echo
C-ECHO verification request/response.
@ find
C-FIND query request/response.
@ storage_query_exec
Stage 4: Execute storage/query operations (blocking allowed)
@ p_data_tf
P-DATA-TF (Data Transfer)
kcenon::pacs::VoidResult VoidResult
VoidResult type alias for operations without return value.
Definition association.h:59
kcenon::pacs::network::pdu_type type
The type of PDU that was decoded.
uint16_t message_id
Message ID from DIMSE command (if applicable)

References kcenon::pacs::network::pipeline::c_echo_rq, kcenon::pacs::network::pipeline::c_echo_rsp, kcenon::pacs::network::pipeline::c_find_rq, kcenon::pacs::network::pipeline::c_find_rsp, kcenon::pacs::network::pipeline::c_get_rq, kcenon::pacs::network::pipeline::c_get_rsp, kcenon::pacs::network::pipeline::c_move_rq, kcenon::pacs::network::pipeline::c_move_rsp, kcenon::pacs::network::pipeline::c_store_rq, kcenon::pacs::network::pipeline::c_store_rsp, kcenon::pacs::network::pipeline::echo, kcenon::pacs::network::pipeline::find, kcenon::pacs::network::pipeline::get, kcenon::pacs::network::pipeline::move, kcenon::pacs::network::pipeline::other, kcenon::pacs::network::p_data_tf, kcenon::pacs::network::pipeline::storage_query_exec, and kcenon::pacs::network::pipeline::store.

◆ get_context() [1/2]

auto kcenon::pacs::network::pipeline::dimse_process_job::get_context ( ) const -> const job_context&
nodiscardoverridevirtualnoexcept

◆ get_context() [2/2]

auto kcenon::pacs::network::pipeline::dimse_process_job::get_context ( ) -> job_context &override
nodiscardoverridevirtualnoexcept

Get the job context (mutable)

Returns
Reference to the job context

Implements kcenon::pacs::network::pipeline::pipeline_job_base.

Definition at line 120 of file dimse_process_job.cpp.

120 {
121 return context_;
122}

References context_.

◆ get_name()

auto kcenon::pacs::network::pipeline::dimse_process_job::get_name ( ) const -> std::string
nodiscardoverridevirtual

Get the job name.

Implements kcenon::pacs::network::pipeline::pipeline_job_base.

Examples
/home/runner/work/pacs_system/pacs_system/include/kcenon/pacs/network/pipeline/jobs/dimse_process_job.h.

Definition at line 124 of file dimse_process_job.cpp.

124 {
125 return "dimse_process_job[session=" +
126 std::to_string(context_.session_id) +
127 ", pdu_type=" + std::to_string(static_cast<int>(pdu_.type)) + "]";
128}

References context_, pdu_, kcenon::pacs::network::pipeline::job_context::session_id, and kcenon::pacs::network::pipeline::decoded_pdu::type.

◆ get_pdu()

auto kcenon::pacs::network::pipeline::dimse_process_job::get_pdu ( ) const -> const decoded_pdu&
nodiscardnoexcept

Get the decoded PDU.

Examples
/home/runner/work/pacs_system/pacs_system/include/kcenon/pacs/network/pipeline/jobs/dimse_process_job.h.

Definition at line 130 of file dimse_process_job.cpp.

130 {
131 return pdu_;
132}

References pdu_.

◆ operator=() [1/2]

dimse_process_job & kcenon::pacs::network::pipeline::dimse_process_job::operator= ( const dimse_process_job & )
delete

◆ operator=() [2/2]

dimse_process_job & kcenon::pacs::network::pipeline::dimse_process_job::operator= ( dimse_process_job && )
default

◆ process_association_pdu()

auto kcenon::pacs::network::pipeline::dimse_process_job::process_association_pdu ( ) -> VoidResult
nodiscardprivate

Process association PDUs (A-ASSOCIATE, A-RELEASE, A-ABORT)

Examples
/home/runner/work/pacs_system/pacs_system/include/kcenon/pacs/network/pipeline/jobs/dimse_process_job.h.

Definition at line 227 of file dimse_process_job.cpp.

227 {
228 // Invoke association callback
229 if (on_association_) {
231 }
232
233 // Association PDUs don't go through the execution pipeline
234 // They are handled directly by the association state machine
235 return ok();
236}
std::vector< uint8_t > data
Raw PDU data for further processing.

◆ process_p_data()

auto kcenon::pacs::network::pipeline::dimse_process_job::process_p_data ( ) -> Result<dimse_request>
nodiscardprivate

Process P-DATA-TF PDU.

Examples
/home/runner/work/pacs_system/pacs_system/include/kcenon/pacs/network/pipeline/jobs/dimse_process_job.h.

Definition at line 134 of file dimse_process_job.cpp.

134 {
135 dimse_request request;
136 request.session_id = pdu_.session_id;
137 request.presentation_context_id = pdu_.presentation_context_id;
138
139 // PDV data starts after length (4) + context ID (1) + control header (1)
140 if (pdu_.data.size() < 6) {
142 "PDV data too short");
143 }
144
145 // Extract command from PDV data
146 // The command is DICOM dataset starting at offset 6
147 const auto& data = pdu_.data;
148 size_t offset = 6;
149
150 // Parse DICOM command elements
151 // Minimum: (0000,0000) CommandGroupLength + (0000,0100) CommandField
152 while (offset + 8 <= data.size()) {
153 // Tag: group (2) + element (2)
154 uint16_t group = static_cast<uint16_t>(data[offset]) |
155 (static_cast<uint16_t>(data[offset + 1]) << 8);
156 uint16_t element = static_cast<uint16_t>(data[offset + 2]) |
157 (static_cast<uint16_t>(data[offset + 3]) << 8);
158 offset += 4;
159
160 // VR is implicit for command set (Implicit VR Little Endian)
161 // Length (4 bytes)
162 if (offset + 4 > data.size()) break;
163 uint32_t length = static_cast<uint32_t>(data[offset]) |
164 (static_cast<uint32_t>(data[offset + 1]) << 8) |
165 (static_cast<uint32_t>(data[offset + 2]) << 16) |
166 (static_cast<uint32_t>(data[offset + 3]) << 24);
167 offset += 4;
168
169 if (offset + length > data.size()) break;
170
171 // Extract key elements
172 if (group == 0x0000) {
173 switch (element) {
174 case 0x0100: // CommandField
175 if (length >= 2) {
176 request.command_type = static_cast<dimse_command_type>(
177 static_cast<uint16_t>(data[offset]) |
178 (static_cast<uint16_t>(data[offset + 1]) << 8)
179 );
180 }
181 break;
182 case 0x0110: // MessageID
183 if (length >= 2) {
184 request.message_id = static_cast<uint16_t>(data[offset]) |
185 (static_cast<uint16_t>(data[offset + 1]) << 8);
186 }
187 break;
188 case 0x0002: // AffectedSOPClassUID
189 case 0x0003: // RequestedSOPClassUID
190 request.sop_class_uid = std::string(
191 reinterpret_cast<const char*>(&data[offset]), length);
192 // Trim trailing nulls/spaces
193 while (!request.sop_class_uid.empty() &&
194 (request.sop_class_uid.back() == '\0' ||
195 request.sop_class_uid.back() == ' ')) {
196 request.sop_class_uid.pop_back();
197 }
198 break;
199 case 0x1000: // AffectedSOPInstanceUID
200 case 0x1001: // RequestedSOPInstanceUID
201 request.sop_instance_uid = std::string(
202 reinterpret_cast<const char*>(&data[offset]), length);
203 while (!request.sop_instance_uid.empty() &&
204 (request.sop_instance_uid.back() == '\0' ||
205 request.sop_instance_uid.back() == ' ')) {
206 request.sop_instance_uid.pop_back();
207 }
208 break;
209 case 0x0700: // Priority
210 if (length >= 2) {
211 request.priority = static_cast<uint16_t>(data[offset]) |
212 (static_cast<uint16_t>(data[offset + 1]) << 8);
213 }
214 break;
215 }
216 }
217
218 offset += length;
219 }
220
221 // Store full command data for later use
222 request.command_data = pdu_.data;
223
224 return ok(std::move(request));
225}
constexpr int insufficient_data
Definition result.h:82
dimse_command_type
DICOM DIMSE command types.
@ length
Linear distance measurement.
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
uint8_t presentation_context_id
Presentation context ID (for P-DATA-TF)

References kcenon::pacs::network::pipeline::dimse_request::command_data, kcenon::pacs::network::pipeline::dimse_request::command_type, kcenon::pacs::error_codes::insufficient_data, kcenon::pacs::network::pipeline::dimse_request::message_id, kcenon::pacs::pacs_error(), kcenon::pacs::network::pipeline::dimse_request::presentation_context_id, kcenon::pacs::network::pipeline::dimse_request::priority, kcenon::pacs::network::pipeline::dimse_request::session_id, kcenon::pacs::network::pipeline::dimse_request::sop_class_uid, and kcenon::pacs::network::pipeline::dimse_request::sop_instance_uid.

Here is the call graph for this function:

Member Data Documentation

◆ context_

job_context kcenon::pacs::network::pipeline::dimse_process_job::context_
private

◆ on_association_

association_callback kcenon::pacs::network::pipeline::dimse_process_job::on_association_
private

◆ on_error_

error_callback kcenon::pacs::network::pipeline::dimse_process_job::on_error_
private

◆ on_request_

request_callback kcenon::pacs::network::pipeline::dimse_process_job::on_request_
private

◆ pdu_

decoded_pdu kcenon::pacs::network::pipeline::dimse_process_job::pdu_
private

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