Mercurial > hg > orthanc
comparison OrthancServer/Sources/ServerContext.h @ 4044:d25f4c0fa160 framework
splitting code into OrthancFramework and OrthancServer
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Wed, 10 Jun 2020 20:30:34 +0200 |
parents | OrthancServer/ServerContext.h@e42f5445d20d |
children | 05b8fd21089c |
comparison
equal
deleted
inserted
replaced
4043:6c6239aec462 | 4044:d25f4c0fa160 |
---|---|
1 /** | |
2 * Orthanc - A Lightweight, RESTful DICOM Store | |
3 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics | |
4 * Department, University Hospital of Liege, Belgium | |
5 * Copyright (C) 2017-2020 Osimis S.A., Belgium | |
6 * | |
7 * This program is free software: you can redistribute it and/or | |
8 * modify it under the terms of the GNU General Public License as | |
9 * published by the Free Software Foundation, either version 3 of the | |
10 * License, or (at your option) any later version. | |
11 * | |
12 * In addition, as a special exception, the copyright holders of this | |
13 * program give permission to link the code of its release with the | |
14 * OpenSSL project's "OpenSSL" library (or with modified versions of it | |
15 * that use the same license as the "OpenSSL" library), and distribute | |
16 * the linked executables. You must obey the GNU General Public License | |
17 * in all respects for all of the code used other than "OpenSSL". If you | |
18 * modify file(s) with this exception, you may extend this exception to | |
19 * your version of the file(s), but you are not obligated to do so. If | |
20 * you do not wish to do so, delete this exception statement from your | |
21 * version. If you delete this exception statement from all source files | |
22 * in the program, then also delete it here. | |
23 * | |
24 * This program is distributed in the hope that it will be useful, but | |
25 * WITHOUT ANY WARRANTY; without even the implied warranty of | |
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
27 * General Public License for more details. | |
28 * | |
29 * You should have received a copy of the GNU General Public License | |
30 * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
31 **/ | |
32 | |
33 | |
34 #pragma once | |
35 | |
36 #include "IServerListener.h" | |
37 #include "LuaScripting.h" | |
38 #include "OrthancHttpHandler.h" | |
39 #include "ServerIndex.h" | |
40 #include "ServerJobs/IStorageCommitmentFactory.h" | |
41 | |
42 #include "../Core/Cache/MemoryCache.h" | |
43 #include "../Core/DicomParsing/IDicomTranscoder.h" | |
44 | |
45 | |
46 namespace Orthanc | |
47 { | |
48 class DicomInstanceToStore; | |
49 class IStorageArea; | |
50 class JobsEngine; | |
51 class MetricsRegistry; | |
52 class OrthancPlugins; | |
53 class ParsedDicomFile; | |
54 class RestApiOutput; | |
55 class SetOfInstancesJob; | |
56 class SharedArchive; | |
57 class SharedMessageQueue; | |
58 class StorageCommitmentReports; | |
59 | |
60 | |
61 /** | |
62 * This class is responsible for maintaining the storage area on the | |
63 * filesystem (including compression), as well as the index of the | |
64 * DICOM store. It implements the required locking mechanisms. | |
65 **/ | |
66 class ServerContext : | |
67 public IStorageCommitmentFactory, | |
68 public IDicomTranscoder, | |
69 private JobsRegistry::IObserver | |
70 { | |
71 public: | |
72 class ILookupVisitor : public boost::noncopyable | |
73 { | |
74 public: | |
75 virtual ~ILookupVisitor() | |
76 { | |
77 } | |
78 | |
79 virtual bool IsDicomAsJsonNeeded() const = 0; | |
80 | |
81 virtual void MarkAsComplete() = 0; | |
82 | |
83 virtual void Visit(const std::string& publicId, | |
84 const std::string& instanceId, | |
85 const DicomMap& mainDicomTags, | |
86 const Json::Value* dicomAsJson) = 0; | |
87 }; | |
88 | |
89 | |
90 private: | |
91 class LuaServerListener : public IServerListener | |
92 { | |
93 private: | |
94 ServerContext& context_; | |
95 | |
96 public: | |
97 LuaServerListener(ServerContext& context) : | |
98 context_(context) | |
99 { | |
100 } | |
101 | |
102 virtual void SignalStoredInstance(const std::string& publicId, | |
103 const DicomInstanceToStore& instance, | |
104 const Json::Value& simplifiedTags) | |
105 { | |
106 context_.mainLua_.SignalStoredInstance(publicId, instance, simplifiedTags); | |
107 } | |
108 | |
109 virtual void SignalChange(const ServerIndexChange& change) | |
110 { | |
111 context_.mainLua_.SignalChange(change); | |
112 } | |
113 | |
114 virtual bool FilterIncomingInstance(const DicomInstanceToStore& instance, | |
115 const Json::Value& simplified) | |
116 { | |
117 return context_.filterLua_.FilterIncomingInstance(instance, simplified); | |
118 } | |
119 }; | |
120 | |
121 class DicomCacheProvider : public Deprecated::ICachePageProvider // TODO | |
122 { | |
123 private: | |
124 ServerContext& context_; | |
125 | |
126 public: | |
127 DicomCacheProvider(ServerContext& context) : context_(context) | |
128 { | |
129 } | |
130 | |
131 virtual IDynamicObject* Provide(const std::string& id); | |
132 }; | |
133 | |
134 class ServerListener | |
135 { | |
136 private: | |
137 IServerListener *listener_; | |
138 std::string description_; | |
139 | |
140 public: | |
141 ServerListener(IServerListener& listener, | |
142 const std::string& description) : | |
143 listener_(&listener), | |
144 description_(description) | |
145 { | |
146 } | |
147 | |
148 IServerListener& GetListener() | |
149 { | |
150 return *listener_; | |
151 } | |
152 | |
153 const std::string& GetDescription() | |
154 { | |
155 return description_; | |
156 } | |
157 }; | |
158 | |
159 typedef std::list<ServerListener> ServerListeners; | |
160 | |
161 | |
162 static void ChangeThread(ServerContext* that, | |
163 unsigned int sleepDelay); | |
164 | |
165 static void SaveJobsThread(ServerContext* that, | |
166 unsigned int sleepDelay); | |
167 | |
168 void ReadDicomAsJsonInternal(std::string& result, | |
169 const std::string& instancePublicId); | |
170 | |
171 void SaveJobsEngine(); | |
172 | |
173 virtual void SignalJobSubmitted(const std::string& jobId) ORTHANC_OVERRIDE; | |
174 | |
175 virtual void SignalJobSuccess(const std::string& jobId) ORTHANC_OVERRIDE; | |
176 | |
177 virtual void SignalJobFailure(const std::string& jobId) ORTHANC_OVERRIDE; | |
178 | |
179 ServerIndex index_; | |
180 IStorageArea& area_; | |
181 | |
182 bool compressionEnabled_; | |
183 bool storeMD5_; | |
184 | |
185 DicomCacheProvider provider_; | |
186 boost::mutex dicomCacheMutex_; | |
187 Deprecated::MemoryCache dicomCache_; // TODO | |
188 | |
189 LuaScripting mainLua_; | |
190 LuaScripting filterLua_; | |
191 LuaServerListener luaListener_; | |
192 std::unique_ptr<SharedArchive> mediaArchive_; | |
193 | |
194 // The "JobsEngine" must be *after* "LuaScripting", as | |
195 // "LuaScripting" embeds "LuaJobManager" that registers as an | |
196 // observer to "SequenceOfOperationsJob", whose lifetime | |
197 // corresponds to that of "JobsEngine". It must also be after | |
198 // "mediaArchive_", as jobs might access this archive. | |
199 JobsEngine jobsEngine_; | |
200 | |
201 #if ORTHANC_ENABLE_PLUGINS == 1 | |
202 OrthancPlugins* plugins_; | |
203 #endif | |
204 | |
205 ServerListeners listeners_; | |
206 boost::shared_mutex listenersMutex_; | |
207 | |
208 bool done_; | |
209 bool haveJobsChanged_; | |
210 bool isJobsEngineUnserialized_; | |
211 SharedMessageQueue pendingChanges_; | |
212 boost::thread changeThread_; | |
213 boost::thread saveJobsThread_; | |
214 | |
215 std::unique_ptr<SharedArchive> queryRetrieveArchive_; | |
216 std::string defaultLocalAet_; | |
217 OrthancHttpHandler httpHandler_; | |
218 bool saveJobs_; | |
219 FindStorageAccessMode findStorageAccessMode_; | |
220 unsigned int limitFindInstances_; | |
221 unsigned int limitFindResults_; | |
222 | |
223 std::unique_ptr<MetricsRegistry> metricsRegistry_; | |
224 bool isHttpServerSecure_; | |
225 bool isExecuteLuaEnabled_; | |
226 bool overwriteInstances_; | |
227 | |
228 std::unique_ptr<StorageCommitmentReports> storageCommitmentReports_; | |
229 | |
230 bool transcodeDicomProtocol_; | |
231 std::unique_ptr<IDicomTranscoder> dcmtkTranscoder_; | |
232 BuiltinDecoderTranscoderOrder builtinDecoderTranscoderOrder_; | |
233 bool isIngestTranscoding_; | |
234 DicomTransferSyntax ingestTransferSyntax_; | |
235 | |
236 StoreStatus StoreAfterTranscoding(std::string& resultPublicId, | |
237 DicomInstanceToStore& dicom, | |
238 StoreInstanceMode mode); | |
239 | |
240 public: | |
241 class DicomCacheLocker : public boost::noncopyable | |
242 { | |
243 private: | |
244 ServerContext& that_; | |
245 ParsedDicomFile *dicom_; | |
246 boost::mutex::scoped_lock lock_; | |
247 | |
248 public: | |
249 DicomCacheLocker(ServerContext& that, | |
250 const std::string& instancePublicId); | |
251 | |
252 ~DicomCacheLocker(); | |
253 | |
254 ParsedDicomFile& GetDicom() | |
255 { | |
256 return *dicom_; | |
257 } | |
258 }; | |
259 | |
260 ServerContext(IDatabaseWrapper& database, | |
261 IStorageArea& area, | |
262 bool unitTesting, | |
263 size_t maxCompletedJobs); | |
264 | |
265 ~ServerContext(); | |
266 | |
267 void SetupJobsEngine(bool unitTesting, | |
268 bool loadJobsFromDatabase); | |
269 | |
270 ServerIndex& GetIndex() | |
271 { | |
272 return index_; | |
273 } | |
274 | |
275 void SetCompressionEnabled(bool enabled); | |
276 | |
277 bool IsCompressionEnabled() const | |
278 { | |
279 return compressionEnabled_; | |
280 } | |
281 | |
282 void RemoveFile(const std::string& fileUuid, | |
283 FileContentType type); | |
284 | |
285 bool AddAttachment(const std::string& resourceId, | |
286 FileContentType attachmentType, | |
287 const void* data, | |
288 size_t size); | |
289 | |
290 StoreStatus Store(std::string& resultPublicId, | |
291 DicomInstanceToStore& dicom, | |
292 StoreInstanceMode mode); | |
293 | |
294 void AnswerAttachment(RestApiOutput& output, | |
295 const std::string& resourceId, | |
296 FileContentType content); | |
297 | |
298 void ChangeAttachmentCompression(const std::string& resourceId, | |
299 FileContentType attachmentType, | |
300 CompressionType compression); | |
301 | |
302 void ReadDicomAsJson(std::string& result, | |
303 const std::string& instancePublicId, | |
304 const std::set<DicomTag>& ignoreTagLength); | |
305 | |
306 void ReadDicomAsJson(Json::Value& result, | |
307 const std::string& instancePublicId, | |
308 const std::set<DicomTag>& ignoreTagLength); | |
309 | |
310 void ReadDicomAsJson(std::string& result, | |
311 const std::string& instancePublicId) | |
312 { | |
313 std::set<DicomTag> ignoreTagLength; | |
314 ReadDicomAsJson(result, instancePublicId, ignoreTagLength); | |
315 } | |
316 | |
317 void ReadDicomAsJson(Json::Value& result, | |
318 const std::string& instancePublicId) | |
319 { | |
320 std::set<DicomTag> ignoreTagLength; | |
321 ReadDicomAsJson(result, instancePublicId, ignoreTagLength); | |
322 } | |
323 | |
324 void ReadDicom(std::string& dicom, | |
325 const std::string& instancePublicId) | |
326 { | |
327 ReadAttachment(dicom, instancePublicId, FileContentType_Dicom, true); | |
328 } | |
329 | |
330 // TODO CACHING MECHANISM AT THIS POINT | |
331 void ReadAttachment(std::string& result, | |
332 const std::string& instancePublicId, | |
333 FileContentType content, | |
334 bool uncompressIfNeeded); | |
335 | |
336 void ReadAttachment(std::string& result, | |
337 const FileInfo& attachment); | |
338 | |
339 void SetStoreMD5ForAttachments(bool storeMD5); | |
340 | |
341 bool IsStoreMD5ForAttachments() const | |
342 { | |
343 return storeMD5_; | |
344 } | |
345 | |
346 JobsEngine& GetJobsEngine() | |
347 { | |
348 return jobsEngine_; | |
349 } | |
350 | |
351 bool DeleteResource(Json::Value& target, | |
352 const std::string& uuid, | |
353 ResourceType expectedType); | |
354 | |
355 void SignalChange(const ServerIndexChange& change); | |
356 | |
357 SharedArchive& GetQueryRetrieveArchive() | |
358 { | |
359 return *queryRetrieveArchive_; | |
360 } | |
361 | |
362 SharedArchive& GetMediaArchive() | |
363 { | |
364 return *mediaArchive_; | |
365 } | |
366 | |
367 const std::string& GetDefaultLocalApplicationEntityTitle() const | |
368 { | |
369 return defaultLocalAet_; | |
370 } | |
371 | |
372 LuaScripting& GetLuaScripting() | |
373 { | |
374 return mainLua_; | |
375 } | |
376 | |
377 OrthancHttpHandler& GetHttpHandler() | |
378 { | |
379 return httpHandler_; | |
380 } | |
381 | |
382 void Stop(); | |
383 | |
384 void Apply(ILookupVisitor& visitor, | |
385 const DatabaseLookup& lookup, | |
386 ResourceType queryLevel, | |
387 size_t since, | |
388 size_t limit); | |
389 | |
390 bool LookupOrReconstructMetadata(std::string& target, | |
391 const std::string& publicId, | |
392 MetadataType type); | |
393 | |
394 | |
395 /** | |
396 * Management of the plugins | |
397 **/ | |
398 | |
399 #if ORTHANC_ENABLE_PLUGINS == 1 | |
400 void SetPlugins(OrthancPlugins& plugins); | |
401 | |
402 void ResetPlugins(); | |
403 | |
404 const OrthancPlugins& GetPlugins() const; | |
405 | |
406 OrthancPlugins& GetPlugins(); | |
407 #endif | |
408 | |
409 bool HasPlugins() const; | |
410 | |
411 void AddChildInstances(SetOfInstancesJob& job, | |
412 const std::string& publicId); | |
413 | |
414 void SignalUpdatedModalities(); | |
415 | |
416 void SignalUpdatedPeers(); | |
417 | |
418 MetricsRegistry& GetMetricsRegistry() | |
419 { | |
420 return *metricsRegistry_; | |
421 } | |
422 | |
423 void SetHttpServerSecure(bool isSecure) | |
424 { | |
425 isHttpServerSecure_ = isSecure; | |
426 } | |
427 | |
428 bool IsHttpServerSecure() const | |
429 { | |
430 return isHttpServerSecure_; | |
431 } | |
432 | |
433 void SetExecuteLuaEnabled(bool enabled) | |
434 { | |
435 isExecuteLuaEnabled_ = enabled; | |
436 } | |
437 | |
438 bool IsExecuteLuaEnabled() const | |
439 { | |
440 return isExecuteLuaEnabled_; | |
441 } | |
442 | |
443 void SetOverwriteInstances(bool overwrite) | |
444 { | |
445 overwriteInstances_ = overwrite; | |
446 } | |
447 | |
448 bool IsOverwriteInstances() const | |
449 { | |
450 return overwriteInstances_; | |
451 } | |
452 | |
453 virtual IStorageCommitmentFactory::ILookupHandler* | |
454 CreateStorageCommitment(const std::string& jobId, | |
455 const std::string& transactionUid, | |
456 const std::vector<std::string>& sopClassUids, | |
457 const std::vector<std::string>& sopInstanceUids, | |
458 const std::string& remoteAet, | |
459 const std::string& calledAet) ORTHANC_OVERRIDE; | |
460 | |
461 StorageCommitmentReports& GetStorageCommitmentReports() | |
462 { | |
463 return *storageCommitmentReports_; | |
464 } | |
465 | |
466 ImageAccessor* DecodeDicomFrame(const std::string& publicId, | |
467 unsigned int frameIndex); | |
468 | |
469 ImageAccessor* DecodeDicomFrame(const DicomInstanceToStore& dicom, | |
470 unsigned int frameIndex); | |
471 | |
472 ImageAccessor* DecodeDicomFrame(const void* dicom, | |
473 size_t size, | |
474 unsigned int frameIndex); | |
475 | |
476 void StoreWithTranscoding(std::string& sopClassUid, | |
477 std::string& sopInstanceUid, | |
478 DicomStoreUserConnection& connection, | |
479 const std::string& dicom, | |
480 bool hasMoveOriginator, | |
481 const std::string& moveOriginatorAet, | |
482 uint16_t moveOriginatorId); | |
483 | |
484 // This method can be used even if the global option | |
485 // "TranscodeDicomProtocol" is set to "false" | |
486 virtual bool Transcode(DicomImage& target, | |
487 DicomImage& source /* in, "GetParsed()" possibly modified */, | |
488 const std::set<DicomTransferSyntax>& allowedSyntaxes, | |
489 bool allowNewSopInstanceUid) ORTHANC_OVERRIDE; | |
490 | |
491 bool IsTranscodeDicomProtocol() const | |
492 { | |
493 return transcodeDicomProtocol_; | |
494 } | |
495 }; | |
496 } |