@@ -362,7 +362,7 @@ void CCDBDownloader::tryNewHost(PerformData* performData, CURL* easy_handle)
362362{
363363 auto requestData = performData->requestData ;
364364 std::string newUrl = requestData->hosts .at (performData->hostInd ) + " /" + requestData->path + " /" + std::to_string (requestData->timestamp );
365- LOG (debug) << " Connecting to another host " << newUrl;
365+ LOG (debug) << " Connecting to another host " << newUrl << " \n " ;
366366 requestData->hoPair .header .clear ();
367367 curl_easy_setopt (easy_handle, CURLOPT_URL, newUrl.c_str ());
368368 mHandlesToBeAdded .push_back (easy_handle);
@@ -374,9 +374,11 @@ void CCDBDownloader::getLocalContent(PerformData* performData, std::string& newL
374374 LOG (debug) << " Redirecting to local content " << newLocation << " \n " ;
375375 if (requestData->localContentCallback (newLocation)) {
376376 contentRetrieved = true ;
377+ LOG (debug) << " Local content retrieved succesfully: " << newLocation << " n" ;
377378 } else {
378379 // Prepare next redirect url
379380 newLocation = getNewLocation (performData, locations);
381+ LOG (debug) << " Failed to retrieve local content: " << newLocation << " \n " ;
380382 }
381383}
382384
@@ -396,15 +398,15 @@ std::string CCDBDownloader::getNewLocation(PerformData* performData, std::vector
396398void CCDBDownloader::httpRedirect (PerformData* performData, std::string& newLocation, CURL* easy_handle)
397399{
398400 auto requestData = performData->requestData ;
399- LOG (debug) << " Trying content location " << newLocation;
401+ LOG (debug) << " Trying content location " << newLocation << " \n " ;
400402 curl_easy_setopt (easy_handle, CURLOPT_URL, newLocation.c_str ());
401403 mHandlesToBeAdded .push_back (easy_handle);
402404}
403405
404406void CCDBDownloader::followRedirect (PerformData* performData, CURL* easy_handle, std::vector<std::string>& locations, bool & rescheduled, bool & contentRetrieved)
405407{
406408 std::string newLocation = getNewLocation (performData, locations);
407- if ( newLocation.find (" alien:/" , 0 ) != std::string::npos || newLocation.find (" file:/" , 0 ) != std::string::npos) {
409+ while (!contentRetrieved && ( newLocation.find (" alien:/" , 0 ) != std::string::npos || newLocation.find (" file:/" , 0 ) != std::string::npos) ) {
408410 getLocalContent (performData, newLocation, contentRetrieved, locations);
409411 }
410412 if (!contentRetrieved && newLocation != " " ) {
@@ -508,17 +510,17 @@ void CCDBDownloader::transferFinished(CURL* easy_handle, CURLcode curlCode)
508510 std::string currentHost = requestData->hosts [performData->hostInd ];
509511 std::string loggingMessage = prepareLogMessage (currentHost, requestData->userAgent , requestData->path , requestData->timestamp , requestData->headers , httpCode);
510512
511- // Get alternative locations for the same host
512- auto locations = getLocations (&(requestData->hoPair .header ));
513+ // Get new locations based on received headers
514+ updateLocations (&(requestData->hoPair .header ), &requestData-> locations , &performData-> locInd );
513515
514516 // React to received http code
515517 if (200 <= httpCode && httpCode < 400 ) {
516518 LOG (debug) << loggingMessage;
517519 if (304 == httpCode) {
518520 LOGP (debug, " Object exists but I am not serving it since it's already in your possession" );
519521 contentRetrieved = true ;
520- } else if (300 <= httpCode && httpCode < 400 && performData->locInd < locations.size ()) {
521- followRedirect (performData, easy_handle, locations, rescheduled, contentRetrieved);
522+ } else if (300 <= httpCode && httpCode < 400 && performData->locInd < requestData-> locations .size ()) {
523+ followRedirect (performData, easy_handle, requestData-> locations , rescheduled, contentRetrieved);
522524 } else if (200 <= httpCode && httpCode < 300 ) {
523525 contentRetrieved = true ; // Can be overruled by following error check
524526 }
@@ -531,8 +533,16 @@ void CCDBDownloader::transferFinished(CURL* easy_handle, CURLcode curlCode)
531533 contentRetrieved = false ;
532534 }
533535
534- // Check if content was retrieved, or scheduled to be retrieved
535- if (!rescheduled && !contentRetrieved && performData->locInd == locations.size ()) {
536+ // Check if content was retrieved or scheduled to be retrieved
537+ if (!rescheduled && !contentRetrieved) {
538+ // Current location failed without providing 3xx http code, try next redirect for the same host
539+ if (performData->locInd < requestData->locations .size ()) {
540+ followRedirect (performData, easy_handle, requestData->locations , rescheduled, contentRetrieved);
541+ }
542+ }
543+
544+ // Check again because content might have been retrieved or rescheduled via a redirect
545+ if (!rescheduled && !contentRetrieved) {
536546 // Ran out of locations to redirect, try new host
537547 if (++performData->hostInd < requestData->hosts .size ()) {
538548 tryNewHost (performData, easy_handle);
@@ -650,24 +660,37 @@ CURLcode CCDBDownloader::perform(CURL* handle)
650660 return batchBlockingPerform (handleVector).back ();
651661}
652662
653- std::vector<std::string> CCDBDownloader::getLocations (std::multimap<std::string, std::string>* headerMap) const
663+ void CCDBDownloader::updateLocations (std::multimap<std::string, std::string>* headerMap, std::vector<std::string>* locations, int * locIndex ) const
654664{
655- std::vector<std::string> locs;
665+ std::vector<std::string> newLocations;
666+
656667 auto iter = headerMap->find (" Location" );
657668 if (iter != headerMap->end ()) {
658- locs.push_back (iter->second );
669+ auto range = headerMap->equal_range (" Location" );
670+ for (auto it = range.first ; it != range.second ; ++it) {
671+ if (std::find (locations->begin (), locations->end (), it->second ) == locations->end ()) {
672+ if (std::find (newLocations.begin (), newLocations.end (), it->second ) == newLocations.end ()) {
673+ newLocations.push_back (it->second );
674+ }
675+ }
676+ }
659677 }
678+
660679 // add alternative locations (not yet included)
661680 auto iter2 = headerMap->find (" Content-Location" );
662681 if (iter2 != headerMap->end ()) {
663682 auto range = headerMap->equal_range (" Content-Location" );
664683 for (auto it = range.first ; it != range.second ; ++it) {
665- if (std::find (locs.begin (), locs.end (), it->second ) == locs.end ()) {
666- locs.push_back (it->second );
684+ if (std::find (locations->begin (), locations->end (), it->second ) == locations->end ()) {
685+ if (std::find (newLocations.begin (), newLocations.end (), it->second ) == newLocations.end ()) {
686+ newLocations.push_back (it->second );
687+ }
667688 }
668689 }
669690 }
670- return locs;
691+
692+ // Insert location list at the current location index. This assures that the provided locations will be tried first.
693+ locations->insert (locations->begin () + (*locIndex), newLocations.begin (), newLocations.end ());
671694}
672695
673696std::vector<CURLcode> CCDBDownloader::batchBlockingPerform (std::vector<CURL*> const & handleVector)
0 commit comments