Mercurial > hg > orthanc
comparison OrthancServer/ServerJobs/StorageCommitmentScpJob.cpp @ 3661:25117919a36b storage-commitment
simplification
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Mon, 10 Feb 2020 17:54:40 +0100 |
parents | f159b731c47d |
children | d8371b4302ff |
comparison
equal
deleted
inserted
replaced
3660:f159b731c47d | 3661:25117919a36b |
---|---|
42 #include "../ServerContext.h" | 42 #include "../ServerContext.h" |
43 | 43 |
44 | 44 |
45 static const char* ANSWER = "Answer"; | 45 static const char* ANSWER = "Answer"; |
46 static const char* CALLED_AET = "CalledAet"; | 46 static const char* CALLED_AET = "CalledAet"; |
47 static const char* INDEX = "Index"; | |
47 static const char* LOOKUP = "Lookup"; | 48 static const char* LOOKUP = "Lookup"; |
48 static const char* REMOTE_MODALITY = "RemoteModality"; | 49 static const char* REMOTE_MODALITY = "RemoteModality"; |
49 static const char* SETUP = "Setup"; | 50 static const char* SETUP = "Setup"; |
50 static const char* SOP_CLASS_UID = "SopClassUid"; | 51 static const char* SOP_CLASS_UIDS = "SopClassUids"; |
51 static const char* SOP_INSTANCE_UID = "SopInstanceUid"; | 52 static const char* SOP_INSTANCE_UIDS = "SopInstanceUids"; |
52 static const char* TRANSACTION_UID = "TransactionUid"; | 53 static const char* TRANSACTION_UID = "TransactionUid"; |
53 static const char* TYPE = "Type"; | 54 static const char* TYPE = "Type"; |
54 | 55 |
55 | 56 |
56 | 57 |
94 | 95 |
95 | 96 |
96 class StorageCommitmentScpJob::LookupCommand : public StorageCommitmentCommand | 97 class StorageCommitmentScpJob::LookupCommand : public StorageCommitmentCommand |
97 { | 98 { |
98 private: | 99 private: |
99 StorageCommitmentScpJob& that_; | 100 StorageCommitmentScpJob& that_; |
100 bool hasFailureReason_; | 101 size_t index_; |
101 std::string sopClassUid_; | 102 bool hasFailureReason_; |
102 std::string sopInstanceUid_; | |
103 StorageCommitmentFailureReason failureReason_; | 103 StorageCommitmentFailureReason failureReason_; |
104 | 104 |
105 public: | 105 public: |
106 LookupCommand(StorageCommitmentScpJob& that, | 106 LookupCommand(StorageCommitmentScpJob& that, |
107 const std::string& sopClassUid, | 107 size_t index) : |
108 const std::string& sopInstanceUid) : | |
109 that_(that), | 108 that_(that), |
110 hasFailureReason_(false), | 109 index_(index), |
111 sopClassUid_(sopClassUid), | 110 hasFailureReason_(false) |
112 sopInstanceUid_(sopInstanceUid) | |
113 { | 111 { |
114 } | 112 } |
115 | 113 |
116 virtual CommandType GetType() const | 114 virtual CommandType GetType() const |
117 { | 115 { |
124 { | 122 { |
125 throw OrthancException(ErrorCode_BadSequenceOfCalls); | 123 throw OrthancException(ErrorCode_BadSequenceOfCalls); |
126 } | 124 } |
127 else | 125 else |
128 { | 126 { |
129 failureReason_ = that_.Lookup(sopClassUid_, sopInstanceUid_); | 127 failureReason_ = that_.Lookup(index_); |
130 hasFailureReason_ = true; | 128 hasFailureReason_ = true; |
131 return true; | 129 return true; |
132 } | 130 } |
133 } | 131 } |
134 | 132 |
135 const std::string& GetSopClassUid() const | 133 size_t GetIndex() const |
136 { | 134 { |
137 return sopClassUid_; | 135 return index_; |
138 } | 136 } |
139 | 137 |
140 const std::string& GetSopInstanceUid() const | |
141 { | |
142 return sopInstanceUid_; | |
143 } | |
144 | |
145 StorageCommitmentFailureReason GetFailureReason() const | 138 StorageCommitmentFailureReason GetFailureReason() const |
146 { | 139 { |
147 if (hasFailureReason_) | 140 if (hasFailureReason_) |
148 { | 141 { |
149 return failureReason_; | 142 return failureReason_; |
156 | 149 |
157 virtual void Serialize(Json::Value& target) const | 150 virtual void Serialize(Json::Value& target) const |
158 { | 151 { |
159 target = Json::objectValue; | 152 target = Json::objectValue; |
160 target[TYPE] = LOOKUP; | 153 target[TYPE] = LOOKUP; |
161 target[SOP_CLASS_UID] = sopClassUid_; | 154 target[INDEX] = static_cast<unsigned int>(index_); |
162 target[SOP_INSTANCE_UID] = sopInstanceUid_; | |
163 } | 155 } |
164 }; | 156 }; |
165 | 157 |
166 | 158 |
167 class StorageCommitmentScpJob::AnswerCommand : public StorageCommitmentCommand | 159 class StorageCommitmentScpJob::AnswerCommand : public StorageCommitmentCommand |
222 { | 214 { |
223 return new SetupCommand(that_); | 215 return new SetupCommand(that_); |
224 } | 216 } |
225 else if (type == LOOKUP) | 217 else if (type == LOOKUP) |
226 { | 218 { |
227 return new LookupCommand(that_, | 219 return new LookupCommand(that_, SerializationToolbox::ReadUnsignedInteger(source, INDEX)); |
228 SerializationToolbox::ReadString(source, SOP_CLASS_UID), | |
229 SerializationToolbox::ReadString(source, SOP_INSTANCE_UID)); | |
230 } | 220 } |
231 else if (type == ANSWER) | 221 else if (type == ANSWER) |
232 { | 222 { |
233 return new AnswerCommand(that_); | 223 return new AnswerCommand(that_); |
234 } | 224 } |
238 } | 228 } |
239 } | 229 } |
240 }; | 230 }; |
241 | 231 |
242 | 232 |
243 void StorageCommitmentScpJob::Setup(const std::string& jobId) | 233 void StorageCommitmentScpJob::CheckInvariants() |
244 { | 234 { |
245 const size_t n = GetCommandsCount(); | 235 const size_t n = GetCommandsCount(); |
246 | 236 |
247 if (n <= 1) | 237 if (n <= 1) |
248 { | 238 { |
249 throw OrthancException(ErrorCode_InternalError); | 239 throw OrthancException(ErrorCode_InternalError); |
250 } | 240 } |
251 | 241 |
252 std::vector<std::string> sopClassUids, sopInstanceUids; | |
253 | |
254 sopClassUids.reserve(n); | |
255 sopInstanceUids.reserve(n); | |
256 | |
257 for (size_t i = 0; i < n; i++) | 242 for (size_t i = 0; i < n; i++) |
258 { | 243 { |
259 const CommandType type = dynamic_cast<const StorageCommitmentCommand&>(GetCommand(i)).GetType(); | 244 const CommandType type = dynamic_cast<const StorageCommitmentCommand&>(GetCommand(i)).GetType(); |
260 | 245 |
261 if ((i == 0 && type != CommandType_Setup) || | 246 if ((i == 0 && type != CommandType_Setup) || |
266 } | 251 } |
267 | 252 |
268 if (type == CommandType_Lookup) | 253 if (type == CommandType_Lookup) |
269 { | 254 { |
270 const LookupCommand& lookup = dynamic_cast<const LookupCommand&>(GetCommand(i)); | 255 const LookupCommand& lookup = dynamic_cast<const LookupCommand&>(GetCommand(i)); |
271 sopClassUids.push_back(lookup.GetSopClassUid()); | 256 if (lookup.GetIndex() != i - 1) |
272 sopInstanceUids.push_back(lookup.GetSopInstanceUid()); | 257 { |
273 } | 258 throw OrthancException(ErrorCode_InternalError); |
274 } | 259 } |
275 | 260 } |
276 lookupHandler_.reset(context_.CreateStorageCommitment(jobId, transactionUid_, sopClassUids, sopInstanceUids)); | 261 } |
277 } | 262 } |
278 | 263 |
279 | 264 |
280 StorageCommitmentFailureReason StorageCommitmentScpJob::Lookup(const std::string& sopClassUid, | 265 void StorageCommitmentScpJob::Setup(const std::string& jobId) |
281 const std::string& sopInstanceUid) | 266 { |
282 { | 267 CheckInvariants(); |
268 lookupHandler_.reset(context_.CreateStorageCommitment(jobId, transactionUid_, sopClassUids_, sopInstanceUids_)); | |
269 } | |
270 | |
271 | |
272 StorageCommitmentFailureReason StorageCommitmentScpJob::Lookup(size_t index) | |
273 { | |
274 #ifndef NDEBUG | |
275 CheckInvariants(); | |
276 #endif | |
277 | |
278 if (index >= sopClassUids_.size()) | |
279 { | |
280 throw OrthancException(ErrorCode_InternalError); | |
281 } | |
282 | |
283 if (lookupHandler_.get() != NULL) | 283 if (lookupHandler_.get() != NULL) |
284 { | 284 { |
285 return lookupHandler_->Lookup(sopClassUid, sopInstanceUid); | 285 return lookupHandler_->Lookup(sopClassUids_[index], sopInstanceUids_[index]); |
286 } | 286 } |
287 else | 287 else |
288 { | 288 { |
289 // This is the default implementation of Orthanc (if no storage | 289 // This is the default implementation of Orthanc (if no storage |
290 // commitment plugin is installed) | 290 // commitment plugin is installed) |
291 bool success = false; | 291 bool success = false; |
292 | 292 |
293 try | 293 try |
294 { | 294 { |
295 std::vector<std::string> orthancId; | 295 std::vector<std::string> orthancId; |
296 context_.GetIndex().LookupIdentifierExact(orthancId, ResourceType_Instance, DICOM_TAG_SOP_INSTANCE_UID, sopInstanceUid); | 296 context_.GetIndex().LookupIdentifierExact(orthancId, ResourceType_Instance, DICOM_TAG_SOP_INSTANCE_UID, sopInstanceUids_[index]); |
297 | 297 |
298 if (orthancId.size() == 1) | 298 if (orthancId.size() == 1) |
299 { | 299 { |
300 std::string a, b; | 300 std::string a, b; |
301 | 301 |
303 // from the file storage, and that the actual SOP | 303 // from the file storage, and that the actual SOP |
304 // class/instance UIDs do match | 304 // class/instance UIDs do match |
305 ServerContext::DicomCacheLocker locker(context_, orthancId[0]); | 305 ServerContext::DicomCacheLocker locker(context_, orthancId[0]); |
306 if (locker.GetDicom().GetTagValue(a, DICOM_TAG_SOP_CLASS_UID) && | 306 if (locker.GetDicom().GetTagValue(a, DICOM_TAG_SOP_CLASS_UID) && |
307 locker.GetDicom().GetTagValue(b, DICOM_TAG_SOP_INSTANCE_UID) && | 307 locker.GetDicom().GetTagValue(b, DICOM_TAG_SOP_INSTANCE_UID) && |
308 a == sopClassUid && | 308 a == sopClassUids_[index] && |
309 b == sopInstanceUid) | 309 b == sopInstanceUids_[index]) |
310 { | 310 { |
311 success = true; | 311 success = true; |
312 } | 312 } |
313 } | 313 } |
314 } | 314 } |
315 catch (OrthancException&) | 315 catch (OrthancException&) |
316 { | 316 { |
317 } | 317 } |
318 | 318 |
319 LOG(INFO) << " Storage commitment SCP job: " << (success ? "Success" : "Failure") | 319 LOG(INFO) << " Storage commitment SCP job: " << (success ? "Success" : "Failure") |
320 << " while looking for " << sopClassUid << " / " << sopInstanceUid; | 320 << " while looking for " << sopClassUids_[index] << " / " << sopInstanceUids_[index]; |
321 | 321 |
322 return (success ? | 322 return (success ? |
323 StorageCommitmentFailureReason_Success : | 323 StorageCommitmentFailureReason_Success : |
324 StorageCommitmentFailureReason_NoSuchObjectInstance /* 0x0112 == 274 */); | 324 StorageCommitmentFailureReason_NoSuchObjectInstance /* 0x0112 == 274 */); |
325 } | 325 } |
326 } | 326 } |
327 | 327 |
328 | 328 |
329 void StorageCommitmentScpJob::Answer() | 329 void StorageCommitmentScpJob::Answer() |
330 { | 330 { |
331 CheckInvariants(); | |
331 LOG(INFO) << " Storage commitment SCP job: Sending answer"; | 332 LOG(INFO) << " Storage commitment SCP job: Sending answer"; |
332 | 333 |
333 const size_t n = GetCommandsCount(); | 334 std::vector<StorageCommitmentFailureReason> failureReasons; |
334 | 335 failureReasons.reserve(sopClassUids_.size()); |
335 if (n <= 1) | 336 |
337 for (size_t i = 1; i < GetCommandsCount() - 1; i++) | |
338 { | |
339 const LookupCommand& lookup = dynamic_cast<const LookupCommand&>(GetCommand(i)); | |
340 failureReasons.push_back(lookup.GetFailureReason()); | |
341 } | |
342 | |
343 if (failureReasons.size() != sopClassUids_.size()) | |
336 { | 344 { |
337 throw OrthancException(ErrorCode_InternalError); | 345 throw OrthancException(ErrorCode_InternalError); |
338 } | |
339 | |
340 std::vector<std::string> sopClassUids, sopInstanceUids; | |
341 std::vector<StorageCommitmentFailureReason> failureReasons; | |
342 | |
343 sopClassUids.reserve(n); | |
344 sopInstanceUids.reserve(n); | |
345 failureReasons.reserve(n); | |
346 | |
347 for (size_t i = 0; i < n; i++) | |
348 { | |
349 const CommandType type = dynamic_cast<const StorageCommitmentCommand&>(GetCommand(i)).GetType(); | |
350 | |
351 if ((i == 0 && type != CommandType_Setup) || | |
352 (i >= 1 && i < n - 1 && type != CommandType_Lookup) || | |
353 (i == n - 1 && type != CommandType_Answer)) | |
354 { | |
355 throw OrthancException(ErrorCode_InternalError); | |
356 } | |
357 | |
358 if (type == CommandType_Lookup) | |
359 { | |
360 const LookupCommand& lookup = dynamic_cast<const LookupCommand&>(GetCommand(i)); | |
361 sopClassUids.push_back(lookup.GetSopClassUid()); | |
362 sopInstanceUids.push_back(lookup.GetSopInstanceUid()); | |
363 failureReasons.push_back(lookup.GetFailureReason()); | |
364 } | |
365 } | 346 } |
366 | 347 |
367 DicomUserConnection scu(calledAet_, remoteModality_); | 348 DicomUserConnection scu(calledAet_, remoteModality_); |
368 scu.ReportStorageCommitment(transactionUid_, sopClassUids, sopInstanceUids, failureReasons); | 349 scu.ReportStorageCommitment(transactionUid_, sopClassUids_, sopInstanceUids_, failureReasons); |
369 } | 350 } |
370 | 351 |
371 | 352 |
372 StorageCommitmentScpJob::StorageCommitmentScpJob(ServerContext& context, | 353 StorageCommitmentScpJob::StorageCommitmentScpJob(ServerContext& context, |
373 const std::string& transactionUid, | 354 const std::string& transactionUid, |
389 | 370 |
390 AddCommand(new SetupCommand(*this)); | 371 AddCommand(new SetupCommand(*this)); |
391 } | 372 } |
392 | 373 |
393 | 374 |
375 void StorageCommitmentScpJob::Reserve(size_t size) | |
376 { | |
377 if (ready_) | |
378 { | |
379 throw OrthancException(ErrorCode_BadSequenceOfCalls); | |
380 } | |
381 else | |
382 { | |
383 sopClassUids_.reserve(size); | |
384 sopInstanceUids_.reserve(size); | |
385 } | |
386 } | |
387 | |
388 | |
394 void StorageCommitmentScpJob::AddInstance(const std::string& sopClassUid, | 389 void StorageCommitmentScpJob::AddInstance(const std::string& sopClassUid, |
395 const std::string& sopInstanceUid) | 390 const std::string& sopInstanceUid) |
396 { | 391 { |
397 if (ready_) | 392 if (ready_) |
398 { | 393 { |
399 throw OrthancException(ErrorCode_BadSequenceOfCalls); | 394 throw OrthancException(ErrorCode_BadSequenceOfCalls); |
400 } | 395 } |
401 else | 396 else |
402 { | 397 { |
403 AddCommand(new LookupCommand(*this, sopClassUid, sopInstanceUid)); | 398 assert(sopClassUids_.size() == sopInstanceUids_.size()); |
399 AddCommand(new LookupCommand(*this, sopClassUids_.size())); | |
400 sopClassUids_.push_back(sopClassUid); | |
401 sopInstanceUids_.push_back(sopInstanceUid); | |
404 } | 402 } |
405 } | 403 } |
406 | 404 |
407 | 405 |
408 void StorageCommitmentScpJob::MarkAsReady() | 406 void StorageCommitmentScpJob::MarkAsReady() |
427 context_(context) | 425 context_(context) |
428 { | 426 { |
429 transactionUid_ = SerializationToolbox::ReadString(serialized, TRANSACTION_UID); | 427 transactionUid_ = SerializationToolbox::ReadString(serialized, TRANSACTION_UID); |
430 remoteModality_ = RemoteModalityParameters(serialized[REMOTE_MODALITY]); | 428 remoteModality_ = RemoteModalityParameters(serialized[REMOTE_MODALITY]); |
431 calledAet_ = SerializationToolbox::ReadString(serialized, CALLED_AET); | 429 calledAet_ = SerializationToolbox::ReadString(serialized, CALLED_AET); |
430 SerializationToolbox::ReadArrayOfStrings(sopClassUids_, serialized, SOP_CLASS_UIDS); | |
431 SerializationToolbox::ReadArrayOfStrings(sopInstanceUids_, serialized, SOP_INSTANCE_UIDS); | |
432 } | 432 } |
433 | 433 |
434 | 434 |
435 bool StorageCommitmentScpJob::Serialize(Json::Value& target) | 435 bool StorageCommitmentScpJob::Serialize(Json::Value& target) |
436 { | 436 { |
441 else | 441 else |
442 { | 442 { |
443 target[TRANSACTION_UID] = transactionUid_; | 443 target[TRANSACTION_UID] = transactionUid_; |
444 remoteModality_.Serialize(target[REMOTE_MODALITY], true /* force advanced format */); | 444 remoteModality_.Serialize(target[REMOTE_MODALITY], true /* force advanced format */); |
445 target[CALLED_AET] = calledAet_; | 445 target[CALLED_AET] = calledAet_; |
446 SerializationToolbox::WriteArrayOfStrings(target, sopClassUids_, SOP_CLASS_UIDS); | |
447 SerializationToolbox::WriteArrayOfStrings(target, sopInstanceUids_, SOP_INSTANCE_UIDS); | |
446 return true; | 448 return true; |
447 } | 449 } |
448 } | 450 } |
449 } | 451 } |