Mercurial > hg > orthanc
comparison OrthancServer/ServerJobs/StorageCommitmentScpJob.cpp @ 3660:f159b731c47d storage-commitment
IStorageCommitmentFactory
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Mon, 10 Feb 2020 17:39:53 +0100 |
parents | 08eb0f93c491 |
children | 25117919a36b |
comparison
equal
deleted
inserted
replaced
3659:08eb0f93c491 | 3660:f159b731c47d |
---|---|
64 | 64 |
65 | 65 |
66 class StorageCommitmentScpJob::SetupCommand : public StorageCommitmentCommand | 66 class StorageCommitmentScpJob::SetupCommand : public StorageCommitmentCommand |
67 { | 67 { |
68 private: | 68 private: |
69 ServerContext& context_; | 69 StorageCommitmentScpJob& that_; |
70 | 70 |
71 public: | 71 public: |
72 SetupCommand(ServerContext& context) : | 72 SetupCommand(StorageCommitmentScpJob& that) : |
73 context_(context) | 73 that_(that) |
74 { | 74 { |
75 } | 75 } |
76 | 76 |
77 virtual CommandType GetType() const | 77 virtual CommandType GetType() const |
78 { | 78 { |
79 return CommandType_Setup; | 79 return CommandType_Setup; |
80 } | 80 } |
81 | 81 |
82 virtual bool Execute(const std::string& jobId) ORTHANC_OVERRIDE | 82 virtual bool Execute(const std::string& jobId) ORTHANC_OVERRIDE |
83 { | 83 { |
84 that_.Setup(jobId); | |
84 return true; | 85 return true; |
85 } | 86 } |
86 | 87 |
87 virtual void Serialize(Json::Value& target) const | 88 virtual void Serialize(Json::Value& target) const |
88 { | 89 { |
93 | 94 |
94 | 95 |
95 class StorageCommitmentScpJob::LookupCommand : public StorageCommitmentCommand | 96 class StorageCommitmentScpJob::LookupCommand : public StorageCommitmentCommand |
96 { | 97 { |
97 private: | 98 private: |
98 ServerContext& context_; | 99 StorageCommitmentScpJob& that_; |
99 bool hasFailureReason_; | 100 bool hasFailureReason_; |
100 std::string sopClassUid_; | 101 std::string sopClassUid_; |
101 std::string sopInstanceUid_; | 102 std::string sopInstanceUid_; |
102 StorageCommitmentFailureReason failureReason_; | 103 StorageCommitmentFailureReason failureReason_; |
103 | 104 |
104 public: | 105 public: |
105 LookupCommand(ServerContext& context, | 106 LookupCommand(StorageCommitmentScpJob& that, |
106 const std::string& sopClassUid, | 107 const std::string& sopClassUid, |
107 const std::string& sopInstanceUid) : | 108 const std::string& sopInstanceUid) : |
108 context_(context), | 109 that_(that), |
109 hasFailureReason_(false), | 110 hasFailureReason_(false), |
110 sopClassUid_(sopClassUid), | 111 sopClassUid_(sopClassUid), |
111 sopInstanceUid_(sopInstanceUid) | 112 sopInstanceUid_(sopInstanceUid) |
112 { | 113 { |
113 } | 114 } |
121 { | 122 { |
122 if (hasFailureReason_) | 123 if (hasFailureReason_) |
123 { | 124 { |
124 throw OrthancException(ErrorCode_BadSequenceOfCalls); | 125 throw OrthancException(ErrorCode_BadSequenceOfCalls); |
125 } | 126 } |
126 | 127 else |
128 { | |
129 failureReason_ = that_.Lookup(sopClassUid_, sopInstanceUid_); | |
130 hasFailureReason_ = true; | |
131 return true; | |
132 } | |
133 } | |
134 | |
135 const std::string& GetSopClassUid() const | |
136 { | |
137 return sopClassUid_; | |
138 } | |
139 | |
140 const std::string& GetSopInstanceUid() const | |
141 { | |
142 return sopInstanceUid_; | |
143 } | |
144 | |
145 StorageCommitmentFailureReason GetFailureReason() const | |
146 { | |
147 if (hasFailureReason_) | |
148 { | |
149 return failureReason_; | |
150 } | |
151 else | |
152 { | |
153 throw OrthancException(ErrorCode_BadSequenceOfCalls); | |
154 } | |
155 } | |
156 | |
157 virtual void Serialize(Json::Value& target) const | |
158 { | |
159 target = Json::objectValue; | |
160 target[TYPE] = LOOKUP; | |
161 target[SOP_CLASS_UID] = sopClassUid_; | |
162 target[SOP_INSTANCE_UID] = sopInstanceUid_; | |
163 } | |
164 }; | |
165 | |
166 | |
167 class StorageCommitmentScpJob::AnswerCommand : public StorageCommitmentCommand | |
168 { | |
169 private: | |
170 StorageCommitmentScpJob& that_; | |
171 | |
172 public: | |
173 AnswerCommand(StorageCommitmentScpJob& that) : | |
174 that_(that) | |
175 { | |
176 if (that_.ready_) | |
177 { | |
178 throw OrthancException(ErrorCode_BadSequenceOfCalls); | |
179 } | |
180 else | |
181 { | |
182 that_.ready_ = true; | |
183 } | |
184 } | |
185 | |
186 virtual CommandType GetType() const | |
187 { | |
188 return CommandType_Answer; | |
189 } | |
190 | |
191 virtual bool Execute(const std::string& jobId) ORTHANC_OVERRIDE | |
192 { | |
193 that_.Answer(); | |
194 return true; | |
195 } | |
196 | |
197 virtual void Serialize(Json::Value& target) const | |
198 { | |
199 target = Json::objectValue; | |
200 target[TYPE] = ANSWER; | |
201 } | |
202 }; | |
203 | |
204 | |
205 class StorageCommitmentScpJob::Unserializer : public SetOfCommandsJob::ICommandUnserializer | |
206 { | |
207 private: | |
208 StorageCommitmentScpJob& that_; | |
209 | |
210 public: | |
211 Unserializer(StorageCommitmentScpJob& that) : | |
212 that_(that) | |
213 { | |
214 that_.ready_ = false; | |
215 } | |
216 | |
217 virtual ICommand* Unserialize(const Json::Value& source) const | |
218 { | |
219 const std::string type = SerializationToolbox::ReadString(source, TYPE); | |
220 | |
221 if (type == SETUP) | |
222 { | |
223 return new SetupCommand(that_); | |
224 } | |
225 else if (type == LOOKUP) | |
226 { | |
227 return new LookupCommand(that_, | |
228 SerializationToolbox::ReadString(source, SOP_CLASS_UID), | |
229 SerializationToolbox::ReadString(source, SOP_INSTANCE_UID)); | |
230 } | |
231 else if (type == ANSWER) | |
232 { | |
233 return new AnswerCommand(that_); | |
234 } | |
235 else | |
236 { | |
237 throw OrthancException(ErrorCode_BadFileFormat); | |
238 } | |
239 } | |
240 }; | |
241 | |
242 | |
243 void StorageCommitmentScpJob::Setup(const std::string& jobId) | |
244 { | |
245 const size_t n = GetCommandsCount(); | |
246 | |
247 if (n <= 1) | |
248 { | |
249 throw OrthancException(ErrorCode_InternalError); | |
250 } | |
251 | |
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++) | |
258 { | |
259 const CommandType type = dynamic_cast<const StorageCommitmentCommand&>(GetCommand(i)).GetType(); | |
260 | |
261 if ((i == 0 && type != CommandType_Setup) || | |
262 (i >= 1 && i < n - 1 && type != CommandType_Lookup) || | |
263 (i == n - 1 && type != CommandType_Answer)) | |
264 { | |
265 throw OrthancException(ErrorCode_InternalError); | |
266 } | |
267 | |
268 if (type == CommandType_Lookup) | |
269 { | |
270 const LookupCommand& lookup = dynamic_cast<const LookupCommand&>(GetCommand(i)); | |
271 sopClassUids.push_back(lookup.GetSopClassUid()); | |
272 sopInstanceUids.push_back(lookup.GetSopInstanceUid()); | |
273 } | |
274 } | |
275 | |
276 lookupHandler_.reset(context_.CreateStorageCommitment(jobId, transactionUid_, sopClassUids, sopInstanceUids)); | |
277 } | |
278 | |
279 | |
280 StorageCommitmentFailureReason StorageCommitmentScpJob::Lookup(const std::string& sopClassUid, | |
281 const std::string& sopInstanceUid) | |
282 { | |
283 if (lookupHandler_.get() != NULL) | |
284 { | |
285 return lookupHandler_->Lookup(sopClassUid, sopInstanceUid); | |
286 } | |
287 else | |
288 { | |
289 // This is the default implementation of Orthanc (if no storage | |
290 // commitment plugin is installed) | |
127 bool success = false; | 291 bool success = false; |
128 | 292 |
129 try | 293 try |
130 { | 294 { |
131 std::vector<std::string> orthancId; | 295 std::vector<std::string> orthancId; |
132 context_.GetIndex().LookupIdentifierExact(orthancId, ResourceType_Instance, DICOM_TAG_SOP_INSTANCE_UID, sopInstanceUid_); | 296 context_.GetIndex().LookupIdentifierExact(orthancId, ResourceType_Instance, DICOM_TAG_SOP_INSTANCE_UID, sopInstanceUid); |
133 | 297 |
134 if (orthancId.size() == 1) | 298 if (orthancId.size() == 1) |
135 { | 299 { |
136 std::string a, b; | 300 std::string a, b; |
137 | 301 |
139 // from the file storage, and that the actual SOP | 303 // from the file storage, and that the actual SOP |
140 // class/instance UIDs do match | 304 // class/instance UIDs do match |
141 ServerContext::DicomCacheLocker locker(context_, orthancId[0]); | 305 ServerContext::DicomCacheLocker locker(context_, orthancId[0]); |
142 if (locker.GetDicom().GetTagValue(a, DICOM_TAG_SOP_CLASS_UID) && | 306 if (locker.GetDicom().GetTagValue(a, DICOM_TAG_SOP_CLASS_UID) && |
143 locker.GetDicom().GetTagValue(b, DICOM_TAG_SOP_INSTANCE_UID) && | 307 locker.GetDicom().GetTagValue(b, DICOM_TAG_SOP_INSTANCE_UID) && |
144 a == sopClassUid_ && | 308 a == sopClassUid && |
145 b == sopInstanceUid_) | 309 b == sopInstanceUid) |
146 { | 310 { |
147 success = true; | 311 success = true; |
148 } | 312 } |
149 } | 313 } |
150 } | 314 } |
151 catch (OrthancException&) | 315 catch (OrthancException&) |
152 { | 316 { |
153 } | 317 } |
154 | 318 |
155 LOG(INFO) << " Storage commitment SCP job: " << (success ? "Success" : "Failure") | 319 LOG(INFO) << " Storage commitment SCP job: " << (success ? "Success" : "Failure") |
156 << " while looking for " << sopClassUid_ << " / " << sopInstanceUid_; | 320 << " while looking for " << sopClassUid << " / " << sopInstanceUid; |
157 | 321 |
158 failureReason_ = (success ? | 322 return (success ? |
159 StorageCommitmentFailureReason_Success : | 323 StorageCommitmentFailureReason_Success : |
160 StorageCommitmentFailureReason_NoSuchObjectInstance /* 0x0112 == 274 */); | 324 StorageCommitmentFailureReason_NoSuchObjectInstance /* 0x0112 == 274 */); |
161 hasFailureReason_ = true; | 325 } |
162 | 326 } |
163 return true; | |
164 } | |
165 | |
166 const std::string& GetSopClassUid() const | |
167 { | |
168 return sopClassUid_; | |
169 } | |
170 | |
171 const std::string& GetSopInstanceUid() const | |
172 { | |
173 return sopInstanceUid_; | |
174 } | |
175 | |
176 StorageCommitmentFailureReason GetFailureReason() const | |
177 { | |
178 if (hasFailureReason_) | |
179 { | |
180 return failureReason_; | |
181 } | |
182 else | |
183 { | |
184 throw OrthancException(ErrorCode_BadSequenceOfCalls); | |
185 } | |
186 } | |
187 | |
188 virtual void Serialize(Json::Value& target) const | |
189 { | |
190 target = Json::objectValue; | |
191 target[TYPE] = LOOKUP; | |
192 target[SOP_CLASS_UID] = sopClassUid_; | |
193 target[SOP_INSTANCE_UID] = sopInstanceUid_; | |
194 } | |
195 }; | |
196 | |
197 | 327 |
198 class StorageCommitmentScpJob::AnswerCommand : public StorageCommitmentCommand | |
199 { | |
200 private: | |
201 StorageCommitmentScpJob& that_; | |
202 | |
203 public: | |
204 AnswerCommand(StorageCommitmentScpJob& that) : | |
205 that_(that) | |
206 { | |
207 if (that_.ready_) | |
208 { | |
209 throw OrthancException(ErrorCode_BadSequenceOfCalls); | |
210 } | |
211 else | |
212 { | |
213 that_.ready_ = true; | |
214 } | |
215 } | |
216 | |
217 virtual CommandType GetType() const | |
218 { | |
219 return CommandType_Answer; | |
220 } | |
221 | |
222 virtual bool Execute(const std::string& jobId) ORTHANC_OVERRIDE | |
223 { | |
224 that_.Answer(); | |
225 return true; | |
226 } | |
227 | |
228 virtual void Serialize(Json::Value& target) const | |
229 { | |
230 target = Json::objectValue; | |
231 target[TYPE] = ANSWER; | |
232 } | |
233 }; | |
234 | |
235 | |
236 class StorageCommitmentScpJob::Unserializer : public SetOfCommandsJob::ICommandUnserializer | |
237 { | |
238 private: | |
239 StorageCommitmentScpJob& that_; | |
240 ServerContext& context_; | |
241 | |
242 public: | |
243 Unserializer(StorageCommitmentScpJob& that, | |
244 ServerContext& context) : | |
245 that_(that), | |
246 context_(context) | |
247 { | |
248 that_.ready_ = false; | |
249 } | |
250 | |
251 virtual ICommand* Unserialize(const Json::Value& source) const | |
252 { | |
253 const std::string type = SerializationToolbox::ReadString(source, TYPE); | |
254 | |
255 if (type == SETUP) | |
256 { | |
257 return new SetupCommand(context_); | |
258 } | |
259 else if (type == LOOKUP) | |
260 { | |
261 return new LookupCommand(context_, | |
262 SerializationToolbox::ReadString(source, SOP_CLASS_UID), | |
263 SerializationToolbox::ReadString(source, SOP_INSTANCE_UID)); | |
264 } | |
265 else if (type == ANSWER) | |
266 { | |
267 return new AnswerCommand(that_); | |
268 } | |
269 else | |
270 { | |
271 throw OrthancException(ErrorCode_BadFileFormat); | |
272 } | |
273 } | |
274 }; | |
275 | |
276 | 328 |
277 void StorageCommitmentScpJob::Answer() | 329 void StorageCommitmentScpJob::Answer() |
278 { | 330 { |
279 LOG(INFO) << " Storage commitment SCP job: Sending answer"; | 331 LOG(INFO) << " Storage commitment SCP job: Sending answer"; |
280 | 332 |
333 throw OrthancException(ErrorCode_InexistentItem, | 385 throw OrthancException(ErrorCode_InexistentItem, |
334 "Unknown remote modality for storage commitment SCP: " + remoteAet); | 386 "Unknown remote modality for storage commitment SCP: " + remoteAet); |
335 } | 387 } |
336 } | 388 } |
337 | 389 |
338 AddCommand(new SetupCommand(context)); | 390 AddCommand(new SetupCommand(*this)); |
339 } | 391 } |
340 | 392 |
341 | 393 |
342 void StorageCommitmentScpJob::AddInstance(const std::string& sopClassUid, | 394 void StorageCommitmentScpJob::AddInstance(const std::string& sopClassUid, |
343 const std::string& sopInstanceUid) | 395 const std::string& sopInstanceUid) |
346 { | 398 { |
347 throw OrthancException(ErrorCode_BadSequenceOfCalls); | 399 throw OrthancException(ErrorCode_BadSequenceOfCalls); |
348 } | 400 } |
349 else | 401 else |
350 { | 402 { |
351 AddCommand(new LookupCommand(context_, sopClassUid, sopInstanceUid)); | 403 AddCommand(new LookupCommand(*this, sopClassUid, sopInstanceUid)); |
352 } | 404 } |
353 } | 405 } |
354 | 406 |
355 | 407 |
356 void StorageCommitmentScpJob::MarkAsReady() | 408 void StorageCommitmentScpJob::MarkAsReady() |
369 } | 421 } |
370 | 422 |
371 | 423 |
372 StorageCommitmentScpJob::StorageCommitmentScpJob(ServerContext& context, | 424 StorageCommitmentScpJob::StorageCommitmentScpJob(ServerContext& context, |
373 const Json::Value& serialized) : | 425 const Json::Value& serialized) : |
374 SetOfCommandsJob(new Unserializer(*this, context), serialized), | 426 SetOfCommandsJob(new Unserializer(*this), serialized), |
375 context_(context) | 427 context_(context) |
376 { | 428 { |
377 transactionUid_ = SerializationToolbox::ReadString(serialized, TRANSACTION_UID); | 429 transactionUid_ = SerializationToolbox::ReadString(serialized, TRANSACTION_UID); |
378 remoteModality_ = RemoteModalityParameters(serialized[REMOTE_MODALITY]); | 430 remoteModality_ = RemoteModalityParameters(serialized[REMOTE_MODALITY]); |
379 calledAet_ = SerializationToolbox::ReadString(serialized, CALLED_AET); | 431 calledAet_ = SerializationToolbox::ReadString(serialized, CALLED_AET); |