diff 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
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/OrthancServer/Sources/ServerContext.h	Wed Jun 10 20:30:34 2020 +0200
@@ -0,0 +1,496 @@
+/**
+ * Orthanc - A Lightweight, RESTful DICOM Store
+ * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
+ * Department, University Hospital of Liege, Belgium
+ * Copyright (C) 2017-2020 Osimis S.A., Belgium
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * In addition, as a special exception, the copyright holders of this
+ * program give permission to link the code of its release with the
+ * OpenSSL project's "OpenSSL" library (or with modified versions of it
+ * that use the same license as the "OpenSSL" library), and distribute
+ * the linked executables. You must obey the GNU General Public License
+ * in all respects for all of the code used other than "OpenSSL". If you
+ * modify file(s) with this exception, you may extend this exception to
+ * your version of the file(s), but you are not obligated to do so. If
+ * you do not wish to do so, delete this exception statement from your
+ * version. If you delete this exception statement from all source files
+ * in the program, then also delete it here.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+
+#pragma once
+
+#include "IServerListener.h"
+#include "LuaScripting.h"
+#include "OrthancHttpHandler.h"
+#include "ServerIndex.h"
+#include "ServerJobs/IStorageCommitmentFactory.h"
+
+#include "../Core/Cache/MemoryCache.h"
+#include "../Core/DicomParsing/IDicomTranscoder.h"
+
+
+namespace Orthanc
+{
+  class DicomInstanceToStore;
+  class IStorageArea;
+  class JobsEngine;
+  class MetricsRegistry;
+  class OrthancPlugins;
+  class ParsedDicomFile;
+  class RestApiOutput;
+  class SetOfInstancesJob;
+  class SharedArchive;
+  class SharedMessageQueue;
+  class StorageCommitmentReports;
+  
+  
+  /**
+   * This class is responsible for maintaining the storage area on the
+   * filesystem (including compression), as well as the index of the
+   * DICOM store. It implements the required locking mechanisms.
+   **/
+  class ServerContext :
+    public IStorageCommitmentFactory,
+    public IDicomTranscoder,
+    private JobsRegistry::IObserver
+  {
+  public:
+    class ILookupVisitor : public boost::noncopyable
+    {
+    public:
+      virtual ~ILookupVisitor()
+      {
+      }
+
+      virtual bool IsDicomAsJsonNeeded() const = 0;
+      
+      virtual void MarkAsComplete() = 0;
+
+      virtual void Visit(const std::string& publicId,
+                         const std::string& instanceId,
+                         const DicomMap& mainDicomTags,
+                         const Json::Value* dicomAsJson) = 0;
+    };
+    
+    
+  private:
+    class LuaServerListener : public IServerListener
+    {
+    private:
+      ServerContext& context_;
+
+    public:
+      LuaServerListener(ServerContext& context) :
+        context_(context)
+      {
+      }
+
+      virtual void SignalStoredInstance(const std::string& publicId,
+                                        const DicomInstanceToStore& instance,
+                                        const Json::Value& simplifiedTags)
+      {
+        context_.mainLua_.SignalStoredInstance(publicId, instance, simplifiedTags);
+      }
+    
+      virtual void SignalChange(const ServerIndexChange& change)
+      {
+        context_.mainLua_.SignalChange(change);
+      }
+
+      virtual bool FilterIncomingInstance(const DicomInstanceToStore& instance,
+                                          const Json::Value& simplified)
+      {
+        return context_.filterLua_.FilterIncomingInstance(instance, simplified);
+      }
+    };
+    
+    class DicomCacheProvider : public Deprecated::ICachePageProvider  // TODO
+    {
+    private:
+      ServerContext& context_;
+
+    public:
+      DicomCacheProvider(ServerContext& context) : context_(context)
+      {
+      }
+      
+      virtual IDynamicObject* Provide(const std::string& id);
+    };
+
+    class ServerListener
+    {
+    private:
+      IServerListener *listener_;
+      std::string      description_;
+
+    public:
+      ServerListener(IServerListener& listener,
+                     const std::string& description) :
+        listener_(&listener),
+        description_(description)
+      {
+      }
+
+      IServerListener& GetListener()
+      {
+        return *listener_;
+      }
+
+      const std::string& GetDescription()
+      {
+        return description_;
+      }
+    };
+
+    typedef std::list<ServerListener>  ServerListeners;
+
+
+    static void ChangeThread(ServerContext* that,
+                             unsigned int sleepDelay);
+
+    static void SaveJobsThread(ServerContext* that,
+                               unsigned int sleepDelay);
+
+    void ReadDicomAsJsonInternal(std::string& result,
+                                 const std::string& instancePublicId);
+
+    void SaveJobsEngine();
+
+    virtual void SignalJobSubmitted(const std::string& jobId) ORTHANC_OVERRIDE;
+
+    virtual void SignalJobSuccess(const std::string& jobId) ORTHANC_OVERRIDE;
+
+    virtual void SignalJobFailure(const std::string& jobId) ORTHANC_OVERRIDE;
+
+    ServerIndex index_;
+    IStorageArea& area_;
+
+    bool compressionEnabled_;
+    bool storeMD5_;
+    
+    DicomCacheProvider provider_;
+    boost::mutex dicomCacheMutex_;
+    Deprecated::MemoryCache dicomCache_;  // TODO
+
+    LuaScripting mainLua_;
+    LuaScripting filterLua_;
+    LuaServerListener  luaListener_;
+    std::unique_ptr<SharedArchive>  mediaArchive_;
+    
+    // The "JobsEngine" must be *after* "LuaScripting", as
+    // "LuaScripting" embeds "LuaJobManager" that registers as an
+    // observer to "SequenceOfOperationsJob", whose lifetime
+    // corresponds to that of "JobsEngine". It must also be after
+    // "mediaArchive_", as jobs might access this archive.
+    JobsEngine jobsEngine_;
+    
+#if ORTHANC_ENABLE_PLUGINS == 1
+    OrthancPlugins* plugins_;
+#endif
+
+    ServerListeners listeners_;
+    boost::shared_mutex listenersMutex_;
+
+    bool done_;
+    bool haveJobsChanged_;
+    bool isJobsEngineUnserialized_;
+    SharedMessageQueue  pendingChanges_;
+    boost::thread  changeThread_;
+    boost::thread  saveJobsThread_;
+        
+    std::unique_ptr<SharedArchive>  queryRetrieveArchive_;
+    std::string defaultLocalAet_;
+    OrthancHttpHandler  httpHandler_;
+    bool saveJobs_;
+    FindStorageAccessMode findStorageAccessMode_;
+    unsigned int limitFindInstances_;
+    unsigned int limitFindResults_;
+
+    std::unique_ptr<MetricsRegistry>  metricsRegistry_;
+    bool isHttpServerSecure_;
+    bool isExecuteLuaEnabled_;
+    bool overwriteInstances_;
+
+    std::unique_ptr<StorageCommitmentReports>  storageCommitmentReports_;
+
+    bool transcodeDicomProtocol_;
+    std::unique_ptr<IDicomTranscoder>  dcmtkTranscoder_;
+    BuiltinDecoderTranscoderOrder builtinDecoderTranscoderOrder_;
+    bool isIngestTranscoding_;
+    DicomTransferSyntax ingestTransferSyntax_;
+
+    StoreStatus StoreAfterTranscoding(std::string& resultPublicId,
+                                      DicomInstanceToStore& dicom,
+                                      StoreInstanceMode mode);
+
+  public:
+    class DicomCacheLocker : public boost::noncopyable
+    {
+    private:
+      ServerContext& that_;
+      ParsedDicomFile *dicom_;
+      boost::mutex::scoped_lock lock_;
+
+    public:
+      DicomCacheLocker(ServerContext& that,
+                       const std::string& instancePublicId);
+
+      ~DicomCacheLocker();
+
+      ParsedDicomFile& GetDicom()
+      {
+        return *dicom_;
+      }
+    };
+
+    ServerContext(IDatabaseWrapper& database,
+                  IStorageArea& area,
+                  bool unitTesting,
+                  size_t maxCompletedJobs);
+
+    ~ServerContext();
+
+    void SetupJobsEngine(bool unitTesting,
+                         bool loadJobsFromDatabase);
+
+    ServerIndex& GetIndex()
+    {
+      return index_;
+    }
+
+    void SetCompressionEnabled(bool enabled);
+
+    bool IsCompressionEnabled() const
+    {
+      return compressionEnabled_;
+    }
+
+    void RemoveFile(const std::string& fileUuid,
+                    FileContentType type);
+
+    bool AddAttachment(const std::string& resourceId,
+                       FileContentType attachmentType,
+                       const void* data,
+                       size_t size);
+
+    StoreStatus Store(std::string& resultPublicId,
+                      DicomInstanceToStore& dicom,
+                      StoreInstanceMode mode);
+
+    void AnswerAttachment(RestApiOutput& output,
+                          const std::string& resourceId,
+                          FileContentType content);
+
+    void ChangeAttachmentCompression(const std::string& resourceId,
+                                     FileContentType attachmentType,
+                                     CompressionType compression);
+
+    void ReadDicomAsJson(std::string& result,
+                         const std::string& instancePublicId,
+                         const std::set<DicomTag>& ignoreTagLength);
+
+    void ReadDicomAsJson(Json::Value& result,
+                         const std::string& instancePublicId,
+                         const std::set<DicomTag>& ignoreTagLength);
+
+    void ReadDicomAsJson(std::string& result,
+                         const std::string& instancePublicId)
+    {
+      std::set<DicomTag> ignoreTagLength;
+      ReadDicomAsJson(result, instancePublicId, ignoreTagLength);
+    }
+
+    void ReadDicomAsJson(Json::Value& result,
+                         const std::string& instancePublicId)
+    {
+      std::set<DicomTag> ignoreTagLength;
+      ReadDicomAsJson(result, instancePublicId, ignoreTagLength);
+    }
+
+    void ReadDicom(std::string& dicom,
+                   const std::string& instancePublicId)
+    {
+      ReadAttachment(dicom, instancePublicId, FileContentType_Dicom, true);
+    }
+    
+    // TODO CACHING MECHANISM AT THIS POINT
+    void ReadAttachment(std::string& result,
+                        const std::string& instancePublicId,
+                        FileContentType content,
+                        bool uncompressIfNeeded);
+    
+    void ReadAttachment(std::string& result,
+                        const FileInfo& attachment);
+
+    void SetStoreMD5ForAttachments(bool storeMD5);
+
+    bool IsStoreMD5ForAttachments() const
+    {
+      return storeMD5_;
+    }
+
+    JobsEngine& GetJobsEngine()
+    {
+      return jobsEngine_;
+    }
+
+    bool DeleteResource(Json::Value& target,
+                        const std::string& uuid,
+                        ResourceType expectedType);
+
+    void SignalChange(const ServerIndexChange& change);
+
+    SharedArchive& GetQueryRetrieveArchive()
+    {
+      return *queryRetrieveArchive_;
+    }
+
+    SharedArchive& GetMediaArchive()
+    {
+      return *mediaArchive_;
+    }
+
+    const std::string& GetDefaultLocalApplicationEntityTitle() const
+    {
+      return defaultLocalAet_;
+    }
+
+    LuaScripting& GetLuaScripting()
+    {
+      return mainLua_;
+    }
+
+    OrthancHttpHandler& GetHttpHandler()
+    {
+      return httpHandler_;
+    }
+
+    void Stop();
+
+    void Apply(ILookupVisitor& visitor,
+               const DatabaseLookup& lookup,
+               ResourceType queryLevel,
+               size_t since,
+               size_t limit);
+
+    bool LookupOrReconstructMetadata(std::string& target,
+                                     const std::string& publicId,
+                                     MetadataType type);
+
+
+    /**
+     * Management of the plugins
+     **/
+
+#if ORTHANC_ENABLE_PLUGINS == 1
+    void SetPlugins(OrthancPlugins& plugins);
+
+    void ResetPlugins();
+
+    const OrthancPlugins& GetPlugins() const;
+
+    OrthancPlugins& GetPlugins();
+#endif
+
+    bool HasPlugins() const;
+
+    void AddChildInstances(SetOfInstancesJob& job,
+                           const std::string& publicId);
+
+    void SignalUpdatedModalities();
+
+    void SignalUpdatedPeers();
+
+    MetricsRegistry& GetMetricsRegistry()
+    {
+      return *metricsRegistry_;
+    }
+
+    void SetHttpServerSecure(bool isSecure)
+    {
+      isHttpServerSecure_ = isSecure;
+    }
+
+    bool IsHttpServerSecure() const
+    {
+      return isHttpServerSecure_;
+    }
+
+    void SetExecuteLuaEnabled(bool enabled)
+    {
+      isExecuteLuaEnabled_ = enabled;
+    }
+
+    bool IsExecuteLuaEnabled() const
+    {
+      return isExecuteLuaEnabled_;
+    }
+
+    void SetOverwriteInstances(bool overwrite)
+    {
+      overwriteInstances_ = overwrite;
+    }
+    
+    bool IsOverwriteInstances() const
+    {
+      return overwriteInstances_;
+    }
+    
+    virtual IStorageCommitmentFactory::ILookupHandler*
+    CreateStorageCommitment(const std::string& jobId,
+                            const std::string& transactionUid,
+                            const std::vector<std::string>& sopClassUids,
+                            const std::vector<std::string>& sopInstanceUids,
+                            const std::string& remoteAet,
+                            const std::string& calledAet) ORTHANC_OVERRIDE;
+
+    StorageCommitmentReports& GetStorageCommitmentReports()
+    {
+      return *storageCommitmentReports_;
+    }
+
+    ImageAccessor* DecodeDicomFrame(const std::string& publicId,
+                                    unsigned int frameIndex);
+
+    ImageAccessor* DecodeDicomFrame(const DicomInstanceToStore& dicom,
+                                    unsigned int frameIndex);
+
+    ImageAccessor* DecodeDicomFrame(const void* dicom,
+                                    size_t size,
+                                    unsigned int frameIndex);
+    
+    void StoreWithTranscoding(std::string& sopClassUid,
+                              std::string& sopInstanceUid,
+                              DicomStoreUserConnection& connection,
+                              const std::string& dicom,
+                              bool hasMoveOriginator,
+                              const std::string& moveOriginatorAet,
+                              uint16_t moveOriginatorId);
+
+    // This method can be used even if the global option
+    // "TranscodeDicomProtocol" is set to "false"
+    virtual bool Transcode(DicomImage& target,
+                           DicomImage& source /* in, "GetParsed()" possibly modified */,
+                           const std::set<DicomTransferSyntax>& allowedSyntaxes,
+                           bool allowNewSopInstanceUid) ORTHANC_OVERRIDE;
+
+    bool IsTranscodeDicomProtocol() const
+    {
+      return transcodeDicomProtocol_;
+    }
+  };
+}