changeset 1672:4c5a85c3ff43 db-changes

sample database plugin now working
author Sebastien Jodogne <s.jodogne@gmail.com>
date Fri, 02 Oct 2015 12:20:49 +0200
parents 2f2e2ec17bc4
children 0bbcfd9695e5
files Core/SQLite/Connection.h OrthancServer/DatabaseWrapper.cpp OrthancServer/DatabaseWrapper.h OrthancServer/DatabaseWrapperBase.h OrthancServer/IDatabaseWrapper.h OrthancServer/main.cpp Plugins/Engine/OrthancPluginDatabase.cpp Plugins/Engine/OrthancPluginDatabase.h Plugins/Engine/PluginsManager.cpp Plugins/Samples/DatabasePlugin/Database.cpp UnitTestsSources/ServerIndexTests.cpp
diffstat 11 files changed, 187 insertions(+), 449 deletions(-) [+]
line wrap: on
line diff
--- a/Core/SQLite/Connection.h	Thu Oct 01 17:44:43 2015 +0200
+++ b/Core/SQLite/Connection.h	Fri Oct 02 12:20:49 2015 +0200
@@ -46,7 +46,7 @@
 struct sqlite3;
 struct sqlite3_stmt;
 
-#define SQLITE_FROM_HERE SQLite::StatementId(__FILE__, __LINE__)
+#define SQLITE_FROM_HERE ::Orthanc::SQLite::StatementId(__FILE__, __LINE__)
 
 namespace Orthanc
 {
--- a/OrthancServer/DatabaseWrapper.cpp	Thu Oct 01 17:44:43 2015 +0200
+++ b/OrthancServer/DatabaseWrapper.cpp	Fri Oct 02 12:20:49 2015 +0200
@@ -259,13 +259,11 @@
   DatabaseWrapper::DatabaseWrapper(const std::string& path) : listener_(NULL), base_(db_)
   {
     db_.Open(path);
-    Open();
   }
 
   DatabaseWrapper::DatabaseWrapper() : listener_(NULL), base_(db_)
   {
     db_.OpenInMemory();
-    Open();
   }
 
   void DatabaseWrapper::Open()
--- a/OrthancServer/DatabaseWrapper.h	Thu Oct 01 17:44:43 2015 +0200
+++ b/OrthancServer/DatabaseWrapper.h	Fri Oct 02 12:20:49 2015 +0200
@@ -59,8 +59,6 @@
     Internals::SignalRemainingAncestor* signalRemainingAncestor_;
     unsigned int version_;
 
-    void Open();
-
     void ClearTable(const std::string& tableName);
 
   public:
@@ -68,6 +66,13 @@
 
     DatabaseWrapper();
 
+    virtual void Open();
+
+    virtual void Close()
+    {
+      db_.Close();
+    }
+
     virtual void SetListener(IDatabaseListener& listener);
 
     virtual void SetGlobalProperty(GlobalProperty property,
--- a/OrthancServer/DatabaseWrapperBase.h	Thu Oct 01 17:44:43 2015 +0200
+++ b/OrthancServer/DatabaseWrapperBase.h	Fri Oct 02 12:20:49 2015 +0200
@@ -46,6 +46,11 @@
 
 namespace Orthanc
 {
+  /**
+   * This class is shared between the Orthanc core and the sample
+   * database plugin whose code is in
+   * "../Plugins/Samples/DatabasePlugin".
+   **/
   class DatabaseWrapperBase
   {
   private:
--- a/OrthancServer/IDatabaseWrapper.h	Thu Oct 01 17:44:43 2015 +0200
+++ b/OrthancServer/IDatabaseWrapper.h	Fri Oct 02 12:20:49 2015 +0200
@@ -51,6 +51,10 @@
     {
     }
 
+    virtual void Open() = 0;
+
+    virtual void Close() = 0;
+
     virtual void AddAttachment(int64_t id,
                                const FileInfo& attachment) = 0;
 
--- a/OrthancServer/main.cpp	Thu Oct 01 17:44:43 2015 +0200
+++ b/OrthancServer/main.cpp	Fri Oct 02 12:20:49 2015 +0200
@@ -657,14 +657,8 @@
 
 static bool ConfigureServerContext(IDatabaseWrapper& database,
                                    IStorageArea& storageArea,
-                                   OrthancPlugins *plugins,
-                                   bool allowDatabaseUpgrade)
+                                   OrthancPlugins *plugins)
 {
-  if (!UpgradeDatabase(database, storageArea, allowDatabaseUpgrade))
-  {
-    return false;
-  }
-
   ServerContext context(database, storageArea);
 
   HttpClient::SetDefaultTimeout(Configuration::GetGlobalIntegerParameter("HttpTimeout", 0));
@@ -714,6 +708,26 @@
 }
 
 
+static bool ConfigureDatabase(IDatabaseWrapper& database,
+                              IStorageArea& storageArea,
+                              OrthancPlugins *plugins,
+                              bool allowDatabaseUpgrade)
+{
+  database.Open();
+  
+  if (!UpgradeDatabase(database, storageArea, allowDatabaseUpgrade))
+  {
+    return false;
+  }
+
+  bool success = ConfigureServerContext(database, storageArea, plugins);
+
+  database.Close();
+
+  return success;
+}
+
+
 static bool ConfigurePlugins(int argc, 
                              char* argv[],
                              bool allowDatabaseUpgrade)
@@ -751,14 +765,14 @@
   assert(database != NULL);
   assert(storage.get() != NULL);
 
-  return ConfigureServerContext(*database, *storage, &plugins, allowDatabaseUpgrade);
+  return ConfigureDatabase(*database, *storage, &plugins, allowDatabaseUpgrade);
 
 #elif ORTHANC_PLUGINS_ENABLED == 0
   // The plugins are disabled
   databasePtr.reset(Configuration::CreateDatabaseWrapper());
   storage.reset(Configuration::CreateStorageArea());
 
-  return ConfigureServerContext(*databasePtr, *storage, NULL, allowDatabaseUpgrade);
+  return ConfigureDatabase(*databasePtr, *storage, NULL, allowDatabaseUpgrade);
 
 #else
 #  error The macro ORTHANC_PLUGINS_ENABLED must be set to 0 or 1
--- a/Plugins/Engine/OrthancPluginDatabase.cpp	Thu Oct 01 17:44:43 2015 +0200
+++ b/Plugins/Engine/OrthancPluginDatabase.cpp	Fri Oct 02 12:20:49 2015 +0200
@@ -46,50 +46,6 @@
 
 namespace Orthanc
 {
-  static OrthancPluginResourceType Convert(ResourceType type)
-  {
-    switch (type)
-    {
-      case ResourceType_Patient:
-        return OrthancPluginResourceType_Patient;
-
-      case ResourceType_Study:
-        return OrthancPluginResourceType_Study;
-
-      case ResourceType_Series:
-        return OrthancPluginResourceType_Series;
-
-      case ResourceType_Instance:
-        return OrthancPluginResourceType_Instance;
-
-      default:
-        throw OrthancException(ErrorCode_InternalError);
-    }
-  }
-
-
-  static ResourceType Convert(OrthancPluginResourceType type)
-  {
-    switch (type)
-    {
-      case OrthancPluginResourceType_Patient:
-        return ResourceType_Patient;
-
-      case OrthancPluginResourceType_Study:
-        return ResourceType_Study;
-
-      case OrthancPluginResourceType_Series:
-        return ResourceType_Series;
-
-      case OrthancPluginResourceType_Instance:
-        return ResourceType_Instance;
-
-      default:
-        throw OrthancException(ErrorCode_InternalError);
-    }
-  }
-
-
   static FileInfo Convert(const OrthancPluginAttachment& attachment)
   {
     return FileInfo(attachment.uuid,
@@ -102,6 +58,16 @@
   }
 
 
+  void OrthancPluginDatabase::CheckSuccess(OrthancPluginErrorCode code)
+  {
+    if (code != OrthancPluginErrorCode_Success)
+    {
+      errorDictionary_.LogError(code, true);
+      throw OrthancException(static_cast<ErrorCode>(code));
+    }
+  }
+
+
   void OrthancPluginDatabase::ResetAnswers()
   {
     type_ = _OrthancPluginDatabaseAnswerType_None;
@@ -234,50 +200,26 @@
     tmp.compressedSize = attachment.GetCompressedSize();
     tmp.compressedHash = attachment.GetCompressedMD5().c_str();
 
-    OrthancPluginErrorCode error = backend_.addAttachment(payload_, id, &tmp);
-
-    if (error != OrthancPluginErrorCode_Success)
-    {
-      errorDictionary_.LogError(error, true);
-      throw OrthancException(static_cast<ErrorCode>(error));
-    }
+    CheckSuccess(backend_.addAttachment(payload_, id, &tmp));
   }
 
 
   void OrthancPluginDatabase::AttachChild(int64_t parent,
                                           int64_t child)
   {
-    OrthancPluginErrorCode error = backend_.attachChild(payload_, parent, child);
-
-    if (error != OrthancPluginErrorCode_Success)
-    {
-      errorDictionary_.LogError(error, true);
-      throw OrthancException(static_cast<ErrorCode>(error));
-    }
+    CheckSuccess(backend_.attachChild(payload_, parent, child));
   }
 
 
   void OrthancPluginDatabase::ClearChanges()
   {
-    OrthancPluginErrorCode error = backend_.clearChanges(payload_);
-
-    if (error != OrthancPluginErrorCode_Success)
-    {
-      errorDictionary_.LogError(error, true);
-      throw OrthancException(static_cast<ErrorCode>(error));
-    }
+    CheckSuccess(backend_.clearChanges(payload_));
   }
 
 
   void OrthancPluginDatabase::ClearExportedResources()
   {
-    OrthancPluginErrorCode error = backend_.clearExportedResources(payload_);
-
-    if (error != OrthancPluginErrorCode_Success)
-    {
-      errorDictionary_.LogError(error, true);
-      throw OrthancException(static_cast<ErrorCode>(error));
-    }
+    CheckSuccess(backend_.clearExportedResources(payload_));
   }
 
 
@@ -285,15 +227,7 @@
                                                 ResourceType type)
   {
     int64_t id;
-
-    OrthancPluginErrorCode error = backend_.createResource(&id, payload_, publicId.c_str(), Convert(type));
-
-    if (error != OrthancPluginErrorCode_Success)
-    {
-      errorDictionary_.LogError(error, true);
-      throw OrthancException(static_cast<ErrorCode>(error));
-    }
-
+    CheckSuccess(backend_.createResource(&id, payload_, publicId.c_str(), Plugins::Convert(type)));
     return id;
   }
 
@@ -301,38 +235,20 @@
   void OrthancPluginDatabase::DeleteAttachment(int64_t id,
                                                FileContentType attachment)
   {
-    OrthancPluginErrorCode error = backend_.deleteAttachment(payload_, id, static_cast<int32_t>(attachment));
-
-    if (error != OrthancPluginErrorCode_Success)
-    {
-      errorDictionary_.LogError(error, true);
-      throw OrthancException(static_cast<ErrorCode>(error));
-    }
+    CheckSuccess(backend_.deleteAttachment(payload_, id, static_cast<int32_t>(attachment)));
   }
 
 
   void OrthancPluginDatabase::DeleteMetadata(int64_t id,
                                              MetadataType type)
   {
-    OrthancPluginErrorCode error = backend_.deleteMetadata(payload_, id, static_cast<int32_t>(type));
-
-    if (error != OrthancPluginErrorCode_Success)
-    {
-      errorDictionary_.LogError(error, true);
-      throw OrthancException(static_cast<ErrorCode>(error));
-    }
+    CheckSuccess(backend_.deleteMetadata(payload_, id, static_cast<int32_t>(type)));
   }
 
 
   void OrthancPluginDatabase::DeleteResource(int64_t id)
   {
-    OrthancPluginErrorCode error = backend_.deleteResource(payload_, id);
-
-    if (error != OrthancPluginErrorCode_Success)
-    {
-      errorDictionary_.LogError(error, true);
-      throw OrthancException(static_cast<ErrorCode>(error));
-    }
+    CheckSuccess(backend_.deleteResource(payload_, id));
   }
 
 
@@ -362,15 +278,7 @@
                                               ResourceType resourceType)
   {
     ResetAnswers();
-
-    OrthancPluginErrorCode error = backend_.getAllPublicIds(GetContext(), payload_, Convert(resourceType));
-
-    if (error != OrthancPluginErrorCode_Success)
-    {
-      errorDictionary_.LogError(error, true);
-      throw OrthancException(static_cast<ErrorCode>(error));
-    }
-
+    CheckSuccess(backend_.getAllPublicIds(GetContext(), payload_, Plugins::Convert(resourceType)));
     ForwardAnswers(target);
   }
 
@@ -384,16 +292,8 @@
     {
       // This extension is available since Orthanc 0.9.4
       ResetAnswers();
-
-      OrthancPluginErrorCode error = extensions_.getAllPublicIdsWithLimit
-        (GetContext(), payload_, Convert(resourceType), since, limit);
-
-      if (error != OrthancPluginErrorCode_Success)
-      {
-        errorDictionary_.LogError(error, true);
-        throw OrthancException(static_cast<ErrorCode>(error));
-      }
-
+      CheckSuccess(extensions_.getAllPublicIdsWithLimit
+                   (GetContext(), payload_, Plugins::Convert(resourceType), since, limit));
       ForwardAnswers(target);
     }
     else
@@ -440,13 +340,7 @@
     answerDone_ = &done;
     done = false;
 
-    OrthancPluginErrorCode error = backend_.getChanges(GetContext(), payload_, since, maxResults);
-
-    if (error != OrthancPluginErrorCode_Success)
-    {
-      errorDictionary_.LogError(error, true);
-      throw OrthancException(static_cast<ErrorCode>(error));
-    }
+    CheckSuccess(backend_.getChanges(GetContext(), payload_, since, maxResults));
   }
 
 
@@ -454,15 +348,7 @@
                                                     int64_t id)
   {
     ResetAnswers();
-
-    OrthancPluginErrorCode error = backend_.getChildrenInternalId(GetContext(), payload_, id);
-
-    if (error != OrthancPluginErrorCode_Success)
-    {
-      errorDictionary_.LogError(error, true);
-      throw OrthancException(static_cast<ErrorCode>(error));
-    }
-
+    CheckSuccess(backend_.getChildrenInternalId(GetContext(), payload_, id));
     ForwardAnswers(target);
   }
 
@@ -471,15 +357,7 @@
                                                   int64_t id)
   {
     ResetAnswers();
-
-    OrthancPluginErrorCode error = backend_.getChildrenPublicId(GetContext(), payload_, id);
-
-    if (error != OrthancPluginErrorCode_Success)
-    {
-      errorDictionary_.LogError(error, true);
-      throw OrthancException(static_cast<ErrorCode>(error));
-    }
-
+    CheckSuccess(backend_.getChildrenPublicId(GetContext(), payload_, id));
     ForwardAnswers(target);
   }
 
@@ -494,13 +372,7 @@
     answerDone_ = &done;
     done = false;
 
-    OrthancPluginErrorCode error = backend_.getExportedResources(GetContext(), payload_, since, maxResults);
-
-    if (error != OrthancPluginErrorCode_Success)
-    {
-      errorDictionary_.LogError(error, true);
-      throw OrthancException(static_cast<ErrorCode>(error));
-    }
+    CheckSuccess(backend_.getExportedResources(GetContext(), payload_, since, maxResults));
   }
 
 
@@ -512,13 +384,7 @@
     answerChanges_ = &target;
     answerDone_ = &ignored;
 
-    OrthancPluginErrorCode error = backend_.getLastChange(GetContext(), payload_);
-
-    if (error != OrthancPluginErrorCode_Success)
-    {
-      errorDictionary_.LogError(error, true);
-      throw OrthancException(static_cast<ErrorCode>(error));
-    }
+    CheckSuccess(backend_.getLastChange(GetContext(), payload_));
   }
 
 
@@ -530,13 +396,7 @@
     answerExportedResources_ = &target;
     answerDone_ = &ignored;
 
-    OrthancPluginErrorCode error = backend_.getLastExportedResource(GetContext(), payload_);
-
-    if (error != OrthancPluginErrorCode_Success)
-    {
-      errorDictionary_.LogError(error, true);
-      throw OrthancException(static_cast<ErrorCode>(error));
-    }
+    CheckSuccess(backend_.getLastExportedResource(GetContext(), payload_));
   }
 
 
@@ -546,13 +406,7 @@
     ResetAnswers();
     answerDicomMap_ = &map;
 
-    OrthancPluginErrorCode error = backend_.getMainDicomTags(GetContext(), payload_, id);
-
-    if (error != OrthancPluginErrorCode_Success)
-    {
-      errorDictionary_.LogError(error, true);
-      throw OrthancException(static_cast<ErrorCode>(error));
-    }
+    CheckSuccess(backend_.getMainDicomTags(GetContext(), payload_, id));
   }
 
 
@@ -561,14 +415,8 @@
     ResetAnswers();
     std::string s;
 
-    OrthancPluginErrorCode error = backend_.getPublicId(GetContext(), payload_, resourceId);
+    CheckSuccess(backend_.getPublicId(GetContext(), payload_, resourceId));
 
-    if (error != OrthancPluginErrorCode_Success)
-    {
-      errorDictionary_.LogError(error, true);
-      throw OrthancException(static_cast<ErrorCode>(error));
-    }
-    
     if (!ForwardSingleAnswer(s))
     {
       throw OrthancException(ErrorCode_DatabasePlugin);
@@ -581,15 +429,7 @@
   uint64_t OrthancPluginDatabase::GetResourceCount(ResourceType resourceType)
   {
     uint64_t count;
-
-    OrthancPluginErrorCode error = backend_.getResourceCount(&count, payload_, Convert(resourceType));
-
-    if (error != OrthancPluginErrorCode_Success)
-    {
-      errorDictionary_.LogError(error, true);
-      throw OrthancException(static_cast<ErrorCode>(error));
-    }
-
+    CheckSuccess(backend_.getResourceCount(&count, payload_, Plugins::Convert(resourceType)));
     return count;
   }
 
@@ -597,31 +437,15 @@
   ResourceType OrthancPluginDatabase::GetResourceType(int64_t resourceId)
   {
     OrthancPluginResourceType type;
-
-    OrthancPluginErrorCode error = backend_.getResourceType(&type, payload_, resourceId);
-
-    if (error != OrthancPluginErrorCode_Success)
-    {
-      errorDictionary_.LogError(error, true);
-      throw OrthancException(static_cast<ErrorCode>(error));
-    }
-
-    return Convert(type);
+    CheckSuccess(backend_.getResourceType(&type, payload_, resourceId));
+    return Plugins::Convert(type);
   }
 
 
   uint64_t OrthancPluginDatabase::GetTotalCompressedSize()
   {
     uint64_t size;
-
-    OrthancPluginErrorCode error = backend_.getTotalCompressedSize(&size, payload_);
-
-    if (error != OrthancPluginErrorCode_Success)
-    {
-      errorDictionary_.LogError(error, true);
-      throw OrthancException(static_cast<ErrorCode>(error));
-    }
-
+    CheckSuccess(backend_.getTotalCompressedSize(&size, payload_));
     return size;
   }
 
@@ -629,15 +453,7 @@
   uint64_t OrthancPluginDatabase::GetTotalUncompressedSize()
   {
     uint64_t size;
-
-    OrthancPluginErrorCode error = backend_.getTotalUncompressedSize(&size, payload_);
-
-    if (error != OrthancPluginErrorCode_Success)
-    {
-      errorDictionary_.LogError(error, true);
-      throw OrthancException(static_cast<ErrorCode>(error));
-    }
-
+    CheckSuccess(backend_.getTotalUncompressedSize(&size, payload_));
     return size;
   }
 
@@ -645,15 +461,7 @@
   bool OrthancPluginDatabase::IsExistingResource(int64_t internalId)
   {
     int32_t existing;
-
-    OrthancPluginErrorCode error = backend_.isExistingResource(&existing, payload_, internalId);
-
-    if (error != OrthancPluginErrorCode_Success)
-    {
-      errorDictionary_.LogError(error, true);
-      throw OrthancException(static_cast<ErrorCode>(error));
-    }
-
+    CheckSuccess(backend_.isExistingResource(&existing, payload_, internalId));
     return (existing != 0);
   }
 
@@ -661,15 +469,7 @@
   bool OrthancPluginDatabase::IsProtectedPatient(int64_t internalId)
   {
     int32_t isProtected;
-
-    OrthancPluginErrorCode error = backend_.isProtectedPatient(&isProtected, payload_, internalId);
-
-    if (error != OrthancPluginErrorCode_Success)
-    {
-      errorDictionary_.LogError(error, true);
-      throw OrthancException(static_cast<ErrorCode>(error));
-    }
-
+    CheckSuccess(backend_.isProtectedPatient(&isProtected, payload_, internalId));
     return (isProtected != 0);
   }
 
@@ -678,14 +478,7 @@
                                                     int64_t id)
   {
     ResetAnswers();
-
-    OrthancPluginErrorCode error = backend_.listAvailableMetadata(GetContext(), payload_, id);
- 
-    if (error != OrthancPluginErrorCode_Success)
-    {
-      errorDictionary_.LogError(error, true);
-      throw OrthancException(static_cast<ErrorCode>(error));
-    }
+    CheckSuccess(backend_.listAvailableMetadata(GetContext(), payload_, id));
 
     if (type_ != _OrthancPluginDatabaseAnswerType_None &&
         type_ != _OrthancPluginDatabaseAnswerType_Int32)
@@ -711,13 +504,7 @@
   {
     ResetAnswers();
 
-    OrthancPluginErrorCode error = backend_.listAvailableAttachments(GetContext(), payload_, id);
-
-    if (error != OrthancPluginErrorCode_Success)
-    {
-      errorDictionary_.LogError(error, true);
-      throw OrthancException(static_cast<ErrorCode>(error));
-    }
+    CheckSuccess(backend_.listAvailableAttachments(GetContext(), payload_, id));
 
     if (type_ != _OrthancPluginDatabaseAnswerType_None &&
         type_ != _OrthancPluginDatabaseAnswerType_Int32)
@@ -744,17 +531,11 @@
     OrthancPluginChange tmp;
     tmp.seq = change.GetSeq();
     tmp.changeType = static_cast<int32_t>(change.GetChangeType());
-    tmp.resourceType = Convert(change.GetResourceType());
+    tmp.resourceType = Plugins::Convert(change.GetResourceType());
     tmp.publicId = change.GetPublicId().c_str();
     tmp.date = change.GetDate().c_str();
 
-    OrthancPluginErrorCode error = backend_.logChange(payload_, &tmp);
-
-    if (error != OrthancPluginErrorCode_Success)
-    {
-      errorDictionary_.LogError(error, true);
-      throw OrthancException(static_cast<ErrorCode>(error));
-    }
+    CheckSuccess(backend_.logChange(payload_, &tmp));
   }
 
 
@@ -762,7 +543,7 @@
   {
     OrthancPluginExportedResource tmp;
     tmp.seq = resource.GetSeq();
-    tmp.resourceType = Convert(resource.GetResourceType());
+    tmp.resourceType = Plugins::Convert(resource.GetResourceType());
     tmp.publicId = resource.GetPublicId().c_str();
     tmp.modality = resource.GetModality().c_str();
     tmp.date = resource.GetDate().c_str();
@@ -771,13 +552,7 @@
     tmp.seriesInstanceUid = resource.GetSeriesInstanceUid().c_str();
     tmp.sopInstanceUid = resource.GetSopInstanceUid().c_str();
 
-    OrthancPluginErrorCode error = backend_.logExportedResource(payload_, &tmp);
-
-    if (error != OrthancPluginErrorCode_Success)
-    {
-      errorDictionary_.LogError(error, true);
-      throw OrthancException(static_cast<ErrorCode>(error));
-    }
+    CheckSuccess(backend_.logExportedResource(payload_, &tmp));
   }
 
     
@@ -787,14 +562,8 @@
   {
     ResetAnswers();
 
-    OrthancPluginErrorCode error = backend_.lookupAttachment
-      (GetContext(), payload_, id, static_cast<int32_t>(contentType));
-
-    if (error != OrthancPluginErrorCode_Success)
-    {
-      errorDictionary_.LogError(error, true);
-      throw OrthancException(static_cast<ErrorCode>(error));
-    }
+    CheckSuccess(backend_.lookupAttachment
+                 (GetContext(), payload_, id, static_cast<int32_t>(contentType)));
 
     if (type_ == _OrthancPluginDatabaseAnswerType_None)
     {
@@ -818,14 +587,8 @@
   {
     ResetAnswers();
 
-    OrthancPluginErrorCode error = backend_.lookupGlobalProperty
-      (GetContext(), payload_, static_cast<int32_t>(property));
-
-    if (error != OrthancPluginErrorCode_Success)
-    {
-      errorDictionary_.LogError(error, true);
-      throw OrthancException(static_cast<ErrorCode>(error));
-    }
+    CheckSuccess(backend_.lookupGlobalProperty
+                 (GetContext(), payload_, static_cast<int32_t>(property)));
 
     return ForwardSingleAnswer(target);
   }
@@ -842,13 +605,7 @@
     tmp.element = tag.GetElement();
     tmp.value = value.c_str();
 
-    OrthancPluginErrorCode error = backend_.lookupIdentifier(GetContext(), payload_, &tmp);
-
-    if (error != OrthancPluginErrorCode_Success)
-    {
-      errorDictionary_.LogError(error, true);
-      throw OrthancException(static_cast<ErrorCode>(error));
-    }
+    CheckSuccess(backend_.lookupIdentifier(GetContext(), payload_, &tmp));
 
     ForwardAnswers(target);
   }
@@ -858,15 +615,7 @@
                                                const std::string& value)
   {
     ResetAnswers();
-
-    OrthancPluginErrorCode error = backend_.lookupIdentifier2(GetContext(), payload_, value.c_str());
-
-    if (error != OrthancPluginErrorCode_Success)
-    {
-      errorDictionary_.LogError(error, true);
-      throw OrthancException(static_cast<ErrorCode>(error));
-    }
-
+    CheckSuccess(backend_.lookupIdentifier2(GetContext(), payload_, value.c_str()));
     ForwardAnswers(target);
   }
 
@@ -876,15 +625,7 @@
                                              MetadataType type)
   {
     ResetAnswers();
-
-    OrthancPluginErrorCode error = backend_.lookupMetadata(GetContext(), payload_, id, static_cast<int32_t>(type));
-
-    if (error != OrthancPluginErrorCode_Success)
-    {
-      errorDictionary_.LogError(error, true);
-      throw OrthancException(static_cast<ErrorCode>(error));
-    }
-
+    CheckSuccess(backend_.lookupMetadata(GetContext(), payload_, id, static_cast<int32_t>(type)));
     return ForwardSingleAnswer(target);
   }
 
@@ -893,15 +634,7 @@
                                            int64_t resourceId)
   {
     ResetAnswers();
-
-    OrthancPluginErrorCode error = backend_.lookupParent(GetContext(), payload_, resourceId);
-
-    if (error != OrthancPluginErrorCode_Success)
-    {
-      errorDictionary_.LogError(error, true);
-      throw OrthancException(static_cast<ErrorCode>(error));
-    }
-
+    CheckSuccess(backend_.lookupParent(GetContext(), payload_, resourceId));
     return ForwardSingleAnswer(parentId);
   }
 
@@ -912,13 +645,7 @@
   {
     ResetAnswers();
 
-    OrthancPluginErrorCode error = backend_.lookupResource(GetContext(), payload_, publicId.c_str());
-
-    if (error != OrthancPluginErrorCode_Success)
-    {
-      errorDictionary_.LogError(error, true);
-      throw OrthancException(static_cast<ErrorCode>(error));
-    }
+    CheckSuccess(backend_.lookupResource(GetContext(), payload_, publicId.c_str()));
 
     if (type_ == _OrthancPluginDatabaseAnswerType_None)
     {
@@ -941,15 +668,7 @@
   bool OrthancPluginDatabase::SelectPatientToRecycle(int64_t& internalId)
   {
     ResetAnswers();
-
-    OrthancPluginErrorCode error = backend_.selectPatientToRecycle(GetContext(), payload_);
-
-    if (error != OrthancPluginErrorCode_Success)
-    {
-      errorDictionary_.LogError(error, true);
-      throw OrthancException(static_cast<ErrorCode>(error));
-    }
-
+    CheckSuccess(backend_.selectPatientToRecycle(GetContext(), payload_));
     return ForwardSingleAnswer(internalId);
   }
 
@@ -958,15 +677,7 @@
                                                      int64_t patientIdToAvoid)
   {
     ResetAnswers();
-
-    OrthancPluginErrorCode error = backend_.selectPatientToRecycle2(GetContext(), payload_, patientIdToAvoid);
-
-    if (error != OrthancPluginErrorCode_Success)
-    {
-      errorDictionary_.LogError(error, true);
-      throw OrthancException(static_cast<ErrorCode>(error));
-    }
-
+    CheckSuccess(backend_.selectPatientToRecycle2(GetContext(), payload_, patientIdToAvoid));
     return ForwardSingleAnswer(internalId);
   }
 
@@ -974,14 +685,8 @@
   void OrthancPluginDatabase::SetGlobalProperty(GlobalProperty property,
                                                 const std::string& value)
   {
-    OrthancPluginErrorCode error = backend_.setGlobalProperty
-      (payload_, static_cast<int32_t>(property), value.c_str());
-
-    if (error != OrthancPluginErrorCode_Success)
-    {
-      errorDictionary_.LogError(error, true);
-      throw OrthancException(static_cast<ErrorCode>(error));
-    }
+    CheckSuccess(backend_.setGlobalProperty
+                 (payload_, static_cast<int32_t>(property), value.c_str()));
   }
 
 
@@ -993,13 +698,7 @@
       throw OrthancException(ErrorCode_DatabasePlugin);
     }
 
-    OrthancPluginErrorCode error = extensions_.clearMainDicomTags(payload_, id);
-    
-    if (error != OrthancPluginErrorCode_Success)
-    {
-      errorDictionary_.LogError(error, true);
-      throw OrthancException(static_cast<ErrorCode>(error));
-    }
+    CheckSuccess(extensions_.clearMainDicomTags(payload_, id));
   }
 
 
@@ -1012,22 +711,18 @@
     tmp.element = tag.GetElement();
     tmp.value = value.c_str();
 
-    OrthancPluginErrorCode error;
+    OrthancPluginErrorCode code;
 
     if (tag.IsIdentifier())
     {
-      error = backend_.setIdentifierTag(payload_, id, &tmp);
+      code = backend_.setIdentifierTag(payload_, id, &tmp);
     }
     else
     {
-      error = backend_.setMainDicomTag(payload_, id, &tmp);
+      code = backend_.setMainDicomTag(payload_, id, &tmp);
     }
 
-    if (error != OrthancPluginErrorCode_Success)
-    {
-      errorDictionary_.LogError(error, true);
-      throw OrthancException(static_cast<ErrorCode>(error));
-    }
+    CheckSuccess(code);
   }
 
 
@@ -1035,27 +730,15 @@
                                           MetadataType type,
                                           const std::string& value)
   {
-    OrthancPluginErrorCode error = backend_.setMetadata
-      (payload_, id, static_cast<int32_t>(type), value.c_str());
-
-    if (error != OrthancPluginErrorCode_Success)
-    {
-      errorDictionary_.LogError(error, true);
-      throw OrthancException(static_cast<ErrorCode>(error));
-    }
+    CheckSuccess(backend_.setMetadata
+                 (payload_, id, static_cast<int32_t>(type), value.c_str()));
   }
 
 
   void OrthancPluginDatabase::SetProtectedPatient(int64_t internalId, 
                                                   bool isProtected)
   {
-    OrthancPluginErrorCode error = backend_.setProtectedPatient(payload_, internalId, isProtected);
-
-    if (error != OrthancPluginErrorCode_Success)
-    {
-      errorDictionary_.LogError(error, true);
-      throw OrthancException(static_cast<ErrorCode>(error));
-    }
+    CheckSuccess(backend_.setProtectedPatient(payload_, internalId, isProtected));
   }
 
 
@@ -1066,6 +749,15 @@
     void* payload_;
     PluginsErrorDictionary&  errorDictionary_;
 
+    void CheckSuccess(OrthancPluginErrorCode code)
+    {
+      if (code != OrthancPluginErrorCode_Success)
+      {
+        errorDictionary_.LogError(code, true);
+        throw OrthancException(static_cast<ErrorCode>(code));
+      }
+    }
+
   public:
     Transaction(const OrthancPluginDatabaseBackend& backend,
                 void* payload,
@@ -1078,35 +770,17 @@
 
     virtual void Begin()
     {
-      OrthancPluginErrorCode error = backend_.startTransaction(payload_);
-
-      if (error != OrthancPluginErrorCode_Success)
-      {
-        errorDictionary_.LogError(error, true);
-        throw OrthancException(static_cast<ErrorCode>(error));
-      }
+      CheckSuccess(backend_.startTransaction(payload_));
     }
 
     virtual void Rollback()
     {
-      OrthancPluginErrorCode error = backend_.rollbackTransaction(payload_);
-
-      if (error != OrthancPluginErrorCode_Success)
-      {
-        errorDictionary_.LogError(error, true);
-        throw OrthancException(static_cast<ErrorCode>(error));
-      }
+      CheckSuccess(backend_.rollbackTransaction(payload_));
     }
 
     virtual void Commit()
     {
-      OrthancPluginErrorCode error = backend_.commitTransaction(payload_);
-
-      if (error != OrthancPluginErrorCode_Success)
-      {
-        errorDictionary_.LogError(error, true);
-        throw OrthancException(static_cast<ErrorCode>(error));
-      }
+      CheckSuccess(backend_.commitTransaction(payload_));
     }
   };
 
@@ -1132,14 +806,14 @@
         
       case _OrthancPluginDatabaseAnswerType_RemainingAncestor:
       {
-        ResourceType type = Convert(static_cast<OrthancPluginResourceType>(answer.valueInt32));
+        ResourceType type = Plugins::Convert(static_cast<OrthancPluginResourceType>(answer.valueInt32));
         listener.SignalRemainingAncestor(type, answer.valueString);
         break;
       }
       
       case _OrthancPluginDatabaseAnswerType_DeletedResource:
       {
-        ResourceType type = Convert(static_cast<OrthancPluginResourceType>(answer.valueInt32));
+        ResourceType type = Plugins::Convert(static_cast<OrthancPluginResourceType>(answer.valueInt32));
         ServerIndexChange change(ChangeType_Deleted, type, answer.valueString);
         listener.SignalChange(change);
         break;
@@ -1156,14 +830,7 @@
     if (extensions_.getDatabaseVersion != NULL)
     {
       uint32_t version;
-      OrthancPluginErrorCode error = extensions_.getDatabaseVersion(&version, payload_);
-
-      if (error != OrthancPluginErrorCode_Success)
-      {
-        errorDictionary_.LogError(error, true);
-        throw OrthancException(static_cast<ErrorCode>(error));
-      }
-
+      CheckSuccess(extensions_.getDatabaseVersion(&version, payload_));
       return version;
     }
     else
@@ -1181,15 +848,9 @@
   {
     if (extensions_.upgradeDatabase != NULL)
     {
-      OrthancPluginErrorCode error = extensions_.upgradeDatabase(
-        payload_, targetVersion, 
-        reinterpret_cast<OrthancPluginStorageArea*>(&storageArea));
-
-      if (error != OrthancPluginErrorCode_Success)
-      {
-        errorDictionary_.LogError(error, true);
-        throw OrthancException(static_cast<ErrorCode>(error));
-      }
+      CheckSuccess(extensions_.upgradeDatabase(
+                     payload_, targetVersion, 
+                     reinterpret_cast<OrthancPluginStorageArea*>(&storageArea)));
     }
   }
 
@@ -1279,7 +940,7 @@
       case _OrthancPluginDatabaseAnswerType_Resource:
       {
         OrthancPluginResourceType type = static_cast<OrthancPluginResourceType>(answer.valueInt32);
-        answerResources_.push_back(std::make_pair(answer.valueInt64, Convert(type)));
+        answerResources_.push_back(std::make_pair(answer.valueInt64, Plugins::Convert(type)));
         break;
       }
 
@@ -1339,7 +1000,7 @@
           answerChanges_->push_back
             (ServerIndexChange(change.seq,
                                static_cast<ChangeType>(change.changeType),
-                               Convert(change.resourceType),
+                               Plugins::Convert(change.resourceType),
                                change.publicId,
                                change.date));                                   
         }
@@ -1365,7 +1026,7 @@
           assert(answerExportedResources_ != NULL);
           answerExportedResources_->push_back
             (ExportedResource(exported.seq,
-                              Convert(exported.resourceType),
+                              Plugins::Convert(exported.resourceType),
                               exported.publicId,
                               exported.modality,
                               exported.date,
--- a/Plugins/Engine/OrthancPluginDatabase.h	Thu Oct 01 17:44:43 2015 +0200
+++ b/Plugins/Engine/OrthancPluginDatabase.h	Fri Oct 02 12:20:49 2015 +0200
@@ -72,6 +72,8 @@
       return reinterpret_cast<OrthancPluginDatabaseContext*>(this);
     }
 
+    void CheckSuccess(OrthancPluginErrorCode code);
+
     void ResetAnswers();
 
     void ForwardAnswers(std::list<int64_t>& target);
@@ -90,6 +92,16 @@
                           size_t extensionsSize,
                           void *payload);
 
+    virtual void Open()
+    {
+      CheckSuccess(backend_.open(payload_));
+    }
+
+    virtual void Close()
+    {
+      CheckSuccess(backend_.close(payload_));
+    }
+
     const SharedLibrary& GetSharedLibrary() const
     {
       return library_;
--- a/Plugins/Engine/PluginsManager.cpp	Thu Oct 01 17:44:43 2015 +0200
+++ b/Plugins/Engine/PluginsManager.cpp	Fri Oct 02 12:20:49 2015 +0200
@@ -191,7 +191,7 @@
       catch (OrthancException& e)
       {
         // This service provider has failed
-        LOG(ERROR) << "Exception while invoking a plugin service: " << e.What();
+        LOG(ERROR) << "Exception while invoking plugin service " << service << ": " << e.What();
         return static_cast<OrthancPluginErrorCode>(e.GetErrorCode());
       }
     }
--- a/Plugins/Samples/DatabasePlugin/Database.cpp	Thu Oct 01 17:44:43 2015 +0200
+++ b/Plugins/Samples/DatabasePlugin/Database.cpp	Fri Oct 02 12:20:49 2015 +0200
@@ -32,9 +32,11 @@
 
 #include "Database.h"
 
-#include <EmbeddedResources.h>
+#include "../../../Core/DicomFormat/DicomArray.h"
 
-#include "../../../Core/DicomFormat/DicomArray.h"
+#include <EmbeddedResources.h>
+#include <boost/lexical_cast.hpp>
+
 
 namespace Internals
 {
@@ -106,7 +108,7 @@
     virtual void Compute(Orthanc::SQLite::FunctionContext& context)
     {
       output_.SignalDeletedResource(context.GetStringValue(0),
-                                    static_cast<OrthancPluginResourceType>(context.GetIntValue(1)));
+                                    Orthanc::Plugins::Convert(static_cast<Orthanc::ResourceType>(context.GetIntValue(1))));
     }
   };
 }
@@ -117,7 +119,7 @@
 private:
   bool hasRemainingAncestor_;
   std::string remainingPublicId_;
-  Orthanc::ResourceType remainingType_;
+  OrthancPluginResourceType remainingType_;
 
 public:
   SignalRemainingAncestor() : 
@@ -147,7 +149,7 @@
     {
       hasRemainingAncestor_ = true;
       remainingPublicId_ = context.GetStringValue(0);
-      remainingType_ = static_cast<Orthanc::ResourceType>(context.GetIntValue(1));
+      remainingType_ = Orthanc::Plugins::Convert(static_cast<Orthanc::ResourceType>(context.GetIntValue(1)));
     }
   }
 
@@ -162,7 +164,7 @@
     return remainingPublicId_;
   }
 
-  Orthanc::ResourceType GetRemainingAncestorType() const
+  OrthancPluginResourceType GetRemainingAncestorType() const
   {
     assert(hasRemainingAncestor_);
     return remainingType_;
@@ -175,13 +177,20 @@
   path_(path),
   base_(db_)
 {
-  db_.Open(path_);
-  Open();
 }
 
 
 void Database::Open()
 {
+  db_.Open(path_);
+
+  // http://www.sqlite.org/pragma.html
+  db_.Execute("PRAGMA SYNCHRONOUS=NORMAL;");
+  db_.Execute("PRAGMA JOURNAL_MODE=WAL;");
+  db_.Execute("PRAGMA LOCKING_MODE=EXCLUSIVE;");
+  db_.Execute("PRAGMA WAL_AUTOCHECKPOINT=1000;");
+  //db_.Execute("PRAGMA TEMP_STORE=memory");
+
   if (!db_.DoesTableExist("GlobalProperties"))
   {
     std::string query;
@@ -218,7 +227,17 @@
 
 void Database::DeleteResource(int64_t id)
 {
-  // TODO
+  signalRemainingAncestor_->Reset();
+
+  Orthanc::SQLite::Statement s(db_, SQLITE_FROM_HERE, "DELETE FROM Resources WHERE internalId=?");
+  s.BindInt64(0, id);
+  s.Run();
+
+  if (signalRemainingAncestor_->HasRemainingAncestor())
+  {
+    GetOutput().SignalRemainingAncestor(signalRemainingAncestor_->GetRemainingAncestorId(),
+                                        signalRemainingAncestor_->GetRemainingAncestorType());
+  }
 }
 
 
@@ -226,7 +245,7 @@
                    const Orthanc::ServerIndexChange& change)
 {
   output.AnswerChange(change.GetSeq(), 
-                      static_cast<int32_t>(change.GetChangeType()),
+                      change.GetChangeType(),
                       Orthanc::Plugins::Convert(change.GetResourceType()),
                       change.GetPublicId(),
                       change.GetDate());
@@ -500,7 +519,21 @@
 
 uint32_t Database::GetDatabaseVersion()
 {
-  return 6;
+  std::string version;
+
+  if (!LookupGlobalProperty(version, Orthanc::GlobalProperty_DatabaseSchemaVersion))
+  {
+    throw OrthancPlugins::DatabaseException(OrthancPluginErrorCode_InternalError);
+  }
+
+  try
+  {
+    return boost::lexical_cast<uint32_t>(version);
+  }
+  catch (boost::bad_lexical_cast&)
+  {
+    throw OrthancPlugins::DatabaseException(OrthancPluginErrorCode_InternalError);
+  }
 }
 
 
--- a/UnitTestsSources/ServerIndexTests.cpp	Thu Oct 01 17:44:43 2015 +0200
+++ b/UnitTestsSources/ServerIndexTests.cpp	Fri Oct 02 12:20:49 2015 +0200
@@ -122,10 +122,12 @@
       }
 
       index_->SetListener(*listener_);
+      index_->Open();
     }
 
     virtual void TearDown()
     {
+      index_->Close();
       index_.reset(NULL);
       listener_.reset(NULL);
     }
@@ -660,6 +662,7 @@
   Toolbox::RemoveFile(path + "/index");
   FilesystemStorage storage(path);
   DatabaseWrapper db;   // The SQLite DB is in memory
+  db.Open();
   ServerContext context(db, storage);
   ServerIndex& index = context.GetIndex();
 
@@ -669,6 +672,7 @@
   ASSERT_EQ(4u, index.IncrementGlobalSequence(GlobalProperty_AnonymizationSequence));
 
   context.Stop();
+  db.Close();
 }
 
 
@@ -728,6 +732,7 @@
   Toolbox::RemoveFile(path + "/index");
   FilesystemStorage storage(path);
   DatabaseWrapper db;   // The SQLite DB is in memory
+  db.Open();
   ServerContext context(db, storage);
   ServerIndex& index = context.GetIndex();
 
@@ -781,4 +786,5 @@
   ASSERT_THROW(Toolbox::GetFileSize(path + "/index"), OrthancException);  
 
   context.Stop();
+  db.Close();
 }