Mercurial > hg > orthanc
comparison OrthancServer/Sources/ServerIndex.h @ 4587:888868a5dc4e db-changes
ServerIndex now uses StatelessDatabaseOperations
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Wed, 10 Mar 2021 15:59:03 +0100 |
parents | f0bdd99f3d81 |
children | 4a0bf1019335 |
comparison
equal
deleted
inserted
replaced
4586:1d96fe7e054e | 4587:888868a5dc4e |
---|---|
31 **/ | 31 **/ |
32 | 32 |
33 | 33 |
34 #pragma once | 34 #pragma once |
35 | 35 |
36 #include "Database/StatelessDatabaseOperations.h" | |
36 #include "../../OrthancFramework/Sources/Cache/LeastRecentlyUsedIndex.h" | 37 #include "../../OrthancFramework/Sources/Cache/LeastRecentlyUsedIndex.h" |
37 #include "../../OrthancFramework/Sources/DicomFormat/DicomMap.h" | |
38 | |
39 #include "Database/IDatabaseWrapper.h" | |
40 #include "DicomInstanceOrigin.h" | |
41 | 38 |
42 #include <boost/thread.hpp> | 39 #include <boost/thread.hpp> |
43 #include <boost/noncopyable.hpp> | |
44 | 40 |
45 namespace Orthanc | 41 namespace Orthanc |
46 { | 42 { |
47 class DatabaseLookup; | |
48 class ParsedDicomFile; | |
49 class ServerContext; | 43 class ServerContext; |
50 | 44 |
51 class ServerIndex : public boost::noncopyable | 45 class ServerIndex : public StatelessDatabaseOperations |
52 { | 46 { |
53 public: | |
54 typedef std::list<FileInfo> Attachments; | |
55 typedef std::map<std::pair<ResourceType, MetadataType>, std::string> MetadataMap; | |
56 | |
57 private: | 47 private: |
58 class TransactionContextFactory; | 48 class TransactionContextFactory; |
59 class Listener; | 49 class Listener; |
60 class Transaction; | |
61 class UnstableResourcePayload; | 50 class UnstableResourcePayload; |
62 class MainDicomTagsRegistry; | |
63 | 51 |
64 bool done_; | 52 bool done_; |
65 boost::mutex monitoringMutex_; | 53 boost::mutex monitoringMutex_; |
66 boost::mutex databaseMutex_; // TODO - REMOVE | |
67 boost::thread flushThread_; | 54 boost::thread flushThread_; |
68 boost::thread unstableResourcesMonitorThread_; | 55 boost::thread unstableResourcesMonitorThread_; |
69 | 56 |
70 std::unique_ptr<Listener> listener_; | 57 std::unique_ptr<Listener> listener_; |
71 IDatabaseWrapper& db_; | |
72 LeastRecentlyUsedIndex<int64_t, UnstableResourcePayload> unstableResources_; | 58 LeastRecentlyUsedIndex<int64_t, UnstableResourcePayload> unstableResources_; |
73 | 59 |
74 uint64_t maximumStorageSize_; | 60 uint64_t maximumStorageSize_; |
75 unsigned int maximumPatients_; | 61 unsigned int maximumPatients_; |
76 std::unique_ptr<MainDicomTagsRegistry> mainDicomTagsRegistry_; | |
77 | 62 |
78 static void FlushThread(ServerIndex* that, | 63 static void FlushThread(ServerIndex* that, |
79 unsigned int threadSleep); | 64 unsigned int threadSleep); |
80 | 65 |
81 static void UnstableResourcesMonitorThread(ServerIndex* that, | 66 static void UnstableResourcesMonitorThread(ServerIndex* that, |
82 unsigned int threadSleep); | 67 unsigned int threadSleep); |
83 | 68 |
84 void StandaloneRecycling(uint64_t maximumStorageSize, | |
85 unsigned int maximumPatientCount); | |
86 | |
87 void MarkAsUnstable(int64_t id, | 69 void MarkAsUnstable(int64_t id, |
88 Orthanc::ResourceType type, | 70 Orthanc::ResourceType type, |
89 const std::string& publicId); | 71 const std::string& publicId); |
90 | |
91 void NormalizeLookup(std::vector<DatabaseConstraint>& target, | |
92 const DatabaseLookup& source, | |
93 ResourceType level) const; | |
94 | 72 |
95 bool IsUnstableResource(int64_t id); | 73 bool IsUnstableResource(int64_t id); |
96 | 74 |
97 public: | 75 public: |
98 ServerIndex(ServerContext& context, | 76 ServerIndex(ServerContext& context, |
107 void SetMaximumStorageSize(uint64_t size); | 85 void SetMaximumStorageSize(uint64_t size); |
108 | 86 |
109 // "count == 0" means no limit on the number of patients | 87 // "count == 0" means no limit on the number of patients |
110 void SetMaximumPatientCount(unsigned int count); | 88 void SetMaximumPatientCount(unsigned int count); |
111 | 89 |
112 // It is assumed that "GetDatabaseVersion()" can run out of a | |
113 // database transaction | |
114 unsigned int GetDatabaseVersion() | |
115 { | |
116 return db_.GetDatabaseVersion(); | |
117 } | |
118 | |
119 | |
120 | |
121 /*** | |
122 ** PROTOTYPING FOR DB REFACTORING BELOW | |
123 ***/ | |
124 | |
125 public: | |
126 class ITransactionContext : public boost::noncopyable | |
127 { | |
128 public: | |
129 virtual ~ITransactionContext() | |
130 { | |
131 } | |
132 | |
133 virtual bool IsUnstableResource(int64_t id) = 0; | |
134 | |
135 virtual bool LookupRemainingLevel(std::string& remainingPublicId /* out */, | |
136 ResourceType& remainingLevel /* out */) = 0; | |
137 | |
138 virtual void MarkAsUnstable(int64_t id, | |
139 Orthanc::ResourceType type, | |
140 const std::string& publicId) = 0; | |
141 | |
142 virtual void SignalAttachmentsAdded(uint64_t compressedSize) = 0; | |
143 | |
144 virtual void SignalChange(const ServerIndexChange& change) = 0; | |
145 }; | |
146 | |
147 | |
148 class ITransactionContextFactory : public boost::noncopyable | |
149 { | |
150 public: | |
151 virtual ~ITransactionContextFactory() | |
152 { | |
153 } | |
154 | |
155 virtual ITransactionContext* Create() = 0; | |
156 }; | |
157 | |
158 | |
159 class ReadOnlyTransaction : public boost::noncopyable | |
160 { | |
161 private: | |
162 ITransactionContext& context_; | |
163 | |
164 protected: | |
165 IDatabaseWrapper& db_; | |
166 | |
167 public: | |
168 explicit ReadOnlyTransaction(IDatabaseWrapper& db, | |
169 ITransactionContext& context) : | |
170 context_(context), | |
171 db_(db) | |
172 { | |
173 } | |
174 | |
175 ITransactionContext& GetTransactionContext() | |
176 { | |
177 return context_; | |
178 } | |
179 | |
180 /** | |
181 * Higher-level constructions | |
182 **/ | |
183 | |
184 SeriesStatus GetSeriesStatus(int64_t id, | |
185 int64_t expectedNumberOfInstances); | |
186 | |
187 void MainDicomTagsToJson(Json::Value& result, | |
188 int64_t resourceId, | |
189 ResourceType resourceType); | |
190 | |
191 /** | |
192 * Read-only methods from "IDatabaseWrapper" | |
193 **/ | |
194 | |
195 void ApplyLookupResources(std::list<std::string>& resourcesId, | |
196 std::list<std::string>* instancesId, // Can be NULL if not needed | |
197 const std::vector<DatabaseConstraint>& lookup, | |
198 ResourceType queryLevel, | |
199 size_t limit) | |
200 { | |
201 return db_.ApplyLookupResources(resourcesId, instancesId, lookup, queryLevel, limit); | |
202 } | |
203 | |
204 void GetAllMetadata(std::map<MetadataType, std::string>& target, | |
205 int64_t id) | |
206 { | |
207 db_.GetAllMetadata(target, id); | |
208 } | |
209 | |
210 void GetAllPublicIds(std::list<std::string>& target, | |
211 ResourceType resourceType) | |
212 { | |
213 return db_.GetAllPublicIds(target, resourceType); | |
214 } | |
215 | |
216 void GetAllPublicIds(std::list<std::string>& target, | |
217 ResourceType resourceType, | |
218 size_t since, | |
219 size_t limit) | |
220 { | |
221 return db_.GetAllPublicIds(target, resourceType, since, limit); | |
222 } | |
223 | |
224 void GetChanges(std::list<ServerIndexChange>& target /*out*/, | |
225 bool& done /*out*/, | |
226 int64_t since, | |
227 uint32_t maxResults) | |
228 { | |
229 db_.GetChanges(target, done, since, maxResults); | |
230 } | |
231 | |
232 void GetChildrenInternalId(std::list<int64_t>& target, | |
233 int64_t id) | |
234 { | |
235 db_.GetChildrenInternalId(target, id); | |
236 } | |
237 | |
238 void GetChildrenPublicId(std::list<std::string>& target, | |
239 int64_t id) | |
240 { | |
241 db_.GetChildrenPublicId(target, id); | |
242 } | |
243 | |
244 void GetExportedResources(std::list<ExportedResource>& target /*out*/, | |
245 bool& done /*out*/, | |
246 int64_t since, | |
247 uint32_t maxResults) | |
248 { | |
249 return db_.GetExportedResources(target, done, since, maxResults); | |
250 } | |
251 | |
252 void GetLastChange(std::list<ServerIndexChange>& target /*out*/) | |
253 { | |
254 db_.GetLastChange(target); | |
255 } | |
256 | |
257 void GetLastExportedResource(std::list<ExportedResource>& target /*out*/) | |
258 { | |
259 return db_.GetLastExportedResource(target); | |
260 } | |
261 | |
262 int64_t GetLastChangeIndex() | |
263 { | |
264 return db_.GetLastChangeIndex(); | |
265 } | |
266 | |
267 void GetMainDicomTags(DicomMap& map, | |
268 int64_t id) | |
269 { | |
270 db_.GetMainDicomTags(map, id); | |
271 } | |
272 | |
273 std::string GetPublicId(int64_t resourceId) | |
274 { | |
275 return db_.GetPublicId(resourceId); | |
276 } | |
277 | |
278 uint64_t GetResourceCount(ResourceType resourceType) | |
279 { | |
280 return db_.GetResourceCount(resourceType); | |
281 } | |
282 | |
283 ResourceType GetResourceType(int64_t resourceId) | |
284 { | |
285 return db_.GetResourceType(resourceId); | |
286 } | |
287 | |
288 uint64_t GetTotalCompressedSize() | |
289 { | |
290 return db_.GetTotalCompressedSize(); | |
291 } | |
292 | |
293 uint64_t GetTotalUncompressedSize() | |
294 { | |
295 return db_.GetTotalUncompressedSize(); | |
296 } | |
297 | |
298 bool IsProtectedPatient(int64_t internalId) | |
299 { | |
300 return db_.IsProtectedPatient(internalId); | |
301 } | |
302 | |
303 void ListAvailableAttachments(std::set<FileContentType>& target, | |
304 int64_t id) | |
305 { | |
306 db_.ListAvailableAttachments(target, id); | |
307 } | |
308 | |
309 bool LookupAttachment(FileInfo& attachment, | |
310 int64_t id, | |
311 FileContentType contentType) | |
312 { | |
313 return db_.LookupAttachment(attachment, id, contentType); | |
314 } | |
315 | |
316 bool LookupGlobalProperty(std::string& target, | |
317 GlobalProperty property) | |
318 { | |
319 return db_.LookupGlobalProperty(target, property); | |
320 } | |
321 | |
322 bool LookupMetadata(std::string& target, | |
323 int64_t id, | |
324 MetadataType type) | |
325 { | |
326 return db_.LookupMetadata(target, id, type); | |
327 } | |
328 | |
329 bool LookupParent(int64_t& parentId, | |
330 int64_t resourceId) | |
331 { | |
332 return db_.LookupParent(parentId, resourceId); | |
333 } | |
334 | |
335 bool LookupResource(int64_t& id, | |
336 ResourceType& type, | |
337 const std::string& publicId) | |
338 { | |
339 return db_.LookupResource(id, type, publicId); | |
340 } | |
341 | |
342 bool LookupResourceAndParent(int64_t& id, | |
343 ResourceType& type, | |
344 std::string& parentPublicId, | |
345 const std::string& publicId) | |
346 { | |
347 return db_.LookupResourceAndParent(id, type, parentPublicId, publicId); | |
348 } | |
349 }; | |
350 | |
351 | |
352 class ReadWriteTransaction : public ReadOnlyTransaction | |
353 { | |
354 public: | |
355 ReadWriteTransaction(IDatabaseWrapper& db, | |
356 ITransactionContext& context) : | |
357 ReadOnlyTransaction(db, context) | |
358 { | |
359 } | |
360 | |
361 void AddAttachment(int64_t id, | |
362 const FileInfo& attachment) | |
363 { | |
364 db_.AddAttachment(id, attachment); | |
365 } | |
366 | |
367 void ClearChanges() | |
368 { | |
369 db_.ClearChanges(); | |
370 } | |
371 | |
372 void ClearExportedResources() | |
373 { | |
374 db_.ClearExportedResources(); | |
375 } | |
376 | |
377 void ClearMainDicomTags(int64_t id) | |
378 { | |
379 return db_.ClearMainDicomTags(id); | |
380 } | |
381 | |
382 bool CreateInstance(IDatabaseWrapper::CreateInstanceResult& result, /* out */ | |
383 int64_t& instanceId, /* out */ | |
384 const std::string& patient, | |
385 const std::string& study, | |
386 const std::string& series, | |
387 const std::string& instance) | |
388 { | |
389 return db_.CreateInstance(result, instanceId, patient, study, series, instance); | |
390 } | |
391 | |
392 void DeleteAttachment(int64_t id, | |
393 FileContentType attachment) | |
394 { | |
395 return db_.DeleteAttachment(id, attachment); | |
396 } | |
397 | |
398 void DeleteMetadata(int64_t id, | |
399 MetadataType type) | |
400 { | |
401 db_.DeleteMetadata(id, type); | |
402 } | |
403 | |
404 void DeleteResource(int64_t id) | |
405 { | |
406 db_.DeleteResource(id); | |
407 } | |
408 | |
409 void LogChange(int64_t internalId, | |
410 ChangeType changeType, | |
411 ResourceType resourceType, | |
412 const std::string& publicId); | |
413 | |
414 void LogExportedResource(const ExportedResource& resource) | |
415 { | |
416 db_.LogExportedResource(resource); | |
417 } | |
418 | |
419 void SetGlobalProperty(GlobalProperty property, | |
420 const std::string& value) | |
421 { | |
422 db_.SetGlobalProperty(property, value); | |
423 } | |
424 | |
425 void SetMetadata(int64_t id, | |
426 MetadataType type, | |
427 const std::string& value) | |
428 { | |
429 return db_.SetMetadata(id, type, value); | |
430 } | |
431 | |
432 void SetProtectedPatient(int64_t internalId, | |
433 bool isProtected) | |
434 { | |
435 db_.SetProtectedPatient(internalId, isProtected); | |
436 } | |
437 | |
438 void SetResourcesContent(const ResourcesContent& content) | |
439 { | |
440 db_.SetResourcesContent(content); | |
441 } | |
442 | |
443 void Recycle(uint64_t maximumStorageSize, | |
444 unsigned int maximumPatients, | |
445 uint64_t addedInstanceSize, | |
446 const std::string& newPatientId); | |
447 }; | |
448 | |
449 | |
450 class IReadOnlyOperations : public boost::noncopyable | |
451 { | |
452 public: | |
453 virtual ~IReadOnlyOperations() | |
454 { | |
455 } | |
456 | |
457 virtual void Apply(ReadOnlyTransaction& transaction) = 0; | |
458 }; | |
459 | |
460 | |
461 class IReadWriteOperations : public boost::noncopyable | |
462 { | |
463 public: | |
464 virtual ~IReadWriteOperations() | |
465 { | |
466 } | |
467 | |
468 virtual void Apply(ReadWriteTransaction& transaction) = 0; | |
469 }; | |
470 | |
471 private: | |
472 void ApplyInternal(IReadOnlyOperations* readOperations, | |
473 IReadWriteOperations* writeOperations); | |
474 | |
475 std::unique_ptr<ITransactionContextFactory> factory_; | |
476 unsigned int maxRetries_; | |
477 | |
478 public: | |
479 void SetTransactionContextFactory(ITransactionContextFactory* factory /* takes ownership */); | |
480 | |
481 void Apply(IReadOnlyOperations& operations); | |
482 | |
483 void Apply(IReadWriteOperations& operations); | |
484 | |
485 bool ExpandResource(Json::Value& target, | |
486 const std::string& publicId, | |
487 ResourceType level); | |
488 | |
489 void GetAllMetadata(std::map<MetadataType, std::string>& target, | |
490 const std::string& publicId, | |
491 ResourceType level); | |
492 | |
493 void GetAllUuids(std::list<std::string>& target, | |
494 ResourceType resourceType); | |
495 | |
496 void GetAllUuids(std::list<std::string>& target, | |
497 ResourceType resourceType, | |
498 size_t since, | |
499 size_t limit); | |
500 | |
501 void GetGlobalStatistics(/* out */ uint64_t& diskSize, | |
502 /* out */ uint64_t& uncompressedSize, | |
503 /* out */ uint64_t& countPatients, | |
504 /* out */ uint64_t& countStudies, | |
505 /* out */ uint64_t& countSeries, | |
506 /* out */ uint64_t& countInstances); | |
507 | |
508 bool LookupAttachment(FileInfo& attachment, | |
509 const std::string& instancePublicId, | |
510 FileContentType contentType); | |
511 | |
512 void GetChanges(Json::Value& target, | |
513 int64_t since, | |
514 unsigned int maxResults); | |
515 | |
516 void GetLastChange(Json::Value& target); | |
517 | |
518 void GetExportedResources(Json::Value& target, | |
519 int64_t since, | |
520 unsigned int maxResults); | |
521 | |
522 void GetLastExportedResource(Json::Value& target); | |
523 | |
524 bool IsProtectedPatient(const std::string& publicId); | |
525 | |
526 void GetChildren(std::list<std::string>& result, | |
527 const std::string& publicId); | |
528 | |
529 void GetChildInstances(std::list<std::string>& result, | |
530 const std::string& publicId); | |
531 | |
532 bool LookupMetadata(std::string& target, | |
533 const std::string& publicId, | |
534 ResourceType expectedType, | |
535 MetadataType type); | |
536 | |
537 void ListAvailableAttachments(std::set<FileContentType>& target, | |
538 const std::string& publicId, | |
539 ResourceType expectedType); | |
540 | |
541 bool LookupParent(std::string& target, | |
542 const std::string& publicId); | |
543 | |
544 void GetResourceStatistics(/* out */ ResourceType& type, | |
545 /* out */ uint64_t& diskSize, | |
546 /* out */ uint64_t& uncompressedSize, | |
547 /* out */ unsigned int& countStudies, | |
548 /* out */ unsigned int& countSeries, | |
549 /* out */ unsigned int& countInstances, | |
550 /* out */ uint64_t& dicomDiskSize, | |
551 /* out */ uint64_t& dicomUncompressedSize, | |
552 const std::string& publicId); | |
553 | |
554 void LookupIdentifierExact(std::vector<std::string>& result, | |
555 ResourceType level, | |
556 const DicomTag& tag, | |
557 const std::string& value); | |
558 | |
559 bool LookupGlobalProperty(std::string& value, | |
560 GlobalProperty property); | |
561 | |
562 std::string GetGlobalProperty(GlobalProperty property, | |
563 const std::string& defaultValue); | |
564 | |
565 bool GetMainDicomTags(DicomMap& result, | |
566 const std::string& publicId, | |
567 ResourceType expectedType, | |
568 ResourceType levelOfInterest); | |
569 | |
570 // Only applicable at the instance level | |
571 bool GetAllMainDicomTags(DicomMap& result, | |
572 const std::string& instancePublicId); | |
573 | |
574 bool LookupResourceType(ResourceType& type, | |
575 const std::string& publicId); | |
576 | |
577 bool LookupParent(std::string& target, | |
578 const std::string& publicId, | |
579 ResourceType parentType); | |
580 | |
581 void ApplyLookupResources(std::vector<std::string>& resourcesId, | |
582 std::vector<std::string>* instancesId, // Can be NULL if not needed | |
583 const DatabaseLookup& lookup, | |
584 ResourceType queryLevel, | |
585 size_t limit); | |
586 | |
587 bool DeleteResource(Json::Value& target /* out */, | |
588 const std::string& uuid, | |
589 ResourceType expectedType); | |
590 | |
591 void LogExportedResource(const std::string& publicId, | |
592 const std::string& remoteModality); | |
593 | |
594 void SetProtectedPatient(const std::string& publicId, | |
595 bool isProtected); | |
596 | |
597 void SetMetadata(const std::string& publicId, | |
598 MetadataType type, | |
599 const std::string& value); | |
600 | |
601 void DeleteMetadata(const std::string& publicId, | |
602 MetadataType type); | |
603 | |
604 uint64_t IncrementGlobalSequence(GlobalProperty sequence); | |
605 | |
606 void DeleteChanges(); | |
607 | |
608 void DeleteExportedResources(); | |
609 | |
610 void SetGlobalProperty(GlobalProperty property, | |
611 const std::string& value); | |
612 | |
613 void DeleteAttachment(const std::string& publicId, | |
614 FileContentType type); | |
615 | |
616 void LogChange(ChangeType changeType, | |
617 const std::string& publicId, | |
618 ResourceType level); | |
619 | |
620 void ReconstructInstance(const ParsedDicomFile& dicom); | |
621 | |
622 StoreStatus Store(std::map<MetadataType, std::string>& instanceMetadata, | 90 StoreStatus Store(std::map<MetadataType, std::string>& instanceMetadata, |
623 const DicomMap& dicomSummary, | 91 const DicomMap& dicomSummary, |
624 const Attachments& attachments, | 92 const Attachments& attachments, |
625 const MetadataMap& metadata, | 93 const MetadataMap& metadata, |
626 const DicomInstanceOrigin& origin, | 94 const DicomInstanceOrigin& origin, |