From 4511c655a4f3a83d357d60eaa6c50593049e253a Mon Sep 17 00:00:00 2001 From: Cedric CAFFY <cedric.caffy@cern.ch> Date: Thu, 30 Jan 2020 15:44:08 +0100 Subject: [PATCH] Honoured NB_MASTER_FILES, MASTER_DATA_IN_BYTES and DIRTY in the catalogue and in the CTA frontend --- catalogue/CatalogueTest.cpp | 8 +++++++- catalogue/MysqlCatalogue.cpp | 7 ++++++- catalogue/OracleCatalogue.cpp | 6 ++++++ catalogue/PostgresCatalogue.cpp | 6 ++++++ catalogue/RdbmsCatalogue.cpp | 28 +++++++++++++++++++++++++--- catalogue/RdbmsCatalogue.hpp | 7 +++++++ catalogue/SqliteCatalogue.cpp | 6 ++++++ common/dataStructures/Tape.cpp | 5 ++++- common/dataStructures/Tape.hpp | 5 ++++- xroot_plugins/XrdCtaTapeLs.hpp | 5 ++++- 10 files changed, 75 insertions(+), 8 deletions(-) diff --git a/catalogue/CatalogueTest.cpp b/catalogue/CatalogueTest.cpp index ff57919511..b6d16c23ae 100644 --- a/catalogue/CatalogueTest.cpp +++ b/catalogue/CatalogueTest.cpp @@ -10690,6 +10690,7 @@ TEST_P(cta_catalogue_CatalogueTest, filesWrittenToTape_1_archive_file_1_tape_cop ASSERT_EQ(1, tapes.size()); const common::dataStructures::Tape &tape = tapes.front(); ASSERT_EQ(1, tape.lastFSeq); + ASSERT_TRUE(tape.dirty); } { @@ -12503,7 +12504,11 @@ TEST_P(cta_catalogue_CatalogueTest, deleteArchiveFile) { log::LogContext dummyLc(m_dummyLog); m_catalogue->deleteArchiveFile("disk_instance", archiveFileId, dummyLc); - + + for(auto &tape:m_catalogue->getTapes()){ + ASSERT_TRUE(tape.dirty); + } + ASSERT_FALSE(m_catalogue->getArchiveFilesItor().hasMore()); } @@ -14617,6 +14622,7 @@ TEST_P(cta_catalogue_CatalogueTest, reclaimTape_full_lastFSeq_0_no_tape_files) { ASSERT_FALSE(tape.labelLog); ASSERT_FALSE(tape.lastReadLog); ASSERT_FALSE(tape.lastWriteLog); + ASSERT_TRUE(tape.dirty); const common::dataStructures::EntryLog creationLog = tape.creationLog; ASSERT_EQ(m_admin.username, creationLog.username); diff --git a/catalogue/MysqlCatalogue.cpp b/catalogue/MysqlCatalogue.cpp index edd101bdd7..554f0f5bec 100644 --- a/catalogue/MysqlCatalogue.cpp +++ b/catalogue/MysqlCatalogue.cpp @@ -524,6 +524,12 @@ void MysqlCatalogue::deleteArchiveFile(const std::string &diskInstanceName, cons stmt.bindUint64(":ARCHIVE_FILE_ID", archiveFileId); stmt.executeNonQuery(); } + + for(auto &tapeFile: archiveFile->tapeFiles){ + //We deleted the TAPE_FILE so the tapes containing them should be set as dirty + setTapeDirty(conn,tapeFile.vid); + } + const auto deleteFromTapeFileTime = t.secs(utils::Timer::resetCounter); { @@ -533,7 +539,6 @@ void MysqlCatalogue::deleteArchiveFile(const std::string &diskInstanceName, cons stmt.executeNonQuery(); } const auto deleteFromArchiveFileTime = t.secs(utils::Timer::resetCounter); - conn.commit(); const auto commitTime = t.secs(); diff --git a/catalogue/OracleCatalogue.cpp b/catalogue/OracleCatalogue.cpp index ec64025b2f..71cc86aaea 100644 --- a/catalogue/OracleCatalogue.cpp +++ b/catalogue/OracleCatalogue.cpp @@ -869,6 +869,12 @@ void OracleCatalogue::deleteArchiveFile(const std::string &diskInstanceName, con stmt.bindUint64(":ARCHIVE_FILE_ID", archiveFileId); stmt.executeNonQuery(); } + + for(auto &tapeFile: archiveFile->tapeFiles){ + //We deleted the TAPE_FILE so the tapes containing them should be set as dirty + setTapeDirty(conn,tapeFile.vid); + } + const auto deleteFromTapeFileTime = t.secs(utils::Timer::resetCounter); { diff --git a/catalogue/PostgresCatalogue.cpp b/catalogue/PostgresCatalogue.cpp index f9d7bc4909..aaa4762d9b 100644 --- a/catalogue/PostgresCatalogue.cpp +++ b/catalogue/PostgresCatalogue.cpp @@ -808,6 +808,12 @@ void PostgresCatalogue::deleteArchiveFile(const std::string &diskInstanceName, c stmt.bindUint64(":ARCHIVE_FILE_ID", archiveFileId); stmt.executeNonQuery(); } + + for(auto &tapeFile: archiveFile->tapeFiles){ + //We deleted the TAPE_FILE so the tapes containing them should be set as dirty + setTapeDirty(conn,tapeFile.vid); + } + const auto deleteFromTapeFileTime = t.secs(utils::Timer::resetCounter); { diff --git a/catalogue/RdbmsCatalogue.cpp b/catalogue/RdbmsCatalogue.cpp index 9464f340ff..26c8f6aeaf 100644 --- a/catalogue/RdbmsCatalogue.cpp +++ b/catalogue/RdbmsCatalogue.cpp @@ -2361,11 +2361,14 @@ std::list<common::dataStructures::Tape> RdbmsCatalogue::getTapes(rdbms::Conn &co "TAPE.ENCRYPTION_KEY_NAME AS ENCRYPTION_KEY_NAME," "TAPE.CAPACITY_IN_BYTES AS CAPACITY_IN_BYTES," "TAPE.DATA_IN_BYTES AS DATA_IN_BYTES," + "TAPE.NB_MASTER_FILES AS NB_MASTER_FILES," + "TAPE.MASTER_DATA_IN_BYTES AS MASTER_DATA_IN_BYTES," "TAPE.LAST_FSEQ AS LAST_FSEQ," "TAPE.IS_DISABLED AS IS_DISABLED," "TAPE.IS_FULL AS IS_FULL," "TAPE.IS_READ_ONLY AS IS_READ_ONLY," "TAPE.IS_FROM_CASTOR AS IS_FROM_CASTOR," + "TAPE.DIRTY AS DIRTY," "TAPE.LABEL_DRIVE AS LABEL_DRIVE," "TAPE.LABEL_TIME AS LABEL_TIME," @@ -2517,12 +2520,15 @@ std::list<common::dataStructures::Tape> RdbmsCatalogue::getTapes(rdbms::Conn &co tape.encryptionKeyName = rset.columnOptionalString("ENCRYPTION_KEY_NAME"); tape.capacityInBytes = rset.columnUint64("CAPACITY_IN_BYTES"); tape.dataOnTapeInBytes = rset.columnUint64("DATA_IN_BYTES"); + tape.nbMasterFiles = rset.columnUint64("NB_MASTER_FILES"); + tape.masterDataInBytes = rset.columnUint64("MASTER_DATA_IN_BYTES"); tape.lastFSeq = rset.columnUint64("LAST_FSEQ"); tape.disabled = rset.columnBool("IS_DISABLED"); tape.full = rset.columnBool("IS_FULL"); tape.readOnly = rset.columnBool("IS_READ_ONLY"); tape.isFromCastor = rset.columnBool("IS_FROM_CASTOR"); - + tape.dirty = rset.columnBool("DIRTY"); + tape.labelLog = getTapeLogFromRset(rset, "LABEL_DRIVE", "LABEL_TIME"); tape.lastReadLog = getTapeLogFromRset(rset, "LAST_READ_DRIVE", "LAST_READ_TIME"); tape.lastWriteLog = getTapeLogFromRset(rset, "LAST_WRITE_DRIVE", "LAST_WRITE_TIME"); @@ -2857,6 +2863,20 @@ void RdbmsCatalogue::deleteTapeFiles(rdbms::Conn& conn, const std::string& vid) } } +void RdbmsCatalogue::setTapeDirty(rdbms::Conn& conn, const std::string& vid) const { + try { + const char * const sql = + "UPDATE TAPE SET DIRTY='1' WHERE VID = :VID"; + auto stmt = conn.createStmt(sql); + stmt.bindString(":VID", vid); + stmt.executeNonQuery(); + } catch(exception::Exception &ex) { + ex.getMessage().str(std::string(__FUNCTION__) + ": " + ex.getMessage().str()); + throw; + } +} + + void RdbmsCatalogue::resetTapeCounters(rdbms::Conn& conn, const common::dataStructures::SecurityIdentity& admin, const std::string& vid) const { try { const time_t now = time(nullptr); @@ -2867,7 +2887,8 @@ void RdbmsCatalogue::resetTapeCounters(rdbms::Conn& conn, const common::dataStru "IS_FULL = '0'," "LAST_UPDATE_USER_NAME = :LAST_UPDATE_USER_NAME," "LAST_UPDATE_HOST_NAME = :LAST_UPDATE_HOST_NAME," - "LAST_UPDATE_TIME = :LAST_UPDATE_TIME " + "LAST_UPDATE_TIME = :LAST_UPDATE_TIME," + "DIRTY = '1' " "WHERE " "VID = :VID"; auto stmt = conn.createStmt(sql); @@ -6112,7 +6133,8 @@ void RdbmsCatalogue::updateTape( "LAST_FSEQ = :LAST_FSEQ," "DATA_IN_BYTES = DATA_IN_BYTES + :DATA_IN_BYTES," "LAST_WRITE_DRIVE = :LAST_WRITE_DRIVE," - "LAST_WRITE_TIME = :LAST_WRITE_TIME " + "LAST_WRITE_TIME = :LAST_WRITE_TIME," + "DIRTY='1' " "WHERE " "VID = :VID"; auto stmt = conn.createStmt(sql); diff --git a/catalogue/RdbmsCatalogue.hpp b/catalogue/RdbmsCatalogue.hpp index cd4863683d..961dc70833 100644 --- a/catalogue/RdbmsCatalogue.hpp +++ b/catalogue/RdbmsCatalogue.hpp @@ -425,6 +425,13 @@ public: */ void deleteTapeFiles(rdbms::Conn &conn, const std::string& vid) const; + /** + * Set the DIRTY flag to true + * @param conn the database connection + * @param vid the vid in which we want to set it as dirty + */ + void setTapeDirty(rdbms::Conn &conn, const std::string &vid) const; + /** * Reset the counters of a tape * @param conn the database connection diff --git a/catalogue/SqliteCatalogue.cpp b/catalogue/SqliteCatalogue.cpp index 5432b89552..f468098f20 100644 --- a/catalogue/SqliteCatalogue.cpp +++ b/catalogue/SqliteCatalogue.cpp @@ -127,6 +127,12 @@ void SqliteCatalogue::deleteArchiveFile(const std::string &diskInstanceName, con stmt.bindUint64(":ARCHIVE_FILE_ID", archiveFileId); stmt.executeNonQuery(); } + + for(auto &tapeFile: archiveFile->tapeFiles){ + //We deleted the TAPE_FILE so the tapes containing them should be set as dirty + setTapeDirty(conn,tapeFile.vid); + } + const auto deleteFromTapeFileTime = t.secs(utils::Timer::resetCounter); { diff --git a/common/dataStructures/Tape.cpp b/common/dataStructures/Tape.cpp index b8afb13c43..93dcb94293 100644 --- a/common/dataStructures/Tape.cpp +++ b/common/dataStructures/Tape.cpp @@ -31,9 +31,12 @@ Tape::Tape(): lastFSeq(0), capacityInBytes(0), dataOnTapeInBytes(0), + nbMasterFiles(0), + masterDataInBytes(0), full(false), disabled(false), - readOnly(false) {} + readOnly(false) + {} //------------------------------------------------------------------------------ // operator== diff --git a/common/dataStructures/Tape.hpp b/common/dataStructures/Tape.hpp index fadecc15bc..433df119aa 100644 --- a/common/dataStructures/Tape.hpp +++ b/common/dataStructures/Tape.hpp @@ -51,6 +51,8 @@ struct Tape { std::string vo; uint64_t capacityInBytes; uint64_t dataOnTapeInBytes; + uint64_t nbMasterFiles; + uint64_t masterDataInBytes; /** * The optional name of the encryption key. @@ -63,7 +65,8 @@ struct Tape { bool full; bool disabled; bool readOnly; - bool isFromCastor; + bool isFromCastor; + bool dirty; uint64_t readMountCount; uint64_t writeMountCount; EntryLog creationLog; diff --git a/xroot_plugins/XrdCtaTapeLs.hpp b/xroot_plugins/XrdCtaTapeLs.hpp index f6455ee084..ecb8723586 100644 --- a/xroot_plugins/XrdCtaTapeLs.hpp +++ b/xroot_plugins/XrdCtaTapeLs.hpp @@ -114,7 +114,10 @@ int TapeLsStream::fillBuffer(XrdSsiPb::OStreamBuffer<Data> *streambuf) { tape_item->set_from_castor(tape.isFromCastor); tape_item->set_read_mount_count(tape.readMountCount); tape_item->set_write_mount_count(tape.writeMountCount); - + tape_item->set_nb_master_files(tape.nbMasterFiles); + tape_item->set_master_data_in_bytes(tape.masterDataInBytes); + tape_item->set_dirty(tape.dirty); + if(tape.labelLog) { ::cta::common::TapeLog * labelLog = tape_item->mutable_label_log(); labelLog->set_drive(tape.labelLog.value().drive); -- GitLab