changeset 3105:2e1711f80f74 db-changes

More consistent handling of the "Last" field returned by the "/changes" URI
author Sebastien Jodogne <s.jodogne@gmail.com>
date Thu, 10 Jan 2019 18:02:34 +0100
parents b2b6db5ad9a5
children 897d539ae0e9
files NEWS OrthancServer/Database/IDatabaseWrapper.h OrthancServer/Database/SQLiteDatabaseWrapper.cpp OrthancServer/Database/SQLiteDatabaseWrapper.h OrthancServer/ServerIndex.cpp Plugins/Engine/OrthancPluginDatabase.cpp Plugins/Engine/OrthancPluginDatabase.h Plugins/Include/orthanc/OrthancCDatabasePlugin.h
diffstat 8 files changed, 101 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/NEWS	Mon Jan 07 17:23:04 2019 +0100
+++ b/NEWS	Thu Jan 10 18:02:34 2019 +0100
@@ -1,6 +1,16 @@
 Pending changes in the mainline
 ===============================
 
+REST API
+--------
+
+* More consistent handling of the "Last" field returned by the "/changes" URI
+
+Plugins
+-------
+
+* New primitives to speed up databases (custom index plugins)
+
 Maintenance
 -----------
 
--- a/OrthancServer/Database/IDatabaseWrapper.h	Mon Jan 07 17:23:04 2019 +0100
+++ b/OrthancServer/Database/IDatabaseWrapper.h	Thu Jan 10 18:02:34 2019 +0100
@@ -240,5 +240,7 @@
     virtual void GetChildrenMetadata(std::list<std::string>& target,
                                      int64_t resourceId,
                                      MetadataType metadata) = 0;
+
+    virtual int64_t GetLastChangeIndex() = 0;
   };
 }
--- a/OrthancServer/Database/SQLiteDatabaseWrapper.cpp	Mon Jan 07 17:23:04 2019 +0100
+++ b/OrthancServer/Database/SQLiteDatabaseWrapper.cpp	Thu Jan 10 18:02:34 2019 +0100
@@ -1270,4 +1270,23 @@
       }
     }
   }
+
+
+  int64_t SQLiteDatabaseWrapper::GetLastChangeIndex()
+  {
+    SQLite::Statement s(db_, SQLITE_FROM_HERE, 
+                        "SELECT seq FROM sqlite_sequence WHERE name='Changes'");
+
+    if (s.Step())
+    {
+      int64_t c = s.ColumnInt(0);
+      assert(!s.Step());
+      return c;
+    }
+    else
+    {
+      // No change has been recorded so far in the database
+      return 0;
+    }
+  }
 }
--- a/OrthancServer/Database/SQLiteDatabaseWrapper.h	Mon Jan 07 17:23:04 2019 +0100
+++ b/OrthancServer/Database/SQLiteDatabaseWrapper.h	Thu Jan 10 18:02:34 2019 +0100
@@ -353,5 +353,7 @@
     {
       IGetChildrenMetadata::Apply(*this, target, resourceId, metadata);
     }
+
+    virtual int64_t GetLastChangeIndex() ORTHANC_OVERRIDE;
   };
 }
--- a/OrthancServer/ServerIndex.cpp	Mon Jan 07 17:23:04 2019 +0100
+++ b/OrthancServer/ServerIndex.cpp	Thu Jan 10 18:02:34 2019 +0100
@@ -1308,7 +1308,9 @@
                         const std::list<T>& log,
                         const std::string& name,
                         bool done,
-                        int64_t since)
+                        int64_t since,
+                        bool hasLast,
+                        int64_t last)
   {
     Json::Value items = Json::arrayValue;
     for (typename std::list<T>::const_iterator
@@ -1323,7 +1325,19 @@
     target[name] = items;
     target["Done"] = done;
 
-    int64_t last = (log.empty() ? since : log.back().GetSeq());
+    if (!hasLast)
+    {
+      // Best-effort guess of the last index in the sequence
+      if (log.empty())
+      {
+        last = since;
+      }
+      else
+      {
+        last = log.back().GetSeq();
+      }
+    }
+    
     target["Last"] = static_cast<int>(last);
   }
 
@@ -1334,6 +1348,8 @@
   {
     std::list<ServerIndexChange> changes;
     bool done;
+    bool hasLast = false;
+    int64_t last = 0;
 
     {
       boost::mutex::scoped_lock lock(mutex_);
@@ -1341,17 +1357,26 @@
       // Fix wrt. Orthanc <= 1.3.2: A transaction was missing, as
       // "GetLastChange()" involves calls to "GetPublicId()"
       Transaction transaction(*this);
+
       db_.GetChanges(changes, done, since, maxResults);
+      if (changes.empty())
+      {
+        last = db_.GetLastChangeIndex();
+        hasLast = true;
+      }
+      
       transaction.Commit(0);
     }
 
-    FormatLog(target, changes, "Changes", done, since);
+    FormatLog(target, changes, "Changes", done, since, hasLast, last);
   }
 
 
   void ServerIndex::GetLastChange(Json::Value& target)
   {
     std::list<ServerIndexChange> changes;
+    bool hasLast = false;
+    int64_t last = 0;
 
     {
       boost::mutex::scoped_lock lock(mutex_);
@@ -1359,11 +1384,18 @@
       // Fix wrt. Orthanc <= 1.3.2: A transaction was missing, as
       // "GetLastChange()" involves calls to "GetPublicId()"
       Transaction transaction(*this);
+
       db_.GetLastChange(changes);
+      if (changes.empty())
+      {
+        last = db_.GetLastChangeIndex();
+        hasLast = true;
+      }
+
       transaction.Commit(0);
     }
 
-    FormatLog(target, changes, "Changes", true, 0);
+    FormatLog(target, changes, "Changes", true, 0, hasLast, last);
   }
 
 
@@ -1469,7 +1501,7 @@
       db_.GetExportedResources(exported, done, since, maxResults);
     }
 
-    FormatLog(target, exported, "Exports", done, since);
+    FormatLog(target, exported, "Exports", done, since, false, -1);
   }
 
 
@@ -1482,7 +1514,7 @@
       db_.GetLastExportedResource(exported);
     }
 
-    FormatLog(target, exported, "Exports", true, 0);
+    FormatLog(target, exported, "Exports", true, 0, false, -1);
   }
 
 
--- a/Plugins/Engine/OrthancPluginDatabase.cpp	Mon Jan 07 17:23:04 2019 +0100
+++ b/Plugins/Engine/OrthancPluginDatabase.cpp	Thu Jan 10 18:02:34 2019 +0100
@@ -278,6 +278,11 @@
     {
       LOG(WARNING) << "Performance warning in the database index: Some extensions are missing in the plugin";
     }
+
+    if (extensions_.getLastChangeIndex == NULL)
+    {
+      LOG(WARNING) << "The database extension GetLastChangeIndex() is missing";
+    }
   }
 
 
@@ -1392,4 +1397,21 @@
       ForwardAnswers(target);
     }
   }
+
+
+  int64_t OrthancPluginDatabase::GetLastChangeIndex()
+  {
+    if (extensions_.getLastChangeIndex == NULL)
+    {
+      // This was the default behavior in Orthanc <= 1.5.1
+      // https://groups.google.com/d/msg/orthanc-users/QhzB6vxYeZ0/YxabgqpfBAAJ
+      return 0;
+    }
+    else
+    {
+      int64_t result = 0;
+      CheckSuccess(extensions_.getLastChangeIndex(&result, payload_));
+      return result;
+    }
+  }
 }
--- a/Plugins/Engine/OrthancPluginDatabase.h	Mon Jan 07 17:23:04 2019 +0100
+++ b/Plugins/Engine/OrthancPluginDatabase.h	Thu Jan 10 18:02:34 2019 +0100
@@ -360,6 +360,8 @@
                                      int64_t resourceId,
                                      MetadataType metadata)
       ORTHANC_OVERRIDE;
+
+    virtual int64_t GetLastChangeIndex() ORTHANC_OVERRIDE;
   };
 }
 
--- a/Plugins/Include/orthanc/OrthancCDatabasePlugin.h	Mon Jan 07 17:23:04 2019 +0100
+++ b/Plugins/Include/orthanc/OrthancCDatabasePlugin.h	Thu Jan 10 18:02:34 2019 +0100
@@ -814,6 +814,12 @@
       int64_t resourceId,
       int32_t metadata);
 
+    OrthancPluginErrorCode  (*getLastChangeIndex) (
+      /* outputs */
+      int64_t* target,
+      /* inputs */
+      void* payload);
+                   
   } OrthancPluginDatabaseExtensions;
 
 /*<! @endcond */