/* */ #include "DHTGetPeersCommand.h" #include "DHTTaskQueue.h" #include "DHTTaskFactory.h" #include "DHTTask.h" #include "DownloadEngine.h" #include "RequestGroup.h" #include "DHTNode.h" #include "DHTNodeLookupEntry.h" #include "BtRuntime.h" #include "PeerStorage.h" #include "Peer.h" #include "Logger.h" #include "LogFactory.h" #include "bittorrent_helper.h" #include "DownloadContext.h" #include "wallclock.h" #include "fmt.h" namespace aria2 { namespace { const time_t GET_PEER_INTERVAL = (15*60); // Interval when the size of peer list is low. const time_t GET_PEER_INTERVAL_LOW = (5*60); // Interval when the peer list is empty. const time_t GET_PEER_INTERVAL_ZERO = 60; // Interval for retry. const time_t GET_PEER_INTERVAL_RETRY = 5; // Maximum retries. Try more than 5 to drop bad node. const size_t MAX_RETRIES = 10; } // namespace DHTGetPeersCommand::DHTGetPeersCommand (cuid_t cuid, RequestGroup* requestGroup, DownloadEngine* e) : Command(cuid), requestGroup_(requestGroup), e_(e), numRetry_(0), lastGetPeerTime_(0) { requestGroup_->increaseNumCommand(); } DHTGetPeersCommand::~DHTGetPeersCommand() { requestGroup_->decreaseNumCommand(); } bool DHTGetPeersCommand::execute() { if(btRuntime_->isHalt()) { return true; } time_t elapsed = lastGetPeerTime_.difference(global::wallclock); if(!task_ && (elapsed >= GET_PEER_INTERVAL || (((btRuntime_->lessThanMinPeers() && ((numRetry_ && elapsed >= GET_PEER_INTERVAL_RETRY) || elapsed >= GET_PEER_INTERVAL_LOW)) || (btRuntime_->getConnections() == 0 && elapsed >= GET_PEER_INTERVAL_ZERO)) && !requestGroup_->downloadFinished()))) { A2_LOG_DEBUG(fmt("Issuing PeerLookup for infoHash=%s", bittorrent::getInfoHashString (requestGroup_->getDownloadContext()).c_str())); task_ = taskFactory_->createPeerLookupTask (requestGroup_->getDownloadContext(), btRuntime_, peerStorage_); taskQueue_->addPeriodicTask2(task_); } else if(task_ && task_->finished()) { A2_LOG_DEBUG("task finished detected"); lastGetPeerTime_ = global::wallclock; if(numRetry_ < MAX_RETRIES && btRuntime_->lessThanMinPeers()) { ++numRetry_; A2_LOG_DEBUG(fmt("Too few peers. Try again(%lu)", static_cast(numRetry_))); } else { numRetry_ = 0; } task_.reset(); } e_->addCommand(this); return false; } void DHTGetPeersCommand::setTaskQueue(const SharedHandle& taskQueue) { taskQueue_ = taskQueue; } void DHTGetPeersCommand::setTaskFactory(const SharedHandle& taskFactory) { taskFactory_ = taskFactory; } void DHTGetPeersCommand::setBtRuntime(const SharedHandle& btRuntime) { btRuntime_ = btRuntime; } void DHTGetPeersCommand::setPeerStorage(const SharedHandle& ps) { peerStorage_ = ps; } } // namespace aria2