Mercurial > hg > orthanc-databases
comparison PostgreSQL/Plugins/PostgreSQLIndex.cpp @ 428:4d0bacbd0fba pg-transactions
rewrote CreateInstance to make it compatible with READ COMMITED transactions
author | Alain Mazy <am@osimis.io> |
---|---|
date | Thu, 30 Nov 2023 14:46:38 +0100 |
parents | 3cdea26ece73 |
children | 7c1fe5d6c12c |
comparison
equal
deleted
inserted
replaced
427:3cdea26ece73 | 428:4d0bacbd0fba |
---|---|
202 DatabaseManager::Transaction t(manager, TransactionType_ReadWrite); | 202 DatabaseManager::Transaction t(manager, TransactionType_ReadWrite); |
203 | 203 |
204 int property = 0; | 204 int property = 0; |
205 if (!LookupGlobalIntegerProperty(property, manager, MISSING_SERVER_IDENTIFIER, | 205 if (!LookupGlobalIntegerProperty(property, manager, MISSING_SERVER_IDENTIFIER, |
206 Orthanc::GlobalProperty_HasCreateInstance) || | 206 Orthanc::GlobalProperty_HasCreateInstance) || |
207 property != 2) | 207 property != 3) |
208 { | 208 { |
209 LOG(INFO) << "Installing the CreateInstance extension"; | 209 LOG(INFO) << "Installing the CreateInstance extension"; |
210 | 210 |
211 if (property == 1) | 211 if (property == 1) |
212 { | 212 { |
213 // Drop older, experimental versions of this extension | 213 // Drop older, experimental versions of this extension |
214 t.GetDatabaseTransaction().ExecuteMultiLines("DROP FUNCTION CreateInstance(" | 214 t.GetDatabaseTransaction().ExecuteMultiLines("DROP FUNCTION CreateInstance(" |
215 "IN patient TEXT, IN study TEXT, IN series TEXT, in instance TEXT)"); | 215 "IN patient TEXT, IN study TEXT, IN series TEXT, in instance TEXT)"); |
216 } | 216 } |
217 | 217 |
218 // property == 2 was a first version of the CreateInstance -> we need to replace it by the new one | |
219 // property == 3 is a new version (in v5.2) with same signature and CREATE OR UPDATE | |
220 // -> we can replace the previous one without deleting it | |
221 // and we can create it if it has never been created. | |
218 std::string query; | 222 std::string query; |
219 Orthanc::EmbeddedResources::GetFileResource | 223 Orthanc::EmbeddedResources::GetFileResource |
220 (query, Orthanc::EmbeddedResources::POSTGRESQL_CREATE_INSTANCE); | 224 (query, Orthanc::EmbeddedResources::POSTGRESQL_CREATE_INSTANCE); |
221 t.GetDatabaseTransaction().ExecuteMultiLines(query); | 225 t.GetDatabaseTransaction().ExecuteMultiLines(query); |
222 | 226 |
223 SetGlobalIntegerProperty(manager, MISSING_SERVER_IDENTIFIER, Orthanc::GlobalProperty_HasCreateInstance, 2); | 227 SetGlobalIntegerProperty(manager, MISSING_SERVER_IDENTIFIER, Orthanc::GlobalProperty_HasCreateInstance, 3); |
224 } | 228 } |
225 | 229 |
226 | 230 |
227 if (!LookupGlobalIntegerProperty(property, manager, MISSING_SERVER_IDENTIFIER, | 231 if (!LookupGlobalIntegerProperty(property, manager, MISSING_SERVER_IDENTIFIER, |
228 Orthanc::GlobalProperty_GetTotalSizeIsFast) || | 232 Orthanc::GlobalProperty_GetTotalSizeIsFast) || |
365 statement.Execute(); | 369 statement.Execute(); |
366 | 370 |
367 result = static_cast<uint64_t>(statement.ReadInteger64(0)); | 371 result = static_cast<uint64_t>(statement.ReadInteger64(0)); |
368 } | 372 } |
369 | 373 |
370 assert(result == IndexBackend::GetTotalCompressedSize(manager)); | 374 // disabled because this is not alway true while transactions are being executed in READ COMITTED TRANSACTION. This is however true when no files are being delete/added |
375 //assert(result == IndexBackend::GetTotalCompressedSize(manager)); | |
371 return result; | 376 return result; |
372 } | 377 } |
373 | 378 |
374 | 379 |
375 uint64_t PostgreSQLIndex::GetTotalUncompressedSize(DatabaseManager& manager) | 380 uint64_t PostgreSQLIndex::GetTotalUncompressedSize(DatabaseManager& manager) |
386 statement.Execute(); | 391 statement.Execute(); |
387 | 392 |
388 result = static_cast<uint64_t>(statement.ReadInteger64(0)); | 393 result = static_cast<uint64_t>(statement.ReadInteger64(0)); |
389 } | 394 } |
390 | 395 |
391 assert(result == IndexBackend::GetTotalUncompressedSize(manager)); | 396 // disabled because this is not alway true while transactions are being executed in READ COMITTED TRANSACTION. This is however true when no files are being delete/added |
397 // assert(result == IndexBackend::GetTotalUncompressedSize(manager)); | |
392 return result; | 398 return result; |
393 } | 399 } |
394 | 400 |
395 | 401 |
396 #if ORTHANC_PLUGINS_HAS_DATABASE_CONSTRAINT == 1 | 402 #if ORTHANC_PLUGINS_HAS_DATABASE_CONSTRAINT == 1 |
414 args.SetUtf8Value("patient", hashPatient); | 420 args.SetUtf8Value("patient", hashPatient); |
415 args.SetUtf8Value("study", hashStudy); | 421 args.SetUtf8Value("study", hashStudy); |
416 args.SetUtf8Value("series", hashSeries); | 422 args.SetUtf8Value("series", hashSeries); |
417 args.SetUtf8Value("instance", hashInstance); | 423 args.SetUtf8Value("instance", hashInstance); |
418 | 424 |
419 { // The CreateInstance procedure is not 100% safe in highly concurrent environments when the | 425 statement.Execute(args); |
420 // transaction isolation is set to "READ COMMITED": (e.g, with 10 clients | |
421 // anonymizing studies in parallel with the "ResourceModification" config set to 8, we have observed | |
422 // the same series being created twice). Therefore, we protect the whole CreateInstance procedure | |
423 // with an advisory lock | |
424 PostgreSQLDatabase& db = dynamic_cast<PostgreSQLDatabase&>(manager.GetDatabase()); | |
425 PostgreSQLDatabase::TransientAdvisoryLock lock(db, POSTGRESQL_LOCK_CREATE_INSTANCE, 100, 1); | |
426 | |
427 statement.Execute(args); | |
428 } | |
429 | 426 |
430 if (statement.IsDone() || | 427 if (statement.IsDone() || |
431 statement.GetResultFieldsCount() != 8) | 428 statement.GetResultFieldsCount() != 8) |
432 { | 429 { |
433 throw Orthanc::OrthancException(Orthanc::ErrorCode_Database); | 430 throw Orthanc::OrthancException(Orthanc::ErrorCode_Database); |
482 statement.Execute(args); | 479 statement.Execute(args); |
483 | 480 |
484 result = static_cast<uint64_t>(statement.ReadInteger64(0)); | 481 result = static_cast<uint64_t>(statement.ReadInteger64(0)); |
485 } | 482 } |
486 | 483 |
484 // disabled because this is not alway true while transactions are being executed in READ COMITTED TRANSACTION. This is however true when no files are being delete/added | |
487 assert(result == IndexBackend::GetResourcesCount(manager, resourceType)); | 485 assert(result == IndexBackend::GetResourcesCount(manager, resourceType)); |
486 | |
488 return result; | 487 return result; |
489 } | 488 } |
490 | 489 |
491 | 490 |
492 int64_t PostgreSQLIndex::GetLastChangeIndex(DatabaseManager& manager) | 491 int64_t PostgreSQLIndex::GetLastChangeIndex(DatabaseManager& manager) |