/* */ #include "PeerChokeCommand.h" #include "Util.h" PeerChokeCommand::PeerChokeCommand(int32_t cuid, RequestGroup* requestGroup, DownloadEngine* e, const BtContextHandle& btContext, int32_t interval): Command(cuid), BtContextAwareCommand(btContext), RequestGroupAware(requestGroup), interval(interval), e(e), rotate(0) {} PeerChokeCommand::~PeerChokeCommand() {} class ChokePeer { public: ChokePeer() {} void operator()(PeerHandle& peer) { peer->chokingRequired = true; } }; void PeerChokeCommand::optUnchokingPeer(Peers& peers) const { if(peers.empty()) { return; } random_shuffle(peers.begin(), peers.end()); int32_t optUnchokCount = 1; for(Peers::iterator itr = peers.begin(); itr != peers.end(); itr++) { Peers::value_type peer = *itr; if(optUnchokCount > 0 && !peer->snubbing) { optUnchokCount--; peer->optUnchoking = true; logger->debug("opt, unchoking %s, download speed=%d", peer->ipaddr.c_str(), peer->calculateDownloadSpeed()); } else { peer->optUnchoking = false; } } } class UploadFaster { public: bool operator() (const PeerHandle& left, const PeerHandle& right) const { return left->calculateUploadSpeed() > right->calculateUploadSpeed(); } }; void PeerChokeCommand::orderByUploadRate(Peers& peers) const { sort(peers.begin(), peers.end(), UploadFaster()); } class DownloadFaster { public: bool operator() (const PeerHandle& left, const PeerHandle& right) const { return left->calculateDownloadSpeed() > right->calculateDownloadSpeed(); } }; void PeerChokeCommand::orderByDownloadRate(Peers& peers) const { sort(peers.begin(), peers.end(), DownloadFaster()); } bool PeerChokeCommand::execute() { if(btRuntime->isHalt()) { return true; } if(checkPoint.elapsed(interval)) { checkPoint.reset(); Peers peers = peerStorage->getActivePeers(); for_each(peers.begin(), peers.end(), ChokePeer()); if(pieceStorage->downloadFinished()) { orderByUploadRate(peers); } else { orderByDownloadRate(peers); } int32_t unchokingCount = 4;//peers.size() >= 4 ? 4 : peers.size(); for(Peers::iterator itr = peers.begin(); itr != peers.end() && unchokingCount > 0; ) { PeerHandle peer = *itr; if(peer->peerInterested && !peer->snubbing) { unchokingCount--; peer->chokingRequired = false; peer->optUnchoking = false; itr = peers.erase(itr); if(pieceStorage->downloadFinished()) { logger->debug("cat01, unchoking %s, upload speed=%d", peer->ipaddr.c_str(), peer->calculateUploadSpeed()); } else { logger->debug("cat01, unchoking %s, download speed=%d", peer->ipaddr.c_str(), peer->calculateDownloadSpeed()); } } else { itr++; } } for(Peers::iterator itr = peers.begin(); itr != peers.end(); ) { PeerHandle peer = *itr; if(!peer->peerInterested && !peer->snubbing) { peer->chokingRequired = false; peer->optUnchoking = false; itr = peers.erase(itr); if(pieceStorage->downloadFinished()) { logger->debug("cat02, unchoking %s, upload speed=%d", peer->ipaddr.c_str(), peer->calculateUploadSpeed()); } else { logger->debug("cat02, unchoking %s, download speed=%d", peer->ipaddr.c_str(), peer->calculateDownloadSpeed()); } break; } else { itr++; } } if(rotate%3 == 0) { optUnchokingPeer(peers); rotate = 0; } rotate++; } e->commands.push_back(this); return false; }