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,