Mercurial > hg > orthanc
diff OrthancServer/Sources/Database/StatelessDatabaseOperations.cpp @ 4627:f7d5372b59b3 db-changes
handling revisions of attachments
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Tue, 20 Apr 2021 15:11:59 +0200 |
parents | 95ffe3b6ef7c |
children | 37357df3dc27 |
line wrap: on
line diff
--- a/OrthancServer/Sources/Database/StatelessDatabaseOperations.cpp Mon Apr 19 10:28:43 2021 +0200 +++ b/OrthancServer/Sources/Database/StatelessDatabaseOperations.cpp Tue Apr 20 15:11:59 2021 +0200 @@ -920,7 +920,8 @@ target["Type"] = "Instance"; FileInfo attachment; - if (!transaction.LookupAttachment(attachment, internalId, FileContentType_Dicom)) + int64_t revision; // ignored + if (!transaction.LookupAttachment(attachment, revision, internalId, FileContentType_Dicom)) { throw OrthancException(ErrorCode_InternalError); } @@ -1015,10 +1016,11 @@ bool StatelessDatabaseOperations::LookupAttachment(FileInfo& attachment, + int64_t& revision, const std::string& instancePublicId, FileContentType contentType) { - class Operations : public ReadOnlyOperationsT4<bool&, FileInfo&, const std::string&, FileContentType> + class Operations : public ReadOnlyOperationsT5<bool&, FileInfo&, int64_t&, const std::string&, FileContentType> { public: virtual void ApplyTuple(ReadOnlyTransaction& transaction, @@ -1026,13 +1028,13 @@ { int64_t internalId; ResourceType type; - if (!transaction.LookupResource(internalId, type, tuple.get<2>())) + if (!transaction.LookupResource(internalId, type, tuple.get<3>())) { throw OrthancException(ErrorCode_UnknownResource); } - else if (transaction.LookupAttachment(tuple.get<1>(), internalId, tuple.get<3>())) + else if (transaction.LookupAttachment(tuple.get<1>(), tuple.get<2>(), internalId, tuple.get<4>())) { - assert(tuple.get<1>().GetContentType() == tuple.get<3>()); + assert(tuple.get<1>().GetContentType() == tuple.get<4>()); tuple.get<0>() = true; } else @@ -1044,7 +1046,7 @@ bool found; Operations operations; - operations.Apply(*this, found, attachment, instancePublicId, contentType); + operations.Apply(*this, found, attachment, revision, instancePublicId, contentType); return found; } @@ -1547,7 +1549,8 @@ it = f.begin(); it != f.end(); ++it) { FileInfo attachment; - if (transaction.LookupAttachment(attachment, resource, *it)) + int64_t revision; // ignored + if (transaction.LookupAttachment(attachment, revision, resource, *it)) { if (attachment.GetContentType() == FileContentType_Dicom) { @@ -2244,7 +2247,7 @@ } else { - newRevision_ = oldRevision_ + 1; + newRevision_ = expectedRevision + 1; } } else @@ -2478,23 +2481,38 @@ } - void StatelessDatabaseOperations::DeleteAttachment(const std::string& publicId, - FileContentType type) + bool StatelessDatabaseOperations::DeleteAttachment(const std::string& publicId, + FileContentType type, + bool hasRevision, + int64_t revision) { class Operations : public IReadWriteOperations { private: const std::string& publicId_; FileContentType type_; - + bool hasRevision_; + int64_t revision_; + bool found_; + public: Operations(const std::string& publicId, - FileContentType type) : + FileContentType type, + bool hasRevision, + int64_t revision) : publicId_(publicId), - type_(type) + type_(type), + hasRevision_(hasRevision), + revision_(revision), + found_(false) { } + bool HasFound() const + { + return found_; + } + virtual void Apply(ReadWriteTransaction& transaction) ORTHANC_OVERRIDE { ResourceType resourceType; @@ -2505,18 +2523,35 @@ } else { - transaction.DeleteAttachment(id, type_); + FileInfo info; + int64_t expectedRevision; + if (transaction.LookupAttachment(info, expectedRevision, id, type_)) + { + if (hasRevision_ && + expectedRevision != revision_) + { + throw OrthancException(ErrorCode_Revision); + } + + found_ = true; + transaction.DeleteAttachment(id, type_); - if (IsUserContentType(type_)) + if (IsUserContentType(type_)) + { + transaction.LogChange(id, ChangeType_UpdatedAttachment, resourceType, publicId_); + } + } + else { - transaction.LogChange(id, ChangeType_UpdatedAttachment, resourceType, publicId_); + found_ = false; } } } }; - Operations operations(publicId, type); + Operations operations(publicId, type, hasRevision, revision); Apply(operations); + return operations.HasFound(); } @@ -3018,7 +3053,7 @@ for (Attachments::const_iterator it = attachments_.begin(); it != attachments_.end(); ++it) { - transaction.AddAttachment(instanceId, *it); + transaction.AddAttachment(instanceId, *it, 0 /* this is the first revision */); } @@ -3219,30 +3254,42 @@ } - StoreStatus StatelessDatabaseOperations::AddAttachment(const FileInfo& attachment, + StoreStatus StatelessDatabaseOperations::AddAttachment(int64_t& newRevision, + const FileInfo& attachment, const std::string& publicId, uint64_t maximumStorageSize, - unsigned int maximumPatients) + unsigned int maximumPatients, + bool hasOldRevision, + int64_t oldRevision) { class Operations : public IReadWriteOperations { private: + int64_t& newRevision_; StoreStatus status_; const FileInfo& attachment_; const std::string& publicId_; uint64_t maximumStorageSize_; unsigned int maximumPatientCount_; - + bool hasOldRevision_; + int64_t oldRevision_; + public: - Operations(const FileInfo& attachment, + Operations(int64_t& newRevision, + const FileInfo& attachment, const std::string& publicId, uint64_t maximumStorageSize, - unsigned int maximumPatientCount) : + unsigned int maximumPatientCount, + bool hasOldRevision, + int64_t oldRevision) : + newRevision_(newRevision), status_(StoreStatus_Failure), attachment_(attachment), publicId_(publicId), maximumStorageSize_(maximumStorageSize), - maximumPatientCount_(maximumPatientCount) + maximumPatientCount_(maximumPatientCount), + hasOldRevision_(hasOldRevision), + oldRevision_(oldRevision) { } @@ -3261,8 +3308,30 @@ } else { - // Remove possible previous attachment - transaction.DeleteAttachment(resourceId, attachment_.GetContentType()); + // Possibly remove previous attachment + { + FileInfo oldFile; + int64_t expectedRevision; + if (transaction.LookupAttachment(oldFile, expectedRevision, resourceId, attachment_.GetContentType())) + { + if (hasOldRevision_ && + expectedRevision != oldRevision_) + { + throw OrthancException(ErrorCode_Revision); + } + else + { + newRevision_ = expectedRevision + 1; + transaction.DeleteAttachment(resourceId, attachment_.GetContentType()); + } + } + else + { + // The attachment is not existing yet: Ignore "oldRevision" + // and initialize a new sequence of revisions + newRevision_ = 0; + } + } // Locate the patient of the target resource int64_t patientId = resourceId; @@ -3286,7 +3355,7 @@ transaction.Recycle(maximumStorageSize_, maximumPatientCount_, attachment_.GetCompressedSize(), transaction.GetPublicId(patientId)); - transaction.AddAttachment(resourceId, attachment_); + transaction.AddAttachment(resourceId, attachment_, newRevision_); if (IsUserContentType(attachment_.GetContentType())) { @@ -3301,7 +3370,7 @@ }; - Operations operations(attachment, publicId, maximumStorageSize, maximumPatients); + Operations operations(newRevision, attachment, publicId, maximumStorageSize, maximumPatients, hasOldRevision, oldRevision); Apply(operations); return operations.GetStatus(); }