Mercurial > hg > orthanc
annotate OrthancServer/ServerIndex.cpp @ 190:b6cef9d45cc3
getallpublicids
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Tue, 13 Nov 2012 11:20:50 +0100 |
parents | ccbc2cf64a0d |
children | bff0b77b02fa |
rev | line source |
---|---|
0 | 1 /** |
62 | 2 * Orthanc - A Lightweight, RESTful DICOM Store |
0 | 3 * Copyright (C) 2012 Medical Physics Department, CHU of Liege, |
4 * Belgium | |
5 * | |
6 * This program is free software: you can redistribute it and/or | |
7 * modify it under the terms of the GNU General Public License as | |
8 * published by the Free Software Foundation, either version 3 of the | |
9 * License, or (at your option) any later version. | |
136 | 10 * |
11 * In addition, as a special exception, the copyright holders of this | |
12 * program give permission to link the code of its release with the | |
13 * OpenSSL project's "OpenSSL" library (or with modified versions of it | |
14 * that use the same license as the "OpenSSL" library), and distribute | |
15 * the linked executables. You must obey the GNU General Public License | |
16 * in all respects for all of the code used other than "OpenSSL". If you | |
17 * modify file(s) with this exception, you may extend this exception to | |
18 * your version of the file(s), but you are not obligated to do so. If | |
19 * you do not wish to do so, delete this exception statement from your | |
20 * version. If you delete this exception statement from all source files | |
21 * in the program, then also delete it here. | |
0 | 22 * |
23 * This program is distributed in the hope that it will be useful, but | |
24 * WITHOUT ANY WARRANTY; without even the implied warranty of | |
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
26 * General Public License for more details. | |
27 * | |
28 * You should have received a copy of the GNU General Public License | |
29 * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
30 **/ | |
31 | |
32 | |
33 #include "ServerIndex.h" | |
34 | |
62 | 35 using namespace Orthanc; |
0 | 36 |
6 | 37 #ifndef NOMINMAX |
2 | 38 #define NOMINMAX |
6 | 39 #endif |
40 | |
8 | 41 #include "EmbeddedResources.h" |
0 | 42 #include "../Core/Toolbox.h" |
43 #include "../Core/Uuid.h" | |
44 #include "../Core/DicomFormat/DicomArray.h" | |
45 #include "../Core/SQLite/Transaction.h" | |
46 #include "FromDcmtkBridge.h" | |
47 | |
48 #include <boost/lexical_cast.hpp> | |
49 #include <stdio.h> | |
108 | 50 #include <glog/logging.h> |
0 | 51 |
62 | 52 namespace Orthanc |
0 | 53 { |
54 namespace Internals | |
55 { | |
56 class DeleteFromFileStorageFunction : public SQLite::IScalarFunction | |
57 { | |
58 private: | |
180
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
59 std::auto_ptr<FileStorage> fileStorage_; |
0 | 60 |
61 public: | |
180
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
62 DeleteFromFileStorageFunction(const std::string& path) |
0 | 63 { |
180
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
64 if (path != ":memory:") |
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
65 { |
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
66 fileStorage_.reset(new FileStorage(path)); |
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
67 } |
0 | 68 } |
69 | |
70 virtual const char* GetName() const | |
71 { | |
72 return "DeleteFromFileStorage"; | |
73 } | |
74 | |
75 virtual unsigned int GetCardinality() const | |
76 { | |
77 return 1; | |
78 } | |
79 | |
80 virtual void Compute(SQLite::FunctionContext& context) | |
81 { | |
180
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
82 if (fileStorage_.get() == NULL) |
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
83 { |
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
84 // In-memory index, for unit tests |
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
85 return; |
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
86 } |
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
87 |
0 | 88 std::string fileUuid = context.GetStringValue(0); |
108 | 89 LOG(INFO) << "Removing file [" << fileUuid << "]"; |
180
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
90 |
0 | 91 if (Toolbox::IsUuid(fileUuid)) |
92 { | |
180
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
93 fileStorage_->Remove(fileUuid); |
0 | 94 } |
95 } | |
96 }; | |
97 | |
98 | |
99 class SignalDeletedLevelFunction : public SQLite::IScalarFunction | |
100 { | |
101 private: | |
102 int remainingLevel_; | |
103 std::string remainingLevelUuid_; | |
104 | |
105 public: | |
106 void Clear() | |
107 { | |
108 remainingLevel_ = std::numeric_limits<int>::max(); | |
109 } | |
110 | |
111 bool HasRemainingLevel() const | |
112 { | |
113 return (remainingLevel_ != 0 && | |
114 remainingLevel_ != std::numeric_limits<int>::max()); | |
115 } | |
116 | |
117 const std::string& GetRemainingLevelUuid() const | |
118 { | |
119 assert(HasRemainingLevel()); | |
120 return remainingLevelUuid_; | |
121 } | |
122 | |
123 const char* GetRemainingLevelType() const | |
124 { | |
125 assert(HasRemainingLevel()); | |
126 switch (remainingLevel_) | |
127 { | |
128 case 1: | |
129 return "patient"; | |
130 case 2: | |
131 return "study"; | |
132 case 3: | |
133 return "series"; | |
134 default: | |
62 | 135 throw OrthancException(ErrorCode_InternalError); |
0 | 136 } |
137 } | |
138 | |
139 virtual const char* GetName() const | |
140 { | |
141 return "SignalDeletedLevel"; | |
142 } | |
143 | |
144 virtual unsigned int GetCardinality() const | |
145 { | |
146 return 2; | |
147 } | |
148 | |
149 virtual void Compute(SQLite::FunctionContext& context) | |
150 { | |
151 int level = context.GetIntValue(0); | |
152 if (level < remainingLevel_) | |
153 { | |
154 remainingLevel_ = level; | |
155 remainingLevelUuid_ = context.GetStringValue(1); | |
156 } | |
157 | |
158 //printf("deleted level [%d] [%s]\n", level, context.GetStringValue(1).c_str()); | |
159 } | |
160 }; | |
161 } | |
162 | |
163 | |
164 void ServerIndex::StoreMainDicomTags(const std::string& uuid, | |
165 const DicomMap& map) | |
166 { | |
167 DicomArray flattened(map); | |
168 for (size_t i = 0; i < flattened.GetSize(); i++) | |
169 { | |
138 | 170 SQLite::Statement s(db_, SQLITE_FROM_HERE, "INSERT INTO MainDicomTags VALUES(?, ?, ?, ?)"); |
0 | 171 s.BindString(0, uuid); |
172 s.BindInt(1, flattened.GetElement(i).GetTag().GetGroup()); | |
173 s.BindInt(2, flattened.GetElement(i).GetTag().GetElement()); | |
174 s.BindString(3, flattened.GetElement(i).GetValue().AsString()); | |
175 s.Run(); | |
176 } | |
177 } | |
178 | |
179 bool ServerIndex::GetMainDicomStringTag(std::string& result, | |
180 const std::string& uuid, | |
181 const DicomTag& tag) | |
182 { | |
183 SQLite::Statement s(db_, SQLITE_FROM_HERE, | |
184 "SELECT * FROM MainDicomTags WHERE uuid=? AND tagGroup=? AND tagElement=?"); | |
185 s.BindString(0, uuid); | |
186 s.BindInt(1, tag.GetGroup()); | |
187 s.BindInt(2, tag.GetElement()); | |
188 if (!s.Step()) | |
189 { | |
190 return false; | |
191 } | |
192 | |
193 result = s.ColumnString(0); | |
194 return true; | |
195 } | |
196 | |
197 bool ServerIndex::GetMainDicomIntTag(int& result, | |
198 const std::string& uuid, | |
199 const DicomTag& tag) | |
200 { | |
201 std::string s; | |
202 if (!GetMainDicomStringTag(s, uuid, tag)) | |
203 { | |
204 return false; | |
205 } | |
206 | |
207 try | |
208 { | |
209 result = boost::lexical_cast<int>(s); | |
210 return true; | |
211 } | |
212 catch (boost::bad_lexical_cast) | |
213 { | |
214 return false; | |
215 } | |
216 } | |
217 | |
180
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
218 |
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
219 bool ServerIndex::HasInstance(DicomInstanceHasher& hasher) |
0 | 220 { |
221 SQLite::Statement s(db_, SQLITE_FROM_HERE, "SELECT uuid FROM Instances WHERE dicomInstance=?"); | |
179 | 222 s.BindString(0, hasher.GetInstanceUid()); |
180
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
223 return s.Step(); |
0 | 224 } |
225 | |
226 | |
227 void ServerIndex::RecordChange(const std::string& resourceType, | |
228 const std::string& uuid) | |
229 { | |
230 SQLite::Statement s(db_, SQLITE_FROM_HERE, "INSERT INTO Changes VALUES(NULL, ?, ?)"); | |
231 s.BindString(0, resourceType); | |
232 s.BindString(1, uuid); | |
233 s.Run(); | |
234 } | |
235 | |
236 | |
180
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
237 void ServerIndex::CreateInstance(DicomInstanceHasher& hasher, |
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
238 const DicomMap& dicomSummary, |
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
239 const std::string& fileUuid, |
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
240 uint64_t fileSize, |
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
241 const std::string& jsonUuid, |
187
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
242 const std::string& remoteAet) |
0 | 243 { |
82 | 244 SQLite::Statement s2(db_, SQLITE_FROM_HERE, "INSERT INTO Resources VALUES(?, ?)"); |
180
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
245 s2.BindString(0, hasher.HashInstance()); |
82 | 246 s2.BindInt(1, ResourceType_Instance); |
247 s2.Run(); | |
248 | |
80 | 249 SQLite::Statement s(db_, SQLITE_FROM_HERE, "INSERT INTO Instances VALUES(?, ?, ?, ?, ?, ?, ?, ?)"); |
180
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
250 s.BindString(0, hasher.HashInstance()); |
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
251 s.BindString(1, hasher.HashSeries()); |
179 | 252 s.BindString(2, hasher.GetInstanceUid()); |
0 | 253 s.BindString(3, fileUuid); |
254 s.BindInt64(4, fileSize); | |
255 s.BindString(5, jsonUuid); | |
187
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
256 s.BindString(6, remoteAet); |
80 | 257 |
258 const DicomValue* indexInSeries; | |
259 if ((indexInSeries = dicomSummary.TestAndGetValue(DICOM_TAG_INSTANCE_NUMBER)) != NULL || | |
260 (indexInSeries = dicomSummary.TestAndGetValue(DICOM_TAG_IMAGE_INDEX)) != NULL) | |
261 { | |
262 s.BindInt(7, boost::lexical_cast<unsigned int>(indexInSeries->AsString())); | |
263 } | |
264 else | |
265 { | |
266 s.BindNull(7); | |
267 } | |
268 | |
0 | 269 s.Run(); |
270 | |
180
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
271 RecordChange("instances", hasher.HashInstance()); |
0 | 272 |
273 DicomMap dicom; | |
274 dicomSummary.ExtractInstanceInformation(dicom); | |
180
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
275 StoreMainDicomTags(hasher.HashInstance(), dicom); |
0 | 276 } |
277 | |
278 void ServerIndex::RemoveInstance(const std::string& uuid) | |
279 { | |
280 SQLite::Statement s(db_, SQLITE_FROM_HERE, "DELETE FROM Instances WHERE uuid=?"); | |
281 s.BindString(0, uuid); | |
282 s.Run(); | |
283 } | |
284 | |
180
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
285 bool ServerIndex::HasSeries(DicomInstanceHasher& hasher) |
0 | 286 { |
287 SQLite::Statement s(db_, SQLITE_FROM_HERE, "SELECT uuid FROM Series WHERE dicomSeries=?"); | |
179 | 288 s.BindString(0, hasher.GetSeriesUid()); |
180
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
289 return s.Step(); |
0 | 290 } |
291 | |
180
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
292 void ServerIndex::CreateSeries(DicomInstanceHasher& hasher, |
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
293 const DicomMap& dicomSummary) |
0 | 294 { |
82 | 295 SQLite::Statement s2(db_, SQLITE_FROM_HERE, "INSERT INTO Resources VALUES(?, ?)"); |
180
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
296 s2.BindString(0, hasher.HashSeries()); |
82 | 297 s2.BindInt(1, ResourceType_Series); |
298 s2.Run(); | |
299 | |
77 | 300 SQLite::Statement s(db_, SQLITE_FROM_HERE, "INSERT INTO Series VALUES(?, ?, ?, ?)"); |
180
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
301 s.BindString(0, hasher.HashSeries()); |
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
302 s.BindString(1, hasher.HashStudy()); |
179 | 303 s.BindString(2, hasher.GetSeriesUid()); |
80 | 304 |
305 const DicomValue* expectedNumberOfInstances; | |
84 | 306 if (//(expectedNumberOfInstances = dicomSummary.TestAndGetValue(DICOM_TAG_NUMBER_OF_FRAMES)) != NULL || |
80 | 307 (expectedNumberOfInstances = dicomSummary.TestAndGetValue(DICOM_TAG_NUMBER_OF_SLICES)) != NULL || |
82 | 308 //(expectedNumberOfInstances = dicomSummary.TestAndGetValue(DICOM_TAG_CARDIAC_NUMBER_OF_IMAGES)) != NULL || |
80 | 309 (expectedNumberOfInstances = dicomSummary.TestAndGetValue(DICOM_TAG_IMAGES_IN_ACQUISITION)) != NULL) |
310 { | |
311 s.BindInt(3, boost::lexical_cast<unsigned int>(expectedNumberOfInstances->AsString())); | |
312 } | |
313 else | |
314 { | |
315 s.BindNull(3); | |
316 } | |
317 | |
0 | 318 s.Run(); |
319 | |
180
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
320 RecordChange("series", hasher.HashSeries()); |
0 | 321 |
322 DicomMap dicom; | |
323 dicomSummary.ExtractSeriesInformation(dicom); | |
180
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
324 StoreMainDicomTags(hasher.HashSeries(), dicom); |
0 | 325 } |
326 | |
180
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
327 bool ServerIndex::HasStudy(DicomInstanceHasher& hasher) |
0 | 328 { |
329 SQLite::Statement s(db_, SQLITE_FROM_HERE, "SELECT uuid FROM Studies WHERE dicomStudy=?"); | |
179 | 330 s.BindString(0, hasher.GetStudyUid()); |
180
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
331 return s.Step(); |
0 | 332 } |
333 | |
180
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
334 void ServerIndex::CreateStudy(DicomInstanceHasher& hasher, |
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
335 const DicomMap& dicomSummary) |
0 | 336 { |
82 | 337 SQLite::Statement s2(db_, SQLITE_FROM_HERE, "INSERT INTO Resources VALUES(?, ?)"); |
180
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
338 s2.BindString(0, hasher.HashStudy()); |
82 | 339 s2.BindInt(1, ResourceType_Study); |
340 s2.Run(); | |
341 | |
0 | 342 SQLite::Statement s(db_, SQLITE_FROM_HERE, "INSERT INTO Studies VALUES(?, ?, ?)"); |
180
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
343 s.BindString(0, hasher.HashStudy()); |
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
344 s.BindString(1, hasher.HashPatient()); |
179 | 345 s.BindString(2, hasher.GetStudyUid()); |
0 | 346 s.Run(); |
347 | |
180
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
348 RecordChange("studies", hasher.HashStudy()); |
0 | 349 |
350 DicomMap dicom; | |
351 dicomSummary.ExtractStudyInformation(dicom); | |
180
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
352 StoreMainDicomTags(hasher.HashStudy(), dicom); |
0 | 353 } |
354 | |
355 | |
356 | |
180
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
357 bool ServerIndex::HasPatient(DicomInstanceHasher& hasher) |
0 | 358 { |
359 SQLite::Statement s(db_, SQLITE_FROM_HERE, "SELECT uuid FROM Patients WHERE dicomPatientId=?"); | |
179 | 360 s.BindString(0,hasher.GetPatientId()); |
180
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
361 return s.Step(); |
0 | 362 } |
363 | |
180
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
364 void ServerIndex::CreatePatient(DicomInstanceHasher& hasher, |
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
365 const DicomMap& dicomSummary) |
0 | 366 { |
80 | 367 std::string dicomPatientId = dicomSummary.GetValue(DICOM_TAG_PATIENT_ID).AsString(); |
0 | 368 |
82 | 369 SQLite::Statement s2(db_, SQLITE_FROM_HERE, "INSERT INTO Resources VALUES(?, ?)"); |
180
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
370 s2.BindString(0, hasher.HashPatient()); |
82 | 371 s2.BindInt(1, ResourceType_Patient); |
372 s2.Run(); | |
373 | |
0 | 374 SQLite::Statement s(db_, SQLITE_FROM_HERE, "INSERT INTO Patients VALUES(?, ?)"); |
180
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
375 s.BindString(0, hasher.HashPatient()); |
0 | 376 s.BindString(1, dicomPatientId); |
377 s.Run(); | |
378 | |
180
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
379 RecordChange("patients", hasher.HashPatient()); |
0 | 380 |
381 DicomMap dicom; | |
382 dicomSummary.ExtractPatientInformation(dicom); | |
180
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
383 StoreMainDicomTags(hasher.HashPatient(), dicom); |
0 | 384 } |
385 | |
386 | |
387 void ServerIndex::GetMainDicomTags(DicomMap& map, | |
388 const std::string& uuid) | |
389 { | |
390 map.Clear(); | |
391 | |
392 SQLite::Statement s(db_, SQLITE_FROM_HERE, "SELECT * FROM MainDicomTags WHERE uuid=?"); | |
393 s.BindString(0, uuid); | |
394 while (s.Step()) | |
395 { | |
396 map.SetValue(s.ColumnInt(1), | |
397 s.ColumnInt(2), | |
398 s.ColumnString(3)); | |
399 } | |
400 } | |
401 | |
402 void ServerIndex::MainDicomTagsToJson(Json::Value& target, | |
403 const std::string& uuid) | |
404 { | |
405 DicomMap map; | |
406 GetMainDicomTags(map, uuid); | |
407 target["MainDicomTags"] = Json::objectValue; | |
408 FromDcmtkBridge::ToJson(target["MainDicomTags"], map); | |
409 } | |
410 | |
411 | |
412 bool ServerIndex::DeleteInternal(Json::Value& target, | |
413 const std::string& uuid, | |
414 const std::string& tableName) | |
415 { | |
416 boost::mutex::scoped_lock scoped_lock(mutex_); | |
417 | |
418 deletedLevels_->Clear(); | |
419 | |
420 SQLite::Statement s(db_, "DELETE FROM " + tableName + " WHERE uuid=?"); | |
421 s.BindString(0, uuid); | |
422 | |
423 if (!s.Run()) | |
424 { | |
425 return false; | |
426 } | |
427 | |
428 if (db_.GetLastChangeCount() == 0) | |
429 { | |
430 // Nothing was deleted, inexistent UUID | |
431 return false; | |
432 } | |
433 | |
434 if (deletedLevels_->HasRemainingLevel()) | |
435 { | |
436 std::string type(deletedLevels_->GetRemainingLevelType()); | |
437 const std::string& uuid = deletedLevels_->GetRemainingLevelUuid(); | |
438 | |
439 target["RemainingAncestor"] = Json::Value(Json::objectValue); | |
440 target["RemainingAncestor"]["Path"] = "/" + type + "/" + uuid; | |
441 target["RemainingAncestor"]["Type"] = type; | |
442 target["RemainingAncestor"]["ID"] = uuid; | |
443 } | |
444 else | |
445 { | |
446 target["RemainingAncestor"] = Json::nullValue; | |
447 } | |
448 | |
449 return true; | |
450 } | |
451 | |
452 | |
186
f68c039b0571
preparing refactoring of ServerIndex
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
180
diff
changeset
|
453 namespace Internals |
f68c039b0571
preparing refactoring of ServerIndex
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
180
diff
changeset
|
454 { |
189
ccbc2cf64a0d
record main dicom tags and changes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
188
diff
changeset
|
455 class ServerIndexListenerTodo : public IServerIndexListener |
186
f68c039b0571
preparing refactoring of ServerIndex
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
180
diff
changeset
|
456 { |
f68c039b0571
preparing refactoring of ServerIndex
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
180
diff
changeset
|
457 public: |
f68c039b0571
preparing refactoring of ServerIndex
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
180
diff
changeset
|
458 virtual void SignalRemainingAncestor(ResourceType parentType, |
f68c039b0571
preparing refactoring of ServerIndex
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
180
diff
changeset
|
459 const std::string& publicId) |
f68c039b0571
preparing refactoring of ServerIndex
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
180
diff
changeset
|
460 { |
f68c039b0571
preparing refactoring of ServerIndex
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
180
diff
changeset
|
461 LOG(INFO) << "Remaning ancestor \"" << publicId << "\" (" << parentType << ")"; |
f68c039b0571
preparing refactoring of ServerIndex
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
180
diff
changeset
|
462 } |
f68c039b0571
preparing refactoring of ServerIndex
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
180
diff
changeset
|
463 |
f68c039b0571
preparing refactoring of ServerIndex
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
180
diff
changeset
|
464 virtual void SignalFileDeleted(const std::string& fileUuid) |
f68c039b0571
preparing refactoring of ServerIndex
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
180
diff
changeset
|
465 { |
f68c039b0571
preparing refactoring of ServerIndex
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
180
diff
changeset
|
466 LOG(INFO) << "Deleted file " << fileUuid; |
f68c039b0571
preparing refactoring of ServerIndex
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
180
diff
changeset
|
467 } |
f68c039b0571
preparing refactoring of ServerIndex
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
180
diff
changeset
|
468 |
f68c039b0571
preparing refactoring of ServerIndex
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
180
diff
changeset
|
469 }; |
f68c039b0571
preparing refactoring of ServerIndex
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
180
diff
changeset
|
470 } |
f68c039b0571
preparing refactoring of ServerIndex
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
180
diff
changeset
|
471 |
f68c039b0571
preparing refactoring of ServerIndex
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
180
diff
changeset
|
472 |
0 | 473 ServerIndex::ServerIndex(const std::string& storagePath) |
474 { | |
189
ccbc2cf64a0d
record main dicom tags and changes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
188
diff
changeset
|
475 listener2_.reset(new Internals::ServerIndexListenerTodo); |
186
f68c039b0571
preparing refactoring of ServerIndex
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
180
diff
changeset
|
476 |
180
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
477 if (storagePath == ":memory:") |
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
478 { |
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
479 db_.OpenInMemory(); |
186
f68c039b0571
preparing refactoring of ServerIndex
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
180
diff
changeset
|
480 db2_.reset(new DatabaseWrapper(*listener2_)); |
180
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
481 } |
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
482 else |
0 | 483 { |
180
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
484 boost::filesystem::path p = storagePath; |
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
485 |
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
486 try |
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
487 { |
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
488 boost::filesystem::create_directories(storagePath); |
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
489 } |
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
490 catch (boost::filesystem::filesystem_error) |
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
491 { |
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
492 } |
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
493 |
186
f68c039b0571
preparing refactoring of ServerIndex
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
180
diff
changeset
|
494 db2_.reset(new DatabaseWrapper(p.string() + "/index2", *listener2_)); |
f68c039b0571
preparing refactoring of ServerIndex
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
180
diff
changeset
|
495 |
180
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
496 p /= "index"; |
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
497 db_.Open(p.string()); |
0 | 498 } |
499 | |
500 db_.Register(new Internals::DeleteFromFileStorageFunction(storagePath)); | |
501 deletedLevels_ = (Internals::SignalDeletedLevelFunction*) | |
502 db_.Register(new Internals::SignalDeletedLevelFunction); | |
503 | |
504 if (!db_.DoesTableExist("GlobalProperties")) | |
505 { | |
108 | 506 LOG(INFO) << "Creating the database"; |
0 | 507 std::string query; |
508 EmbeddedResources::GetFileResource(query, EmbeddedResources::PREPARE_DATABASE); | |
509 db_.Execute(query); | |
510 } | |
511 } | |
512 | |
513 | |
187
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
514 StoreStatus ServerIndex::Store2(const DicomMap& dicomSummary, |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
515 const std::string& fileUuid, |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
516 uint64_t uncompressedFileSize, |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
517 const std::string& jsonUuid, |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
518 const std::string& remoteAet) |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
519 { |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
520 boost::mutex::scoped_lock scoped_lock(mutex_); |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
521 |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
522 DicomInstanceHasher hasher(dicomSummary); |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
523 |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
524 try |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
525 { |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
526 std::auto_ptr<SQLite::Transaction> t(db2_->StartTransaction()); |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
527 t->Begin(); |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
528 |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
529 int64_t patient, study, series, instance; |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
530 ResourceType type; |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
531 bool isNewSeries = false; |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
532 |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
533 // Do nothing if the instance already exists |
188
090cefdab1d1
fix because of Windows macros
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
187
diff
changeset
|
534 if (db2_->LookupResource(hasher.HashInstance(), patient, type)) |
187
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
535 { |
188
090cefdab1d1
fix because of Windows macros
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
187
diff
changeset
|
536 assert(type == ResourceType_Instance); |
187
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
537 return StoreStatus_AlreadyStored; |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
538 } |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
539 |
190 | 540 // Create the instance |
187
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
541 instance = db2_->CreateResource(hasher.HashInstance(), ResourceType_Instance); |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
542 |
189
ccbc2cf64a0d
record main dicom tags and changes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
188
diff
changeset
|
543 DicomMap dicom; |
ccbc2cf64a0d
record main dicom tags and changes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
188
diff
changeset
|
544 dicomSummary.ExtractInstanceInformation(dicom); |
ccbc2cf64a0d
record main dicom tags and changes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
188
diff
changeset
|
545 db2_->SetMainDicomTags(instance, dicom); |
ccbc2cf64a0d
record main dicom tags and changes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
188
diff
changeset
|
546 |
190 | 547 // Create the patient/study/series/instance hierarchy |
188
090cefdab1d1
fix because of Windows macros
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
187
diff
changeset
|
548 if (!db2_->LookupResource(hasher.HashSeries(), series, type)) |
187
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
549 { |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
550 // This is a new series |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
551 isNewSeries = true; |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
552 series = db2_->CreateResource(hasher.HashSeries(), ResourceType_Series); |
189
ccbc2cf64a0d
record main dicom tags and changes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
188
diff
changeset
|
553 dicomSummary.ExtractSeriesInformation(dicom); |
ccbc2cf64a0d
record main dicom tags and changes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
188
diff
changeset
|
554 db2_->SetMainDicomTags(series, dicom); |
187
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
555 db2_->AttachChild(series, instance); |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
556 |
188
090cefdab1d1
fix because of Windows macros
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
187
diff
changeset
|
557 if (!db2_->LookupResource(hasher.HashStudy(), study, type)) |
187
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
558 { |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
559 // This is a new study |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
560 study = db2_->CreateResource(hasher.HashStudy(), ResourceType_Study); |
189
ccbc2cf64a0d
record main dicom tags and changes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
188
diff
changeset
|
561 dicomSummary.ExtractStudyInformation(dicom); |
ccbc2cf64a0d
record main dicom tags and changes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
188
diff
changeset
|
562 db2_->SetMainDicomTags(study, dicom); |
187
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
563 db2_->AttachChild(study, series); |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
564 |
188
090cefdab1d1
fix because of Windows macros
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
187
diff
changeset
|
565 if (!db2_->LookupResource(hasher.HashPatient(), patient, type)) |
187
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
566 { |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
567 // This is a new patient |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
568 patient = db2_->CreateResource(hasher.HashPatient(), ResourceType_Patient); |
189
ccbc2cf64a0d
record main dicom tags and changes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
188
diff
changeset
|
569 dicomSummary.ExtractPatientInformation(dicom); |
ccbc2cf64a0d
record main dicom tags and changes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
188
diff
changeset
|
570 db2_->SetMainDicomTags(patient, dicom); |
187
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
571 db2_->AttachChild(patient, study); |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
572 } |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
573 else |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
574 { |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
575 assert(type == ResourceType_Patient); |
189
ccbc2cf64a0d
record main dicom tags and changes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
188
diff
changeset
|
576 db2_->AttachChild(patient, study); |
187
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
577 } |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
578 } |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
579 else |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
580 { |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
581 assert(type == ResourceType_Study); |
189
ccbc2cf64a0d
record main dicom tags and changes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
188
diff
changeset
|
582 db2_->AttachChild(study, series); |
187
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
583 } |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
584 } |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
585 else |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
586 { |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
587 assert(type == ResourceType_Series); |
189
ccbc2cf64a0d
record main dicom tags and changes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
188
diff
changeset
|
588 db2_->AttachChild(series, instance); |
187
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
589 } |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
590 |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
591 // Attach the files to the newly created instance |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
592 db2_->AttachFile(instance, "_dicom", fileUuid, uncompressedFileSize); |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
593 db2_->AttachFile(instance, "_json", jsonUuid, 0); // TODO "0" |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
594 |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
595 // Attach the metadata |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
596 db2_->SetMetadata(instance, MetadataType_Instance_ReceptionDate, Toolbox::GetNowIsoString()); |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
597 db2_->SetMetadata(instance, MetadataType_Instance_RemoteAet, remoteAet); |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
598 |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
599 const DicomValue* value; |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
600 if ((value = dicomSummary.TestAndGetValue(DICOM_TAG_INSTANCE_NUMBER)) != NULL || |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
601 (value = dicomSummary.TestAndGetValue(DICOM_TAG_IMAGE_INDEX)) != NULL) |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
602 { |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
603 db2_->SetMetadata(instance, MetadataType_Instance_IndexInSeries, value->AsString()); |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
604 } |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
605 |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
606 if (isNewSeries) |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
607 { |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
608 if ((value = dicomSummary.TestAndGetValue(DICOM_TAG_NUMBER_OF_SLICES)) != NULL || |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
609 (value = dicomSummary.TestAndGetValue(DICOM_TAG_IMAGES_IN_ACQUISITION)) != NULL) |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
610 { |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
611 db2_->SetMetadata(series, MetadataType_Series_ExpectedNumberOfInstances, value->AsString()); |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
612 } |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
613 } |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
614 |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
615 t->Commit(); |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
616 } |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
617 catch (OrthancException& e) |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
618 { |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
619 LOG(ERROR) << "EXCEPTION2 [" << e.What() << "]" << " " << db_.GetErrorMessage(); |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
620 } |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
621 |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
622 return StoreStatus_Failure; |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
623 } |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
624 |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
625 |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
626 StoreStatus ServerIndex::Store(const DicomMap& dicomSummary, |
0 | 627 const std::string& fileUuid, |
628 uint64_t uncompressedFileSize, | |
629 const std::string& jsonUuid, | |
187
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
630 const std::string& remoteAet) |
0 | 631 { |
187
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
632 Store2(dicomSummary, fileUuid, uncompressedFileSize, jsonUuid, remoteAet); |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
633 |
0 | 634 boost::mutex::scoped_lock scoped_lock(mutex_); |
635 | |
178 | 636 DicomInstanceHasher hasher(dicomSummary); |
0 | 637 |
638 try | |
639 { | |
640 SQLite::Transaction t(db_); | |
641 t.Begin(); | |
642 | |
180
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
643 if (HasInstance(hasher)) |
0 | 644 { |
645 return StoreStatus_AlreadyStored; | |
646 // TODO: Check consistency? | |
647 } | |
648 | |
180
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
649 if (HasPatient(hasher)) |
0 | 650 { |
651 // TODO: Check consistency? | |
652 } | |
653 else | |
654 { | |
180
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
655 CreatePatient(hasher, dicomSummary); |
0 | 656 } |
657 | |
180
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
658 if (HasStudy(hasher)) |
0 | 659 { |
660 // TODO: Check consistency? | |
661 } | |
662 else | |
663 { | |
180
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
664 CreateStudy(hasher, dicomSummary); |
0 | 665 } |
666 | |
180
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
667 if (HasSeries(hasher)) |
0 | 668 { |
669 // TODO: Check consistency? | |
670 } | |
671 else | |
672 { | |
180
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
673 CreateSeries(hasher, dicomSummary); |
0 | 674 } |
675 | |
180
626777d01dc4
use of hashes to index dicom objects
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
179
diff
changeset
|
676 CreateInstance(hasher, dicomSummary, fileUuid, |
187
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
677 uncompressedFileSize, jsonUuid, remoteAet); |
0 | 678 |
679 t.Commit(); | |
680 return StoreStatus_Success; | |
681 //t.Rollback(); | |
682 } | |
62 | 683 catch (OrthancException& e) |
0 | 684 { |
108 | 685 LOG(ERROR) << "EXCEPTION [" << e.What() << "]" << " " << db_.GetErrorMessage(); |
0 | 686 } |
687 | |
688 return StoreStatus_Failure; | |
689 } | |
690 | |
691 | |
187
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
692 StoreStatus ServerIndex::Store(FileStorage& storage, |
0 | 693 const char* dicomFile, |
694 size_t dicomSize, | |
695 const DicomMap& dicomSummary, | |
696 const Json::Value& dicomJson, | |
187
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
697 const std::string& remoteAet) |
0 | 698 { |
699 std::string fileUuid = storage.Create(dicomFile, dicomSize); | |
700 std::string jsonUuid = storage.Create(dicomJson.toStyledString()); | |
187
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
701 StoreStatus status = Store(dicomSummary, fileUuid, dicomSize, jsonUuid, remoteAet); |
0 | 702 |
703 if (status != StoreStatus_Success) | |
704 { | |
147 | 705 storage.Remove(fileUuid); |
706 storage.Remove(jsonUuid); | |
0 | 707 } |
708 | |
709 switch (status) | |
710 { | |
711 case StoreStatus_Success: | |
187
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
712 LOG(WARNING) << "New instance stored"; |
0 | 713 break; |
714 | |
715 case StoreStatus_AlreadyStored: | |
138 | 716 LOG(WARNING) << "Already stored"; |
0 | 717 break; |
718 | |
719 case StoreStatus_Failure: | |
138 | 720 LOG(ERROR) << "Store failure"; |
0 | 721 break; |
722 } | |
723 | |
724 return status; | |
725 } | |
726 | |
187
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
727 uint64_t ServerIndex::GetTotalCompressedSize() |
0 | 728 { |
729 boost::mutex::scoped_lock scoped_lock(mutex_); | |
187
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
730 return db2_->GetTotalCompressedSize(); |
0 | 731 } |
732 | |
187
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
733 uint64_t ServerIndex::GetTotalUncompressedSize() |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
734 { |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
735 boost::mutex::scoped_lock scoped_lock(mutex_); |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
736 return db2_->GetTotalUncompressedSize(); |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
737 } |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
738 |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
739 |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
186
diff
changeset
|
740 |
0 | 741 |
742 SeriesStatus ServerIndex::GetSeriesStatus(const std::string& seriesUuid) | |
743 { | |
80 | 744 SQLite::Statement s1(db_, SQLITE_FROM_HERE, "SELECT expectedNumberOfInstances FROM Series WHERE uuid=?"); |
745 s1.BindString(0, seriesUuid); | |
82 | 746 if (!s1.Step() || s1.ColumnIsNull(0)) |
80 | 747 { |
748 return SeriesStatus_Unknown; | |
749 } | |
750 | |
751 int numberOfInstances = s1.ColumnInt(0); | |
752 if (numberOfInstances < 0) | |
0 | 753 { |
754 return SeriesStatus_Unknown; | |
755 } | |
756 | |
80 | 757 std::set<int> instances; |
758 SQLite::Statement s2(db_, SQLITE_FROM_HERE, "SELECT indexInSeries FROM Instances WHERE parentSeries=?"); | |
759 s2.BindString(0, seriesUuid); | |
760 while (s2.Step()) | |
761 { | |
762 int index = s2.ColumnInt(0); | |
763 if (index <= 0 || index > numberOfInstances) | |
764 { | |
765 // Out-of-range instance index | |
766 return SeriesStatus_Inconsistent; | |
767 } | |
0 | 768 |
80 | 769 if (instances.find(index) != instances.end()) |
770 { | |
771 // Twice the same instance index | |
772 return SeriesStatus_Inconsistent; | |
773 } | |
774 | |
775 instances.insert(index); | |
776 } | |
777 | |
778 for (int i = 1; i <= numberOfInstances; i++) | |
779 { | |
780 if (instances.find(i) == instances.end()) | |
781 { | |
782 return SeriesStatus_Missing; | |
783 } | |
784 } | |
785 | |
786 return SeriesStatus_Complete; | |
0 | 787 } |
788 | |
789 | |
790 | |
791 bool ServerIndex::GetInstance(Json::Value& result, | |
792 const std::string& instanceUuid) | |
793 { | |
794 assert(result.type() == Json::objectValue); | |
795 boost::mutex::scoped_lock scoped_lock(mutex_); | |
796 | |
80 | 797 SQLite::Statement s(db_, SQLITE_FROM_HERE, "SELECT parentSeries, dicomInstance, fileSize, fileUuid, indexInSeries FROM Instances WHERE uuid=?"); |
0 | 798 s.BindString(0, instanceUuid); |
799 if (!s.Step()) | |
800 { | |
801 return false; | |
802 } | |
803 else | |
804 { | |
805 result["ID"] = instanceUuid; | |
806 result["ParentSeries"] = s.ColumnString(0); | |
807 result["FileSize"] = s.ColumnInt(2); // TODO switch to 64bit with JsonCpp 0.6? | |
808 result["FileUuid"] = s.ColumnString(3); | |
809 MainDicomTagsToJson(result, instanceUuid); | |
80 | 810 |
811 if (s.ColumnIsNull(4)) | |
812 { | |
82 | 813 result["IndexInSeries"] = Json::nullValue; |
80 | 814 } |
815 else | |
816 { | |
817 result["IndexInSeries"] = s.ColumnInt(4); | |
818 } | |
819 | |
0 | 820 return true; |
821 } | |
822 } | |
823 | |
824 | |
825 bool ServerIndex::GetSeries(Json::Value& result, | |
826 const std::string& seriesUuid) | |
827 { | |
828 assert(result.type() == Json::objectValue); | |
829 boost::mutex::scoped_lock scoped_lock(mutex_); | |
830 | |
80 | 831 SQLite::Statement s1(db_, SQLITE_FROM_HERE, "SELECT parentStudy, dicomSeries, expectedNumberOfInstances FROM Series WHERE uuid=?"); |
0 | 832 s1.BindString(0, seriesUuid); |
833 if (!s1.Step()) | |
834 { | |
835 return false; | |
836 } | |
837 | |
838 result["ID"] = seriesUuid; | |
839 result["ParentStudy"] = s1.ColumnString(0); | |
840 MainDicomTagsToJson(result, seriesUuid); | |
841 | |
842 Json::Value instances(Json::arrayValue); | |
843 SQLite::Statement s2(db_, SQLITE_FROM_HERE, "SELECT uuid FROM Instances WHERE parentSeries=?"); | |
844 s2.BindString(0, seriesUuid); | |
845 while (s2.Step()) | |
846 { | |
847 instances.append(s2.ColumnString(0)); | |
848 } | |
849 | |
850 result["Instances"] = instances; | |
851 | |
80 | 852 if (s1.ColumnIsNull(2)) |
853 { | |
82 | 854 result["ExpectedNumberOfInstances"] = Json::nullValue; |
80 | 855 } |
856 else | |
857 { | |
858 result["ExpectedNumberOfInstances"] = s1.ColumnInt(2); | |
859 } | |
860 | |
861 SeriesStatus status = GetSeriesStatus(seriesUuid); | |
862 | |
863 switch (status) | |
864 { | |
865 case SeriesStatus_Complete: | |
866 result["Status"] = "Complete"; | |
867 break; | |
868 | |
869 case SeriesStatus_Missing: | |
870 result["Status"] = "Missing"; | |
871 break; | |
872 | |
873 case SeriesStatus_Inconsistent: | |
874 result["Status"] = "Inconsistent"; | |
875 break; | |
876 | |
877 default: | |
878 case SeriesStatus_Unknown: | |
879 result["Status"] = "Unknown"; | |
880 break; | |
881 } | |
882 | |
0 | 883 return true; |
884 } | |
885 | |
886 | |
887 bool ServerIndex::GetStudy(Json::Value& result, | |
888 const std::string& studyUuid) | |
889 { | |
890 assert(result.type() == Json::objectValue); | |
891 boost::mutex::scoped_lock scoped_lock(mutex_); | |
892 | |
893 SQLite::Statement s1(db_, SQLITE_FROM_HERE, "SELECT parentPatient, dicomStudy FROM Studies WHERE uuid=?"); | |
894 s1.BindString(0, studyUuid); | |
895 if (!s1.Step()) | |
896 { | |
897 return false; | |
898 } | |
899 | |
900 result["ID"] = studyUuid; | |
901 result["ParentPatient"] = s1.ColumnString(0); | |
902 MainDicomTagsToJson(result, studyUuid); | |
903 | |
904 Json::Value series(Json::arrayValue); | |
905 SQLite::Statement s2(db_, SQLITE_FROM_HERE, "SELECT uuid FROM Series WHERE parentStudy=?"); | |
906 s2.BindString(0, studyUuid); | |
907 while (s2.Step()) | |
908 { | |
909 series.append(s2.ColumnString(0)); | |
910 } | |
911 | |
912 result["Series"] = series; | |
913 return true; | |
914 } | |
915 | |
916 | |
917 bool ServerIndex::GetPatient(Json::Value& result, | |
918 const std::string& patientUuid) | |
919 { | |
920 assert(result.type() == Json::objectValue); | |
921 boost::mutex::scoped_lock scoped_lock(mutex_); | |
922 | |
923 SQLite::Statement s1(db_, SQLITE_FROM_HERE, "SELECT dicomPatientId FROM Patients WHERE uuid=?"); | |
924 s1.BindString(0, patientUuid); | |
925 if (!s1.Step()) | |
926 { | |
927 return false; | |
928 } | |
929 | |
930 result["ID"] = patientUuid; | |
931 MainDicomTagsToJson(result, patientUuid); | |
932 | |
933 Json::Value studies(Json::arrayValue); | |
934 SQLite::Statement s2(db_, SQLITE_FROM_HERE, "SELECT uuid FROM Studies WHERE parentPatient=?"); | |
935 s2.BindString(0, patientUuid); | |
936 while (s2.Step()) | |
937 { | |
938 studies.append(s2.ColumnString(0)); | |
939 } | |
940 | |
941 result["Studies"] = studies; | |
942 return true; | |
943 } | |
944 | |
945 | |
946 bool ServerIndex::GetJsonFile(std::string& fileUuid, | |
947 const std::string& instanceUuid) | |
948 { | |
949 boost::mutex::scoped_lock scoped_lock(mutex_); | |
950 | |
951 SQLite::Statement s(db_, SQLITE_FROM_HERE, "SELECT jsonUuid FROM Instances WHERE uuid=?"); | |
952 s.BindString(0, instanceUuid); | |
953 if (s.Step()) | |
954 { | |
955 fileUuid = s.ColumnString(0); | |
956 return true; | |
957 } | |
958 else | |
959 { | |
960 return false; | |
961 } | |
962 } | |
963 | |
964 bool ServerIndex::GetDicomFile(std::string& fileUuid, | |
965 const std::string& instanceUuid) | |
966 { | |
967 boost::mutex::scoped_lock scoped_lock(mutex_); | |
968 | |
969 SQLite::Statement s(db_, SQLITE_FROM_HERE, "SELECT fileUuid FROM Instances WHERE uuid=?"); | |
970 s.BindString(0, instanceUuid); | |
971 if (s.Step()) | |
972 { | |
973 fileUuid = s.ColumnString(0); | |
974 return true; | |
975 } | |
976 else | |
977 { | |
978 return false; | |
979 } | |
980 } | |
981 | |
982 | |
983 void ServerIndex::GetAllUuids(Json::Value& target, | |
190 | 984 ResourceType resourceType) |
0 | 985 { |
190 | 986 boost::mutex::scoped_lock scoped_lock(mutex_); |
987 | |
988 std::string tableName; | |
989 | |
990 switch (resourceType) | |
991 { | |
992 case ResourceType_Patient: | |
993 tableName = "Patients"; | |
994 break; | |
995 | |
996 case ResourceType_Study: | |
997 tableName = "Studies"; | |
998 break; | |
999 | |
1000 case ResourceType_Series: | |
1001 tableName = "Series"; | |
1002 break; | |
1003 | |
1004 case ResourceType_Instance: | |
1005 tableName = "Instances"; | |
1006 break; | |
1007 | |
1008 default: | |
1009 throw OrthancException(ErrorCode_InternalError); | |
1010 } | |
1011 | |
0 | 1012 assert(target.type() == Json::arrayValue); |
1013 | |
1014 std::string query = "SELECT uuid FROM " + tableName; | |
1015 SQLite::Statement s(db_, query); | |
1016 while (s.Step()) | |
1017 { | |
1018 target.append(s.ColumnString(0)); | |
1019 } | |
1020 } | |
1021 | |
1022 | |
1023 bool ServerIndex::GetChanges(Json::Value& target, | |
1024 int64_t since, | |
1025 const std::string& filter, | |
1026 unsigned int maxResults) | |
1027 { | |
1028 assert(target.type() == Json::objectValue); | |
1029 boost::mutex::scoped_lock scoped_lock(mutex_); | |
1030 | |
1031 if (filter.size() != 0 && | |
1032 filter != "instances" && | |
1033 filter != "series" && | |
1034 filter != "studies" && | |
1035 filter != "patients") | |
1036 { | |
1037 return false; | |
1038 } | |
1039 | |
1040 std::auto_ptr<SQLite::Statement> s; | |
1041 if (filter.size() == 0) | |
1042 { | |
1043 s.reset(new SQLite::Statement(db_, SQLITE_FROM_HERE, "SELECT * FROM Changes WHERE seq>? " | |
1044 "ORDER BY seq LIMIT ?")); | |
1045 s->BindInt64(0, since); | |
1046 s->BindInt(1, maxResults); | |
1047 } | |
1048 else | |
1049 { | |
1050 s.reset(new SQLite::Statement(db_, SQLITE_FROM_HERE, "SELECT * FROM Changes WHERE seq>? " | |
1051 "AND basePath=? ORDER BY seq LIMIT ?")); | |
1052 s->BindInt64(0, since); | |
1053 s->BindString(1, filter); | |
1054 s->BindInt(2, maxResults); | |
1055 } | |
1056 | |
1057 int64_t lastSeq = 0; | |
1058 Json::Value results(Json::arrayValue); | |
1059 while (s->Step()) | |
1060 { | |
1061 int64_t seq = s->ColumnInt64(0); | |
1062 std::string basePath = s->ColumnString(1); | |
1063 std::string uuid = s->ColumnString(2); | |
1064 | |
1065 if (filter.size() == 0 || | |
1066 filter == basePath) | |
1067 { | |
1068 Json::Value change(Json::objectValue); | |
1069 change["Seq"] = static_cast<int>(seq); // TODO JsonCpp in 64bit | |
1070 change["BasePath"] = basePath; | |
1071 change["ID"] = uuid; | |
1072 results.append(change); | |
1073 } | |
1074 | |
1075 if (seq > lastSeq) | |
1076 { | |
1077 lastSeq = seq; | |
1078 } | |
1079 } | |
1080 | |
1081 target["Results"] = results; | |
1082 target["LastSeq"] = static_cast<int>(lastSeq); // TODO JsonCpp in 64bit | |
1083 | |
1084 return true; | |
1085 } | |
82 | 1086 |
0 | 1087 } |