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

reorganization
author Sebastien Jodogne <s.jodogne@gmail.com>
date Fri, 31 Jan 2020 14:29:35 +0100
parents
children ae866fc06df5
comparison
equal deleted inserted replaced
3635:8c0ef729d5a8 3636:bce6ee64f2a4
1 /**
2 * Orthanc - A Lightweight, RESTful DICOM Store
3 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
4 * Department, University Hospital of Liege, Belgium
5 * Copyright (C) 2017-2019 Osimis S.A., Belgium
6 *
7 * This program is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation, either version 3 of the
10 * License, or (at your option) any later version.
11 *
12 * In addition, as a special exception, the copyright holders of this
13 * program give permission to link the code of its release with the
14 * OpenSSL project's "OpenSSL" library (or with modified versions of it
15 * that use the same license as the "OpenSSL" library), and distribute
16 * the linked executables. You must obey the GNU General Public License
17 * in all respects for all of the code used other than "OpenSSL". If you
18 * modify file(s) with this exception, you may extend this exception to
19 * your version of the file(s), but you are not obligated to do so. If
20 * you do not wish to do so, delete this exception statement from your
21 * version. If you delete this exception statement from all source files
22 * in the program, then also delete it here.
23 *
24 * This program is distributed in the hope that it will be useful, but
25 * WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
27 * General Public License for more details.
28 *
29 * You should have received a copy of the GNU General Public License
30 * along with this program. If not, see <http://www.gnu.org/licenses/>.
31 **/
32
33
34 #include "../PrecompiledHeadersServer.h"
35 #include "StorageCommitmentScpJob.h"
36
37 #include "../../Core/DicomNetworking/DicomUserConnection.h"
38 #include "../../Core/Logging.h"
39 #include "../../Core/OrthancException.h"
40 #include "../OrthancConfiguration.h"
41 #include "../ServerContext.h"
42
43
44 namespace Orthanc
45 {
46 class StorageCommitmentScpJob::LookupCommand : public SetOfCommandsJob::ICommand
47 {
48 private:
49 StorageCommitmentScpJob& that_;
50 std::string sopClassUid_;
51 std::string sopInstanceUid_;
52
53 public:
54 LookupCommand(StorageCommitmentScpJob& that,
55 const std::string& sopClassUid,
56 const std::string& sopInstanceUid) :
57 that_(that),
58 sopClassUid_(sopClassUid),
59 sopInstanceUid_(sopInstanceUid)
60 {
61 }
62
63 virtual bool Execute()
64 {
65 that_.LookupInstance(sopClassUid_, sopInstanceUid_);
66 return true;
67 }
68
69 virtual void Serialize(Json::Value& target) const
70 {
71 target = Json::objectValue;
72 target["Type"] = "Lookup";
73 target["SopClassUid"] = sopClassUid_;
74 target["SopInstanceUid"] = sopInstanceUid_;
75 }
76 };
77
78
79 class StorageCommitmentScpJob::AnswerCommand : public SetOfCommandsJob::ICommand
80 {
81 private:
82 StorageCommitmentScpJob& that_;
83
84 public:
85 AnswerCommand(StorageCommitmentScpJob& that) :
86 that_(that)
87 {
88 }
89
90 virtual bool Execute()
91 {
92 that_.Answer();
93 return true;
94 }
95
96 virtual void Serialize(Json::Value& target) const
97 {
98 target = Json::objectValue;
99 target["Type"] = "Answer";
100 }
101 };
102
103
104 class StorageCommitmentScpJob::Unserializer : public SetOfCommandsJob::ICommandUnserializer
105 {
106 private:
107 StorageCommitmentScpJob& that_;
108
109 public:
110 Unserializer(StorageCommitmentScpJob& that) :
111 that_(that)
112 {
113 }
114
115 virtual ICommand* Unserialize(const Json::Value& source) const
116 {
117 std::cout << "===================================\n";
118 std::cout << source.toStyledString();
119
120 /*DicomMap findAnswer;
121 findAnswer.Unserialize(source);
122 return new Command(that_, findAnswer);*/
123
124 throw OrthancException(ErrorCode_NotImplemented);
125 }
126 };
127
128
129 void StorageCommitmentScpJob::LookupInstance(const std::string& sopClassUid,
130 const std::string& sopInstanceUid)
131 {
132 bool success = false;
133
134 try
135 {
136 std::vector<std::string> orthancId;
137 context_.GetIndex().LookupIdentifierExact(orthancId, ResourceType_Instance, DICOM_TAG_SOP_INSTANCE_UID, sopInstanceUid);
138
139 if (orthancId.size() == 1)
140 {
141 std::string a, b;
142
143 // Make sure that the DICOM file can be re-read by DCMTK
144 // from the file storage, and that the actual SOP
145 // class/instance UIDs do match
146 ServerContext::DicomCacheLocker locker(context_, orthancId[0]);
147 if (locker.GetDicom().GetTagValue(a, DICOM_TAG_SOP_CLASS_UID) &&
148 locker.GetDicom().GetTagValue(b, DICOM_TAG_SOP_INSTANCE_UID) &&
149 a == sopClassUid &&
150 b == sopInstanceUid)
151 {
152 success = true;
153 }
154 }
155 }
156 catch (OrthancException&)
157 {
158 }
159
160 LOG(INFO) << " Storage commitment SCP job: " << (success ? "Success" : "Failure")
161 << " while looking for " << sopClassUid << " / " << sopInstanceUid;
162
163 if (success)
164 {
165 successSopClassUids_.push_back(sopClassUid);
166 successSopInstanceUids_.push_back(sopInstanceUid);
167 }
168 else
169 {
170 failedSopClassUids_.push_back(sopClassUid);
171 failedSopInstanceUids_.push_back(sopInstanceUid);
172 }
173 }
174
175
176 void StorageCommitmentScpJob::Answer()
177 {
178 LOG(INFO) << " Storage commitment SCP job: Sending answer";
179
180 DicomUserConnection scu(calledAet_, remoteModality_);
181 scu.ReportStorageCommitment(transactionUid_, successSopClassUids_, successSopInstanceUids_,
182 failedSopClassUids_, failedSopInstanceUids_);
183 }
184
185
186 StorageCommitmentScpJob::StorageCommitmentScpJob(ServerContext& context,
187 const std::string& transactionUid,
188 const std::string& remoteAet,
189 const std::string& calledAet) :
190 context_(context),
191 ready_(false),
192 transactionUid_(transactionUid),
193 calledAet_(calledAet)
194 {
195 {
196 OrthancConfiguration::ReaderLock lock;
197 if (!lock.GetConfiguration().LookupDicomModalityUsingAETitle(remoteModality_, remoteAet))
198 {
199 throw OrthancException(ErrorCode_InexistentItem,
200 "Unknown remote modality for storage commitment SCP: " + remoteAet);
201 }
202 }
203 }
204
205
206 void StorageCommitmentScpJob::AddInstance(const std::string& sopClassUid,
207 const std::string& sopInstanceUid)
208 {
209 if (ready_)
210 {
211 throw OrthancException(ErrorCode_BadSequenceOfCalls);
212 }
213 else
214 {
215 AddCommand(new LookupCommand(*this, sopClassUid, sopInstanceUid));
216 }
217 }
218
219
220 void StorageCommitmentScpJob::MarkAsReady()
221 {
222 if (ready_)
223 {
224 throw OrthancException(ErrorCode_BadSequenceOfCalls);
225 }
226 else
227 {
228 AddCommand(new AnswerCommand(*this));
229 ready_ = true;
230 }
231 }
232
233
234 void StorageCommitmentScpJob::GetPublicContent(Json::Value& value)
235 {
236 SetOfCommandsJob::GetPublicContent(value);
237
238 value["LocalAet"] = calledAet_;
239 value["RemoteAet"] = remoteModality_.GetApplicationEntityTitle();
240 value["TransactionUid"] = transactionUid_;
241 }
242 }