From 8f7bd42f8ddc25a45db594d93301fdf87c0fe183 Mon Sep 17 00:00:00 2001
From: Steven Murray <Steven.Murray@cern.ch>
Date: Fri, 9 Nov 2018 14:50:34 +0100
Subject: [PATCH] Removed the need for a deferred transaction from
 SQLiteCatalogue::getNextArchiveFileId() and getNextStorageClassId()

---
 catalogue/SqliteCatalogue.cpp                | 69 ++++++++------------
 catalogue/sqlite_catalogue_schema_header.sql |  8 +--
 2 files changed, 30 insertions(+), 47 deletions(-)

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