# HG changeset patch # User Alain Mazy # Date 1702398010 -3600 # Node ID 38f1d06875ad0e233a07b6332e4c4721ae985907 # Parent 46ed738c3e5d8aae4863ffeede533249c43f847e delete attachment in case of same instance being uploaded multiple times at the same time diff -r 46ed738c3e5d -r 38f1d06875ad OrthancFramework/Resources/CodeGeneration/ErrorCodes.json --- 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" + }, diff -r 46ed738c3e5d -r 38f1d06875ad OrthancFramework/Sources/Enumerations.cpp --- 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; diff -r 46ed738c3e5d -r 38f1d06875ad OrthancFramework/Sources/Enumerations.h --- 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 */, diff -r 46ed738c3e5d -r 38f1d06875ad OrthancServer/Plugins/Include/orthanc/OrthancCPlugin.h --- 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 */, diff -r 46ed738c3e5d -r 38f1d06875ad OrthancServer/Sources/Database/StatelessDatabaseOperations.cpp --- 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 diff -r 46ed738c3e5d -r 38f1d06875ad OrthancServer/Sources/ServerContext.cpp --- 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 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(); diff -r 46ed738c3e5d -r 38f1d06875ad OrthancServer/Sources/main.cpp --- 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");