diff --git a/ReleaseNotes.md b/ReleaseNotes.md index b6ad9d63878a9e47759f3092ebd80d6ed83902de..6a1cf186b5685ec65dc4c94c94d9be9f864df310 100644 --- a/ReleaseNotes.md +++ b/ReleaseNotes.md @@ -8,6 +8,7 @@ - cta/CTA#999 - Add a default mount rule for recalls - cta/CTA#1109 - Add --dirtybit option to cta-admin ta ch and show dirty bit value in cta-admin --json ta ls - cta/CTA#1111 - Add disk instance and disk instance tables to catalogue and respective cta-admin diskinstance/diskinstancespace add/ls/ch/rm commands +- cta/CTA#1108 - Make cta-admin --json sq show mount policy with highest priority and mount policy with lowest request age for each queue. ## Bug fixes - cta/CTA#1102 - Make requeued jobs retain their original creation time diff --git a/common/dataStructures/QueueAndMountSummary.hpp b/common/dataStructures/QueueAndMountSummary.hpp index 5f0f42afb5b288cda1287be6fa7d3b9084fe5ae0..b08db2417bc2d28ba8f602ff4fe6ca69a795eb90 100644 --- a/common/dataStructures/QueueAndMountSummary.hpp +++ b/common/dataStructures/QueueAndMountSummary.hpp @@ -61,6 +61,8 @@ struct QueueAndMountSummary { time_t sleepTime; }; optional<SleepForSpaceInfo> sleepForSpaceInfo; + std::string highestPriorityMountPolicy; + std::string lowestRequestAgeMountPolicy; std::list<std::string> mountPolicies; static QueueAndMountSummary &getOrCreateEntry(std::list<QueueAndMountSummary> &summaryList, diff --git a/scheduler/OStoreDB/OStoreDB.cpp b/scheduler/OStoreDB/OStoreDB.cpp index 38e98c9938e0fa8a27b64025d731ca9d458cfd61..fef6380958a6ccffbd3b1e8517fce00eeeb78004 100644 --- a/scheduler/OStoreDB/OStoreDB.cpp +++ b/scheduler/OStoreDB/OStoreDB.cpp @@ -238,6 +238,8 @@ void OStoreDB::fetchMountInfo(SchedulerDatabase::TapeMountDecisionInfo& tmdi, Ro auto mountPolicyToUse = createBestArchiveMountPolicy(mountPoliciesInQueueList); m.priority = mountPolicyToUse.archivePriority; m.minRequestAge = mountPolicyToUse.archiveMinRequestAge; + m.highestPriorityMountPolicyName = getHighestPriorityArchiveMountPolicyName(mountPoliciesInQueueList); + m.lowestRequestAgeMountPolicyName = getLowestRequestAgeArchiveMountPolicyName(mountPoliciesInQueueList); } } m.logicalLibrary = ""; @@ -301,6 +303,8 @@ void OStoreDB::fetchMountInfo(SchedulerDatabase::TapeMountDecisionInfo& tmdi, Ro auto mountPolicyToUse = createBestArchiveMountPolicy(mountPoliciesInQueueList); m.priority = mountPolicyToUse.archivePriority; m.minRequestAge = mountPolicyToUse.archiveMinRequestAge; + m.highestPriorityMountPolicyName = getHighestPriorityArchiveMountPolicyName(mountPoliciesInQueueList); + m.lowestRequestAgeMountPolicyName = getLowestRequestAgeArchiveMountPolicyName(mountPoliciesInQueueList); } } m.logicalLibrary = ""; @@ -373,6 +377,8 @@ void OStoreDB::fetchMountInfo(SchedulerDatabase::TapeMountDecisionInfo& tmdi, Ro //Getting the default mountPolicies parameters from the queue summary uint64_t minRetrieveRequestAge = rqSummary.minRetrieveRequestAge; uint64_t priority = rqSummary.priority; + optional<std::string> highestPriorityMountPolicyName; + optional<std::string> lowestRequestAgeMountPolicyName; std::list<std::string> queueMountPolicyNames; //Try to get the last values of the mountPolicies from the ones in the Catalogue if(mountPolicies.size()){ @@ -385,6 +391,8 @@ void OStoreDB::fetchMountInfo(SchedulerDatabase::TapeMountDecisionInfo& tmdi, Ro common::dataStructures::MountPolicy mountPolicyToUse = createBestRetrieveMountPolicy(mountPoliciesInQueueList); priority = mountPolicyToUse.retrievePriority; minRetrieveRequestAge = mountPolicyToUse.retrieveMinRequestAge; + highestPriorityMountPolicyName = getHighestPriorityRetrieveMountPolicyName(mountPoliciesInQueueList); + lowestRequestAgeMountPolicyName = getLowestRequestAgeRetrieveMountPolicyName(mountPoliciesInQueueList); } } // Check if we have activities and if all the jobs are covered by one or not (possible mixed case). @@ -404,6 +412,8 @@ void OStoreDB::fetchMountInfo(SchedulerDatabase::TapeMountDecisionInfo& tmdi, Ro m.youngestJobStartTime = rqueue.getJobsSummary().youngestJobStartTime; m.priority = priority; m.minRequestAge = minRetrieveRequestAge; + m.highestPriorityMountPolicyName = highestPriorityMountPolicyName; + m.lowestRequestAgeMountPolicyName = lowestRequestAgeMountPolicyName; m.logicalLibrary = ""; // The logical library is not known here, and will be determined by the caller. m.tapePool = ""; // The tape pool is not know and will be determined by the caller. m.vendor = ""; // The vendor is not known here, and will be determined by the caller. @@ -434,6 +444,8 @@ void OStoreDB::fetchMountInfo(SchedulerDatabase::TapeMountDecisionInfo& tmdi, Ro m.youngestJobStartTime = rqSummary.youngestJobStartTime; m.priority = priority; m.minRequestAge = minRetrieveRequestAge; + m.highestPriorityMountPolicyName = highestPriorityMountPolicyName; + m.lowestRequestAgeMountPolicyName = lowestRequestAgeMountPolicyName; m.logicalLibrary = ""; // The logical library is not known here, and will be determined by the caller. m.tapePool = ""; // The tape pool is not know and will be determined by the caller. m.vendor = ""; // The vendor is not known here, and will be determined by the caller. @@ -572,6 +584,44 @@ common::dataStructures::MountPolicy OStoreDB::createBestArchiveMountPolicy(const return bestMountPolicy; } +//------------------------------------------------------------------------------ +// OStoreDB::getHighestPriorityArchiveMountPolicyName() +//------------------------------------------------------------------------------ +std::string OStoreDB::getHighestPriorityArchiveMountPolicyName(const std::list<common::dataStructures::MountPolicy>& mountPolicies) { + if(mountPolicies.empty()){ + throw cta::exception::Exception("In OStoreDB::getHighestPriorityArchiveMountPolicyName(), empty mount policy list."); + } + //We need to get the most advantageous mountPolicy + //As the Init element of the reduce function is the first element of the list, we start the reduce with the second element (++mountPolicyInQueueList.begin()) + common::dataStructures::MountPolicy bestMountPolicy = cta::utils::reduce(++mountPolicies.begin(), mountPolicies.end(),mountPolicies.front(), + [](const common::dataStructures::MountPolicy & mp1, const common::dataStructures::MountPolicy & mp2){ + if(mp2.archivePriority > mp1.archivePriority){ + return mp2; + } + return mp1; + }); + return bestMountPolicy.name; +} + +//------------------------------------------------------------------------------ +// OStoreDB::getLowestRequestAgeArchiveMountPolicyName() +//------------------------------------------------------------------------------ +std::string OStoreDB::getLowestRequestAgeArchiveMountPolicyName(const std::list<common::dataStructures::MountPolicy>& mountPolicies) { + if(mountPolicies.empty()){ + throw cta::exception::Exception("In OStoreDB::getLowestRequestAgeArchiveMountPolicyName(), empty mount policy list."); + } + //We need to get the most advantageous mountPolicy + //As the Init element of the reduce function is the first element of the list, we start the reduce with the second element (++mountPolicyInQueueList.begin()) + common::dataStructures::MountPolicy bestMountPolicy = cta::utils::reduce(++mountPolicies.begin(), mountPolicies.end(),mountPolicies.front(), + [](const common::dataStructures::MountPolicy & mp1, const common::dataStructures::MountPolicy & mp2){ + if(mp1.archiveMinRequestAge < mp2.archiveMinRequestAge){ + return mp1; + } + return mp2; + }); + return bestMountPolicy.name; +} + //------------------------------------------------------------------------------ // OStoreDB::createBestRetrieveMountPolicy() //------------------------------------------------------------------------------ @@ -594,7 +644,43 @@ common::dataStructures::MountPolicy OStoreDB::createBestRetrieveMountPolicy(cons return bestMountPolicy; } +//------------------------------------------------------------------------------ +// OStoreDB::getHighestPriorityRetrieveMountPolicyName() +//------------------------------------------------------------------------------ +std::string OStoreDB::getHighestPriorityRetrieveMountPolicyName(const std::list<common::dataStructures::MountPolicy>& mountPolicies) { + if(mountPolicies.empty()){ + throw cta::exception::Exception("In OStoreDB::getHighestPriorityRetrieveMountPolicyName(), empty mount policy list."); + } + //We need to get the most advantageous mountPolicy + //As the Init element of the reduce function is the first element of the list, we start the reduce with the second element (++mountPolicyInQueueList.begin()) + common::dataStructures::MountPolicy bestMountPolicy = cta::utils::reduce(++mountPolicies.begin(), mountPolicies.end(),mountPolicies.front(), + [](const common::dataStructures::MountPolicy & mp1, const common::dataStructures::MountPolicy & mp2){ + if(mp1.retrievePriority > mp2.retrievePriority){ + return mp1; + } + return mp2; + }); + return bestMountPolicy.name; +} +//------------------------------------------------------------------------------ +// OStoreDB::getLowestRequestAgeRetrieveMountPolicyName() +//------------------------------------------------------------------------------ +std::string OStoreDB::getLowestRequestAgeRetrieveMountPolicyName(const std::list<common::dataStructures::MountPolicy>& mountPolicies) { + if(mountPolicies.empty()){ + throw cta::exception::Exception("In OStoreDB::getLowestRequestAgeRetrieveMountPolicyName(), empty mount policy list."); + } + //We need to get the most advantageous mountPolicy + //As the Init element of the reduce function is the first element of the list, we start the reduce with the second element (++mountPolicyInQueueList.begin()) + common::dataStructures::MountPolicy bestMountPolicy = cta::utils::reduce(++mountPolicies.begin(), mountPolicies.end(),mountPolicies.front(), + [](const common::dataStructures::MountPolicy & mp1, const common::dataStructures::MountPolicy & mp2){ + if(mp1.retrieveMinRequestAge < mp2.retrieveMinRequestAge){ + return mp1; + } + return mp2; + }); + return bestMountPolicy.name; +} //------------------------------------------------------------------------------ // OStoreDB::getMountInfo() diff --git a/scheduler/OStoreDB/OStoreDB.hpp b/scheduler/OStoreDB/OStoreDB.hpp index fd6dbe0b42bb898ed14af54e4572cdbd03065760..658d852b1d3cb259748d4e928c910e463ead0561 100644 --- a/scheduler/OStoreDB/OStoreDB.hpp +++ b/scheduler/OStoreDB/OStoreDB.hpp @@ -179,6 +179,22 @@ class OStoreDB: public SchedulerDatabase { * @return the best archive mount policy to use */ common::dataStructures::MountPolicy createBestArchiveMountPolicy(const std::list<common::dataStructures::MountPolicy> & mountPolicies); + + /** + * Return the name of the archive mount policy with highest priority from the mountPolicies passed in parameter + * The aim is to do the same as ArchiveQueue::getJobsSummary() regarding the priority + * @param mountPolicies the list of mount policies in order to create the best one. + * @return the archive mount policy with highest priority + */ + std::string getHighestPriorityArchiveMountPolicyName(const std::list<common::dataStructures::MountPolicy> & mountPolicies); + + /** + * Return the name of the archive mount policy with lowest request age from the mountPolicies passed in parameter + * The aim is to do the same as ArchiveQueue::getJobsSummary() regarding the request age + * @param mountPolicies the list of mount policies in order to create the best one. + * @return the archive mount policy with lowest request age + */ + std::string getLowestRequestAgeArchiveMountPolicyName(const std::list<common::dataStructures::MountPolicy> & mountPolicies); /** * Return the best retrieve mount policy from the mountPolicies passed in parameter @@ -188,6 +204,23 @@ class OStoreDB: public SchedulerDatabase { */ common::dataStructures::MountPolicy createBestRetrieveMountPolicy(const std::list<common::dataStructures::MountPolicy> & mountPolicies); + /** + * Return the name of the retrieve mount policy with highest priority from the mountPolicies passed in parameter + * The aim is to do the same as RetrieveQueue::getJobsSummary() regarding the priority + * @param mountPolicies the list of mount policies in order to create the best one. + * @return the retrieve mount policy with highest priority + */ + std::string getHighestPriorityRetrieveMountPolicyName(const std::list<common::dataStructures::MountPolicy> & mountPolicies); + + /** + * Return the name of the retrieve mount policy with lowest request age from the mountPolicies passed in parameter + * The aim is to do the same as RetrieveQueue::getJobsSummary() regarding the request age + * @param mountPolicies the list of mount policies in order to create the best one. + * @return the retrieve mount policy with lowest request age + */ + std::string getLowestRequestAgeRetrieveMountPolicyName(const std::list<common::dataStructures::MountPolicy> & mountPolicies); + + public: std::unique_ptr<SchedulerDatabase::TapeMountDecisionInfo> getMountInfo(log::LogContext& logContext) override; diff --git a/scheduler/Scheduler.cpp b/scheduler/Scheduler.cpp index 441e89d4fce4b23ca9ce23666cbf2e7f51018124..b4d1a6d6fe0c2d2d0ae76d2ded4e2a5f6ee4edce 100644 --- a/scheduler/Scheduler.cpp +++ b/scheduler/Scheduler.cpp @@ -1765,6 +1765,12 @@ std::list<common::dataStructures::QueueAndMountSummary> Scheduler::getQueuesAndM if (pm.mountPolicyNames) { summary.mountPolicies = pm.mountPolicyNames.value(); } + if (pm.highestPriorityMountPolicyName) { + summary.highestPriorityMountPolicy = pm.highestPriorityMountPolicyName.value(); + } + if (pm.lowestRequestAgeMountPolicyName) { + summary.lowestRequestAgeMountPolicy = pm.lowestRequestAgeMountPolicyName.value(); + } break; case common::dataStructures::MountType::Retrieve: // TODO: we should remove the retrieveMinRequestAge if it's redundant, or rename pm.minArchiveRequestAge. @@ -1777,6 +1783,12 @@ std::list<common::dataStructures::QueueAndMountSummary> Scheduler::getQueuesAndM if (pm.mountPolicyNames) { summary.mountPolicies = pm.mountPolicyNames.value(); } + if (pm.highestPriorityMountPolicyName) { + summary.highestPriorityMountPolicy = pm.highestPriorityMountPolicyName.value(); + } + if (pm.lowestRequestAgeMountPolicyName) { + summary.lowestRequestAgeMountPolicy = pm.lowestRequestAgeMountPolicyName.value(); + } if (pm.sleepingMount) { common::dataStructures::QueueAndMountSummary::SleepForSpaceInfo sfsi; sfsi.startTime = pm.sleepStartTime; diff --git a/scheduler/SchedulerDatabase.hpp b/scheduler/SchedulerDatabase.hpp index 56493b933acc39926eb3f21021c8bb490c1b35db..a85a991e9ad123be17293a8fbf5a4ade246db971 100644 --- a/scheduler/SchedulerDatabase.hpp +++ b/scheduler/SchedulerDatabase.hpp @@ -672,6 +672,9 @@ class SchedulerDatabase { optional<std::string> activity; /**Activity if we have on for this potential mount */ + optional<std::string> highestPriorityMountPolicyName; + optional<std::string> lowestRequestAgeMountPolicyName; + optional<std::list<std::string>> mountPolicyNames; /**< Names of mount policies for the mount*/ bool operator < (const PotentialMount &other) const { diff --git a/xroot_plugins/XrdCtaShowQueues.hpp b/xroot_plugins/XrdCtaShowQueues.hpp index e55827a19caa9771e4f05c799c591f8b2dd9c178..28a78afdc753228e404d2a476b3bc4e6350dde42 100644 --- a/xroot_plugins/XrdCtaShowQueues.hpp +++ b/xroot_plugins/XrdCtaShowQueues.hpp @@ -119,6 +119,8 @@ int ShowQueuesStream::fillBuffer(XrdSsiPb::OStreamBuffer<Data> *streambuf) { for (auto &policyName: sq.mountPolicies) { sq_item->add_mount_policies(policyName); } + sq_item->set_highest_priority_mount_policy(sq.highestPriorityMountPolicy); + sq_item->set_lowest_request_age_mount_policy(sq.lowestRequestAgeMountPolicy); is_buffer_full = streambuf->Push(record); } diff --git a/xrootd-ssi-protobuf-interface b/xrootd-ssi-protobuf-interface index ce876d5ef34445deeab59a4f24c93538eec9d41e..4b991b3ae2117f32f31f58730cde29c161335578 160000 --- a/xrootd-ssi-protobuf-interface +++ b/xrootd-ssi-protobuf-interface @@ -1 +1 @@ -Subproject commit ce876d5ef34445deeab59a4f24c93538eec9d41e +Subproject commit 4b991b3ae2117f32f31f58730cde29c161335578