comparison PostgreSQL/Plugins/PostgreSQLIndex.cpp @ 418:a7f0f27fe33c pg-transactions

wip: advisory lock around CreateInstance: not ok see WO-139
author Alain Mazy <am@osimis.io>
date Tue, 27 Jun 2023 15:17:39 +0200
parents 91124cc8a8c7
children 3cdea26ece73
comparison
equal deleted inserted replaced
417:15bfd9a76f8d 418:a7f0f27fe33c
131 { 131 {
132 revision = 1; 132 revision = 1;
133 SetGlobalIntegerProperty(manager, MISSING_SERVER_IDENTIFIER, Orthanc::GlobalProperty_DatabasePatchLevel, revision); 133 SetGlobalIntegerProperty(manager, MISSING_SERVER_IDENTIFIER, Orthanc::GlobalProperty_DatabasePatchLevel, revision);
134 } 134 }
135 135
136 if (revision != 1) 136 if (revision == 1)
137 {
138 LOG(WARNING) << "PostgreSQL plugin: adding UNIQUE(publicId) constraint to the 'Resources' table ";
139 t.GetDatabaseTransaction().ExecuteMultiLines("ALTER TABLE Resources ADD UNIQUE (publicId);");
140
141 revision = 2;
142 SetGlobalIntegerProperty(manager, MISSING_SERVER_IDENTIFIER, Orthanc::GlobalProperty_DatabasePatchLevel, revision);
143 }
144
145 if (revision != 2)
137 { 146 {
138 LOG(ERROR) << "PostgreSQL plugin is incompatible with database schema revision: " << revision; 147 LOG(ERROR) << "PostgreSQL plugin is incompatible with database schema revision: " << revision;
139 throw Orthanc::OrthancException(Orthanc::ErrorCode_Database); 148 throw Orthanc::OrthancException(Orthanc::ErrorCode_Database);
140 } 149 }
141 150
404 Dictionary args; 413 Dictionary args;
405 args.SetUtf8Value("patient", hashPatient); 414 args.SetUtf8Value("patient", hashPatient);
406 args.SetUtf8Value("study", hashStudy); 415 args.SetUtf8Value("study", hashStudy);
407 args.SetUtf8Value("series", hashSeries); 416 args.SetUtf8Value("series", hashSeries);
408 args.SetUtf8Value("instance", hashInstance); 417 args.SetUtf8Value("instance", hashInstance);
409 418
410 statement.Execute(args); 419 { // The CreateInstance procedure is not 100% safe in highly concurrent environments when the
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 }
411 429
412 if (statement.IsDone() || 430 if (statement.IsDone() ||
413 statement.GetResultFieldsCount() != 8) 431 statement.GetResultFieldsCount() != 8)
414 { 432 {
415 throw Orthanc::OrthancException(Orthanc::ErrorCode_Database); 433 throw Orthanc::OrthancException(Orthanc::ErrorCode_Database);