diff --git a/catalogue/SqliteCatalogue.cpp b/catalogue/SqliteCatalogue.cpp index 4f1bc1690971de1c3fda0140431af602088c2019..0ccaa5836e1df0bc91ca6b07d3005c61f1552cdf 100644 --- a/catalogue/SqliteCatalogue.cpp +++ b/catalogue/SqliteCatalogue.cpp @@ -185,21 +185,31 @@ void SqliteCatalogue::deleteArchiveFile(const std::string &diskInstanceName, con //------------------------------------------------------------------------------ uint64_t SqliteCatalogue::getNextArchiveFileId(rdbms::Conn &conn) { try { - conn.executeNonQuery("INSERT INTO ARCHIVE_FILE_ID VALUES(NULL)", rdbms::AutocommitMode::AUTOCOMMIT_ON); + // The SQLite implemenation of getNextArchiveFileId() serializes access to + // the SQLite database in order to avoid busy errors + threading::MutexLocker locker(m_mutex); + + rdbms::AutoRollback autoRollback(conn); + + conn.executeNonQuery("UPDATE ARCHIVE_FILE_ID SET ID = ID + 1", rdbms::AutocommitMode::AUTOCOMMIT_OFF); uint64_t archiveFileId = 0; { - const char *const sql = "SELECT LAST_INSERT_ROWID() AS ID"; + const char *const sql = + "SELECT " + "ID AS ID " + "FROM " + "ARCHIVE_FILE_ID"; auto stmt = conn.createStmt(sql); - auto rset = stmt.executeQuery(rdbms::AutocommitMode::AUTOCOMMIT_ON); + auto rset = stmt.executeQuery(rdbms::AutocommitMode::AUTOCOMMIT_OFF); if(!rset.next()) { - throw exception::Exception(std::string("Unexpected empty result set for '") + sql + "\'"); + throw exception::Exception("ARCHIVE_FILE_ID table is empty"); } archiveFileId = rset.columnUint64("ID"); if(rset.next()) { - throw exception::Exception(std::string("Unexpectedly found more than one row in the result of '") + sql + "\'"); + throw exception::Exception("Found more than one ID counter in the ARCHIVE_FILE_ID table"); } } - conn.executeNonQuery("DELETE FROM ARCHIVE_FILE_ID", rdbms::AutocommitMode::AUTOCOMMIT_ON); + conn.commit(); return archiveFileId; } catch(exception::UserError &) { @@ -214,30 +224,33 @@ uint64_t SqliteCatalogue::getNextArchiveFileId(rdbms::Conn &conn) { // getNextStorageClassId //------------------------------------------------------------------------------ uint64_t SqliteCatalogue::getNextStorageClassId(rdbms::Conn &conn) { - try { - conn.executeNonQuery("INSERT INTO STORAGE_CLASS_ID VALUES(NULL)", rdbms::AutocommitMode::AUTOCOMMIT_ON); - uint64_t storageClassId = 0; - { - const char *const sql = "SELECT LAST_INSERT_ROWID() AS ID"; - auto stmt = conn.createStmt(sql); - auto rset = stmt.executeQuery(rdbms::AutocommitMode::AUTOCOMMIT_ON); - if(!rset.next()) { - throw exception::Exception(std::string("Unexpected empty result set for '") + sql + "\'"); - } - storageClassId = rset.columnUint64("ID"); - if(rset.next()) { - throw exception::Exception(std::string("Unexpectedly found more than one row in the result of '") + sql + "\'"); - } - } - conn.executeNonQuery("DELETE FROM STORAGE_CLASS_ID", rdbms::AutocommitMode::AUTOCOMMIT_ON); + // The SQLite implemenation of getNextStorageClassId() serializes access to + // the SQLite database in order to avoid busy errors + threading::MutexLocker locker(m_mutex); - return storageClassId; - } catch(exception::UserError &) { - throw; - } catch(exception::Exception &ex) { - ex.getMessage().str(std::string(__FUNCTION__) + ": " + ex.getMessage().str()); - throw; + rdbms::AutoRollback autoRollback(conn); + + conn.executeNonQuery("UPDATE STORAGE_CLASS_ID SET ID = ID + 1", rdbms::AutocommitMode::AUTOCOMMIT_OFF); + uint64_t storageClassId = 0; + { + const char *const sql = + "SELECT " + "ID AS ID " + "FROM " + "STORAGE_CLASS_ID"; + auto stmt = conn.createStmt(sql); + auto rset = stmt.executeQuery(rdbms::AutocommitMode::AUTOCOMMIT_OFF); + if(!rset.next()) { + throw exception::Exception("STORAGE_CLASS_ID table is empty"); + } + storageClassId = rset.columnUint64("ID"); + if(rset.next()) { + throw exception::Exception("Found more than one ID counter in the STORAGE_CLASS_ID table"); + } } + conn.commit(); + + return storageClassId; } //------------------------------------------------------------------------------ diff --git a/catalogue/sqlite_catalogue_schema_header.sql b/catalogue/sqlite_catalogue_schema_header.sql index 58e697395870faa928cfb2c1894f0365d935980d..d4b8454715321e269d2f80666f369b0e62a3e37e 100644 --- a/catalogue/sqlite_catalogue_schema_header.sql +++ b/catalogue/sqlite_catalogue_schema_header.sql @@ -1,6 +1,10 @@ CREATE TABLE ARCHIVE_FILE_ID( - ID INTEGER PRIMARY KEY AUTOINCREMENT + ID INTEGER, + CONSTRAINT ARCHIVE_FILE_ID_PK PRIMARY KEY(ID) ); +INSERT INTO ARCHIVE_FILE_ID(ID) VALUES(1); CREATE TABLE STORAGE_CLASS_ID( - ID INTEGER PRIMARY KEY AUTOINCREMENT + ID INTEGER, + CONSTRAINT STORAGE_CLASS_ID_PK PRIMARY KEY(ID) ); +INSERT INTO STORAGE_CLASS_ID(ID) VALUES(1);