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 }