diff --git a/catalogue/OracleCatalogue.cpp b/catalogue/OracleCatalogue.cpp index 946c577a17d9ce84f86b0dfb411e239651a6bf42..f064efd69fdeca65992aac0ff6e066b497b753ba 100644 --- a/catalogue/OracleCatalogue.cpp +++ b/catalogue/OracleCatalogue.cpp @@ -16,6 +16,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include "catalogue/ArchiveFileRow.hpp" #include "catalogue/OracleCatalogue.hpp" #include "common/exception/UserError.hpp" #include "common/exception/Exception.hpp" @@ -276,5 +277,108 @@ common::dataStructures::Tape OracleCatalogue::selectTapeForUpdate(rdbms::PooledC } } +//------------------------------------------------------------------------------ +// filesWrittenToTape +//------------------------------------------------------------------------------ +void OracleCatalogue::filesWrittenToTape(const std::list<TapeFileWritten> &events) { + try { + if(events.empty()) { + return; + } + + const auto &firstEvent = events.front(); + checkTapeFileWrittenFieldsAreSet(firstEvent); + const time_t now = time(nullptr); + std::lock_guard<std::mutex> m_lock(m_mutex); + auto conn = m_connPool.getConn(); + rdbms::AutoRollback autoRollback(conn); + + const auto tape = selectTapeForUpdate(conn, firstEvent.vid); + uint64_t expectedFSeq = tape.lastFSeq + 1; + uint64_t totalCompressedBytesWritten = 0; + + for(const auto &event: events) { + checkTapeFileWrittenFieldsAreSet(firstEvent); + + if(event.vid != firstEvent.vid) { + throw exception::Exception(std::string("VID mismatch: expected=") + firstEvent.vid + " actual=event.vid"); + } + + if(expectedFSeq != event.fSeq) { + exception::Exception ex; + ex.getMessage() << "FSeq mismatch for tape " << firstEvent.vid << ": expected=" << expectedFSeq << " actual=" << + firstEvent.fSeq; + throw ex; + } + expectedFSeq++; + + totalCompressedBytesWritten += event.compressedSize; + } + + const TapeFileWritten &lastEvent = events.back(); + updateTape(conn, rdbms::Stmt::AutocommitMode::OFF, lastEvent.vid, lastEvent.fSeq, totalCompressedBytesWritten, + lastEvent.tapeDrive); + + const char *const sql = + "INSERT INTO TAPE_FILE(" + "VID," + "FSEQ," + "BLOCK_ID," + "COMPRESSED_SIZE_IN_BYTES," + "COPY_NB," + "CREATION_TIME," + "ARCHIVE_FILE_ID)" + "VALUES(" + ":VID," + ":FSEQ," + ":BLOCK_ID," + ":COMPRESSED_SIZE_IN_BYTES," + ":COPY_NB," + ":CREATION_TIME," + ":ARCHIVE_FILE_ID)"; + + for(const auto &event: events) { + checkTapeFileWrittenFieldsAreSet(firstEvent); + + std::unique_ptr<common::dataStructures::ArchiveFile> archiveFile = getArchiveFile(conn, event.archiveFileId); + + // If the archive file does not already exist + if(nullptr == archiveFile.get()) { + // Create one + ArchiveFileRow row; + row.archiveFileId = event.archiveFileId; + row.diskFileId = event.diskFileId; + row.diskInstance = event.diskInstance; + row.size = event.size; + row.checksumType = event.checksumType; + row.checksumValue = event.checksumValue; + row.storageClassName = event.storageClassName; + row.diskFilePath = event.diskFilePath; + row.diskFileUser = event.diskFileUser; + row.diskFileGroup = event.diskFileGroup; + row.diskFileRecoveryBlob = event.diskFileRecoveryBlob; + insertArchiveFile(conn, rdbms::Stmt::AutocommitMode::OFF, row); + } else { + throwIfCommonEventDataMismatch(*archiveFile, event); + } + + auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::OFF); + stmt->bindString(":VID", event.vid); + stmt->bindUint64(":FSEQ", event.fSeq); + stmt->bindUint64(":BLOCK_ID", event.blockId); + stmt->bindUint64(":COMPRESSED_SIZE_IN_BYTES", event.compressedSize); + stmt->bindUint64(":COPY_NB", event.copyNb); + stmt->bindUint64(":CREATION_TIME", now); + stmt->bindUint64(":ARCHIVE_FILE_ID", event.archiveFileId); + stmt->executeNonQuery(); + } // for(const auto &event: events) + + conn.commit(); + + } catch(exception::Exception &ex) { + throw exception::Exception(std::string(__FUNCTION__) + " failed: " + ex.getMessage().str()); + } +} + } // namespace catalogue } // namespace cta diff --git a/catalogue/OracleCatalogue.hpp b/catalogue/OracleCatalogue.hpp index 224c030c307a3a96450170843b0704553c4b40f0..f2b39843ed72fbb2a73751128cabebe91c07baa8 100644 --- a/catalogue/OracleCatalogue.hpp +++ b/catalogue/OracleCatalogue.hpp @@ -82,16 +82,21 @@ public: uint64_t getNextArchiveFileId(rdbms::PooledConn &conn) override; /** - * Selects the specified tape within the Tape table for update. + * Notifies the catalogue that the specified files have been written to tape. * - * This method must be implemented by the sub-classes of RdbmsCatalogue - * because some database technologies directly support SELECT FOR UPDATE - * whilst others do not. + * @param events The tape file written events. + */ + void filesWrittenToTape(const std::list<TapeFileWritten> &events) override; + +private: + + /** + * Selects the specified tape within the Tape table for update. * * @param conn The database connection. * @param vid The volume identifier of the tape. */ - common::dataStructures::Tape selectTapeForUpdate(rdbms::PooledConn &conn, const std::string &vid) override; + common::dataStructures::Tape selectTapeForUpdate(rdbms::PooledConn &conn, const std::string &vid); }; // class OracleCatalogue diff --git a/catalogue/RdbmsCatalogue.cpp b/catalogue/RdbmsCatalogue.cpp index e917188e3a6419bdfce5ec326c229805f36e1303..aff68c9bf39ec3df53e8b1bd7cb82a824dfe2dca 100644 --- a/catalogue/RdbmsCatalogue.cpp +++ b/catalogue/RdbmsCatalogue.cpp @@ -27,7 +27,6 @@ #include "rdbms/AutoRollback.hpp" #include <ctype.h> -#include <iostream> #include <memory> #include <time.h> @@ -3391,7 +3390,8 @@ void RdbmsCatalogue::modifyMountPolicyComment(const common::dataStructures::Secu //------------------------------------------------------------------------------ // insertArchiveFile //------------------------------------------------------------------------------ -void RdbmsCatalogue::insertArchiveFile(rdbms::PooledConn &conn, const ArchiveFileRow &row) { +void RdbmsCatalogue::insertArchiveFile(rdbms::PooledConn &conn, const rdbms::Stmt::AutocommitMode autocommitMode, + const ArchiveFileRow &row) { try { if(!storageClassExists(conn, row.diskInstance, row.storageClassName)) { throw exception::UserError(std::string("Storage class ") + row.diskInstance + ":" + row.storageClassName + @@ -3428,7 +3428,7 @@ void RdbmsCatalogue::insertArchiveFile(rdbms::PooledConn &conn, const ArchiveFil ":STORAGE_CLASS_NAME," ":CREATION_TIME," ":RECONCILIATION_TIME)"; - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::ON); + auto stmt = conn.createStmt(sql, autocommitMode); stmt->bindUint64(":ARCHIVE_FILE_ID", row.archiveFileId); stmt->bindString(":DISK_INSTANCE_NAME", row.diskInstance); @@ -4079,94 +4079,16 @@ uint64_t RdbmsCatalogue::getExpectedNbArchiveRoutes(rdbms::PooledConn &conn, con } } -//------------------------------------------------------------------------------ -// filesWrittenToTape -//------------------------------------------------------------------------------ -void RdbmsCatalogue::filesWrittenToTape(const std::list<TapeFileWritten> &events) { - try { - for(const auto &event : events) { - fileWrittenToTape(event); - } - } catch(exception::Exception &ex) { - throw exception::Exception(std::string(__FUNCTION__) + " failed: " + ex.getMessage().str()); - } -} - -//------------------------------------------------------------------------------ -// fileWrittenToTape -//------------------------------------------------------------------------------ -void RdbmsCatalogue::fileWrittenToTape(const TapeFileWritten &event) { - try { - if(event.diskInstance.empty()) throw exception::Exception("diskInstance is an empty string"); - if(event.diskFileId.empty()) throw exception::Exception("diskFileId is an empty string"); - if(event.diskFilePath.empty()) throw exception::Exception("diskFilePath is an empty string"); - if(event.diskFileUser.empty()) throw exception::Exception("diskFileUser is an empty string"); - if(event.diskFileGroup.empty()) throw exception::Exception("diskFileGroup is an empty string"); - if(event.diskFileRecoveryBlob.empty()) throw exception::Exception("diskFileRecoveryBlob is an empty string"); - if(event.checksumType.empty()) throw exception::Exception("checksumType is an empty string"); - if(event.checksumValue.empty()) throw exception::Exception("checksumValue is an empty string"); - if(event.storageClassName.empty()) throw exception::Exception("storageClassName is an empty string"); - if(event.vid.empty()) throw exception::Exception("vid is an empty string"); - if(event.tapeDrive.empty()) throw exception::Exception("tapeDrive is an empty string"); - - const time_t now = time(nullptr); - std::lock_guard<std::mutex> m_lock(m_mutex); - - auto conn = m_connPool.getConn(); - rdbms::AutoRollback autoRollback(conn); - const common::dataStructures::Tape tape = selectTapeForUpdate(conn, event.vid); - - const uint64_t expectedFSeq = tape.lastFSeq + 1; - if(expectedFSeq != event.fSeq) { - exception::Exception ex; - ex.getMessage() << "FSeq mismatch for tape " << event.vid << ": expected=" << expectedFSeq << " actual=" << - event.fSeq; - throw ex; - } - updateTape(conn, event); - - std::unique_ptr<common::dataStructures::ArchiveFile> archiveFile = getArchiveFile(conn, event.archiveFileId); - - // If the archive file does not already exist - if(nullptr == archiveFile.get()) { - // Create one - ArchiveFileRow row; - row.archiveFileId = event.archiveFileId; - row.diskFileId = event.diskFileId; - row.diskInstance = event.diskInstance; - row.size = event.size; - row.checksumType = event.checksumType; - row.checksumValue = event.checksumValue; - row.storageClassName = event.storageClassName; - row.diskFilePath = event.diskFilePath; - row.diskFileUser = event.diskFileUser; - row.diskFileGroup = event.diskFileGroup; - row.diskFileRecoveryBlob = event.diskFileRecoveryBlob; - insertArchiveFile(conn, row); - } else { - throwIfCommonEventDataMismatch(*archiveFile, event); - } - - // Create the tape file - common::dataStructures::TapeFile tapeFile; - tapeFile.vid = event.vid; - tapeFile.fSeq = event.fSeq; - tapeFile.blockId = event.blockId; - tapeFile.compressedSize = event.compressedSize; - tapeFile.copyNb = event.copyNb; - tapeFile.creationTime = now; - insertTapeFile(conn, tapeFile, event.archiveFileId); - - conn.commit(); - } catch(exception::Exception &ex) { - throw exception::Exception(std::string(__FUNCTION__) + " failed: " + ex.getMessage().str()); - } -} - //------------------------------------------------------------------------------ // updateTape //------------------------------------------------------------------------------ -void RdbmsCatalogue::updateTape(rdbms::PooledConn &conn, const TapeFileWritten &event) { +void RdbmsCatalogue::updateTape( + rdbms::PooledConn &conn, + const rdbms::Stmt::AutocommitMode autocommitMode, + const std::string &vid, + const uint64_t lastFSeq, + const uint64_t compressedBytesWritten, + const std::string &tapeDrive) { try { const time_t now = time(nullptr); const char *const sql = @@ -4177,11 +4099,11 @@ void RdbmsCatalogue::updateTape(rdbms::PooledConn &conn, const TapeFileWritten & "LAST_WRITE_TIME = :LAST_WRITE_TIME " "WHERE " "VID = :VID"; - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::ON); - stmt->bindString(":VID", event.vid); - stmt->bindUint64(":LAST_FSEQ", event.fSeq); - stmt->bindUint64(":DATA_IN_BYTES", event.compressedSize); - stmt->bindString(":LAST_WRITE_DRIVE", event.tapeDrive); + auto stmt = conn.createStmt(sql, autocommitMode); + stmt->bindString(":VID", vid); + stmt->bindUint64(":LAST_FSEQ", lastFSeq); + stmt->bindUint64(":DATA_IN_BYTES", compressedBytesWritten); + stmt->bindString(":LAST_WRITE_DRIVE", tapeDrive); stmt->bindUint64(":LAST_WRITE_TIME", now); stmt->executeNonQuery(); } catch(exception::Exception &ex) { @@ -4488,6 +4410,7 @@ std::list<TapeForWriting> RdbmsCatalogue::getTapesForWriting(const std::string & //------------------------------------------------------------------------------ void RdbmsCatalogue::insertTapeFile( rdbms::PooledConn &conn, + const rdbms::Stmt::AutocommitMode autocommitMode, const common::dataStructures::TapeFile &tapeFile, const uint64_t archiveFileId) { try { @@ -4509,7 +4432,7 @@ void RdbmsCatalogue::insertTapeFile( ":COPY_NB," ":CREATION_TIME," ":ARCHIVE_FILE_ID)"; - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::ON); + auto stmt = conn.createStmt(sql, autocommitMode); stmt->bindString(":VID", tapeFile.vid); stmt->bindUint64(":FSEQ", tapeFile.fSeq); @@ -4757,5 +4680,31 @@ void RdbmsCatalogue::ping() { auto rset = stmt->executeQuery(); } +//------------------------------------------------------------------------------ +// checkTapeWrittenFilesAreSet +//------------------------------------------------------------------------------ +void RdbmsCatalogue::checkTapeFileWrittenFieldsAreSet(const TapeFileWritten &event) { + try { + if(event.diskInstance.empty()) throw exception::Exception("diskInstance is an empty string"); + if(event.diskFileId.empty()) throw exception::Exception("diskFileId is an empty string"); + if(event.diskFilePath.empty()) throw exception::Exception("diskFilePath is an empty string"); + if(event.diskFileUser.empty()) throw exception::Exception("diskFileUser is an empty string"); + if(event.diskFileGroup.empty()) throw exception::Exception("diskFileGroup is an empty string"); + if(event.diskFileRecoveryBlob.empty()) throw exception::Exception("diskFileRecoveryBlob is an empty string"); + if(0 == event.size) throw exception::Exception("size is 0"); + if(event.checksumType.empty()) throw exception::Exception("checksumType is an empty string"); + if(event.checksumValue.empty()) throw exception::Exception("checksumValue is an empty string"); + if(event.storageClassName.empty()) throw exception::Exception("storageClassName is an empty string"); + if(event.vid.empty()) throw exception::Exception("vid is an empty string"); + if(0 == event.fSeq) throw exception::Exception("fSeq is 0"); + if(0 == event.blockId && event.fSeq != 1) throw exception::Exception("blockId is 0 and fSeq is not 1"); + if(0 == event.compressedSize) throw exception::Exception("compressedSize is 0"); + if(0 == event.copyNb) throw exception::Exception("copyNb is 0"); + if(event.tapeDrive.empty()) throw exception::Exception("tapeDrive is an empty string"); + } catch(exception::Exception &ex) { + throw exception::Exception(std::string("TapeFileWrittenEvent is invalid: ") + ex.getMessage().str()); + } +} + } // namespace catalogue } // namespace cta diff --git a/catalogue/RdbmsCatalogue.hpp b/catalogue/RdbmsCatalogue.hpp index 7b74f730b1ce0599c61e3c3c4274b7608c9c9a73..92d1c63162f731c45e52795807e30c89c8b808b8 100644 --- a/catalogue/RdbmsCatalogue.hpp +++ b/catalogue/RdbmsCatalogue.hpp @@ -111,13 +111,6 @@ public: */ std::list<TapeForWriting> getTapesForWriting(const std::string &logicalLibraryName) const override; - /** - * Notifies the catalogue that the specified files have been written to tape. - * - * @param events The tape file written events. - */ - void filesWrittenToTape(const std::list<TapeFileWritten> &events) override; - /** * Notifies the CTA catalogue that the specified tape has been mounted in * order to archive files. @@ -775,9 +768,11 @@ protected: * ArchiveFile table. * * @param conn The database connection. + * @param autocommitMode The autocommit mode of the SQL insert statement. * @param row The row to be inserted. */ - void insertArchiveFile(rdbms::PooledConn &conn, const ArchiveFileRow &row); + void insertArchiveFile(rdbms::PooledConn &conn, const rdbms::Stmt::AutocommitMode autocommitMode, + const ArchiveFileRow &row); /** * Creates the database schema. @@ -824,12 +819,14 @@ protected: * Inserts the specified tape file into the Tape table. * * @param conn The database connection. + * @param autocommitMode The autocommit mode of the SQL insert statement. * @param tapeFile The tape file. * @param archiveFileId The identifier of the archive file of which the tape * file is a copy. */ void insertTapeFile( rdbms::PooledConn &conn, + const rdbms::Stmt::AutocommitMode autocommitMode, const common::dataStructures::TapeFile &tapeFile, const uint64_t archiveFileId); @@ -852,13 +849,24 @@ protected: uint64_t getTapeLastFSeq(rdbms::PooledConn &conn, const std::string &vid) const; /** - * Updates the appropriate tape based on the occurrence of the specified - * event. + * Updates the specified tape with the specified information. * * @param conn The database connection. - * @param event + * @param autocommitMode The autocommit mode of the update statement. + * @param vid The volume identifier of the tape. + * @param lastFSeq The sequence number of the last tape file written to the + * tape. + * @param compressedBytesWritten The number of compressed bytes written to + * the tape. + * @param tapeDrive The name of the tape drive that last wrote to the tape. */ - void updateTape(rdbms::PooledConn &conn, const TapeFileWritten &event); + void updateTape( + rdbms::PooledConn &conn, + const rdbms::Stmt::AutocommitMode autocommitMode, + const std::string &vid, + const uint64_t lastFSeq, + const uint64_t compressedBytesWritten, + const std::string &tapeDrive); /** * Returns the specified archive file or a nullptr pointer if it does not @@ -913,18 +921,6 @@ protected: */ virtual uint64_t getNextArchiveFileId(rdbms::PooledConn &conn) = 0; - /** - * Selects the specified tape within the Tape table for update. - * - * This method must be implemented by the sub-classes of RdbmsCatalogue - * because some database technologies directly support SELECT FOR UPDATE - * whilst others do not. - * - * @param conn The database connection. - * @param vid The volume identifier of the tape. - */ - virtual common::dataStructures::Tape selectTapeForUpdate(rdbms::PooledConn &conn, const std::string &vid) = 0; - /** * Nested class used to implement the getArchiveFileItor() method. */ @@ -1020,14 +1016,13 @@ protected: const std::string &diskInstanceName, const std::string &storageClassName) const; -private: - /** - * Notifies the catalogue that a file has been written to tape. + * Throws an exception if one of the fields of the specified event have not + * been set. * - * @param event The tape file written event. + * @param event The evnt to be checked. */ - void fileWrittenToTape(const TapeFileWritten &event); + void checkTapeFileWrittenFieldsAreSet(const TapeFileWritten &event); }; // class RdbmsCatalogue diff --git a/catalogue/SqliteCatalogue.cpp b/catalogue/SqliteCatalogue.cpp index fd1cac0093087029c51cbb39e318e45d88a5230e..6f6baa4d14dea4fc7d8de10dd0932dfc04361451 100644 --- a/catalogue/SqliteCatalogue.cpp +++ b/catalogue/SqliteCatalogue.cpp @@ -16,6 +16,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include "catalogue/ArchiveFileRow.hpp" #include "catalogue/SqliteCatalogueSchema.hpp" #include "catalogue/SqliteCatalogue.hpp" #include "common/exception/Exception.hpp" @@ -128,7 +129,7 @@ uint64_t SqliteCatalogue::getNextArchiveFileId(rdbms::PooledConn &conn) { //------------------------------------------------------------------------------ // selectTapeForUpdate //------------------------------------------------------------------------------ -common::dataStructures::Tape SqliteCatalogue::selectTapeForUpdate(rdbms::PooledConn &conn, const std::string &vid) { +common::dataStructures::Tape SqliteCatalogue::selectTape(rdbms::PooledConn &conn, const std::string &vid) { try { const char *const sql = "SELECT " @@ -218,5 +219,100 @@ common::dataStructures::Tape SqliteCatalogue::selectTapeForUpdate(rdbms::PooledC } } +//------------------------------------------------------------------------------ +// filesWrittenToTape +//------------------------------------------------------------------------------ +void SqliteCatalogue::filesWrittenToTape(const std::list<TapeFileWritten> &events) { + try { + if(events.empty()) { + return; + } + + const auto &firstEvent = events.front(); + checkTapeFileWrittenFieldsAreSet(firstEvent); + + std::lock_guard<std::mutex> m_lock(m_mutex); + auto conn = m_connPool.getConn(); + rdbms::AutoRollback autoRollback(conn); + + const auto tape = selectTape(conn, firstEvent.vid); + uint64_t expectedFSeq = tape.lastFSeq + 1; + uint64_t totalCompressedBytesWritten = 0; + + for(const auto &event: events) { + checkTapeFileWrittenFieldsAreSet(firstEvent); + + if(event.vid != firstEvent.vid) { + throw exception::Exception(std::string("VID mismatch: expected=") + firstEvent.vid + " actual=event.vid"); + } + + if(expectedFSeq != event.fSeq) { + exception::Exception ex; + ex.getMessage() << "FSeq mismatch for tape " << firstEvent.vid << ": expected=" << expectedFSeq << " actual=" << + firstEvent.fSeq; + throw ex; + } + expectedFSeq++; + + totalCompressedBytesWritten += event.compressedSize; + } + + const TapeFileWritten &lastEvent = events.back(); + updateTape(conn, rdbms::Stmt::AutocommitMode::OFF, lastEvent.vid, lastEvent.fSeq, totalCompressedBytesWritten, + lastEvent.tapeDrive); + + for(const auto &event : events) { + fileWrittenToTape(conn, event); + } + conn.commit(); + } catch(exception::Exception &ex) { + throw exception::Exception(std::string(__FUNCTION__) + " failed: " + ex.getMessage().str()); + } +} + +//------------------------------------------------------------------------------ +// fileWrittenToTape +//------------------------------------------------------------------------------ +void SqliteCatalogue::fileWrittenToTape(rdbms::PooledConn &conn, const TapeFileWritten &event) { + try { + checkTapeFileWrittenFieldsAreSet(event); + + const time_t now = time(nullptr); + std::unique_ptr<common::dataStructures::ArchiveFile> archiveFile = getArchiveFile(conn, event.archiveFileId); + + // If the archive file does not already exist + if(nullptr == archiveFile.get()) { + // Create one + ArchiveFileRow row; + row.archiveFileId = event.archiveFileId; + row.diskFileId = event.diskFileId; + row.diskInstance = event.diskInstance; + row.size = event.size; + row.checksumType = event.checksumType; + row.checksumValue = event.checksumValue; + row.storageClassName = event.storageClassName; + row.diskFilePath = event.diskFilePath; + row.diskFileUser = event.diskFileUser; + row.diskFileGroup = event.diskFileGroup; + row.diskFileRecoveryBlob = event.diskFileRecoveryBlob; + insertArchiveFile(conn, rdbms::Stmt::AutocommitMode::OFF, row); + } else { + throwIfCommonEventDataMismatch(*archiveFile, event); + } + + // Insert the tape file + common::dataStructures::TapeFile tapeFile; + tapeFile.vid = event.vid; + tapeFile.fSeq = event.fSeq; + tapeFile.blockId = event.blockId; + tapeFile.compressedSize = event.compressedSize; + tapeFile.copyNb = event.copyNb; + tapeFile.creationTime = now; + insertTapeFile(conn, rdbms::Stmt::AutocommitMode::OFF, tapeFile, event.archiveFileId); + } catch(exception::Exception &ex) { + throw exception::Exception(std::string(__FUNCTION__) + " failed: " + ex.getMessage().str()); + } +} + } // namespace catalogue } // namespace cta diff --git a/catalogue/SqliteCatalogue.hpp b/catalogue/SqliteCatalogue.hpp index 4c96ba45fb574b39960abcd395a4c78b775dfcc8..b91339f95eb53ba8a98d3e99e3a881ac8bed7944 100644 --- a/catalogue/SqliteCatalogue.hpp +++ b/catalogue/SqliteCatalogue.hpp @@ -76,19 +76,32 @@ protected: * @return A unique archive ID that can be used by a new archive file within * the catalogue. */ - virtual uint64_t getNextArchiveFileId(rdbms::PooledConn &conn) override; + uint64_t getNextArchiveFileId(rdbms::PooledConn &conn) override; /** - * Selects the specified tape within th eTape table for update. + * Notifies the catalogue that the specified files have been written to tape. * - * This method must be implemented by the sub-classes of RdbmsCatalogue - * because some database technologies directly support SELECT FOR UPDATE - * whilst others do not. + * @param events The tape file written events. + */ + void filesWrittenToTape(const std::list<TapeFileWritten> &events) override; + +private: + + /** + * Notifies the catalogue that a file has been written to tape. + * + * @param conn The database connection. + * @param event The tape file written event. + */ + void fileWrittenToTape(rdbms::PooledConn &conn, const TapeFileWritten &event); + + /** + * Selects the specified tape within the Tape table. * * @param conn The database connection. * @param vid The volume identifier of the tape. */ - virtual common::dataStructures::Tape selectTapeForUpdate(rdbms::PooledConn &conn, const std::string &vid) override; + common::dataStructures::Tape selectTape(rdbms::PooledConn &conn, const std::string &vid); }; // class SqliteCatalogue