/* */ #include "BtSeederStateChoke.h" #include #include "Peer.h" #include "Logger.h" #include "LogFactory.h" #include "SimpleRandomizer.h" #include "wallclock.h" namespace aria2 { BtSeederStateChoke::BtSeederStateChoke(): round_(0), lastRound_(0), logger_(LogFactory::getInstance()) {} BtSeederStateChoke::~BtSeederStateChoke() {} BtSeederStateChoke::PeerEntry::PeerEntry (const SharedHandle& peer): peer_(peer), outstandingUpload_(peer->countOutstandingUpload()), lastAmUnchoking_(peer->getLastAmUnchoking()), recentUnchoking_(lastAmUnchoking_.difference(global::wallclock) < TIME_FRAME), uploadSpeed_(peer->calculateUploadSpeed()) {} bool BtSeederStateChoke::PeerEntry::operator<(const PeerEntry& rhs) const { if(this->outstandingUpload_ && !rhs.outstandingUpload_) { return true; } else if(!this->outstandingUpload_ && rhs.outstandingUpload_) { return false; } if(this->recentUnchoking_ && (this->lastAmUnchoking_ > rhs.lastAmUnchoking_)) { return true; } else if(rhs.recentUnchoking_) { return false; } else { return this->uploadSpeed_ > rhs.uploadSpeed_; } } void BtSeederStateChoke::PeerEntry::disableOptUnchoking() { peer_->optUnchoking(false); } void BtSeederStateChoke::unchoke (std::vector& peers) { int count = (round_ == 2) ? 4 : 3; std::sort(peers.begin(), peers.end()); std::vector::iterator r = peers.begin(); for(std::vector::iterator eoi = peers.end(); r != eoi && count; ++r, --count) { (*r).getPeer()->chokingRequired(false); logger_->info("RU: %s, ulspd=%u", (*r).getPeer()->getIPAddress().c_str(), (*r).getUploadSpeed()); } if(round_ < 2) { std::for_each(peers.begin(), peers.end(), std::mem_fun_ref(&PeerEntry::disableOptUnchoking)); if(r != peers.end()) { std::random_shuffle(r, peers.end(), *(SimpleRandomizer::getInstance().get())); (*r).getPeer()->optUnchoking(true); logger_->info("POU: %s", (*r).getPeer()->getIPAddress().c_str()); } } } class ChokingRequired { public: void operator()(const SharedHandle& peer) const { peer->chokingRequired(true); } }; class GenPeerEntry { public: BtSeederStateChoke::PeerEntry operator()(const SharedHandle& peer) const { return BtSeederStateChoke::PeerEntry(peer); } }; class NotInterestedPeer { public: bool operator()(const BtSeederStateChoke::PeerEntry& peerEntry) const { return !peerEntry.getPeer()->peerInterested(); } }; void BtSeederStateChoke::executeChoke (const std::vector >& peerSet) { logger_->info("Seeder state, %d choke round started", round_); lastRound_ = global::wallclock; std::vector peerEntries; std::for_each(peerSet.begin(), peerSet.end(), ChokingRequired()); std::transform(peerSet.begin(), peerSet.end(), std::back_inserter(peerEntries), GenPeerEntry()); peerEntries.erase(std::remove_if(peerEntries.begin(), peerEntries.end(), NotInterestedPeer()), peerEntries.end()); unchoke(peerEntries); if(++round_ == 3) { round_ = 0; } } } // namespace aria2