changeset 5464:38f1d06875ad pg-transactions

delete attachment in case of same instance being uploaded multiple times at the same time
author Alain Mazy <am@osimis.io>
date Tue, 12 Dec 2023 17:20:10 +0100
parents 46ed738c3e5d
children 2829889bfa57
files OrthancFramework/Resources/CodeGeneration/ErrorCodes.json OrthancFramework/Sources/Enumerations.cpp OrthancFramework/Sources/Enumerations.h OrthancServer/Plugins/Include/orthanc/OrthancCPlugin.h OrthancServer/Sources/Database/StatelessDatabaseOperations.cpp OrthancServer/Sources/ServerContext.cpp OrthancServer/Sources/main.cpp
diffstat 7 files changed, 41 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/OrthancFramework/Resources/CodeGeneration/ErrorCodes.json	Fri Dec 08 10:27:24 2023 +0100
+++ b/OrthancFramework/Resources/CodeGeneration/ErrorCodes.json	Tue Dec 12 17:20:10 2023 +0100
@@ -256,6 +256,12 @@
     "Name": "ForbiddenAccess", 
     "Description": "Access to a resource is forbidden"
   }, 
+  {
+    "Code": 46,
+    "HttpStatus": 409,
+    "Name": "DuplicateResource", 
+    "Description": "Duplicate resource"
+  }, 
 
 
 
--- a/OrthancFramework/Sources/Enumerations.cpp	Fri Dec 08 10:27:24 2023 +0100
+++ b/OrthancFramework/Sources/Enumerations.cpp	Tue Dec 12 17:20:10 2023 +0100
@@ -182,6 +182,9 @@
       case ErrorCode_ForbiddenAccess:
         return "Access to a resource is forbidden";
 
+      case ErrorCode_DuplicateResource:
+        return "Duplicate resource";
+
       case ErrorCode_SQLiteNotOpened:
         return "SQLite: The database is not opened";
 
@@ -2264,6 +2267,9 @@
       case ErrorCode_ForbiddenAccess:
         return HttpStatus_403_Forbidden;
 
+      case ErrorCode_DuplicateResource:
+        return HttpStatus_409_Conflict;
+
       case ErrorCode_CreateDicomNotString:
         return HttpStatus_400_BadRequest;
 
--- a/OrthancFramework/Sources/Enumerations.h	Fri Dec 08 10:27:24 2023 +0100
+++ b/OrthancFramework/Sources/Enumerations.h	Tue Dec 12 17:20:10 2023 +0100
@@ -170,6 +170,7 @@
     ErrorCode_Revision = 43    /*!< A bad revision number was provided, which might indicate conflict between multiple writers */,
     ErrorCode_MainDicomTagsMultiplyDefined = 44    /*!< A main DICOM Tag has been defined multiple times for the same resource level */,
     ErrorCode_ForbiddenAccess = 45    /*!< Access to a resource is forbidden */,
+    ErrorCode_DuplicateResource = 46    /*!< Duplicate resource */,
     ErrorCode_SQLiteNotOpened = 1000    /*!< SQLite: The database is not opened */,
     ErrorCode_SQLiteAlreadyOpened = 1001    /*!< SQLite: Connection is already open */,
     ErrorCode_SQLiteCannotOpen = 1002    /*!< SQLite: Unable to open the database */,
--- a/OrthancServer/Plugins/Include/orthanc/OrthancCPlugin.h	Fri Dec 08 10:27:24 2023 +0100
+++ b/OrthancServer/Plugins/Include/orthanc/OrthancCPlugin.h	Tue Dec 12 17:20:10 2023 +0100
@@ -246,6 +246,7 @@
     OrthancPluginErrorCode_Revision = 43    /*!< A bad revision number was provided, which might indicate conflict between multiple writers */,
     OrthancPluginErrorCode_MainDicomTagsMultiplyDefined = 44    /*!< A main DICOM Tag has been defined multiple times for the same resource level */,
     OrthancPluginErrorCode_ForbiddenAccess = 45    /*!< Access to a resource is forbidden */,
+    OrthancPluginErrorCode_DuplicateResource = 46    /*!< Duplicate resource */,
     OrthancPluginErrorCode_SQLiteNotOpened = 1000    /*!< SQLite: The database is not opened */,
     OrthancPluginErrorCode_SQLiteAlreadyOpened = 1001    /*!< SQLite: Connection is already open */,
     OrthancPluginErrorCode_SQLiteCannotOpen = 1002    /*!< SQLite: Unable to open the database */,
--- a/OrthancServer/Sources/Database/StatelessDatabaseOperations.cpp	Fri Dec 08 10:27:24 2023 +0100
+++ b/OrthancServer/Sources/Database/StatelessDatabaseOperations.cpp	Tue Dec 12 17:20:10 2023 +0100
@@ -3157,7 +3157,9 @@
               // in very rare occasions in READ COMMITTED mode when multiple clients are pushing the same instance at the same time,
               // this thread will not create the instance because another thread has created it in the meantime.
               // At the end, there is always a thread that creates the instance and this is what we expect.
-              throw OrthancException(ErrorCode_InternalError, HttpStatus_409_Conflict, "No new instance while overwriting; this might happen if another client has pushed the same instance at the same time.");
+
+              // Note, we must delete the attachments that have already been stored from this failed insertion (they have not yet been added into the DB)
+              throw OrthancException(ErrorCode_DuplicateResource, "No new instance while overwriting; this might happen if another client has pushed the same instance at the same time.");
             }
           }
           else
--- a/OrthancServer/Sources/ServerContext.cpp	Fri Dec 08 10:27:24 2023 +0100
+++ b/OrthancServer/Sources/ServerContext.cpp	Tue Dec 12 17:20:10 2023 +0100
@@ -710,9 +710,29 @@
 
       typedef std::map<MetadataType, std::string>  InstanceMetadata;
       InstanceMetadata  instanceMetadata;
-      result.SetStatus(index_.Store(
-        instanceMetadata, summary, attachments, dicom.GetMetadata(), dicom.GetOrigin(), overwrite,
-        hasTransferSyntax, transferSyntax, hasPixelDataOffset, pixelDataOffset, pixelDataVR, isReconstruct));
+
+      try 
+      {
+        result.SetStatus(index_.Store(
+          instanceMetadata, summary, attachments, dicom.GetMetadata(), dicom.GetOrigin(), overwrite,
+          hasTransferSyntax, transferSyntax, hasPixelDataOffset, pixelDataOffset, pixelDataVR, isReconstruct));
+      }
+      catch (OrthancException& ex)
+      {
+        if (ex.GetErrorCode() == ErrorCode_DuplicateResource)
+        {
+          LOG(WARNING) << "Duplicate instance, deleting the attachments";
+
+          accessor.Remove(dicomInfo);
+
+          if (dicomUntilPixelData.IsValid())
+          {
+            accessor.Remove(dicomUntilPixelData);
+          }
+
+          throw;
+        }
+      }
 
       // Only keep the metadata for the "instance" level
       dicom.ClearMetadata();
--- a/OrthancServer/Sources/main.cpp	Fri Dec 08 10:27:24 2023 +0100
+++ b/OrthancServer/Sources/main.cpp	Tue Dec 12 17:20:10 2023 +0100
@@ -820,6 +820,7 @@
     PrintErrorCode(ErrorCode_Revision, "A bad revision number was provided, which might indicate conflict between multiple writers");
     PrintErrorCode(ErrorCode_MainDicomTagsMultiplyDefined, "A main DICOM Tag has been defined multiple times for the same resource level");
     PrintErrorCode(ErrorCode_ForbiddenAccess, "Access to a resource is forbidden");
+    PrintErrorCode(ErrorCode_DuplicateResource, "Duplicate resource");
     PrintErrorCode(ErrorCode_SQLiteNotOpened, "SQLite: The database is not opened");
     PrintErrorCode(ErrorCode_SQLiteAlreadyOpened, "SQLite: Connection is already open");
     PrintErrorCode(ErrorCode_SQLiteCannotOpen, "SQLite: Unable to open the database");