From 18e7e7c28d914ab6f75c23ea8472ea7779aea70d Mon Sep 17 00:00:00 2001 From: Steven Murray <Steven.Murray@cern.ch> Date: Mon, 12 Feb 2018 21:37:57 +0100 Subject: [PATCH] Added Catalogue::getArchiveFileQueueCriteria() --- catalogue/Catalogue.hpp | 20 +++++++++++ catalogue/CatalogueRetryWrapper.hpp | 8 ++++- catalogue/DummyCatalogue.hpp | 5 ++- catalogue/RdbmsCatalogue.cpp | 52 +++++++++++++++++++++++++++++ catalogue/RdbmsCatalogue.hpp | 20 +++++++++++ 5 files changed, 103 insertions(+), 2 deletions(-) diff --git a/catalogue/Catalogue.hpp b/catalogue/Catalogue.hpp index 808bf0c8c7..bb74b1b135 100644 --- a/catalogue/Catalogue.hpp +++ b/catalogue/Catalogue.hpp @@ -27,6 +27,7 @@ #include "common/dataStructures/AdminHost.hpp" #include "common/dataStructures/AdminUser.hpp" #include "common/dataStructures/ArchiveFile.hpp" +#include "common/dataStructures/ArchiveFileQueueCriteria.hpp" #include "common/dataStructures/ArchiveFileQueueCriteriaAndFileId.hpp" #include "common/dataStructures/ArchiveFileSummary.hpp" #include "common/dataStructures/ArchiveJob.hpp" @@ -96,6 +97,25 @@ public: */ virtual void tapeLabelled(const std::string &vid, const std::string &drive, const bool lbpIsOn) = 0; + /** + * Returns the information required to queue an archive request. + * + * @param diskInstanceName The name of the disk instance to which the + * storage class belongs. + * @param storageClassName The name of the storage class of the file to be + * archived. The storage class name is only guaranteed to be unique within + * its disk instance. The storage class name will be used by the Catalogue + * to determine the destination tape pool for each tape copy. + * @param user The user for whom the file is to be archived. This will be + * used by the Catalogue to determine the mount policy to be used when + * archiving the file. + * @return The information required to queue an archive request. + */ + virtual common::dataStructures::ArchiveFileQueueCriteria getArchiveFileQueueCriteria( + const std::string &diskInstanceName, + const std::string &storageClassName, + const common::dataStructures::UserIdentity &user) = 0; + /** * Prepares the catalogue for a new archive file and returns the information * required to queue the associated archive request. diff --git a/catalogue/CatalogueRetryWrapper.hpp b/catalogue/CatalogueRetryWrapper.hpp index b0b753c118..2bff386595 100644 --- a/catalogue/CatalogueRetryWrapper.hpp +++ b/catalogue/CatalogueRetryWrapper.hpp @@ -68,7 +68,13 @@ public: return retryOnLostConnection(m_log, [&]{return m_catalogue->tapeLabelled(vid, drive, lbpIsOn);}, m_maxTriesToConnect); } - common::dataStructures::ArchiveFileQueueCriteriaAndFileId prepareForNewFile( const std::string &diskInstanceName, const std::string &storageClassName, const common::dataStructures::UserIdentity &user) override { + common::dataStructures::ArchiveFileQueueCriteria getArchiveFileQueueCriteria(const std::string &diskInstanceName, + const std::string &storageClassName, const common::dataStructures::UserIdentity &user) override { + return retryOnLostConnection(m_log, [&]{return m_catalogue->getArchiveFileQueueCriteria(diskInstanceName, storageClassName, user);}, m_maxTriesToConnect); + } + + common::dataStructures::ArchiveFileQueueCriteriaAndFileId prepareForNewFile(const std::string &diskInstanceName, + const std::string &storageClassName, const common::dataStructures::UserIdentity &user) override { return retryOnLostConnection(m_log, [&]{return m_catalogue->prepareForNewFile(diskInstanceName, storageClassName, user);}, m_maxTriesToConnect); } diff --git a/catalogue/DummyCatalogue.hpp b/catalogue/DummyCatalogue.hpp index aa1f55e686..ac9c0be5e9 100644 --- a/catalogue/DummyCatalogue.hpp +++ b/catalogue/DummyCatalogue.hpp @@ -99,7 +99,10 @@ public: void modifyTapeTapePoolName(const common::dataStructures::SecurityIdentity& admin, const std::string& vid, const std::string& tapePoolName) override { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); } void noSpaceLeftOnTape(const std::string& vid) override { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); } void ping() override { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); } - common::dataStructures::ArchiveFileQueueCriteriaAndFileId prepareForNewFile(const std::string& diskInstanceName, const std::string& storageClassName, const common::dataStructures::UserIdentity& user) override { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); } + common::dataStructures::ArchiveFileQueueCriteria getArchiveFileQueueCriteria(const std::string &diskInstanceName, + const std::string &storageClassName, const common::dataStructures::UserIdentity &user) override { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); } + common::dataStructures::ArchiveFileQueueCriteriaAndFileId prepareForNewFile(const std::string &diskInstanceName, + const std::string &storageClassName, const common::dataStructures::UserIdentity &user) override { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); } common::dataStructures::RetrieveFileQueueCriteria prepareToRetrieveFile(const std::string& instanceName, const uint64_t archiveFileId, const common::dataStructures::UserIdentity& user, log::LogContext &lc) override { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); } common::dataStructures::RetrieveFileQueueCriteria prepareToRetrieveFileByDiskFileId(const std::string &diskInstanceName, const std::string &diskFileId, const common::dataStructures::UserIdentity &user, log::LogContext &lc) override { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); } void reclaimTape(const common::dataStructures::SecurityIdentity& admin, const std::string& vid) override { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); } diff --git a/catalogue/RdbmsCatalogue.cpp b/catalogue/RdbmsCatalogue.cpp index e5d8cc4ee3..68c47b85ab 100644 --- a/catalogue/RdbmsCatalogue.cpp +++ b/catalogue/RdbmsCatalogue.cpp @@ -3913,6 +3913,58 @@ void RdbmsCatalogue::tapeLabelled(const std::string &vid, const std::string &dri } } +//------------------------------------------------------------------------------ +// getArchiveFileQueueCriteria +//------------------------------------------------------------------------------ +common::dataStructures::ArchiveFileQueueCriteria RdbmsCatalogue::getArchiveFileQueueCriteria( + const std::string &diskInstanceName, + const std::string &storageClassName, const common::dataStructures::UserIdentity &user) { + try { + auto conn = m_connPool.getConn(); + const common::dataStructures::TapeCopyToPoolMap copyToPoolMap = getTapeCopyToPoolMap(conn, diskInstanceName, + storageClassName); + const uint64_t expectedNbRoutes = getExpectedNbArchiveRoutes(conn, diskInstanceName, storageClassName); + + // Check that the number of archive routes is correct + if(copyToPoolMap.empty()) { + exception::UserError ue; + ue.getMessage() << "Storage class " << diskInstanceName << ":" << storageClassName << " has no archive routes"; + throw ue; + } + if(copyToPoolMap.size() != expectedNbRoutes) { + exception::UserError ue; + ue.getMessage() << "Storage class " << diskInstanceName << ":" << storageClassName << " does not have the" + " expected number of archive routes routes: expected=" << expectedNbRoutes << ", actual=" << + copyToPoolMap.size(); + throw ue; + } + + const RequesterAndGroupMountPolicies mountPolicies = getMountPolicies(conn, diskInstanceName, user.name, + user.group); + // Requester mount policies overrule requester group mount policies + common::dataStructures::MountPolicy mountPolicy; + if(!mountPolicies.requesterMountPolicies.empty()) { + mountPolicy = mountPolicies.requesterMountPolicies.front(); + } else if(!mountPolicies.requesterGroupMountPolicies.empty()) { + mountPolicy = mountPolicies.requesterGroupMountPolicies.front(); + } else { + exception::UserError ue; + ue.getMessage() << "Cannot archive file because there are no mount rules for the requester or their group:" + " storageClass=" << storageClassName << " requester=" << diskInstanceName << ":" << user.name << ":" << + user.group; + throw ue; + } + + return common::dataStructures::ArchiveFileQueueCriteria(copyToPoolMap, mountPolicy); + } catch(exception::LostDatabaseConnection &le) { + throw exception::LostDatabaseConnection(std::string(__FUNCTION__) + " failed: " + le.getMessage().str()); + } catch(exception::UserError &) { + throw; + } catch(exception::Exception &ex) { + throw exception::Exception(std::string(__FUNCTION__) + " failed: " + ex.getMessage().str()); + } +} + //------------------------------------------------------------------------------ // prepareForNewFile //------------------------------------------------------------------------------ diff --git a/catalogue/RdbmsCatalogue.hpp b/catalogue/RdbmsCatalogue.hpp index 99fb948b90..882dd9c7c2 100644 --- a/catalogue/RdbmsCatalogue.hpp +++ b/catalogue/RdbmsCatalogue.hpp @@ -101,6 +101,26 @@ public: */ void tapeLabelled(const std::string &vid, const std::string &drive, const bool lbpIsOn) override; + /** + * Prepares the catalogue for a new archive file and returns the information + * required to queue the associated archive request. + * + * @param diskInstanceName The name of the disk instance to which the + * storage class belongs. + * @param storageClassName The name of the storage class of the file to be + * archived. The storage class name is only guaranteed to be unique within + * its disk instance. The storage class name will be used by the Catalogue + * to determine the destination tape pool for each tape copy. + * @param user The user for whom the file is to be archived. This will be + * used by the Catalogue to determine the mount policy to be used when + * archiving the file. + * @return The information required to queue the associated archive request. + */ + common::dataStructures::ArchiveFileQueueCriteria getArchiveFileQueueCriteria( + const std::string &diskInstanceName, + const std::string &storageClassName, + const common::dataStructures::UserIdentity &user) override; + /** * Prepares the catalogue for a new archive file and returns the information * required to queue the associated archive request. -- GitLab