From 02f1abf80dd1f1459701a9cee66e894fc43846e7 Mon Sep 17 00:00:00 2001 From: Joao Afonso <joao.afonso@cern.ch> Date: Fri, 28 Feb 2025 13:53:44 +0100 Subject: [PATCH 1/3] first draft --- catalogue/TapeSearchCriteria.hpp | 5 ++++ catalogue/rdbms/RdbmsTapeCatalogue.cpp | 27 +++++++++++++++++++- cmdline/CtaAdminCmdParse.hpp | 27 +++++++++++--------- frontend/grpc/ServerTapeLsRequestHandler.cpp | 23 +++++++++-------- xroot_plugins/XrdCtaTapeLs.hpp | 26 ++++++++++--------- 5 files changed, 72 insertions(+), 36 deletions(-) diff --git a/catalogue/TapeSearchCriteria.hpp b/catalogue/TapeSearchCriteria.hpp index 1a0eaa0876..bef57db8da 100644 --- a/catalogue/TapeSearchCriteria.hpp +++ b/catalogue/TapeSearchCriteria.hpp @@ -95,6 +95,11 @@ struct TapeSearchCriteria { */ std::optional<std::vector<std::string>> diskFileIds; + /** + * Check tapes with incomplete tape file copies + */ + std::optional<bool> checkIncompleteFileCopies; + /** * The state of the tapes to look for */ diff --git a/catalogue/rdbms/RdbmsTapeCatalogue.cpp b/catalogue/rdbms/RdbmsTapeCatalogue.cpp index 6461932ba4..ffb521aeee 100644 --- a/catalogue/rdbms/RdbmsTapeCatalogue.cpp +++ b/catalogue/rdbms/RdbmsTapeCatalogue.cpp @@ -1299,7 +1299,8 @@ std::list<common::dataStructures::Tape> RdbmsTapeCatalogue::getTapes(rdbms::Conn searchCriteria.state || searchCriteria.fromCastor || searchCriteria.purchaseOrder || - searchCriteria.physicalLibraryName) { + searchCriteria.physicalLibraryName || + searchCriteria.checkIncompleteFileCopies) { sql += R"SQL( WHERE )SQL"; } @@ -1425,6 +1426,30 @@ std::list<common::dataStructures::Tape> RdbmsTapeCatalogue::getTapes(rdbms::Conn sql += R"SQL( PHYSICAL_LIBRARY.PHYSICAL_LIBRARY_NAME = :PHYSICAL_LIBRARY_NAME )SQL"; + addedAWhereConstraint = true; + } + if (searchCriteria.checkIncompleteFileCopies) { + if (addedAWhereConstraint) { + sql += R"SQL( AND )SQL"; + } + sql += R"SQL( + VID IN ( + SELECT TF.VID FROM ( + SELECT AF.ARCHIVE_FILE_ID, SC.NB_COPIES, COUNT(TF.ARCHIVE_FILE_ID) AS NB_TAPE_COPIES + FROM + ARCHIVE_FILE AF + INNER JOIN STORAGE_CLASS SC ON AF.STORAGE_CLASS_ID = SC.STORAGE_CLASS_ID + INNER JOIN TAPE_FILE TF ON AF.ARCHIVE_FILE_ID = TF.ARCHIVE_FILE_ID + WHERE + SC.NB_COPIES > 1 + GROUP BY + AF.ARCHIVE_FILE_ID, SC.NB_COPIES + HAVING + SC.NB_COPIES <> COUNT(TF.ARCHIVE_FILE_ID) + ) MISSING_COPIES + INNER JOIN TAPE_FILE TF ON MISSING_COPIES.ARCHIVE_FILE_ID = TF.ARCHIVE_FILE_ID + ) + )SQL"; } sql += R"SQL( ORDER BY TAPE.VID )SQL"; diff --git a/cmdline/CtaAdminCmdParse.hpp b/cmdline/CtaAdminCmdParse.hpp index e6029f801a..7f5c17562c 100644 --- a/cmdline/CtaAdminCmdParse.hpp +++ b/cmdline/CtaAdminCmdParse.hpp @@ -259,17 +259,18 @@ const std::map<std::string, OptionBoolean::Key> boolOptions = { {"--fromcastor", OptionBoolean::FROM_CASTOR }, // hasOption options - {"--disabledtape", OptionBoolean::DISABLED }, - {"--justarchive", OptionBoolean::JUSTARCHIVE }, - {"--justmove", OptionBoolean::JUSTMOVE }, - {"--justaddcopies", OptionBoolean::JUSTADDCOPIES }, - {"--justretrieve", OptionBoolean::JUSTRETRIEVE }, - {"--log", OptionBoolean::SHOW_LOG_ENTRIES}, - {"--lookupnamespace", OptionBoolean::LOOKUP_NAMESPACE}, - {"--summary", OptionBoolean::SUMMARY }, - {"--no-recall", OptionBoolean::NO_RECALL }, - {"--dirtybit", OptionBoolean::DIRTY_BIT }, - {"--isrepackvo", OptionBoolean::IS_REPACK_VO } + {"--disabledtape", OptionBoolean::DISABLED }, + {"--justarchive", OptionBoolean::JUSTARCHIVE }, + {"--justmove", OptionBoolean::JUSTMOVE }, + {"--justaddcopies", OptionBoolean::JUSTADDCOPIES }, + {"--justretrieve", OptionBoolean::JUSTRETRIEVE }, + {"--log", OptionBoolean::SHOW_LOG_ENTRIES }, + {"--lookupnamespace", OptionBoolean::LOOKUP_NAMESPACE }, + {"--summary", OptionBoolean::SUMMARY }, + {"--no-recall", OptionBoolean::NO_RECALL }, + {"--dirtybit", OptionBoolean::DIRTY_BIT }, + {"--isrepackvo", OptionBoolean::IS_REPACK_VO }, + {"--incompletefilecopies", OptionBoolean::INCOMPLETE_FILE_COPIES }, }; /*! @@ -516,6 +517,7 @@ const Option opt_archive_route_type {Option::OPT_STR, std::string(R"( <")") + cta::common::dataStructures::toString(ArchiveRouteType::DEFAULT) + R"(" or ")" + cta::common::dataStructures::toString(ArchiveRouteType::REPACK) + R"(">)"}; +const Option opt_incompletefilecopes {Option::OPT_FLAG, "--incompletefilecopies", "--ifc", ""}; /*! * Subset of commands that return streaming output @@ -1034,7 +1036,8 @@ tape (ta) opt_state.optional(), opt_fromcastor.optional(), opt_purchase_order.optional(), - opt_physical_library.optional()} }, + opt_physical_library.optional(), + opt_incompletefilecopes.optional()} }, /**md tapefile (tf) diff --git a/frontend/grpc/ServerTapeLsRequestHandler.cpp b/frontend/grpc/ServerTapeLsRequestHandler.cpp index a2739d7b88..6c6367038f 100644 --- a/frontend/grpc/ServerTapeLsRequestHandler.cpp +++ b/frontend/grpc/ServerTapeLsRequestHandler.cpp @@ -83,17 +83,18 @@ bool cta::frontend::grpc::server::TapeLsRequestHandler::next(const bool bOk) { // Get the search criteria from the optional options - m_searchCriteria.full = requestMsg.getOptional(cta::admin::OptionBoolean::FULL, &bHasAny); - m_searchCriteria.fromCastor = requestMsg.getOptional(cta::admin::OptionBoolean::FROM_CASTOR, &bHasAny); - m_searchCriteria.capacityInBytes = requestMsg.getOptional(cta::admin::OptionUInt64::CAPACITY, &bHasAny); - m_searchCriteria.logicalLibrary = requestMsg.getOptional(cta::admin::OptionString::LOGICAL_LIBRARY, &bHasAny); - m_searchCriteria.tapePool = requestMsg.getOptional(cta::admin::OptionString::TAPE_POOL, &bHasAny); - m_searchCriteria.vo = requestMsg.getOptional(cta::admin::OptionString::VO, &bHasAny); - m_searchCriteria.vid = requestMsg.getOptional(cta::admin::OptionString::VID, &bHasAny); - m_searchCriteria.mediaType = requestMsg.getOptional(cta::admin::OptionString::MEDIA_TYPE, &bHasAny); - m_searchCriteria.vendor = requestMsg.getOptional(cta::admin::OptionString::VENDOR, &bHasAny); - m_searchCriteria.purchaseOrder = requestMsg.getOptional(cta::admin::OptionString::MEDIA_PURCHASE_ORDER_NUMBER, &bHasAny); - m_searchCriteria.diskFileIds = requestMsg.getOptional(cta::admin::OptionStrList::FILE_ID, &bHasAny); + m_searchCriteria.full = requestMsg.getOptional(cta::admin::OptionBoolean::FULL, &bHasAny); + m_searchCriteria.fromCastor = requestMsg.getOptional(cta::admin::OptionBoolean::FROM_CASTOR, &bHasAny); + m_searchCriteria.capacityInBytes = requestMsg.getOptional(cta::admin::OptionUInt64::CAPACITY, &bHasAny); + m_searchCriteria.logicalLibrary = requestMsg.getOptional(cta::admin::OptionString::LOGICAL_LIBRARY, &bHasAny); + m_searchCriteria.tapePool = requestMsg.getOptional(cta::admin::OptionString::TAPE_POOL, &bHasAny); + m_searchCriteria.vo = requestMsg.getOptional(cta::admin::OptionString::VO, &bHasAny); + m_searchCriteria.vid = requestMsg.getOptional(cta::admin::OptionString::VID, &bHasAny); + m_searchCriteria.mediaType = requestMsg.getOptional(cta::admin::OptionString::MEDIA_TYPE, &bHasAny); + m_searchCriteria.vendor = requestMsg.getOptional(cta::admin::OptionString::VENDOR, &bHasAny); + m_searchCriteria.purchaseOrder = requestMsg.getOptional(cta::admin::OptionString::MEDIA_PURCHASE_ORDER_NUMBER, &bHasAny); + m_searchCriteria.diskFileIds = requestMsg.getOptional(cta::admin::OptionStrList::FILE_ID, &bHasAny); + m_searchCriteria.checkIncompleteFileCopies = requestMsg.getOptional(cta::admin::OptionBoolean::INCOMPLETE_FILE_COPIES, &bHasAny); auto stateOpt = requestMsg.getOptional(cta::admin::OptionString::STATE, &bHasAny); if(stateOpt){ m_searchCriteria.state = common::dataStructures::Tape::stringToState(stateOpt.value()); diff --git a/xroot_plugins/XrdCtaTapeLs.hpp b/xroot_plugins/XrdCtaTapeLs.hpp index 8210729141..bcb425b85a 100644 --- a/xroot_plugins/XrdCtaTapeLs.hpp +++ b/xroot_plugins/XrdCtaTapeLs.hpp @@ -68,19 +68,21 @@ TapeLsStream::TapeLsStream(const frontend::AdminCmdStream& requestMsg, cta::cata // Get the search criteria from the optional options - searchCriteria.full = requestMsg.getOptional(OptionBoolean::FULL, &has_any); - searchCriteria.fromCastor = requestMsg.getOptional(OptionBoolean::FROM_CASTOR, &has_any); - searchCriteria.capacityInBytes = requestMsg.getOptional(OptionUInt64::CAPACITY, &has_any); - searchCriteria.logicalLibrary = requestMsg.getOptional(OptionString::LOGICAL_LIBRARY, &has_any); - searchCriteria.tapePool = requestMsg.getOptional(OptionString::TAPE_POOL, &has_any); - searchCriteria.vo = requestMsg.getOptional(OptionString::VO, &has_any); - searchCriteria.vid = requestMsg.getOptional(OptionString::VID, &has_any); - searchCriteria.mediaType = requestMsg.getOptional(OptionString::MEDIA_TYPE, &has_any); - searchCriteria.vendor = requestMsg.getOptional(OptionString::VENDOR, &has_any); - searchCriteria.purchaseOrder = requestMsg.getOptional(OptionString::MEDIA_PURCHASE_ORDER_NUMBER, &has_any); - searchCriteria.physicalLibraryName = requestMsg.getOptional(OptionString::PHYSICAL_LIBRARY, &has_any); - searchCriteria.diskFileIds = requestMsg.getOptional(OptionStrList::FILE_ID, &has_any); + searchCriteria.full = requestMsg.getOptional(OptionBoolean::FULL, &has_any); + searchCriteria.fromCastor = requestMsg.getOptional(OptionBoolean::FROM_CASTOR, &has_any); + searchCriteria.capacityInBytes = requestMsg.getOptional(OptionUInt64::CAPACITY, &has_any); + searchCriteria.logicalLibrary = requestMsg.getOptional(OptionString::LOGICAL_LIBRARY, &has_any); + searchCriteria.tapePool = requestMsg.getOptional(OptionString::TAPE_POOL, &has_any); + searchCriteria.vo = requestMsg.getOptional(OptionString::VO, &has_any); + searchCriteria.vid = requestMsg.getOptional(OptionString::VID, &has_any); + searchCriteria.mediaType = requestMsg.getOptional(OptionString::MEDIA_TYPE, &has_any); + searchCriteria.vendor = requestMsg.getOptional(OptionString::VENDOR, &has_any); + searchCriteria.purchaseOrder = requestMsg.getOptional(OptionString::MEDIA_PURCHASE_ORDER_NUMBER, &has_any); + searchCriteria.physicalLibraryName = requestMsg.getOptional(OptionString::PHYSICAL_LIBRARY, &has_any); + searchCriteria.diskFileIds = requestMsg.getOptional(OptionStrList::FILE_ID, &has_any); + searchCriteria.checkIncompleteFileCopies = requestMsg.getOptional(OptionBoolean::INCOMPLETE_FILE_COPIES, &has_any); auto stateOpt = requestMsg.getOptional(OptionString::STATE, &has_any); + if(stateOpt){ searchCriteria.state = common::dataStructures::Tape::stringToState(stateOpt.value(), true); } -- GitLab From 329b575674cf632ac631f5796c666846b5aa569e Mon Sep 17 00:00:00 2001 From: Joao Afonso <joao.afonso@cern.ch> Date: Mon, 3 Mar 2025 13:57:08 +0100 Subject: [PATCH 2/3] Adding option to list tapes with incomplete tape file copies --- catalogue/rdbms/RdbmsTapeCatalogue.cpp | 2 +- .../modules/ArchiveFileCatalogueTest.cpp | 168 ++++++++++++++++++ .../modules/ArchiveFileCatalogueTest.hpp | 1 + xroot_plugins/XrdCtaTapeLs.hpp | 2 +- xrootd-ssi-protobuf-interface | 2 +- 5 files changed, 172 insertions(+), 3 deletions(-) diff --git a/catalogue/rdbms/RdbmsTapeCatalogue.cpp b/catalogue/rdbms/RdbmsTapeCatalogue.cpp index ffb521aeee..fd580199d5 100644 --- a/catalogue/rdbms/RdbmsTapeCatalogue.cpp +++ b/catalogue/rdbms/RdbmsTapeCatalogue.cpp @@ -1428,7 +1428,7 @@ std::list<common::dataStructures::Tape> RdbmsTapeCatalogue::getTapes(rdbms::Conn )SQL"; addedAWhereConstraint = true; } - if (searchCriteria.checkIncompleteFileCopies) { + if (searchCriteria.checkIncompleteFileCopies.value_or(false)) { if (addedAWhereConstraint) { sql += R"SQL( AND )SQL"; } diff --git a/catalogue/tests/modules/ArchiveFileCatalogueTest.cpp b/catalogue/tests/modules/ArchiveFileCatalogueTest.cpp index 5584cfe9b6..bea4b57d01 100644 --- a/catalogue/tests/modules/ArchiveFileCatalogueTest.cpp +++ b/catalogue/tests/modules/ArchiveFileCatalogueTest.cpp @@ -42,6 +42,7 @@ cta_catalogue_ArchiveFileTest::cta_catalogue_ArchiveFileTest() : m_dummyLog("dummy", "dummy"), m_tape1(CatalogueTestUtils::getTape1()), m_tape2(CatalogueTestUtils::getTape2()), + m_tape3(CatalogueTestUtils::getTape3()), m_mediaType(CatalogueTestUtils::getMediaType()), m_admin(CatalogueTestUtils::getAdmin()), m_diskInstance(CatalogueTestUtils::getDiskInstance()), @@ -4987,4 +4988,171 @@ TEST_P(cta_catalogue_ArchiveFileTest, getArchiveFileQueueCriteria_ignore_repack_ ASSERT_EQ(tapePoolName_default_2, copyToPoolMap_it->second); } +TEST_P(cta_catalogue_ArchiveFileTest, getTapesWithMissingTapeFileCopies) { + const bool logicalLibraryIsDisabled= false; + const uint64_t nbPartialTapes = 2; + const bool isEncrypted = true; + const std::list<std::string> supply; + const std::string diskInstance = m_diskInstance.name; + std::optional<std::string> physicalLibraryName; + + m_catalogue->MediaType()->createMediaType(m_admin, m_mediaType); + m_catalogue->LogicalLibrary()->createLogicalLibrary(m_admin, m_tape1.logicalLibraryName, logicalLibraryIsDisabled, physicalLibraryName, "Create logical library"); + m_catalogue->DiskInstance()->createDiskInstance(m_admin, m_diskInstance.name, m_diskInstance.comment); + m_catalogue->VO()->createVirtualOrganization(m_admin, m_vo); + m_catalogue->TapePool()->createTapePool(m_admin, m_tape1.tapePoolName, m_vo.name, nbPartialTapes, isEncrypted, supply, "Create tape pool"); + m_catalogue->Tape()->createTape(m_admin, m_tape1); + m_catalogue->Tape()->createTape(m_admin, m_tape2); + m_catalogue->Tape()->createTape(m_admin, m_tape3); + m_catalogue->StorageClass()->createStorageClass(m_admin, m_storageClassDualCopy); + + // Storage class 'm_storageClassDualCopy' expects two tape copies for each file + // 1.1. Write 1 single file copy of 'archiveFileId_1' on 'm_tape1' + // 1.2. Write 1 single file copy of 'archiveFileId_2' on 'm_tape2' (different file) + // 2. Check that both tapes are identified as missing a second tape file copy + + constexpr uint64_t archiveFileId_1 = 1234; + constexpr uint64_t archiveFileId_2 = 5678; + + constexpr uint64_t archiveFileSize = 1; + const std::string tapeDrive = "tape_drive"; + + { + auto tapeFileWrittenPtr = std::make_unique<cta::catalogue::TapeFileWritten>(); + auto & tapeFileWritten = *tapeFileWrittenPtr; + + tapeFileWritten.archiveFileId = archiveFileId_1; + tapeFileWritten.diskInstance = diskInstance; + tapeFileWritten.diskFileId = "12340000"; + + tapeFileWritten.diskFileOwnerUid = PUBLIC_DISK_USER; + tapeFileWritten.diskFileGid = PUBLIC_DISK_GROUP; + tapeFileWritten.size = archiveFileSize; + tapeFileWritten.checksumBlob.insert(cta::checksum::ADLER32, "1234"); + tapeFileWritten.storageClassName = m_storageClassDualCopy.name; + tapeFileWritten.vid = m_tape1.vid; + tapeFileWritten.fSeq = 1; + tapeFileWritten.blockId = 4321; + tapeFileWritten.copyNb = 1; + tapeFileWritten.tapeDrive = tapeDrive; + + std::set<cta::catalogue::TapeItemWrittenPointer> fileWrittenSet; + fileWrittenSet.insert(tapeFileWrittenPtr.release()); + m_catalogue->TapeFile()->filesWrittenToTape(fileWrittenSet); + } + + { + auto tapeFileWrittenPtr = std::make_unique<cta::catalogue::TapeFileWritten>(); + auto & tapeFileWritten = *tapeFileWrittenPtr; + + tapeFileWritten.archiveFileId = archiveFileId_2; + tapeFileWritten.diskInstance = diskInstance; + tapeFileWritten.diskFileId = "56780000"; + + tapeFileWritten.diskFileOwnerUid = PUBLIC_DISK_USER; + tapeFileWritten.diskFileGid = PUBLIC_DISK_GROUP; + tapeFileWritten.size = archiveFileSize; + tapeFileWritten.checksumBlob.insert(cta::checksum::ADLER32, "8765"); + tapeFileWritten.storageClassName = m_storageClassDualCopy.name; + tapeFileWritten.vid = m_tape2.vid; + tapeFileWritten.fSeq = 1; + tapeFileWritten.blockId = 5678; + tapeFileWritten.copyNb = 1; + tapeFileWritten.tapeDrive = tapeDrive; + + std::set<cta::catalogue::TapeItemWrittenPointer> fileWrittenSet; + fileWrittenSet.insert(tapeFileWrittenPtr.release()); + m_catalogue->TapeFile()->filesWrittenToTape(fileWrittenSet); + } + + // Tape 1 and 2 should be identified as missing a 2nd copy + { + cta::catalogue::TapeSearchCriteria searchCriteria; + searchCriteria.checkIncompleteFileCopies = true; + const std::list<cta::common::dataStructures::Tape> tapes = m_catalogue->Tape()->getTapes(searchCriteria); + + ASSERT_EQ(2, tapes.size()); + + const auto vidToTape = CatalogueTestUtils::tapeListToMap(tapes); + const cta::common::dataStructures::Tape & tape_1 = vidToTape.at(m_tape1.vid); + ASSERT_EQ(m_tape1.vid, tape_1.vid); + const cta::common::dataStructures::Tape & tape_2 = vidToTape.at(m_tape2.vid); + ASSERT_EQ(m_tape2.vid, tape_2.vid); + } + + // 1.1. Write 1 new file copy of 'archiveFileId_1' on 'm_tape3' + // 2. Only 'm_tape3' should now be identified as missing a second tape file copy + { + auto tapeFileWrittenPtr = std::make_unique<cta::catalogue::TapeFileWritten>(); + auto & tapeFileWritten = *tapeFileWrittenPtr; + + tapeFileWritten.archiveFileId = archiveFileId_1; + tapeFileWritten.diskInstance = diskInstance; + tapeFileWritten.diskFileId = "12340000"; + + tapeFileWritten.diskFileOwnerUid = PUBLIC_DISK_USER; + tapeFileWritten.diskFileGid = PUBLIC_DISK_GROUP; + tapeFileWritten.size = archiveFileSize; + tapeFileWritten.checksumBlob.insert(cta::checksum::ADLER32, "1234"); + tapeFileWritten.storageClassName = m_storageClassDualCopy.name; + tapeFileWritten.vid = m_tape3.vid; + tapeFileWritten.fSeq = 1; + tapeFileWritten.blockId = 4321; + tapeFileWritten.copyNb = 2; + tapeFileWritten.tapeDrive = tapeDrive; + + std::set<cta::catalogue::TapeItemWrittenPointer> fileWrittenSet; + fileWrittenSet.insert(tapeFileWrittenPtr.release()); + m_catalogue->TapeFile()->filesWrittenToTape(fileWrittenSet); + } + + // Only tape 2 should now be identified as missing a 2nd copy + { + cta::catalogue::TapeSearchCriteria searchCriteria; + searchCriteria.checkIncompleteFileCopies = true; + const std::list<cta::common::dataStructures::Tape> tapes = m_catalogue->Tape()->getTapes(searchCriteria); + + ASSERT_EQ(1, tapes.size()); + + const auto vidToTape = CatalogueTestUtils::tapeListToMap(tapes); + const cta::common::dataStructures::Tape & tape_2 = vidToTape.at(m_tape2.vid); + ASSERT_EQ(m_tape2.vid, tape_2.vid); + } + + // 1.1. Write 1 new file copy of 'archiveFileId_2' on 'm_tape3' + // 2. No tapes should now be identified as missing a second tape file copy + { + auto tapeFileWrittenPtr = std::make_unique<cta::catalogue::TapeFileWritten>(); + auto & tapeFileWritten = *tapeFileWrittenPtr; + + tapeFileWritten.archiveFileId = archiveFileId_2; + tapeFileWritten.diskInstance = diskInstance; + tapeFileWritten.diskFileId = "56780000"; + + tapeFileWritten.diskFileOwnerUid = PUBLIC_DISK_USER; + tapeFileWritten.diskFileGid = PUBLIC_DISK_GROUP; + tapeFileWritten.size = archiveFileSize; + tapeFileWritten.checksumBlob.insert(cta::checksum::ADLER32, "8765"); + tapeFileWritten.storageClassName = m_storageClassDualCopy.name; + tapeFileWritten.vid = m_tape3.vid; + tapeFileWritten.fSeq = 2; + tapeFileWritten.blockId = 5678; + tapeFileWritten.copyNb = 2; + tapeFileWritten.tapeDrive = tapeDrive; + + std::set<cta::catalogue::TapeItemWrittenPointer> fileWrittenSet; + fileWrittenSet.insert(tapeFileWrittenPtr.release()); + m_catalogue->TapeFile()->filesWrittenToTape(fileWrittenSet); + } + + // No tapes should now be identified as missing a 2nd copy + { + cta::catalogue::TapeSearchCriteria searchCriteria; + searchCriteria.checkIncompleteFileCopies = true; + const std::list<cta::common::dataStructures::Tape> tapes = m_catalogue->Tape()->getTapes(searchCriteria); + + ASSERT_TRUE(tapes.empty()); + } +} + } // namespace unitTests diff --git a/catalogue/tests/modules/ArchiveFileCatalogueTest.hpp b/catalogue/tests/modules/ArchiveFileCatalogueTest.hpp index da6516c647..b2e39c3265 100644 --- a/catalogue/tests/modules/ArchiveFileCatalogueTest.hpp +++ b/catalogue/tests/modules/ArchiveFileCatalogueTest.hpp @@ -46,6 +46,7 @@ protected: const cta::catalogue::CreateTapeAttributes m_tape1; const cta::catalogue::CreateTapeAttributes m_tape2; + const cta::catalogue::CreateTapeAttributes m_tape3; const cta::catalogue::MediaType m_mediaType; const cta::common::dataStructures::SecurityIdentity m_admin; const cta::common::dataStructures::DiskInstance m_diskInstance; diff --git a/xroot_plugins/XrdCtaTapeLs.hpp b/xroot_plugins/XrdCtaTapeLs.hpp index bcb425b85a..278e75f88f 100644 --- a/xroot_plugins/XrdCtaTapeLs.hpp +++ b/xroot_plugins/XrdCtaTapeLs.hpp @@ -80,7 +80,7 @@ TapeLsStream::TapeLsStream(const frontend::AdminCmdStream& requestMsg, cta::cata searchCriteria.purchaseOrder = requestMsg.getOptional(OptionString::MEDIA_PURCHASE_ORDER_NUMBER, &has_any); searchCriteria.physicalLibraryName = requestMsg.getOptional(OptionString::PHYSICAL_LIBRARY, &has_any); searchCriteria.diskFileIds = requestMsg.getOptional(OptionStrList::FILE_ID, &has_any); - searchCriteria.checkIncompleteFileCopies = requestMsg.getOptional(OptionBoolean::INCOMPLETE_FILE_COPIES, &has_any); + searchCriteria.checkIncompleteFileCopies = requestMsg.getOptional(OptionBoolean::INCOMPLETE_FILE_COPIES, &has_any); auto stateOpt = requestMsg.getOptional(OptionString::STATE, &has_any); if(stateOpt){ diff --git a/xrootd-ssi-protobuf-interface b/xrootd-ssi-protobuf-interface index 95ca6aca15..a0c94a22be 160000 --- a/xrootd-ssi-protobuf-interface +++ b/xrootd-ssi-protobuf-interface @@ -1 +1 @@ -Subproject commit 95ca6aca153a6e72a33a281258e3372d54fe6a74 +Subproject commit a0c94a22bece907d6038e3b1fc452621c64281af -- GitLab From 2164ab82c4c25621aaac1c17422618b1acea50c4 Mon Sep 17 00:00:00 2001 From: Joao Afonso <joao.afonso@cern.ch> Date: Tue, 4 Mar 2025 11:06:30 +0100 Subject: [PATCH 3/3] Modifying --incompletefilecopes to --missingfilecopies --- catalogue/TapeSearchCriteria.hpp | 4 +-- catalogue/rdbms/RdbmsTapeCatalogue.cpp | 4 +-- .../modules/ArchiveFileCatalogueTest.cpp | 6 ++-- cmdline/CtaAdminCmdParse.hpp | 28 +++++++++---------- frontend/grpc/ServerTapeLsRequestHandler.cpp | 24 ++++++++-------- xroot_plugins/XrdCtaTapeLs.hpp | 26 ++++++++--------- xrootd-ssi-protobuf-interface | 2 +- 7 files changed, 47 insertions(+), 47 deletions(-) diff --git a/catalogue/TapeSearchCriteria.hpp b/catalogue/TapeSearchCriteria.hpp index bef57db8da..05160b6b2e 100644 --- a/catalogue/TapeSearchCriteria.hpp +++ b/catalogue/TapeSearchCriteria.hpp @@ -96,9 +96,9 @@ struct TapeSearchCriteria { std::optional<std::vector<std::string>> diskFileIds; /** - * Check tapes with incomplete tape file copies + * Check tapes with missing tape file copies */ - std::optional<bool> checkIncompleteFileCopies; + std::optional<bool> checkMissingFileCopies; /** * The state of the tapes to look for diff --git a/catalogue/rdbms/RdbmsTapeCatalogue.cpp b/catalogue/rdbms/RdbmsTapeCatalogue.cpp index fd580199d5..308a297ca2 100644 --- a/catalogue/rdbms/RdbmsTapeCatalogue.cpp +++ b/catalogue/rdbms/RdbmsTapeCatalogue.cpp @@ -1300,7 +1300,7 @@ std::list<common::dataStructures::Tape> RdbmsTapeCatalogue::getTapes(rdbms::Conn searchCriteria.fromCastor || searchCriteria.purchaseOrder || searchCriteria.physicalLibraryName || - searchCriteria.checkIncompleteFileCopies) { + searchCriteria.checkMissingFileCopies) { sql += R"SQL( WHERE )SQL"; } @@ -1428,7 +1428,7 @@ std::list<common::dataStructures::Tape> RdbmsTapeCatalogue::getTapes(rdbms::Conn )SQL"; addedAWhereConstraint = true; } - if (searchCriteria.checkIncompleteFileCopies.value_or(false)) { + if (searchCriteria.checkMissingFileCopies.value_or(false)) { if (addedAWhereConstraint) { sql += R"SQL( AND )SQL"; } diff --git a/catalogue/tests/modules/ArchiveFileCatalogueTest.cpp b/catalogue/tests/modules/ArchiveFileCatalogueTest.cpp index bea4b57d01..c443f2864f 100644 --- a/catalogue/tests/modules/ArchiveFileCatalogueTest.cpp +++ b/catalogue/tests/modules/ArchiveFileCatalogueTest.cpp @@ -5068,7 +5068,7 @@ TEST_P(cta_catalogue_ArchiveFileTest, getTapesWithMissingTapeFileCopies) { // Tape 1 and 2 should be identified as missing a 2nd copy { cta::catalogue::TapeSearchCriteria searchCriteria; - searchCriteria.checkIncompleteFileCopies = true; + searchCriteria.checkMissingFileCopies = true; const std::list<cta::common::dataStructures::Tape> tapes = m_catalogue->Tape()->getTapes(searchCriteria); ASSERT_EQ(2, tapes.size()); @@ -5109,7 +5109,7 @@ TEST_P(cta_catalogue_ArchiveFileTest, getTapesWithMissingTapeFileCopies) { // Only tape 2 should now be identified as missing a 2nd copy { cta::catalogue::TapeSearchCriteria searchCriteria; - searchCriteria.checkIncompleteFileCopies = true; + searchCriteria.checkMissingFileCopies = true; const std::list<cta::common::dataStructures::Tape> tapes = m_catalogue->Tape()->getTapes(searchCriteria); ASSERT_EQ(1, tapes.size()); @@ -5148,7 +5148,7 @@ TEST_P(cta_catalogue_ArchiveFileTest, getTapesWithMissingTapeFileCopies) { // No tapes should now be identified as missing a 2nd copy { cta::catalogue::TapeSearchCriteria searchCriteria; - searchCriteria.checkIncompleteFileCopies = true; + searchCriteria.checkMissingFileCopies = true; const std::list<cta::common::dataStructures::Tape> tapes = m_catalogue->Tape()->getTapes(searchCriteria); ASSERT_TRUE(tapes.empty()); diff --git a/cmdline/CtaAdminCmdParse.hpp b/cmdline/CtaAdminCmdParse.hpp index 7f5c17562c..c73e72adf2 100644 --- a/cmdline/CtaAdminCmdParse.hpp +++ b/cmdline/CtaAdminCmdParse.hpp @@ -259,18 +259,18 @@ const std::map<std::string, OptionBoolean::Key> boolOptions = { {"--fromcastor", OptionBoolean::FROM_CASTOR }, // hasOption options - {"--disabledtape", OptionBoolean::DISABLED }, - {"--justarchive", OptionBoolean::JUSTARCHIVE }, - {"--justmove", OptionBoolean::JUSTMOVE }, - {"--justaddcopies", OptionBoolean::JUSTADDCOPIES }, - {"--justretrieve", OptionBoolean::JUSTRETRIEVE }, - {"--log", OptionBoolean::SHOW_LOG_ENTRIES }, - {"--lookupnamespace", OptionBoolean::LOOKUP_NAMESPACE }, - {"--summary", OptionBoolean::SUMMARY }, - {"--no-recall", OptionBoolean::NO_RECALL }, - {"--dirtybit", OptionBoolean::DIRTY_BIT }, - {"--isrepackvo", OptionBoolean::IS_REPACK_VO }, - {"--incompletefilecopies", OptionBoolean::INCOMPLETE_FILE_COPIES }, + {"--disabledtape", OptionBoolean::DISABLED }, + {"--justarchive", OptionBoolean::JUSTARCHIVE }, + {"--justmove", OptionBoolean::JUSTMOVE }, + {"--justaddcopies", OptionBoolean::JUSTADDCOPIES }, + {"--justretrieve", OptionBoolean::JUSTRETRIEVE }, + {"--log", OptionBoolean::SHOW_LOG_ENTRIES }, + {"--lookupnamespace", OptionBoolean::LOOKUP_NAMESPACE }, + {"--summary", OptionBoolean::SUMMARY }, + {"--no-recall", OptionBoolean::NO_RECALL }, + {"--dirtybit", OptionBoolean::DIRTY_BIT }, + {"--isrepackvo", OptionBoolean::IS_REPACK_VO }, + {"--missingfilecopies", OptionBoolean::MISSING_FILE_COPIES }, }; /*! @@ -517,7 +517,7 @@ const Option opt_archive_route_type {Option::OPT_STR, std::string(R"( <")") + cta::common::dataStructures::toString(ArchiveRouteType::DEFAULT) + R"(" or ")" + cta::common::dataStructures::toString(ArchiveRouteType::REPACK) + R"(">)"}; -const Option opt_incompletefilecopes {Option::OPT_FLAG, "--incompletefilecopies", "--ifc", ""}; +const Option opt_missingfilecopes {Option::OPT_FLAG, "--missingfilecopies", "--ifc", ""}; /*! * Subset of commands that return streaming output @@ -1037,7 +1037,7 @@ tape (ta) opt_fromcastor.optional(), opt_purchase_order.optional(), opt_physical_library.optional(), - opt_incompletefilecopes.optional()} }, + opt_missingfilecopes.optional()} }, /**md tapefile (tf) diff --git a/frontend/grpc/ServerTapeLsRequestHandler.cpp b/frontend/grpc/ServerTapeLsRequestHandler.cpp index 6c6367038f..04e069a1c3 100644 --- a/frontend/grpc/ServerTapeLsRequestHandler.cpp +++ b/frontend/grpc/ServerTapeLsRequestHandler.cpp @@ -83,18 +83,18 @@ bool cta::frontend::grpc::server::TapeLsRequestHandler::next(const bool bOk) { // Get the search criteria from the optional options - m_searchCriteria.full = requestMsg.getOptional(cta::admin::OptionBoolean::FULL, &bHasAny); - m_searchCriteria.fromCastor = requestMsg.getOptional(cta::admin::OptionBoolean::FROM_CASTOR, &bHasAny); - m_searchCriteria.capacityInBytes = requestMsg.getOptional(cta::admin::OptionUInt64::CAPACITY, &bHasAny); - m_searchCriteria.logicalLibrary = requestMsg.getOptional(cta::admin::OptionString::LOGICAL_LIBRARY, &bHasAny); - m_searchCriteria.tapePool = requestMsg.getOptional(cta::admin::OptionString::TAPE_POOL, &bHasAny); - m_searchCriteria.vo = requestMsg.getOptional(cta::admin::OptionString::VO, &bHasAny); - m_searchCriteria.vid = requestMsg.getOptional(cta::admin::OptionString::VID, &bHasAny); - m_searchCriteria.mediaType = requestMsg.getOptional(cta::admin::OptionString::MEDIA_TYPE, &bHasAny); - m_searchCriteria.vendor = requestMsg.getOptional(cta::admin::OptionString::VENDOR, &bHasAny); - m_searchCriteria.purchaseOrder = requestMsg.getOptional(cta::admin::OptionString::MEDIA_PURCHASE_ORDER_NUMBER, &bHasAny); - m_searchCriteria.diskFileIds = requestMsg.getOptional(cta::admin::OptionStrList::FILE_ID, &bHasAny); - m_searchCriteria.checkIncompleteFileCopies = requestMsg.getOptional(cta::admin::OptionBoolean::INCOMPLETE_FILE_COPIES, &bHasAny); + m_searchCriteria.full = requestMsg.getOptional(cta::admin::OptionBoolean::FULL, &bHasAny); + m_searchCriteria.fromCastor = requestMsg.getOptional(cta::admin::OptionBoolean::FROM_CASTOR, &bHasAny); + m_searchCriteria.capacityInBytes = requestMsg.getOptional(cta::admin::OptionUInt64::CAPACITY, &bHasAny); + m_searchCriteria.logicalLibrary = requestMsg.getOptional(cta::admin::OptionString::LOGICAL_LIBRARY, &bHasAny); + m_searchCriteria.tapePool = requestMsg.getOptional(cta::admin::OptionString::TAPE_POOL, &bHasAny); + m_searchCriteria.vo = requestMsg.getOptional(cta::admin::OptionString::VO, &bHasAny); + m_searchCriteria.vid = requestMsg.getOptional(cta::admin::OptionString::VID, &bHasAny); + m_searchCriteria.mediaType = requestMsg.getOptional(cta::admin::OptionString::MEDIA_TYPE, &bHasAny); + m_searchCriteria.vendor = requestMsg.getOptional(cta::admin::OptionString::VENDOR, &bHasAny); + m_searchCriteria.purchaseOrder = requestMsg.getOptional(cta::admin::OptionString::MEDIA_PURCHASE_ORDER_NUMBER, &bHasAny); + m_searchCriteria.diskFileIds = requestMsg.getOptional(cta::admin::OptionStrList::FILE_ID, &bHasAny); + m_searchCriteria.checkMissingFileCopies = requestMsg.getOptional(cta::admin::OptionBoolean::MISSING_FILE_COPIES, &bHasAny); auto stateOpt = requestMsg.getOptional(cta::admin::OptionString::STATE, &bHasAny); if(stateOpt){ m_searchCriteria.state = common::dataStructures::Tape::stringToState(stateOpt.value()); diff --git a/xroot_plugins/XrdCtaTapeLs.hpp b/xroot_plugins/XrdCtaTapeLs.hpp index 278e75f88f..07edc5b2d0 100644 --- a/xroot_plugins/XrdCtaTapeLs.hpp +++ b/xroot_plugins/XrdCtaTapeLs.hpp @@ -68,19 +68,19 @@ TapeLsStream::TapeLsStream(const frontend::AdminCmdStream& requestMsg, cta::cata // Get the search criteria from the optional options - searchCriteria.full = requestMsg.getOptional(OptionBoolean::FULL, &has_any); - searchCriteria.fromCastor = requestMsg.getOptional(OptionBoolean::FROM_CASTOR, &has_any); - searchCriteria.capacityInBytes = requestMsg.getOptional(OptionUInt64::CAPACITY, &has_any); - searchCriteria.logicalLibrary = requestMsg.getOptional(OptionString::LOGICAL_LIBRARY, &has_any); - searchCriteria.tapePool = requestMsg.getOptional(OptionString::TAPE_POOL, &has_any); - searchCriteria.vo = requestMsg.getOptional(OptionString::VO, &has_any); - searchCriteria.vid = requestMsg.getOptional(OptionString::VID, &has_any); - searchCriteria.mediaType = requestMsg.getOptional(OptionString::MEDIA_TYPE, &has_any); - searchCriteria.vendor = requestMsg.getOptional(OptionString::VENDOR, &has_any); - searchCriteria.purchaseOrder = requestMsg.getOptional(OptionString::MEDIA_PURCHASE_ORDER_NUMBER, &has_any); - searchCriteria.physicalLibraryName = requestMsg.getOptional(OptionString::PHYSICAL_LIBRARY, &has_any); - searchCriteria.diskFileIds = requestMsg.getOptional(OptionStrList::FILE_ID, &has_any); - searchCriteria.checkIncompleteFileCopies = requestMsg.getOptional(OptionBoolean::INCOMPLETE_FILE_COPIES, &has_any); + searchCriteria.full = requestMsg.getOptional(OptionBoolean::FULL, &has_any); + searchCriteria.fromCastor = requestMsg.getOptional(OptionBoolean::FROM_CASTOR, &has_any); + searchCriteria.capacityInBytes = requestMsg.getOptional(OptionUInt64::CAPACITY, &has_any); + searchCriteria.logicalLibrary = requestMsg.getOptional(OptionString::LOGICAL_LIBRARY, &has_any); + searchCriteria.tapePool = requestMsg.getOptional(OptionString::TAPE_POOL, &has_any); + searchCriteria.vo = requestMsg.getOptional(OptionString::VO, &has_any); + searchCriteria.vid = requestMsg.getOptional(OptionString::VID, &has_any); + searchCriteria.mediaType = requestMsg.getOptional(OptionString::MEDIA_TYPE, &has_any); + searchCriteria.vendor = requestMsg.getOptional(OptionString::VENDOR, &has_any); + searchCriteria.purchaseOrder = requestMsg.getOptional(OptionString::MEDIA_PURCHASE_ORDER_NUMBER, &has_any); + searchCriteria.physicalLibraryName = requestMsg.getOptional(OptionString::PHYSICAL_LIBRARY, &has_any); + searchCriteria.diskFileIds = requestMsg.getOptional(OptionStrList::FILE_ID, &has_any); + searchCriteria.checkMissingFileCopies = requestMsg.getOptional(OptionBoolean::MISSING_FILE_COPIES, &has_any); auto stateOpt = requestMsg.getOptional(OptionString::STATE, &has_any); if(stateOpt){ diff --git a/xrootd-ssi-protobuf-interface b/xrootd-ssi-protobuf-interface index a0c94a22be..f59e44742c 160000 --- a/xrootd-ssi-protobuf-interface +++ b/xrootd-ssi-protobuf-interface @@ -1 +1 @@ -Subproject commit a0c94a22bece907d6038e3b1fc452621c64281af +Subproject commit f59e44742c6436a421157e76e5ee062c88d813bf -- GitLab