/* */ #include "ServerStatURISelector.h" #include "ServerStatMan.h" #include "ServerStat.h" #include "Request.h" #include "A2STR.h" #include namespace aria2 { ServerStatURISelector::ServerStatURISelector (const SharedHandle& serverStatMan): _serverStatMan(serverStatMan) {} ServerStatURISelector::~ServerStatURISelector() {} class ServerStatFaster { public: bool operator()(const std::pair, std::string> lhs, const std::pair, std::string> rhs) const { return lhs.first->getDownloadSpeed() > rhs.first->getDownloadSpeed(); } }; std::string ServerStatURISelector::select(std::deque& uris) { if(uris.empty()) { return A2STR::NIL; } // Use first 10 URIs to introduce some randomness. const int NUM_URI = 10; // Ignore low speed server const unsigned int SPEED_THRESHOLD = 20*1024; size_t max = std::min(uris.size(), static_cast(NUM_URI)); std::deque::iterator urisLast = uris.begin()+max; std::deque, std::string> > cands; for(std::deque::iterator i = uris.begin(); i != urisLast; ++i) { Request r; r.setUrl(*i); SharedHandle ss = _serverStatMan->find(r.getHost(), r.getProtocol()); if(!ss.isNull() && ss->isOK() && ss->getDownloadSpeed() > SPEED_THRESHOLD) { cands.push_back(std::pair, std::string>(ss, *i)); } } if(cands.empty()) { for(std::deque::iterator i = uris.begin(); i != uris.end(); ++i) { Request r; r.setUrl(*i); SharedHandle ss = _serverStatMan->find(r.getHost(), r.getProtocol()); // Skip ERROR state URI if(ss.isNull() || ss->isOK()) { std::string nextURI = *i; uris.erase(uris.begin(), i+1); return nextURI; } } // All URIs are inspected but aria2 cannot find usable one. // Return first URI anyway in this case. std::string nextURI = uris.front(); uris.pop_front(); return nextURI; } else { std::sort(cands.begin(), cands.end(), ServerStatFaster()); uris.erase(std::find(uris.begin(), uris.end(), cands.front().second)); return cands.front().second; } } } // namespace aria2