comparison OrthancServer/main.cpp @ 3636:bce6ee64f2a4 storage-commitment

reorganization
author Sebastien Jodogne <s.jodogne@gmail.com>
date Fri, 31 Jan 2020 14:29:35 +0100
parents 8c0ef729d5a8
children f6a73611ec5c
comparison
equal deleted inserted replaced
3635:8c0ef729d5a8 3636:bce6ee64f2a4
48 #include "OrthancConfiguration.h" 48 #include "OrthancConfiguration.h"
49 #include "OrthancFindRequestHandler.h" 49 #include "OrthancFindRequestHandler.h"
50 #include "OrthancInitialization.h" 50 #include "OrthancInitialization.h"
51 #include "OrthancMoveRequestHandler.h" 51 #include "OrthancMoveRequestHandler.h"
52 #include "ServerContext.h" 52 #include "ServerContext.h"
53 #include "ServerJobs/StorageCommitmentScpJob.h"
53 #include "ServerToolbox.h" 54 #include "ServerToolbox.h"
54 55
55 using namespace Orthanc; 56 using namespace Orthanc;
56 57
57 58
87 context_.Store(id, toStore); 88 context_.Store(id, toStore);
88 } 89 }
89 } 90 }
90 }; 91 };
91 92
92
93
94 namespace Orthanc
95 {
96 class StorageCommitmentScpJob : public SetOfCommandsJob
97 {
98 private:
99 class LookupCommand : public SetOfCommandsJob::ICommand
100 {
101 private:
102 StorageCommitmentScpJob& that_;
103 std::string sopClassUid_;
104 std::string sopInstanceUid_;
105
106 public:
107 LookupCommand(StorageCommitmentScpJob& that,
108 const std::string& sopClassUid,
109 const std::string& sopInstanceUid) :
110 that_(that),
111 sopClassUid_(sopClassUid),
112 sopInstanceUid_(sopInstanceUid)
113 {
114 }
115
116 virtual bool Execute()
117 {
118 that_.LookupInstance(sopClassUid_, sopInstanceUid_);
119 return true;
120 }
121
122 virtual void Serialize(Json::Value& target) const
123 {
124 target = Json::objectValue;
125 target["Type"] = "Lookup";
126 target["SopClassUid"] = sopClassUid_;
127 target["SopInstanceUid"] = sopInstanceUid_;
128 }
129 };
130
131 class AnswerCommand : public SetOfCommandsJob::ICommand
132 {
133 private:
134 StorageCommitmentScpJob& that_;
135
136 public:
137 AnswerCommand(StorageCommitmentScpJob& that) :
138 that_(that)
139 {
140 }
141
142 virtual bool Execute()
143 {
144 that_.Answer();
145 return true;
146 }
147
148 virtual void Serialize(Json::Value& target) const
149 {
150 target = Json::objectValue;
151 target["Type"] = "Answer";
152 }
153 };
154
155 class Unserializer : public SetOfCommandsJob::ICommandUnserializer
156 {
157 private:
158 StorageCommitmentScpJob& that_;
159
160 public:
161 Unserializer(StorageCommitmentScpJob& that) :
162 that_(that)
163 {
164 }
165
166 virtual ICommand* Unserialize(const Json::Value& source) const
167 {
168 std::cout << "===================================\n";
169 std::cout << source.toStyledString();
170
171 /*DicomMap findAnswer;
172 findAnswer.Unserialize(source);
173 return new Command(that_, findAnswer);*/
174
175 throw OrthancException(ErrorCode_NotImplemented);
176 }
177 };
178
179 ServerContext& context_;
180 bool ready_;
181 std::string transactionUid_;
182 RemoteModalityParameters remoteModality_;
183 std::string calledAet_;
184 std::list<std::string> successSopClassUids_;
185 std::list<std::string> successSopInstanceUids_;
186 std::list<std::string> failedSopClassUids_;
187 std::list<std::string> failedSopInstanceUids_;
188
189 void LookupInstance(const std::string& sopClassUid,
190 const std::string& sopInstanceUid)
191 {
192 bool success = false;
193
194 try
195 {
196 std::vector<std::string> orthancId;
197 context_.GetIndex().LookupIdentifierExact(orthancId, ResourceType_Instance, DICOM_TAG_SOP_INSTANCE_UID, sopInstanceUid);
198
199 if (orthancId.size() == 1)
200 {
201 std::string a, b;
202
203 ServerContext::DicomCacheLocker locker(context_, orthancId[0]);
204 if (locker.GetDicom().GetTagValue(a, DICOM_TAG_SOP_CLASS_UID) &&
205 locker.GetDicom().GetTagValue(b, DICOM_TAG_SOP_INSTANCE_UID) &&
206 a == sopClassUid &&
207 b == sopInstanceUid)
208 {
209 success = true;
210 }
211 }
212 }
213 catch (OrthancException&)
214 {
215 }
216
217 LOG(INFO) << " Storage commitment SCP job: " << (success ? "Success" : "Failure")
218 << " while looking for " << sopClassUid << " / " << sopInstanceUid;
219
220 if (success)
221 {
222 successSopClassUids_.push_back(sopClassUid);
223 successSopInstanceUids_.push_back(sopInstanceUid);
224 }
225 else
226 {
227 failedSopClassUids_.push_back(sopClassUid);
228 failedSopInstanceUids_.push_back(sopInstanceUid);
229 }
230 }
231
232 void Answer()
233 {
234 LOG(INFO) << " Storage commitment SCP job: Sending answer";
235
236 DicomUserConnection scu(calledAet_, remoteModality_);
237 scu.ReportStorageCommitment(transactionUid_, successSopClassUids_, successSopInstanceUids_,
238 failedSopClassUids_, failedSopInstanceUids_);
239
240 /**
241 * "After the N-EVENT-REPORT has been sent, the Transaction UID is
242 * no longer active and shall not be reused for other
243 * transactions."
244 * http://dicom.nema.org/medical/dicom/2019a/output/chtml/part04/sect_J.3.3.html
245 **/
246 }
247
248 public:
249 StorageCommitmentScpJob(ServerContext& context,
250 const std::string& transactionUid,
251 const std::string& remoteAet,
252 const std::string& calledAet) :
253 context_(context),
254 ready_(false),
255 transactionUid_(transactionUid),
256 calledAet_(calledAet)
257 {
258 {
259 OrthancConfiguration::ReaderLock lock;
260 if (!lock.GetConfiguration().LookupDicomModalityUsingAETitle(remoteModality_, remoteAet))
261 {
262 throw OrthancException(ErrorCode_InexistentItem,
263 "Unknown remote modality for storage commitment SCP: " + remoteAet);
264 }
265 }
266 }
267
268 void AddInstance(const std::string& sopClassUid,
269 const std::string& sopInstanceUid)
270 {
271 if (ready_)
272 {
273 throw OrthancException(ErrorCode_BadSequenceOfCalls);
274 }
275 else
276 {
277 AddCommand(new LookupCommand(*this, sopClassUid, sopInstanceUid));
278 }
279 }
280
281 void MarkAsReady()
282 {
283 if (ready_)
284 {
285 throw OrthancException(ErrorCode_BadSequenceOfCalls);
286 }
287 else
288 {
289 AddCommand(new AnswerCommand(*this));
290 ready_ = true;
291 }
292 }
293
294 virtual void Stop(JobStopReason reason)
295 {
296 }
297
298 virtual void GetJobType(std::string& target)
299 {
300 target = "StorageCommitmentScp";
301 }
302
303 virtual void GetPublicContent(Json::Value& value)
304 {
305 SetOfCommandsJob::GetPublicContent(value);
306
307 value["LocalAet"] = calledAet_;
308 value["RemoteAet"] = remoteModality_.GetApplicationEntityTitle();
309 value["TransactionUid"] = transactionUid_;
310 }
311 };
312 }
313 93
314 94
315 class OrthancStorageCommitmentRequestHandler : public IStorageCommitmentRequestHandler 95 class OrthancStorageCommitmentRequestHandler : public IStorageCommitmentRequestHandler
316 { 96 {
317 private: 97 private:
356 const std::string& remoteIp, 136 const std::string& remoteIp,
357 const std::string& remoteAet, 137 const std::string& remoteAet,
358 const std::string& calledAet) 138 const std::string& calledAet)
359 { 139 {
360 printf("HANDLE REPORT\n"); 140 printf("HANDLE REPORT\n");
141
142 /**
143 * "After the N-EVENT-REPORT has been sent, the Transaction UID is
144 * no longer active and shall not be reused for other
145 * transactions."
146 * http://dicom.nema.org/medical/dicom/2019a/output/chtml/part04/sect_J.3.3.html
147 **/
361 } 148 }
362 }; 149 };
363 150
364 151
365 152