浏览代码

Use ServerStat to find faster server.

Tatsuhiro Tsujikawa 14 年之前
父节点
当前提交
2906484345
共有 7 个文件被更改,包括 116 次插入25 次删除
  1. 37 12
      src/AbstractCommand.cc
  2. 2 1
      src/AbstractCommand.h
  3. 0 12
      src/FeedbackURISelector.cc
  4. 53 0
      src/FileEntry.cc
  5. 8 0
      src/FileEntry.h
  6. 5 0
      src/RequestGroupMan.h
  7. 11 0
      src/ServerStat.h

+ 37 - 12
src/AbstractCommand.cc

@@ -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;
         }
       }

+ 2 - 1
src/AbstractCommand.h

@@ -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);
 

+ 0 - 12
src/FeedbackURISelector.cc

@@ -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)

+ 53 - 0
src/FileEntry.cc

@@ -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:

+ 8 - 0
src/FileEntry.h

@@ -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);

+ 5 - 0
src/RequestGroupMan.h

@@ -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;

+ 11 - 0
src/ServerStat.h

@@ -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