@@ -856,17 +856,39 @@ void RequestManager::requestFailure(std::shared_ptr<XrdAdaptor::ClientRequest> c
856856 m_disabledSources.insert (source_ptr);
857857
858858 std::unique_lock<std::recursive_mutex> sentry (m_source_mutex);
859- if ((!m_activeSources.empty ()) && (m_activeSources[0 ].get () == source_ptr.get ())) {
859+ // Remove the failed source from the container of active sources
860+ if (auto found = std::ranges::find_if (
861+ m_activeSources, [&source_ptr](const std::shared_ptr<Source> &src) { return src.get () == source_ptr.get (); });
862+ found != m_activeSources.end ()) {
860863 auto oldSources = m_activeSources;
861- m_activeSources.erase (m_activeSources.begin ());
862- reportSiteChange (oldSources, m_activeSources);
863- } else if ((m_activeSources.size () > 1 ) && (m_activeSources[1 ].get () == source_ptr.get ())) {
864- auto oldSources = m_activeSources;
865- m_activeSources.erase (m_activeSources.begin () + 1 );
864+ m_activeSources.erase (found);
866865 reportSiteChange (oldSources, m_activeSources);
867866 }
867+ // Find a new source to send the request to
868+ // - First, if there is another active source, use it
869+ // - Then, if there are no active sources, if there are inactive
870+ // sources, use the best inactive source
871+ // - Then, if there are no active or inactice sources, try to open a
872+ // new connection for a new source
868873 std::shared_ptr<Source> new_source;
869- if (m_activeSources.empty ()) {
874+ if (not m_activeSources.empty ()) {
875+ new_source = m_activeSources[0 ];
876+ } else if (not m_inactiveSources.empty ()) {
877+ // similar logic as in checkSourcesImpl()
878+ // assume the "sort open delay" doesn't matter in case of a request failure
879+ auto bestInactiveSource =
880+ std::min_element (m_inactiveSources.begin (),
881+ m_inactiveSources.end (),
882+ [](const std::shared_ptr<Source> &s1, const std::shared_ptr<Source> &s2) {
883+ return s1->getQuality () < s2->getQuality ();
884+ });
885+ new_source = *bestInactiveSource;
886+
887+ auto oldSources = m_activeSources;
888+ m_activeSources.push_back (*bestInactiveSource);
889+ m_inactiveSources.erase (bestInactiveSource);
890+ reportSiteChange (oldSources, m_activeSources);
891+ } else {
870892 std::shared_future<std::shared_ptr<Source>> future = m_open_handler->open ();
871893 timespec now;
872894 GET_CLOCK_MONOTONIC (now);
@@ -910,8 +932,6 @@ void RequestManager::requestFailure(std::shared_ptr<XrdAdaptor::ClientRequest> c
910932 auto oldSources = m_activeSources;
911933 m_activeSources.push_back (new_source);
912934 reportSiteChange (oldSources, m_activeSources);
913- } else {
914- new_source = m_activeSources[0 ];
915935 }
916936 new_source->handle (c_ptr);
917937}
0 commit comments