From 12796ac35958a7a4e4f145b3993bfb41a74adceb Mon Sep 17 00:00:00 2001 From: mvelosob <miguel.veloso.barros@cern.ch> Date: Thu, 5 Aug 2021 11:37:46 +0200 Subject: [PATCH] New options for cta-admin rtf ls (#1016) --- ReleaseNotes.md | 1 + catalogue/CatalogueTest.cpp | 75 ++++++++++++++++++- catalogue/MysqlCatalogue.cpp | 6 +- catalogue/MysqlCatalogue.hpp | 4 +- catalogue/OracleCatalogue.cpp | 6 +- catalogue/OracleCatalogue.hpp | 4 +- catalogue/PostgresCatalogue.cpp | 6 +- catalogue/PostgresCatalogue.hpp | 4 +- catalogue/RdbmsCatalogue.cpp | 13 ++-- catalogue/RdbmsCatalogue.hpp | 8 +- .../RdbmsCatalogueGetFileRecycleLogItor.cpp | 48 +++++++++--- .../RdbmsCatalogueGetFileRecycleLogItor.hpp | 19 ++--- catalogue/RecyleTapeFileSearchCriteria.hpp | 16 +++- catalogue/SqliteCatalogue.cpp | 6 +- catalogue/SqliteCatalogue.hpp | 4 +- cmdline/CtaAdminCmdParse.hpp | 5 +- xroot_plugins/XrdCtaRecycleTapeFileLs.hpp | 15 +++- xroot_plugins/XrdSsiCtaRequestMessage.hpp | 2 +- 18 files changed, 186 insertions(+), 56 deletions(-) diff --git a/ReleaseNotes.md b/ReleaseNotes.md index 2cfab53283..7bdf5c98e7 100644 --- a/ReleaseNotes.md +++ b/ReleaseNotes.md @@ -3,6 +3,7 @@ ## Summary ### Features + - cta/CTA#1016 New options for filtering deleted files using `cta-admin rtf ls` command. ### Bug fixes diff --git a/catalogue/CatalogueTest.cpp b/catalogue/CatalogueTest.cpp index 22939e944f..8130a34a02 100644 --- a/catalogue/CatalogueTest.cpp +++ b/catalogue/CatalogueTest.cpp @@ -15653,7 +15653,8 @@ TEST_P(cta_catalogue_CatalogueTest, filesArePutInTheFileRecycleLogInsteadOfBeing //Check the diskFileId search criteria std::string diskFileId = "12345678"; catalogue::RecycleTapeFileSearchCriteria criteria; - criteria.diskFileId = diskFileId; + criteria.diskFileIds = std::vector<std::string>(); + criteria.diskFileIds->push_back(diskFileId); auto fileRecycleLogItor = m_catalogue->getFileRecycleLogItor(criteria); ASSERT_TRUE(fileRecycleLogItor.hasMore()); auto fileRecycleLog = fileRecycleLogItor.next(); @@ -15664,10 +15665,80 @@ TEST_P(cta_catalogue_CatalogueTest, filesArePutInTheFileRecycleLogInsteadOfBeing //Check the non existing diskFileId search criteria std::string diskFileId = "DOES_NOT_EXIST"; catalogue::RecycleTapeFileSearchCriteria criteria; - criteria.diskFileId = diskFileId; + criteria.diskFileIds = std::vector<std::string>(); + criteria.diskFileIds->push_back(diskFileId); auto fileRecycleLogItor = m_catalogue->getFileRecycleLogItor(criteria); ASSERT_FALSE(fileRecycleLogItor.hasMore()); } + { + //Check the archiveID search criteria + uint64_t archiveFileId = 1; + catalogue::RecycleTapeFileSearchCriteria criteria; + criteria.archiveFileId = archiveFileId; + auto fileRecycleLogItor = m_catalogue->getFileRecycleLogItor(criteria); + ASSERT_TRUE(fileRecycleLogItor.hasMore()); + auto fileRecycleLog = fileRecycleLogItor.next(); + ASSERT_EQ(archiveFileId,fileRecycleLog.archiveFileId); + ASSERT_FALSE(fileRecycleLogItor.hasMore()); + } + { + //Check the non existing archiveFileId search criteria + uint64_t archiveFileId = -1; + catalogue::RecycleTapeFileSearchCriteria criteria; + criteria.archiveFileId = archiveFileId; + auto fileRecycleLogItor = m_catalogue->getFileRecycleLogItor(criteria); + ASSERT_FALSE(fileRecycleLogItor.hasMore()); + } + { + //Check the copynb search criteria + uint64_t copynb = 1; + catalogue::RecycleTapeFileSearchCriteria criteria; + criteria.copynb = copynb; + auto fileRecycleLogItor = m_catalogue->getFileRecycleLogItor(criteria); + int nbFileRecycleLogs = 0; + while(fileRecycleLogItor.hasMore()){ + nbFileRecycleLogs++; + fileRecycleLogItor.next(); + } + ASSERT_EQ(nbArchiveFiles,nbFileRecycleLogs); + } + { + //Check the disk instance search criteria + catalogue::RecycleTapeFileSearchCriteria criteria; + criteria.diskInstance = diskInstance; + auto fileRecycleLogItor = m_catalogue->getFileRecycleLogItor(criteria); + int nbFileRecycleLogs = 0; + while(fileRecycleLogItor.hasMore()){ + nbFileRecycleLogs++; + fileRecycleLogItor.next(); + } + ASSERT_EQ(nbArchiveFiles,nbFileRecycleLogs); + } + { + //Check multiple search criteria together + uint64_t copynb = 1; + uint64_t archiveFileId = 1; + std::string diskFileId = "12345678"; + catalogue::RecycleTapeFileSearchCriteria criteria; + criteria.diskInstance = diskInstance; + criteria.copynb = copynb; + criteria.archiveFileId = archiveFileId; + criteria.diskFileIds = std::vector<std::string>(); + criteria.diskFileIds->push_back(diskFileId); + criteria.vid = tape1.vid; + + auto fileRecycleLogItor = m_catalogue->getFileRecycleLogItor(criteria); + + ASSERT_TRUE(fileRecycleLogItor.hasMore()); + auto fileRecycleLog = fileRecycleLogItor.next(); + ASSERT_EQ(archiveFileId, fileRecycleLog.archiveFileId); + ASSERT_EQ(diskFileId, fileRecycleLog.diskFileId); + ASSERT_EQ(copynb, fileRecycleLog.copyNb); + ASSERT_EQ(tape1.vid, fileRecycleLog.vid); + ASSERT_EQ(diskInstance, fileRecycleLog.diskInstanceName); + + ASSERT_FALSE(fileRecycleLogItor.hasMore()); + } } TEST_P(cta_catalogue_CatalogueTest, sameFileWrittenToSameTapePutThePreviousCopyOnTheFileRecycleLog) { diff --git a/catalogue/MysqlCatalogue.cpp b/catalogue/MysqlCatalogue.cpp index 552bb12973..606b5d151a 100644 --- a/catalogue/MysqlCatalogue.cpp +++ b/catalogue/MysqlCatalogue.cpp @@ -59,10 +59,10 @@ MysqlCatalogue::~MysqlCatalogue() { //------------------------------------------------------------------------------ // createAndPopulateTempTableFxid //------------------------------------------------------------------------------ -std::string MysqlCatalogue::createAndPopulateTempTableFxid(rdbms::Conn &conn, const TapeFileSearchCriteria &tapeFileSearchCriteria) const { +std::string MysqlCatalogue::createAndPopulateTempTableFxid(rdbms::Conn &conn, const optional<std::vector<std::string>> &diskFileIds) const { const std::string tempTableName = "TEMP_DISK_FXIDS"; - if(tapeFileSearchCriteria.diskFileIds) { + if(diskFileIds) { try { std::string sql = "CREATE TEMPORARY TABLE " + tempTableName + "(DISK_FILE_ID VARCHAR(100))"; try { @@ -76,7 +76,7 @@ std::string MysqlCatalogue::createAndPopulateTempTableFxid(rdbms::Conn &conn, co sql = "INSERT INTO " + tempTableName + " VALUES(:DISK_FILE_ID)"; auto stmt = conn.createStmt(sql); - for(auto &diskFileId : tapeFileSearchCriteria.diskFileIds.value()) { + for(auto &diskFileId : diskFileIds.value()) { stmt.bindString(":DISK_FILE_ID", diskFileId); stmt.executeNonQuery(); } diff --git a/catalogue/MysqlCatalogue.hpp b/catalogue/MysqlCatalogue.hpp index 1e6b178516..82d8360bff 100644 --- a/catalogue/MysqlCatalogue.hpp +++ b/catalogue/MysqlCatalogue.hpp @@ -60,10 +60,10 @@ protected: * Creates a temporary table from the list of disk file IDs provided in the search criteria. * * @param conn The database connection. - * @param tapeFileSearchCriteria Search criteria containing a list of disk file IDs (fxid). + * @param diskFileIds List of disk file IDs (fxid). * @return Name of the temporary table */ - std::string createAndPopulateTempTableFxid(rdbms::Conn &conn, const TapeFileSearchCriteria &tapeFileSearchCriteria) const override; + std::string createAndPopulateTempTableFxid(rdbms::Conn &conn, const optional<std::vector<std::string>> &diskFileIds) const override; /** * Returns a unique archive ID that can be used by a new archive file within diff --git a/catalogue/OracleCatalogue.cpp b/catalogue/OracleCatalogue.cpp index 08e63e5afd..bc1a42c354 100644 --- a/catalogue/OracleCatalogue.cpp +++ b/catalogue/OracleCatalogue.cpp @@ -154,11 +154,11 @@ OracleCatalogue::~OracleCatalogue() { //------------------------------------------------------------------------------ // createAndPopulateTempTableFxid //------------------------------------------------------------------------------ -std::string OracleCatalogue::createAndPopulateTempTableFxid(rdbms::Conn &conn, const TapeFileSearchCriteria &tapeFileSearchCriteria) const { +std::string OracleCatalogue::createAndPopulateTempTableFxid(rdbms::Conn &conn, const optional<std::vector<std::string>> &diskFileIds) const { const std::string tempTableName = "ORA$PTT_DISK_FXIDS"; try { - if(tapeFileSearchCriteria.diskFileIds) { + if(diskFileIds) { conn.setAutocommitMode(rdbms::AutocommitMode::AUTOCOMMIT_OFF); std::string sql = "CREATE PRIVATE TEMPORARY TABLE " + tempTableName + "(DISK_FILE_ID VARCHAR2(100))"; @@ -166,7 +166,7 @@ std::string OracleCatalogue::createAndPopulateTempTableFxid(rdbms::Conn &conn, c sql = "INSERT INTO " + tempTableName + " VALUES(:DISK_FILE_ID)"; auto stmt = conn.createStmt(sql); - for(auto &diskFileId : tapeFileSearchCriteria.diskFileIds.value()) { + for(auto &diskFileId : diskFileIds.value()) { stmt.bindString(":DISK_FILE_ID", diskFileId); stmt.executeNonQuery(); } diff --git a/catalogue/OracleCatalogue.hpp b/catalogue/OracleCatalogue.hpp index 03067d1d54..9dd68a65d9 100644 --- a/catalogue/OracleCatalogue.hpp +++ b/catalogue/OracleCatalogue.hpp @@ -61,10 +61,10 @@ public: * Creates a temporary table from the list of disk file IDs provided in the search criteria. * * @param conn The database connection. - * @param tapeFileSearchCriteria Search criteria containing a list of disk file IDs (fxid). + * @param diskFileIds List of disk file IDs (fxid). * @return Name of the temporary table */ - std::string createAndPopulateTempTableFxid(rdbms::Conn &conn, const TapeFileSearchCriteria &tapeFileSearchCriteria) const override; + std::string createAndPopulateTempTableFxid(rdbms::Conn &conn, const optional<std::vector<std::string>> &diskFileIds) const override; /** * Returns a unique archive ID that can be used by a new archive file within diff --git a/catalogue/PostgresCatalogue.cpp b/catalogue/PostgresCatalogue.cpp index da343a4a58..3073bb8935 100644 --- a/catalogue/PostgresCatalogue.cpp +++ b/catalogue/PostgresCatalogue.cpp @@ -152,10 +152,10 @@ PostgresCatalogue::~PostgresCatalogue() { //------------------------------------------------------------------------------ // createAndPopulateTempTableFxid //------------------------------------------------------------------------------ -std::string PostgresCatalogue::createAndPopulateTempTableFxid(rdbms::Conn &conn, const TapeFileSearchCriteria &tapeFileSearchCriteria) const { +std::string PostgresCatalogue::createAndPopulateTempTableFxid(rdbms::Conn &conn, const optional<std::vector<std::string>> &diskFileIds) const { const std::string tempTableName = "TEMP_DISK_FXIDS"; - if(tapeFileSearchCriteria.diskFileIds) { + if(diskFileIds) { try { std::string sql = "CREATE TEMPORARY TABLE " + tempTableName + "(DISK_FILE_ID VARCHAR(100))"; try { @@ -169,7 +169,7 @@ std::string PostgresCatalogue::createAndPopulateTempTableFxid(rdbms::Conn &conn, sql = "INSERT INTO " + tempTableName + " VALUES(:DISK_FILE_ID)"; auto stmt = conn.createStmt(sql); - for(auto &diskFileId : tapeFileSearchCriteria.diskFileIds.value()) { + for(auto &diskFileId : diskFileIds.value()) { stmt.bindString(":DISK_FILE_ID", diskFileId); stmt.executeNonQuery(); } diff --git a/catalogue/PostgresCatalogue.hpp b/catalogue/PostgresCatalogue.hpp index ee2c914b85..da8d3d6bc4 100644 --- a/catalogue/PostgresCatalogue.hpp +++ b/catalogue/PostgresCatalogue.hpp @@ -88,10 +88,10 @@ public: * Creates a temporary table from the list of disk file IDs provided in the search criteria. * * @param conn The database connection. - * @param tapeFileSearchCriteria Search criteria containing a list of disk file IDs (fxid). + * @param diskFileIds List of disk file IDs (fxid). * @return Name of the temporary table */ - std::string createAndPopulateTempTableFxid(rdbms::Conn &conn, const TapeFileSearchCriteria &tapeFileSearchCriteria) const override; + std::string createAndPopulateTempTableFxid(rdbms::Conn &conn, const optional<std::vector<std::string>> &diskFileIds) const override; /** * Returns a unique archive ID that can be used by a new archive file within diff --git a/catalogue/RdbmsCatalogue.cpp b/catalogue/RdbmsCatalogue.cpp index 4db898a66b..262f58418a 100644 --- a/catalogue/RdbmsCatalogue.cpp +++ b/catalogue/RdbmsCatalogue.cpp @@ -6970,7 +6970,7 @@ Catalogue::ArchiveFileItor RdbmsCatalogue::getArchiveFilesItor(const TapeFileSea try { // Create a connection to populate the temporary table (specialised by database type) auto conn = m_archiveFileListingConnPool.getConn(); - const auto tempDiskFxidsTableName = createAndPopulateTempTableFxid(conn, searchCriteria); + const auto tempDiskFxidsTableName = createAndPopulateTempTableFxid(conn, searchCriteria.diskFileIds); // Pass ownership of the connection to the Iterator object auto impl = new RdbmsCatalogueGetArchiveFilesItor(m_log, std::move(conn), searchCriteria, tempDiskFxidsTableName); return ArchiveFileItor(impl); @@ -7002,9 +7002,8 @@ Catalogue::ArchiveFileItor RdbmsCatalogue::getTapeContentsItor(const std::string //------------------------------------------------------------------------------ // checkRecycleTapeFileSearchCriteria //------------------------------------------------------------------------------ -void RdbmsCatalogue::checkRecycleTapeFileSearchCriteria(const RecycleTapeFileSearchCriteria & searchCriteria) const { +void RdbmsCatalogue::checkRecycleTapeFileSearchCriteria(cta::rdbms::Conn &conn, const RecycleTapeFileSearchCriteria & searchCriteria) const { if(searchCriteria.vid) { - auto conn = m_connPool.getConn(); if(!tapeExists(conn, searchCriteria.vid.value())) { throw exception::UserError(std::string("Tape ") + searchCriteria.vid.value() + " does not exist"); } @@ -7013,8 +7012,10 @@ void RdbmsCatalogue::checkRecycleTapeFileSearchCriteria(const RecycleTapeFileSea Catalogue::FileRecycleLogItor RdbmsCatalogue::getFileRecycleLogItor(const RecycleTapeFileSearchCriteria & searchCriteria) const { try { - checkRecycleTapeFileSearchCriteria(searchCriteria); - auto impl = new RdbmsCatalogueGetFileRecycleLogItor(m_log, m_archiveFileListingConnPool, searchCriteria); + auto conn = m_archiveFileListingConnPool.getConn(); + checkRecycleTapeFileSearchCriteria(conn, searchCriteria); + const auto tempDiskFxidsTableName = createAndPopulateTempTableFxid(conn, searchCriteria.diskFileIds); + auto impl = new RdbmsCatalogueGetFileRecycleLogItor(m_log, std::move(conn), searchCriteria, tempDiskFxidsTableName); return FileRecycleLogItor(impl); } catch(exception::UserError &) { throw; @@ -7182,7 +7183,7 @@ common::dataStructures::ArchiveFileSummary RdbmsCatalogue::getTapeFileSummary( addedAWhereConstraint = true; } if(searchCriteria.diskFileIds) { - const auto tempDiskFxidsTableName = createAndPopulateTempTableFxid(conn, searchCriteria); + const auto tempDiskFxidsTableName = createAndPopulateTempTableFxid(conn, searchCriteria.diskFileIds); if(addedAWhereConstraint) sql += " AND "; sql += "ARCHIVE_FILE.DISK_FILE_ID IN (SELECT DISK_FILE_ID FROM " + tempDiskFxidsTableName + ")"; diff --git a/catalogue/RdbmsCatalogue.hpp b/catalogue/RdbmsCatalogue.hpp index 9b025b28c9..91189898e4 100644 --- a/catalogue/RdbmsCatalogue.hpp +++ b/catalogue/RdbmsCatalogue.hpp @@ -851,10 +851,10 @@ public: /** * Throws a UserError exception if the specified searchCriteria is not valid * due to a user error. - * + * @param conn The database connection. * @param searchCriteria The search criteria. */ - void checkRecycleTapeFileSearchCriteria(const RecycleTapeFileSearchCriteria & searchCriteria) const; + void checkRecycleTapeFileSearchCriteria(cta::rdbms::Conn &conn, const RecycleTapeFileSearchCriteria & searchCriteria) const; /** * Returns all the currently deleted files by looking at the FILE_RECYCLE_LOG table @@ -1575,10 +1575,10 @@ protected: * Creates a temporary table from the list of disk file IDs provided in the search criteria. * * @param conn The database connection. - * @param tapeFileSearchCriteria Search criteria containing a list of disk file IDs (fxid). + * @param diskFileIds List of disk file IDs (fxid). * @return Name of the temporary table */ - virtual std::string createAndPopulateTempTableFxid(rdbms::Conn &conn, const TapeFileSearchCriteria &tapeFileSearchCriteria) const = 0; + virtual std::string createAndPopulateTempTableFxid(rdbms::Conn &conn, const optional<std::vector<std::string>> &diskFileIds) const = 0; /** * Returns a unique archive ID that can be used by a new archive file within diff --git a/catalogue/RdbmsCatalogueGetFileRecycleLogItor.cpp b/catalogue/RdbmsCatalogueGetFileRecycleLogItor.cpp index ab9b81519c..71f66cb27f 100644 --- a/catalogue/RdbmsCatalogueGetFileRecycleLogItor.cpp +++ b/catalogue/RdbmsCatalogueGetFileRecycleLogItor.cpp @@ -27,10 +27,11 @@ namespace catalogue { //------------------------------------------------------------------------------ RdbmsCatalogueGetFileRecycleLogItor::RdbmsCatalogueGetFileRecycleLogItor( log::Logger &log, - rdbms::ConnPool &connPool, - const RecycleTapeFileSearchCriteria & searchCriteria): + rdbms::Conn &&conn, + const RecycleTapeFileSearchCriteria & searchCriteria, + const std::string &tempDiskFxidsTableName): m_log(log), - m_connPool(connPool), + m_conn(std::move(conn)), m_searchCriteria(searchCriteria), m_rsetIsEmpty(true), m_hasMoreHasBeenCalled(false) { @@ -65,7 +66,10 @@ RdbmsCatalogueGetFileRecycleLogItor::RdbmsCatalogueGetFileRecycleLogItor( const bool thereIsAtLeastOneSearchCriteria = searchCriteria.vid || - searchCriteria.diskFileId; + searchCriteria.diskFileIds || + searchCriteria.archiveFileId || + searchCriteria.copynb || + searchCriteria.diskInstance; if(thereIsAtLeastOneSearchCriteria) { sql += " WHERE "; @@ -77,12 +81,29 @@ RdbmsCatalogueGetFileRecycleLogItor::RdbmsCatalogueGetFileRecycleLogItor( sql += "FILE_RECYCLE_LOG.VID = :VID"; addedAWhereConstraint = true; } + + if (searchCriteria.archiveFileId) { + if(addedAWhereConstraint) sql += " AND "; + sql += "FILE_RECYCLE_LOG.ARCHIVE_FILE_ID = :ARCHIVE_FILE_ID"; + addedAWhereConstraint = true; + } - if(searchCriteria.diskFileId){ + if(searchCriteria.diskFileIds) { if(addedAWhereConstraint) sql += " AND "; - sql += "FILE_RECYCLE_LOG.DISK_FILE_ID = :DISK_FILE_ID"; + sql += "FILE_RECYCLE_LOG.DISK_FILE_ID IN (SELECT DISK_FILE_ID FROM " + tempDiskFxidsTableName + ")"; addedAWhereConstraint = true; } + + if (searchCriteria.diskInstance) { + if(addedAWhereConstraint) sql += " AND "; + sql += "FILE_RECYCLE_LOG.DISK_INSTANCE_NAME = :DISK_INSTANCE"; + addedAWhereConstraint = true; + } + + if (searchCriteria.copynb) { + if(addedAWhereConstraint) sql += " AND "; + sql += "FILE_RECYCLE_LOG.COPY_NB = :COPY_NB"; + } // Order by FSEQ if we are listing the contents of a tape, else order by archive file ID if(searchCriteria.vid) { @@ -91,15 +112,22 @@ RdbmsCatalogueGetFileRecycleLogItor::RdbmsCatalogueGetFileRecycleLogItor( sql += " ORDER BY FILE_RECYCLE_LOG.ARCHIVE_FILE_ID, FILE_RECYCLE_LOG.COPY_NB"; } - m_conn = connPool.getConn(); m_stmt = m_conn.createStmt(sql); if(searchCriteria.vid){ m_stmt.bindString(":VID", searchCriteria.vid.value()); } - - if(searchCriteria.diskFileId){ - m_stmt.bindString(":DISK_FILE_ID", searchCriteria.diskFileId.value()); + + if (searchCriteria.archiveFileId) { + m_stmt.bindUint64(":ARCHIVE_FILE_ID", searchCriteria.archiveFileId.value()); + } + + if (searchCriteria.diskInstance) { + m_stmt.bindString(":DISK_INSTANCE", searchCriteria.diskInstance.value()); + } + + if (searchCriteria.copynb) { + m_stmt.bindUint64(":COPY_NB", searchCriteria.copynb.value()); } m_rset = m_stmt.executeQuery(); diff --git a/catalogue/RdbmsCatalogueGetFileRecycleLogItor.hpp b/catalogue/RdbmsCatalogueGetFileRecycleLogItor.hpp index c94cfe3949..90e996b82e 100644 --- a/catalogue/RdbmsCatalogueGetFileRecycleLogItor.hpp +++ b/catalogue/RdbmsCatalogueGetFileRecycleLogItor.hpp @@ -29,9 +29,13 @@ public: * Constructor. * * @param log Object representing the API to the CTA logging system. - * @param connPool The database connection pool. + * @param conn A database connection. */ - RdbmsCatalogueGetFileRecycleLogItor(log::Logger &log, rdbms::ConnPool &connPool, const RecycleTapeFileSearchCriteria & searchCriteria); + RdbmsCatalogueGetFileRecycleLogItor( + log::Logger &log, + rdbms::Conn &&conn, + const RecycleTapeFileSearchCriteria & searchCriteria, + const std::string &tempDiskFxidsTableName); /** * Destructor. @@ -54,10 +58,12 @@ private: */ log::Logger &m_log; + /** - * The database connection pool. + * The database connection. */ - rdbms::ConnPool &m_connPool; + rdbms::Conn m_conn; + /** * The search criteria to be used when listing recycled tape files. @@ -79,11 +85,6 @@ private: */ bool m_hasMoreHasBeenCalled; - /** - * The database connection. - */ - rdbms::Conn m_conn; - /** * The database statement. */ diff --git a/catalogue/RecyleTapeFileSearchCriteria.hpp b/catalogue/RecyleTapeFileSearchCriteria.hpp index 8fc4983064..eb4ab60cb7 100644 --- a/catalogue/RecyleTapeFileSearchCriteria.hpp +++ b/catalogue/RecyleTapeFileSearchCriteria.hpp @@ -32,6 +32,15 @@ namespace catalogue { * Please note that no wild cards, for example '*' or '%', are supported. */ struct RecycleTapeFileSearchCriteria { + /** + * The unique identifier of an archive file. + */ + optional<uint64_t> archiveFileId; + + /** + * The name of a disk instance. + */ + optional<std::string> diskInstance; /** * The volume identifier of a tape. @@ -44,7 +53,12 @@ struct RecycleTapeFileSearchCriteria { * These are given as a list of strings in DECIMAL format. EOS provides the fxids in hex format. The parsing and * conversion into decimal is done in the cta-admin client, ready to be built into a SQL query string. */ - optional<std::string> diskFileId; + optional<std::vector<std::string>> diskFileIds; + + /** + * The copy number of the deleted tape file. + */ + optional<uint64_t> copynb; }; // struct TapeFileSearchCriteria diff --git a/catalogue/SqliteCatalogue.cpp b/catalogue/SqliteCatalogue.cpp index c809025876..a48071da05 100644 --- a/catalogue/SqliteCatalogue.cpp +++ b/catalogue/SqliteCatalogue.cpp @@ -192,7 +192,7 @@ void SqliteCatalogue::DO_NOT_USE_deleteArchiveFile_DO_NOT_USE(const std::string //------------------------------------------------------------------------------ // createAndPopulateTempTableFxid //------------------------------------------------------------------------------ -std::string SqliteCatalogue::createAndPopulateTempTableFxid(rdbms::Conn &conn, const TapeFileSearchCriteria &tapeFileSearchCriteria) const { +std::string SqliteCatalogue::createAndPopulateTempTableFxid(rdbms::Conn &conn, const optional<std::vector<std::string>> &diskFileIds) const { try { const std::string tempTableName = "TEMP.DISK_FXIDS"; @@ -200,9 +200,9 @@ std::string SqliteCatalogue::createAndPopulateTempTableFxid(rdbms::Conn &conn, c conn.executeNonQuery("DROP TABLE IF EXISTS " + tempTableName); conn.executeNonQuery("CREATE TEMPORARY TABLE " + tempTableName + "(DISK_FILE_ID TEXT)"); - if(tapeFileSearchCriteria.diskFileIds) { + if(diskFileIds) { auto stmt = conn.createStmt("INSERT INTO " + tempTableName + " VALUES(:DISK_FILE_ID)"); - for(auto &diskFileId : tapeFileSearchCriteria.diskFileIds.value()) { + for(auto &diskFileId : diskFileIds.value()) { stmt.bindString(":DISK_FILE_ID", diskFileId); stmt.executeNonQuery(); } diff --git a/catalogue/SqliteCatalogue.hpp b/catalogue/SqliteCatalogue.hpp index 020589f930..f42f9f14ca 100644 --- a/catalogue/SqliteCatalogue.hpp +++ b/catalogue/SqliteCatalogue.hpp @@ -86,10 +86,10 @@ protected: * Creates a temporary table from the list of disk file IDs provided in the search criteria. * * @param conn The database connection. - * @param tapeFileSearchCriteria Search criteria containing a list of disk file IDs (fxid). + * @param diskFileIds List of disk file IDs (fxid). * @return Name of the temporary table */ - std::string createAndPopulateTempTableFxid(rdbms::Conn &conn, const TapeFileSearchCriteria &tapeFileSearchCriteria) const override; + std::string createAndPopulateTempTableFxid(rdbms::Conn &conn, const optional<std::vector<std::string>> &diskFileIds) const override; /** * Returns a unique archive ID that can be used by a new archive file within diff --git a/cmdline/CtaAdminCmdParse.hpp b/cmdline/CtaAdminCmdParse.hpp index 70b6123de3..da06f29a18 100644 --- a/cmdline/CtaAdminCmdParse.hpp +++ b/cmdline/CtaAdminCmdParse.hpp @@ -408,7 +408,7 @@ const std::map<AdminCmd::Cmd, CmdHelp> cmdHelp = { { AdminCmd::CMD_VERSION, { "version", "v", { } }}, { AdminCmd::CMD_SCHEDULINGINFOS, { "schedulinginfo", "si", { "ls" } }}, { AdminCmd::CMD_RECYCLETAPEFILE, { "recycletf", "rtf", { "ls" }, - " Tape files in the recycle log can be listed by VID or by EOS disk file ID.\n" + " Tape files in the recycle log can be listed by VID, EOS disk file ID, EOS disk instance, ArchiveFileId or copy number.\n" " Disk file IDs should be provided in hexadecimal (fxid).\n\n" }}, }; @@ -614,7 +614,8 @@ const std::map<cmd_key_t, cmd_val_t> cmdOptions = { { }}, {{ AdminCmd::CMD_VERSION, AdminCmd::SUBCMD_NONE }, { }}, {{ AdminCmd::CMD_SCHEDULINGINFOS, AdminCmd::SUBCMD_LS }, { }}, - {{ AdminCmd::CMD_RECYCLETAPEFILE, AdminCmd::SUBCMD_LS }, { opt_vid.optional(), opt_fid.optional() }}, + {{ AdminCmd::CMD_RECYCLETAPEFILE, AdminCmd::SUBCMD_LS }, + { opt_vid.optional(), opt_fid.optional(), opt_fidfile.optional(), opt_copynb.optional(), opt_archivefileid.optional(), opt_instance.optional() }}, }; diff --git a/xroot_plugins/XrdCtaRecycleTapeFileLs.hpp b/xroot_plugins/XrdCtaRecycleTapeFileLs.hpp index 7c18034dd8..86631b2386 100644 --- a/xroot_plugins/XrdCtaRecycleTapeFileLs.hpp +++ b/xroot_plugins/XrdCtaRecycleTapeFileLs.hpp @@ -66,15 +66,28 @@ RecycleTapeFileLsStream::RecycleTapeFileLsStream(const RequestMessage &requestMs searchCriteria.vid = requestMsg.getOptional(OptionString::VID, &has_any); auto diskFileId = requestMsg.getOptional(OptionString::FXID, &has_any); + + searchCriteria.diskFileIds = requestMsg.getOptional(OptionStrList::FILE_ID, &has_any); if(diskFileId){ // single option on the command line we need to do the conversion ourselves. + if(!searchCriteria.diskFileIds) searchCriteria.diskFileIds = std::vector<std::string>(); + auto fid = strtol(diskFileId->c_str(), nullptr, 16); if(fid < 1 || fid == LONG_MAX) { throw cta::exception::UserError(*diskFileId + " is not a valid file ID"); } - searchCriteria.diskFileId = std::to_string(fid); + + searchCriteria.diskFileIds->push_back(std::to_string(fid)); } + // Disk instance on its own does not give a valid set of search criteria (no &has_any) + searchCriteria.diskInstance = requestMsg.getOptional(OptionString::INSTANCE); + + searchCriteria.archiveFileId = requestMsg.getOptional(OptionUInt64::ARCHIVE_FILE_ID, &has_any); + + // Copy number on its own does not give a valid set of search criteria (no &has_any) + searchCriteria.copynb = requestMsg.getOptional(OptionUInt64::COPY_NUMBER); + if(!has_any){ throw cta::exception::UserError("Must specify at least one search option"); } diff --git a/xroot_plugins/XrdSsiCtaRequestMessage.hpp b/xroot_plugins/XrdSsiCtaRequestMessage.hpp index 24bf193b28..846024bb65 100644 --- a/xroot_plugins/XrdSsiCtaRequestMessage.hpp +++ b/xroot_plugins/XrdSsiCtaRequestMessage.hpp @@ -207,7 +207,7 @@ private: void processVirtualOrganization_Add(cta::xrd::Response &response); void processVirtualOrganization_Ch(cta::xrd::Response &response); void processVirtualOrganization_Rm(cta::xrd::Response &response); - + /*! * Process AdminCmd events which can return a stream response * -- GitLab