changeset 1609:c74495267acf

Implementation of the "GetAllPublicIdsWithLimit" extension
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 02 Sep 2015 15:07:47 +0200
parents adc6a5704cdb
children 2dff2bdffdb8
files Plugins/Engine/OrthancPluginDatabase.cpp Plugins/Engine/OrthancPluginDatabase.h Plugins/Engine/OrthancPlugins.cpp Plugins/Include/orthanc/OrthancCDatabasePlugin.h Plugins/Include/orthanc/OrthancCPlugin.h Plugins/Include/orthanc/OrthancCppDatabasePlugin.h
diffstat 6 files changed, 195 insertions(+), 26 deletions(-) [+]
line wrap: on
line diff
--- a/Plugins/Engine/OrthancPluginDatabase.cpp	Wed Sep 02 13:58:08 2015 +0200
+++ b/Plugins/Engine/OrthancPluginDatabase.cpp	Wed Sep 02 15:07:47 2015 +0200
@@ -187,6 +187,8 @@
 
 
   OrthancPluginDatabase::OrthancPluginDatabase(const OrthancPluginDatabaseBackend& backend,
+                                               const OrthancPluginDatabaseExtensions* extensions,
+                                               size_t extensionsSize,
                                                void *payload) : 
     type_(_OrthancPluginDatabaseAnswerType_None),
     backend_(backend),
@@ -197,6 +199,15 @@
     answerExportedResources_(NULL),
     answerDone_(NULL)
   {
+    memset(&extensions_, 0, sizeof(extensions_));
+
+    size_t size = sizeof(extensions_);
+    if (extensionsSize < size)
+    {
+      size = extensionsSize;  // Not all the extensions are available
+    }
+
+    memcpy(&extensions_, extensions, size);
   }
 
 
@@ -331,32 +342,47 @@
                                               size_t since,
                                               size_t limit)
   {
-    // TODO add the corresponding primitives to the SDK
-
-    target.clear();
-
-    if (limit == 0)
+    if (extensions_.getAllPublicIdsWithLimit != NULL)
     {
-      return;
-    }
+      // This extension is available since Orthanc 0.9.4
+      ResetAnswers();
+
+      if (extensions_.getAllPublicIdsWithLimit(GetContext(), payload_, Convert(resourceType), since, limit) != 0)
+      {
+        throw OrthancException(ErrorCode_Plugin);
+      }
 
-    std::list<std::string> tmp;
-    GetAllPublicIds(tmp, resourceType);
+      ForwardAnswers(target);
+    }
+    else
+    {
+      // The extension is not available in the database plugin, use a
+      // fallback implementation
+      target.clear();
+
+      if (limit == 0)
+      {
+        return;
+      }
+
+      std::list<std::string> tmp;
+      GetAllPublicIds(tmp, resourceType);
     
-    if (tmp.size() <= since)
-    {
-      // Not enough results => empty answer
-      return;
-    }
+      if (tmp.size() <= since)
+      {
+        // Not enough results => empty answer
+        return;
+      }
 
-    std::list<std::string>::iterator current = tmp.begin();
-    std::advance(current, since);
+      std::list<std::string>::iterator current = tmp.begin();
+      std::advance(current, since);
 
-    while (limit > 0 && current != tmp.end())
-    {
-      target.push_back(*current);
-      --limit;
-      ++current;
+      while (limit > 0 && current != tmp.end())
+      {
+        target.push_back(*current);
+        --limit;
+        ++current;
+      }
     }
   }
 
--- a/Plugins/Engine/OrthancPluginDatabase.h	Wed Sep 02 13:58:08 2015 +0200
+++ b/Plugins/Engine/OrthancPluginDatabase.h	Wed Sep 02 15:07:47 2015 +0200
@@ -46,6 +46,7 @@
 
     _OrthancPluginDatabaseAnswerType type_;
     OrthancPluginDatabaseBackend backend_;
+    OrthancPluginDatabaseExtensions extensions_;
     void* payload_;
     IDatabaseListener* listener_;
 
@@ -77,6 +78,8 @@
 
   public:
     OrthancPluginDatabase(const OrthancPluginDatabaseBackend& backend,
+                          const OrthancPluginDatabaseExtensions* extensions,
+                          size_t extensionsSize,
                           void *payload);
 
     virtual void AddAttachment(int64_t id,
--- a/Plugins/Engine/OrthancPlugins.cpp	Wed Sep 02 13:58:08 2015 +0200
+++ b/Plugins/Engine/OrthancPlugins.cpp	Wed Sep 02 15:07:47 2015 +0200
@@ -1409,10 +1409,24 @@
       case _OrthancPluginService_RegisterDatabaseBackend:
       {
         LOG(INFO) << "Plugin has registered a custom database back-end";
+
         const _OrthancPluginRegisterDatabaseBackend& p =
           *reinterpret_cast<const _OrthancPluginRegisterDatabaseBackend*>(parameters);
+        pimpl_->database_.reset(new OrthancPluginDatabase(*p.backend, NULL, 0, p.payload));
 
-        pimpl_->database_.reset(new OrthancPluginDatabase(*p.backend, p.payload));
+        *(p.result) = reinterpret_cast<OrthancPluginDatabaseContext*>(pimpl_->database_.get());
+
+        return true;
+      }
+
+      case _OrthancPluginService_RegisterDatabaseBackendV2:
+      {
+        LOG(INFO) << "Plugin has registered a custom database back-end";
+
+        const _OrthancPluginRegisterDatabaseBackendV2& p =
+          *reinterpret_cast<const _OrthancPluginRegisterDatabaseBackendV2*>(parameters);
+        pimpl_->database_.reset(new OrthancPluginDatabase(*p.backend, p.extensions, p.extensionsSize, p.payload));
+
         *(p.result) = reinterpret_cast<OrthancPluginDatabaseContext*>(pimpl_->database_.get());
 
         return true;
@@ -1528,8 +1542,15 @@
       case _OrthancPluginService_FreeImage:
       {
         const _OrthancPluginFreeImage& p = *reinterpret_cast<const _OrthancPluginFreeImage*>(parameters);
-        delete reinterpret_cast<ImageAccessor*>(p.image);
-        return true;
+        if (p.image == NULL)
+        {
+          throw OrthancException(ErrorCode_ParameterOutOfRange);
+        }
+        else
+        {
+          delete reinterpret_cast<ImageAccessor*>(p.image);
+          return true;
+        }
       }
 
       case _OrthancPluginService_UncompressImage:
--- a/Plugins/Include/orthanc/OrthancCDatabasePlugin.h	Wed Sep 02 13:58:08 2015 +0200
+++ b/Plugins/Include/orthanc/OrthancCDatabasePlugin.h	Wed Sep 02 15:07:47 2015 +0200
@@ -630,6 +630,21 @@
       void* payload);
 
   } OrthancPluginDatabaseBackend;
+
+
+  typedef struct
+  {
+    /* Output: Use OrthancPluginDatabaseAnswerString() */
+    int32_t  (*getAllPublicIdsWithLimit) (
+      /* outputs */
+      OrthancPluginDatabaseContext* context,
+      /* inputs */
+      void* payload,
+      OrthancPluginResourceType resourceType,
+      uint64_t since,
+      uint64_t limit);
+  } OrthancPluginDatabaseExtensions;
+
 /*<! @endcond */
 
 
@@ -653,6 +668,8 @@
    * @param payload Pointer containing private information for the database engine.
    * @return The context of the database engine (it must not be manually freed).
    * @ingroup Callbacks
+   * @deprecated
+   * @see OrthancPluginRegisterDatabaseBackendV2
    **/
   ORTHANC_PLUGIN_INLINE OrthancPluginDatabaseContext* OrthancPluginRegisterDatabaseBackend(
     OrthancPluginContext*                context,
@@ -685,6 +702,65 @@
   }
 
 
+  typedef struct
+  {
+    OrthancPluginDatabaseContext**          result;
+    const OrthancPluginDatabaseBackend*     backend;
+    void*                                   payload;
+    const OrthancPluginDatabaseExtensions*  extensions;
+    uint32_t                                extensionsSize;
+  } _OrthancPluginRegisterDatabaseBackendV2;
+
+
+  /**
+   * Register a custom database back-end.
+   *
+   * Instead of manually filling the OrthancPluginDatabaseBackendV2
+   * structure, you should instead implement a concrete C++ class
+   * deriving from ::OrthancPlugins::IDatabaseBackend, and register it
+   * using ::OrthancPlugins::DatabaseBackendAdapter::Register().
+   * 
+   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
+   * @param backend The callbacks of the custom database engine.
+   * @param payload Pointer containing private information for the database engine.
+   * @param extensions Extensions to the base database SDK that was shipped until Orthanc 0.9.3.
+   * @return The context of the database engine (it must not be manually freed).
+   * @ingroup Callbacks
+   **/
+  ORTHANC_PLUGIN_INLINE OrthancPluginDatabaseContext* OrthancPluginRegisterDatabaseBackendV2(
+    OrthancPluginContext*                   context,
+    const OrthancPluginDatabaseBackend*     backend,
+    const OrthancPluginDatabaseExtensions*  extensions,
+    void*                                   payload)
+  {
+    OrthancPluginDatabaseContext* result = NULL;
+    _OrthancPluginRegisterDatabaseBackendV2 params;
+
+    if (sizeof(int32_t) != sizeof(_OrthancPluginDatabaseAnswerType))
+    {
+      return NULL;
+    }
+
+    memset(&params, 0, sizeof(params));
+    params.backend = backend;
+    params.result = &result;
+    params.payload = payload;
+    params.extensions = extensions;
+    params.extensionsSize = sizeof(OrthancPluginDatabaseExtensions);
+
+    if (context->InvokeService(context, _OrthancPluginService_RegisterDatabaseBackendV2, &params) ||
+        result == NULL)
+    {
+      /* Error */
+      return NULL;
+    }
+    else
+    {
+      return result;
+    }
+  }
+
+
 #ifdef  __cplusplus
 }
 #endif
--- a/Plugins/Include/orthanc/OrthancCPlugin.h	Wed Sep 02 13:58:08 2015 +0200
+++ b/Plugins/Include/orthanc/OrthancCPlugin.h	Wed Sep 02 15:07:47 2015 +0200
@@ -17,7 +17,7 @@
  *    - Possibly register its callback for received DICOM instances using ::OrthancPluginRegisterOnStoredInstanceCallback().
  *    - Possibly register its callback for changes to the DICOM store using ::OrthancPluginRegisterOnChangeCallback().
  *    - Possibly register a custom storage area using ::OrthancPluginRegisterStorageArea().
- *    - Possibly register a custom database back-end area using OrthancPluginRegisterDatabaseBackend().
+ *    - Possibly register a custom database back-end area using OrthancPluginRegisterDatabaseBackendV2().
  * -# <tt>void OrthancPluginFinalize()</tt>:
  *    This function is invoked by Orthanc during its shutdown. The plugin
  *    must free all its memory.
@@ -427,6 +427,7 @@
     /* Services for plugins implementing a database back-end */
     _OrthancPluginService_RegisterDatabaseBackend = 5000,
     _OrthancPluginService_DatabaseAnswer = 5001,
+    _OrthancPluginService_RegisterDatabaseBackendV2 = 5002,
 
     /* Primitives for handling images */
     _OrthancPluginService_GetImagePixelFormat = 6000,
--- a/Plugins/Include/orthanc/OrthancCppDatabasePlugin.h	Wed Sep 02 13:58:08 2015 +0200
+++ b/Plugins/Include/orthanc/OrthancCppDatabasePlugin.h	Wed Sep 02 15:07:47 2015 +0200
@@ -314,6 +314,11 @@
     virtual void GetAllPublicIds(std::list<std::string>& target,
                                  OrthancPluginResourceType resourceType) = 0;
 
+    virtual void GetAllPublicIds(std::list<std::string>& target,
+                                 OrthancPluginResourceType resourceType,
+                                 uint64_t since,
+                                 uint64_t limit) = 0;
+
     /* Use GetOutput().AnswerChange() */
     virtual void GetChanges(bool& done /*out*/,
                             int64_t since,
@@ -639,6 +644,38 @@
     }
 
 
+    static int32_t  GetAllPublicIdsWithLimit(OrthancPluginDatabaseContext* context,
+                                             void* payload,
+                                             OrthancPluginResourceType resourceType,
+                                             uint64_t since,
+                                             uint64_t limit)
+    {
+      IDatabaseBackend* backend = reinterpret_cast<IDatabaseBackend*>(payload);
+      backend->GetOutput().SetAllowedAnswers(DatabaseBackendOutput::AllowedAnswers_None);
+
+      try
+      {
+        std::list<std::string> ids;
+        backend->GetAllPublicIds(ids, resourceType, since, limit);
+
+        for (std::list<std::string>::const_iterator
+               it = ids.begin(); it != ids.end(); ++it)
+        {
+          OrthancPluginDatabaseAnswerString(backend->GetOutput().context_,
+                                            backend->GetOutput().database_,
+                                            it->c_str());
+        }
+
+        return 0;
+      }
+      catch (std::runtime_error& e)
+      {
+        LogError(backend, e);
+        return -1;
+      }
+    }
+
+
     static int32_t  GetChanges(OrthancPluginDatabaseContext* context,
                                void* payload,
                                int64_t since,
@@ -1496,6 +1533,9 @@
       OrthancPluginDatabaseBackend  params;
       memset(&params, 0, sizeof(params));
 
+      OrthancPluginDatabaseExtensions  extensions;
+      memset(&extensions, 0, sizeof(extensions));
+
       params.addAttachment = AddAttachment;
       params.attachChild = AttachChild;
       params.clearChanges = ClearChanges;
@@ -1543,7 +1583,9 @@
       params.open = Open;
       params.close = Close;
 
-      OrthancPluginDatabaseContext* database = OrthancPluginRegisterDatabaseBackend(context, &params, &backend);
+      extensions.getAllPublicIdsWithLimit = GetAllPublicIdsWithLimit;
+
+      OrthancPluginDatabaseContext* database = OrthancPluginRegisterDatabaseBackendV2(context, &params, &extensions, &backend);
       if (!context)
       {
         throw std::runtime_error("Unable to register the database backend");