Use ServerStat to find faster server.

pull/1/head
Tatsuhiro Tsujikawa 2011-06-28 00:18:53 +09:00
parent ba6ab14235
commit 2906484345
7 changed files with 116 additions and 25 deletions

View File

@ -92,7 +92,8 @@ AbstractCommand::AbstractCommand
socketRecvBuffer_(socketRecvBuffer),
checkSocketIsReadable_(false), checkSocketIsWritable_(false),
nameResolverCheck_(false),
incNumConnection_(incNumConnection)
incNumConnection_(incNumConnection),
serverStatTimer_(global::wallclock)
{
if(socket_ && socket_->isOpen()) {
setReadCheckSocket(socket_);
@ -117,6 +118,22 @@ AbstractCommand::~AbstractCommand() {
}
}
void AbstractCommand::useFasterRequest
(const SharedHandle<Request>& fasterRequest)
{
A2_LOG_INFO(fmt("CUID#%lld - Use faster Request hostname=%s, port=%u",
getCuid(),
fasterRequest->getHost().c_str(),
fasterRequest->getPort()));
// Cancel current Request object and use faster one.
fileEntry_->removeRequest(req_);
Command* command =
InitiateConnectionCommandFactory::createInitiateConnectionCommand
(getCuid(), fasterRequest, fileEntry_, requestGroup_, e_);
e_->setNoWait(true);
e_->addCommand(command);
}
bool AbstractCommand::execute() {
A2_LOG_DEBUG(fmt("CUID#%lld - socket: read:%d, write:%d, hup:%d, err:%d",
getCuid(),
@ -158,17 +175,25 @@ bool AbstractCommand::execute() {
!getPieceStorage()->hasMissingUnusedPiece()) {
SharedHandle<Request> fasterRequest = fileEntry_->findFasterRequest(req_);
if(fasterRequest) {
A2_LOG_INFO(fmt("CUID#%lld - Use faster Request hostname=%s, port=%u",
getCuid(),
fasterRequest->getHost().c_str(),
fasterRequest->getPort()));
// Cancel current Request object and use faster one.
fileEntry_->removeRequest(req_);
Command* command =
InitiateConnectionCommandFactory::createInitiateConnectionCommand
(getCuid(), fasterRequest, fileEntry_, requestGroup_, e_);
e_->setNoWait(true);
e_->addCommand(command);
useFasterRequest(fasterRequest);
return true;
}
}
// Don't use this feature if PREF_MAX_{OVERALL_}DOWNLOAD_LIMIT
// is used
if(e_->getRequestGroupMan()->getMaxOverallDownloadSpeedLimit() == 0 &&
requestGroup_->getMaxDownloadSpeedLimit() == 0 &&
serverStatTimer_.difference(global::wallclock) >= 10) {
serverStatTimer_ = global::wallclock;
std::vector<std::pair<size_t, std::string> > usedHosts;
if(getOption()->getAsBool(PREF_SELECT_LEAST_USED_HOST)) {
getDownloadEngine()->getRequestGroupMan()->getUsedHosts(usedHosts);
}
SharedHandle<Request> fasterRequest =
fileEntry_->findFasterRequest
(req_, usedHosts, e_->getRequestGroupMan()->getServerStatMan());
if(fasterRequest) {
useFasterRequest(fasterRequest);
return true;
}
}

View File

@ -85,9 +85,10 @@ private:
bool nameResolverCheck_;
bool incNumConnection_;
Timer serverStatTimer_;
size_t calculateMinSplitSize() const;
void useFasterRequest(const SharedHandle<Request>& fasterRequest);
#ifdef ENABLE_ASYNC_DNS
void setNameResolverCheck(const SharedHandle<AsyncNameResolver>& resolver);

View File

@ -56,18 +56,6 @@ FeedbackURISelector::FeedbackURISelector
FeedbackURISelector::~FeedbackURISelector() {}
namespace {
class ServerStatFaster {
public:
bool operator()(const std::pair<SharedHandle<ServerStat>, std::string> lhs,
const std::pair<SharedHandle<ServerStat>, std::string> rhs)
const
{
return lhs.first->getDownloadSpeed() > rhs.first->getDownloadSpeed();
}
};
} // namespace
std::string FeedbackURISelector::select
(FileEntry* fileEntry,
const std::vector<std::pair<size_t, std::string> >& usedHosts)

View File

@ -46,6 +46,8 @@
#include "uri.h"
#include "PeerStat.h"
#include "fmt.h"
#include "ServerStatMan.h"
#include "ServerStat.h"
namespace aria2 {
@ -221,6 +223,57 @@ FileEntry::findFasterRequest(const SharedHandle<Request>& base)
return SharedHandle<Request>();
}
SharedHandle<Request>
FileEntry::findFasterRequest
(const SharedHandle<Request>& base,
const std::vector<std::pair<size_t, std::string> >& usedHosts,
const SharedHandle<ServerStatMan>& serverStatMan)
{
const int startupIdleTime = 10;
const unsigned int SPEED_THRESHOLD = 20*1024;
if(lastFasterReplace_.difference(global::wallclock) < startupIdleTime) {
return SharedHandle<Request>();
}
const SharedHandle<PeerStat>& basestat = base->getPeerStat();
A2_LOG_DEBUG("Search faster server using ServerStat.");
// Use first 10 good URIs to introduce some randomness.
const size_t NUM_URI = 10;
std::vector<std::pair<SharedHandle<ServerStat>, std::string> > fastCands;
std::vector<std::string> normCands;
for(std::deque<std::string>::const_iterator i = uris_.begin(),
eoi = uris_.end(); i != eoi && fastCands.size() < NUM_URI; ++i) {
uri::UriStruct us;
if(!uri::parse(us, *i)) {
continue;
}
if(findSecond(usedHosts.begin(), usedHosts.end(), us.host) !=
usedHosts.end()) {
A2_LOG_DEBUG(fmt("%s is in usedHosts, not considered", (*i).c_str()));
continue;
}
SharedHandle<ServerStat> ss = serverStatMan->find(us.host, us.protocol);
if(ss && ss->isOK()) {
if((basestat &&
ss->getDownloadSpeed() > basestat->calculateDownloadSpeed()*1.5) ||
(!basestat && ss->getDownloadSpeed() > SPEED_THRESHOLD)) {
fastCands.push_back(std::make_pair(ss, *i));
}
}
}
if(!fastCands.empty()) {
A2_LOG_DEBUG("Selected from fastCands");
std::sort(fastCands.begin(), fastCands.end(), ServerStatFaster());
SharedHandle<Request> fastestRequest(new Request());
fastestRequest->setUri(fastCands.front().second);
fastestRequest->setReferer(base->getReferer());
inFlightRequests_.push_back(fastestRequest);
lastFasterReplace_ = global::wallclock;
return fastestRequest;
}
A2_LOG_DEBUG("No faster server found.");
return SharedHandle<Request>();
}
namespace {
class RequestFaster {
public:

View File

@ -53,6 +53,7 @@
namespace aria2 {
class URISelector;
class ServerStatMan;
class FileEntry {
private:
@ -169,6 +170,13 @@ public:
// removed from the pool and returned.
SharedHandle<Request> findFasterRequest(const SharedHandle<Request>& base);
// Finds faster server using ServerStatMan.
SharedHandle<Request>
findFasterRequest
(const SharedHandle<Request>& base,
const std::vector<std::pair<size_t, std::string> >& usedHosts,
const SharedHandle<ServerStatMan>& serverStatMan);
void poolRequest(const SharedHandle<Request>& request);
bool removeRequest(const SharedHandle<Request>& request);

View File

@ -294,6 +294,11 @@ public:
// Returns currently used hosts and its use count.
void getUsedHosts(std::vector<std::pair<size_t, std::string> >& usedHosts);
const SharedHandle<ServerStatMan>& getServerStatMan() const
{
return serverStatMan_;
}
};
typedef SharedHandle<RequestGroupMan> RequestGroupManHandle;

View File

@ -39,6 +39,7 @@
#include <string>
#include <iosfwd>
#include "SharedHandle.h"
#include "TimeA2.h"
namespace aria2 {
@ -167,6 +168,16 @@ private:
std::ostream& operator<<(std::ostream& o, const ServerStat& serverStat);
class ServerStatFaster {
public:
bool operator()
(const std::pair<SharedHandle<ServerStat>, std::string> lhs,
const std::pair<SharedHandle<ServerStat>, std::string> rhs) const
{
return lhs.first->getDownloadSpeed() > rhs.first->getDownloadSpeed();
}
};
} // namespace aria2
#endif // D_SERVER_STAT_H