Mercurial > hg > orthanc
comparison OrthancServer/Sources/Database/StatelessDatabaseOperations.cpp @ 4640:66109d24d26e
"ETag" headers for metadata and attachments now allow strong comparison (MD5 is included)
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Mon, 26 Apr 2021 15:22:44 +0200 |
parents | 37357df3dc27 |
children | da1edb7d6332 |
comparison
equal
deleted
inserted
replaced
4639:c638dd444de0 | 4640:66109d24d26e |
---|---|
2197 void StatelessDatabaseOperations::SetMetadata(int64_t& newRevision, | 2197 void StatelessDatabaseOperations::SetMetadata(int64_t& newRevision, |
2198 const std::string& publicId, | 2198 const std::string& publicId, |
2199 MetadataType type, | 2199 MetadataType type, |
2200 const std::string& value, | 2200 const std::string& value, |
2201 bool hasOldRevision, | 2201 bool hasOldRevision, |
2202 int64_t oldRevision) | 2202 int64_t oldRevision, |
2203 const std::string& oldMD5) | |
2203 { | 2204 { |
2204 class Operations : public IReadWriteOperations | 2205 class Operations : public IReadWriteOperations |
2205 { | 2206 { |
2206 private: | 2207 private: |
2207 int64_t& newRevision_; | 2208 int64_t& newRevision_; |
2208 const std::string& publicId_; | 2209 const std::string& publicId_; |
2209 MetadataType type_; | 2210 MetadataType type_; |
2210 const std::string& value_; | 2211 const std::string& value_; |
2211 bool hasOldRevision_; | 2212 bool hasOldRevision_; |
2212 int64_t oldRevision_; | 2213 int64_t oldRevision_; |
2214 const std::string& oldMD5_; | |
2213 | 2215 |
2214 public: | 2216 public: |
2215 Operations(int64_t& newRevision, | 2217 Operations(int64_t& newRevision, |
2216 const std::string& publicId, | 2218 const std::string& publicId, |
2217 MetadataType type, | 2219 MetadataType type, |
2218 const std::string& value, | 2220 const std::string& value, |
2219 bool hasOldRevision, | 2221 bool hasOldRevision, |
2220 int64_t oldRevision) : | 2222 int64_t oldRevision, |
2223 const std::string& oldMD5) : | |
2221 newRevision_(newRevision), | 2224 newRevision_(newRevision), |
2222 publicId_(publicId), | 2225 publicId_(publicId), |
2223 type_(type), | 2226 type_(type), |
2224 value_(value), | 2227 value_(value), |
2225 hasOldRevision_(hasOldRevision), | 2228 hasOldRevision_(hasOldRevision), |
2226 oldRevision_(oldRevision) | 2229 oldRevision_(oldRevision), |
2230 oldMD5_(oldMD5) | |
2227 { | 2231 { |
2228 } | 2232 } |
2229 | 2233 |
2230 virtual void Apply(ReadWriteTransaction& transaction) ORTHANC_OVERRIDE | 2234 virtual void Apply(ReadWriteTransaction& transaction) ORTHANC_OVERRIDE |
2231 { | 2235 { |
2239 { | 2243 { |
2240 std::string oldValue; | 2244 std::string oldValue; |
2241 int64_t expectedRevision; | 2245 int64_t expectedRevision; |
2242 if (transaction.LookupMetadata(oldValue, expectedRevision, id, type_)) | 2246 if (transaction.LookupMetadata(oldValue, expectedRevision, id, type_)) |
2243 { | 2247 { |
2244 if (hasOldRevision_ && | 2248 if (hasOldRevision_) |
2245 expectedRevision != oldRevision_) | 2249 { |
2246 { | 2250 std::string expectedMD5; |
2247 throw OrthancException(ErrorCode_Revision); | 2251 Toolbox::ComputeMD5(expectedMD5, oldValue); |
2248 } | 2252 |
2249 else | 2253 if (expectedRevision != oldRevision_ || |
2250 { | 2254 expectedMD5 != oldMD5_) |
2251 newRevision_ = expectedRevision + 1; | 2255 { |
2252 } | 2256 throw OrthancException(ErrorCode_Revision); |
2257 } | |
2258 } | |
2259 | |
2260 newRevision_ = expectedRevision + 1; | |
2253 } | 2261 } |
2254 else | 2262 else |
2255 { | 2263 { |
2256 // The metadata is not existing yet: Ignore "oldRevision" | 2264 // The metadata is not existing yet: Ignore "oldRevision" |
2257 // and initialize a new sequence of revisions | 2265 // and initialize a new sequence of revisions |
2266 } | 2274 } |
2267 } | 2275 } |
2268 } | 2276 } |
2269 }; | 2277 }; |
2270 | 2278 |
2271 Operations operations(newRevision, publicId, type, value, hasOldRevision, oldRevision); | 2279 Operations operations(newRevision, publicId, type, value, hasOldRevision, oldRevision, oldMD5); |
2272 Apply(operations); | 2280 Apply(operations); |
2273 } | 2281 } |
2274 | 2282 |
2275 | 2283 |
2276 void StatelessDatabaseOperations::OverwriteMetadata(const std::string& publicId, | 2284 void StatelessDatabaseOperations::OverwriteMetadata(const std::string& publicId, |
2277 MetadataType type, | 2285 MetadataType type, |
2278 const std::string& value) | 2286 const std::string& value) |
2279 { | 2287 { |
2280 int64_t newRevision; // Unused | 2288 int64_t newRevision; // Unused |
2281 SetMetadata(newRevision, publicId, type, value, false /* no old revision */, -1 /* dummy */); | 2289 SetMetadata(newRevision, publicId, type, value, false /* no old revision */, -1 /* dummy */, "" /* dummy */); |
2282 } | 2290 } |
2283 | 2291 |
2284 | 2292 |
2285 bool StatelessDatabaseOperations::DeleteMetadata(const std::string& publicId, | 2293 bool StatelessDatabaseOperations::DeleteMetadata(const std::string& publicId, |
2286 MetadataType type, | 2294 MetadataType type, |
2287 bool hasRevision, | 2295 bool hasRevision, |
2288 int64_t revision) | 2296 int64_t revision, |
2297 const std::string& md5) | |
2289 { | 2298 { |
2290 class Operations : public IReadWriteOperations | 2299 class Operations : public IReadWriteOperations |
2291 { | 2300 { |
2292 private: | 2301 private: |
2293 const std::string& publicId_; | 2302 const std::string& publicId_; |
2294 MetadataType type_; | 2303 MetadataType type_; |
2295 bool hasRevision_; | 2304 bool hasRevision_; |
2296 int64_t revision_; | 2305 int64_t revision_; |
2306 const std::string& md5_; | |
2297 bool found_; | 2307 bool found_; |
2298 | 2308 |
2299 public: | 2309 public: |
2300 Operations(const std::string& publicId, | 2310 Operations(const std::string& publicId, |
2301 MetadataType type, | 2311 MetadataType type, |
2302 bool hasRevision, | 2312 bool hasRevision, |
2303 int64_t revision) : | 2313 int64_t revision, |
2314 const std::string& md5) : | |
2304 publicId_(publicId), | 2315 publicId_(publicId), |
2305 type_(type), | 2316 type_(type), |
2306 hasRevision_(hasRevision), | 2317 hasRevision_(hasRevision), |
2307 revision_(revision), | 2318 revision_(revision), |
2319 md5_(md5), | |
2308 found_(false) | 2320 found_(false) |
2309 { | 2321 { |
2310 } | 2322 } |
2311 | 2323 |
2312 bool HasFound() const | 2324 bool HasFound() const |
2322 { | 2334 { |
2323 throw OrthancException(ErrorCode_UnknownResource); | 2335 throw OrthancException(ErrorCode_UnknownResource); |
2324 } | 2336 } |
2325 else | 2337 else |
2326 { | 2338 { |
2327 std::string s; | 2339 std::string value; |
2328 int64_t expectedRevision; | 2340 int64_t expectedRevision; |
2329 if (transaction.LookupMetadata(s, expectedRevision, id, type_)) | 2341 if (transaction.LookupMetadata(value, expectedRevision, id, type_)) |
2330 { | 2342 { |
2331 if (hasRevision_ && | 2343 if (hasRevision_) |
2332 expectedRevision != revision_) | 2344 { |
2333 { | 2345 std::string expectedMD5; |
2334 throw OrthancException(ErrorCode_Revision); | 2346 Toolbox::ComputeMD5(expectedMD5, value); |
2347 | |
2348 if (expectedRevision != revision_ || | |
2349 expectedMD5 != md5_) | |
2350 { | |
2351 throw OrthancException(ErrorCode_Revision); | |
2352 } | |
2335 } | 2353 } |
2336 | 2354 |
2337 found_ = true; | 2355 found_ = true; |
2338 transaction.DeleteMetadata(id, type_); | 2356 transaction.DeleteMetadata(id, type_); |
2339 | 2357 |
2340 if (IsUserMetadata(type_)) | 2358 if (IsUserMetadata(type_)) |
2341 { | 2359 { |
2342 transaction.LogChange(id, ChangeType_UpdatedMetadata, resourceType, publicId_); | 2360 transaction.LogChange(id, ChangeType_UpdatedMetadata, resourceType, publicId_); |
2343 } | 2361 } |
2344 } | 2362 } |
2348 } | 2366 } |
2349 } | 2367 } |
2350 } | 2368 } |
2351 }; | 2369 }; |
2352 | 2370 |
2353 Operations operations(publicId, type, hasRevision, revision); | 2371 Operations operations(publicId, type, hasRevision, revision, md5); |
2354 Apply(operations); | 2372 Apply(operations); |
2355 return operations.HasFound(); | 2373 return operations.HasFound(); |
2356 } | 2374 } |
2357 | 2375 |
2358 | 2376 |
2483 | 2501 |
2484 | 2502 |
2485 bool StatelessDatabaseOperations::DeleteAttachment(const std::string& publicId, | 2503 bool StatelessDatabaseOperations::DeleteAttachment(const std::string& publicId, |
2486 FileContentType type, | 2504 FileContentType type, |
2487 bool hasRevision, | 2505 bool hasRevision, |
2488 int64_t revision) | 2506 int64_t revision, |
2507 const std::string& md5) | |
2489 { | 2508 { |
2490 class Operations : public IReadWriteOperations | 2509 class Operations : public IReadWriteOperations |
2491 { | 2510 { |
2492 private: | 2511 private: |
2493 const std::string& publicId_; | 2512 const std::string& publicId_; |
2494 FileContentType type_; | 2513 FileContentType type_; |
2495 bool hasRevision_; | 2514 bool hasRevision_; |
2496 int64_t revision_; | 2515 int64_t revision_; |
2516 const std::string& md5_; | |
2497 bool found_; | 2517 bool found_; |
2498 | 2518 |
2499 public: | 2519 public: |
2500 Operations(const std::string& publicId, | 2520 Operations(const std::string& publicId, |
2501 FileContentType type, | 2521 FileContentType type, |
2502 bool hasRevision, | 2522 bool hasRevision, |
2503 int64_t revision) : | 2523 int64_t revision, |
2524 const std::string& md5) : | |
2504 publicId_(publicId), | 2525 publicId_(publicId), |
2505 type_(type), | 2526 type_(type), |
2506 hasRevision_(hasRevision), | 2527 hasRevision_(hasRevision), |
2507 revision_(revision), | 2528 revision_(revision), |
2529 md5_(md5), | |
2508 found_(false) | 2530 found_(false) |
2509 { | 2531 { |
2510 } | 2532 } |
2511 | 2533 |
2512 bool HasFound() const | 2534 bool HasFound() const |
2527 FileInfo info; | 2549 FileInfo info; |
2528 int64_t expectedRevision; | 2550 int64_t expectedRevision; |
2529 if (transaction.LookupAttachment(info, expectedRevision, id, type_)) | 2551 if (transaction.LookupAttachment(info, expectedRevision, id, type_)) |
2530 { | 2552 { |
2531 if (hasRevision_ && | 2553 if (hasRevision_ && |
2532 expectedRevision != revision_) | 2554 (expectedRevision != revision_ || |
2555 info.GetUncompressedMD5() != md5_)) | |
2533 { | 2556 { |
2534 throw OrthancException(ErrorCode_Revision); | 2557 throw OrthancException(ErrorCode_Revision); |
2535 } | 2558 } |
2536 | 2559 |
2537 found_ = true; | 2560 found_ = true; |
2548 } | 2571 } |
2549 } | 2572 } |
2550 } | 2573 } |
2551 }; | 2574 }; |
2552 | 2575 |
2553 Operations operations(publicId, type, hasRevision, revision); | 2576 Operations operations(publicId, type, hasRevision, revision, md5); |
2554 Apply(operations); | 2577 Apply(operations); |
2555 return operations.HasFound(); | 2578 return operations.HasFound(); |
2556 } | 2579 } |
2557 | 2580 |
2558 | 2581 |
3259 const FileInfo& attachment, | 3282 const FileInfo& attachment, |
3260 const std::string& publicId, | 3283 const std::string& publicId, |
3261 uint64_t maximumStorageSize, | 3284 uint64_t maximumStorageSize, |
3262 unsigned int maximumPatients, | 3285 unsigned int maximumPatients, |
3263 bool hasOldRevision, | 3286 bool hasOldRevision, |
3264 int64_t oldRevision) | 3287 int64_t oldRevision, |
3288 const std::string& oldMD5) | |
3265 { | 3289 { |
3266 class Operations : public IReadWriteOperations | 3290 class Operations : public IReadWriteOperations |
3267 { | 3291 { |
3268 private: | 3292 private: |
3269 int64_t& newRevision_; | 3293 int64_t& newRevision_; |
3272 const std::string& publicId_; | 3296 const std::string& publicId_; |
3273 uint64_t maximumStorageSize_; | 3297 uint64_t maximumStorageSize_; |
3274 unsigned int maximumPatientCount_; | 3298 unsigned int maximumPatientCount_; |
3275 bool hasOldRevision_; | 3299 bool hasOldRevision_; |
3276 int64_t oldRevision_; | 3300 int64_t oldRevision_; |
3301 const std::string& oldMD5_; | |
3277 | 3302 |
3278 public: | 3303 public: |
3279 Operations(int64_t& newRevision, | 3304 Operations(int64_t& newRevision, |
3280 const FileInfo& attachment, | 3305 const FileInfo& attachment, |
3281 const std::string& publicId, | 3306 const std::string& publicId, |
3282 uint64_t maximumStorageSize, | 3307 uint64_t maximumStorageSize, |
3283 unsigned int maximumPatientCount, | 3308 unsigned int maximumPatientCount, |
3284 bool hasOldRevision, | 3309 bool hasOldRevision, |
3285 int64_t oldRevision) : | 3310 int64_t oldRevision, |
3311 const std::string& oldMD5) : | |
3286 newRevision_(newRevision), | 3312 newRevision_(newRevision), |
3287 status_(StoreStatus_Failure), | 3313 status_(StoreStatus_Failure), |
3288 attachment_(attachment), | 3314 attachment_(attachment), |
3289 publicId_(publicId), | 3315 publicId_(publicId), |
3290 maximumStorageSize_(maximumStorageSize), | 3316 maximumStorageSize_(maximumStorageSize), |
3291 maximumPatientCount_(maximumPatientCount), | 3317 maximumPatientCount_(maximumPatientCount), |
3292 hasOldRevision_(hasOldRevision), | 3318 hasOldRevision_(hasOldRevision), |
3293 oldRevision_(oldRevision) | 3319 oldRevision_(oldRevision), |
3320 oldMD5_(oldMD5) | |
3294 { | 3321 { |
3295 } | 3322 } |
3296 | 3323 |
3297 StoreStatus GetStatus() const | 3324 StoreStatus GetStatus() const |
3298 { | 3325 { |
3314 FileInfo oldFile; | 3341 FileInfo oldFile; |
3315 int64_t expectedRevision; | 3342 int64_t expectedRevision; |
3316 if (transaction.LookupAttachment(oldFile, expectedRevision, resourceId, attachment_.GetContentType())) | 3343 if (transaction.LookupAttachment(oldFile, expectedRevision, resourceId, attachment_.GetContentType())) |
3317 { | 3344 { |
3318 if (hasOldRevision_ && | 3345 if (hasOldRevision_ && |
3319 expectedRevision != oldRevision_) | 3346 (expectedRevision != oldRevision_ || |
3347 oldFile.GetUncompressedMD5() != oldMD5_)) | |
3320 { | 3348 { |
3321 throw OrthancException(ErrorCode_Revision); | 3349 throw OrthancException(ErrorCode_Revision); |
3322 } | 3350 } |
3323 else | 3351 else |
3324 { | 3352 { |
3369 } | 3397 } |
3370 } | 3398 } |
3371 }; | 3399 }; |
3372 | 3400 |
3373 | 3401 |
3374 Operations operations(newRevision, attachment, publicId, maximumStorageSize, maximumPatients, hasOldRevision, oldRevision); | 3402 Operations operations(newRevision, attachment, publicId, maximumStorageSize, maximumPatients, |
3403 hasOldRevision, oldRevision, oldMD5); | |
3375 Apply(operations); | 3404 Apply(operations); |
3376 return operations.GetStatus(); | 3405 return operations.GetStatus(); |
3377 } | 3406 } |
3378 } | 3407 } |