mirror of https://github.com/aria2/aria2
2008-04-13 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
Rewritten choking algorithm. * src/PeerChokeCommand.{cc, h} * src/BtInterestedMessage.cc * src/PeerSessionResource.{cc, h} * src/DefaultPeerStorage.{cc, h} * src/BtNotInterestedMessage.cc * src/DefaultBtMessageDispatcher.{cc, h} * src/BtMessageDispatcher.h * src/Peer.{cc, h} * src/BtLeecherStateChoke.{cc, h} * src/BtSetup.cc * src/BtSeederStateChoke.{cc, h} * src/PeerStorage.h * test/MockPeerStorage.h * test/MockBtMessageDispatcher.hpull/1/head
parent
8b91d22ca4
commit
d13c416a94
18
ChangeLog
18
ChangeLog
|
@ -1,3 +1,21 @@
|
||||||
|
2008-04-13 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
|
||||||
|
|
||||||
|
Rewritten choking algorithm.
|
||||||
|
* src/PeerChokeCommand.{cc, h}
|
||||||
|
* src/BtInterestedMessage.cc
|
||||||
|
* src/PeerSessionResource.{cc, h}
|
||||||
|
* src/DefaultPeerStorage.{cc, h}
|
||||||
|
* src/BtNotInterestedMessage.cc
|
||||||
|
* src/DefaultBtMessageDispatcher.{cc, h}
|
||||||
|
* src/BtMessageDispatcher.h
|
||||||
|
* src/Peer.{cc, h}
|
||||||
|
* src/BtLeecherStateChoke.{cc, h}
|
||||||
|
* src/BtSetup.cc
|
||||||
|
* src/BtSeederStateChoke.{cc, h}
|
||||||
|
* src/PeerStorage.h
|
||||||
|
* test/MockPeerStorage.h
|
||||||
|
* test/MockBtMessageDispatcher.h
|
||||||
|
|
||||||
2008-04-09 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
|
2008-04-09 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
|
||||||
|
|
||||||
Fixed compilation error on x84-64 platform.
|
Fixed compilation error on x84-64 platform.
|
||||||
|
|
|
@ -37,6 +37,9 @@
|
||||||
#include "DlAbortEx.h"
|
#include "DlAbortEx.h"
|
||||||
#include "message.h"
|
#include "message.h"
|
||||||
#include "Peer.h"
|
#include "Peer.h"
|
||||||
|
#include "BtRegistry.h"
|
||||||
|
#include "BtContext.h"
|
||||||
|
#include "PeerStorage.h"
|
||||||
|
|
||||||
namespace aria2 {
|
namespace aria2 {
|
||||||
|
|
||||||
|
@ -54,6 +57,9 @@ BtInterestedMessageHandle BtInterestedMessage::create(const unsigned char* data,
|
||||||
|
|
||||||
void BtInterestedMessage::doReceivedAction() {
|
void BtInterestedMessage::doReceivedAction() {
|
||||||
peer->peerInterested(true);
|
peer->peerInterested(true);
|
||||||
|
if(!peer->amChoking()) {
|
||||||
|
PEER_STORAGE(btContext)->executeChoke();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BtInterestedMessage::sendPredicate() const {
|
bool BtInterestedMessage::sendPredicate() const {
|
||||||
|
|
|
@ -0,0 +1,179 @@
|
||||||
|
/* <!-- copyright */
|
||||||
|
/*
|
||||||
|
* aria2 - The high speed download utility
|
||||||
|
*
|
||||||
|
* Copyright (C) 2006 Tatsuhiro Tsujikawa
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* In addition, as a special exception, the copyright holders give
|
||||||
|
* permission to link the code of portions of this program with the
|
||||||
|
* OpenSSL library under certain conditions as described in each
|
||||||
|
* individual source file, and distribute linked combinations
|
||||||
|
* including the two.
|
||||||
|
* You must obey the GNU General Public License in all respects
|
||||||
|
* for all of the code used other than OpenSSL. If you modify
|
||||||
|
* file(s) with this exception, you may extend this exception to your
|
||||||
|
* version of the file(s), but you are not obligated to do so. If you
|
||||||
|
* do not wish to do so, delete this exception statement from your
|
||||||
|
* version. If you delete this exception statement from all source
|
||||||
|
* files in the program, then also delete it here.
|
||||||
|
*/
|
||||||
|
/* copyright --> */
|
||||||
|
#include "BtLeecherStateChoke.h"
|
||||||
|
#include "Peer.h"
|
||||||
|
#include "Logger.h"
|
||||||
|
#include "LogFactory.h"
|
||||||
|
#include "a2time.h"
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
namespace aria2 {
|
||||||
|
|
||||||
|
BtLeecherStateChoke::BtLeecherStateChoke():
|
||||||
|
_round(0),
|
||||||
|
_lastRound(0),
|
||||||
|
_logger(LogFactory::getInstance()) {}
|
||||||
|
|
||||||
|
BtLeecherStateChoke::~BtLeecherStateChoke() {}
|
||||||
|
|
||||||
|
class PeerFilter {
|
||||||
|
private:
|
||||||
|
bool _amChoking;
|
||||||
|
bool _peerInterested;
|
||||||
|
public:
|
||||||
|
PeerFilter(bool amChoking, bool peerInterested):
|
||||||
|
_amChoking(amChoking),
|
||||||
|
_peerInterested(peerInterested) {}
|
||||||
|
|
||||||
|
bool operator()(const Peer* peer) const
|
||||||
|
{
|
||||||
|
return peer->amChoking() == _amChoking &&
|
||||||
|
peer->peerInterested() == _peerInterested;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class RegularUnchoker {
|
||||||
|
public:
|
||||||
|
bool operator()(const Peer* peer) const
|
||||||
|
{
|
||||||
|
// peer must be interested to us and sent block in the last 30 seconds
|
||||||
|
return peer->peerInterested() && !peer->getLastDownloadUpdate().elapsed(30);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class DownloadFaster {
|
||||||
|
private:
|
||||||
|
const struct timeval _now;
|
||||||
|
public:
|
||||||
|
|
||||||
|
DownloadFaster(const struct timeval& now):_now(now) {}
|
||||||
|
|
||||||
|
bool operator() (Peer* left, Peer* right) const
|
||||||
|
{
|
||||||
|
return left->calculateDownloadSpeed(_now) > right->calculateDownloadSpeed(_now);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class SnubbedPeer {
|
||||||
|
public:
|
||||||
|
bool operator() (const Peer* peer) const
|
||||||
|
{
|
||||||
|
return peer->snubbing();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void BtLeecherStateChoke::plannedOptimisticUnchoke(std::deque<Peer*>& peers)
|
||||||
|
{
|
||||||
|
std::for_each(peers.begin(), peers.end(),
|
||||||
|
std::bind2nd(std::mem_fun((void (Peer::*)(bool))&Peer::optUnchoking), false));
|
||||||
|
|
||||||
|
std::deque<Peer*>::iterator i = std::partition(peers.begin(), peers.end(), PeerFilter(true, true));
|
||||||
|
if(i != peers.begin()) {
|
||||||
|
std::random_shuffle(peers.begin(), i);
|
||||||
|
(*peers.begin())->optUnchoking(true);
|
||||||
|
_logger->info("POU: %s", (*peers.begin())->ipaddr.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BtLeecherStateChoke::regularUnchoke(std::deque<Peer*>& peers)
|
||||||
|
{
|
||||||
|
std::deque<Peer*>::iterator rest = std::partition(peers.begin(), peers.end(), RegularUnchoker());
|
||||||
|
|
||||||
|
struct timeval now;
|
||||||
|
gettimeofday(&now, 0);
|
||||||
|
|
||||||
|
std::sort(peers.begin(), rest, DownloadFaster(now));
|
||||||
|
|
||||||
|
// the number of regular unchokers
|
||||||
|
int count = 3;
|
||||||
|
|
||||||
|
bool fastOptUnchoker = false;
|
||||||
|
std::deque<Peer*>::iterator peerIter = peers.begin();
|
||||||
|
for(;peerIter != rest && count; ++peerIter, --count) {
|
||||||
|
(*peerIter)->chokingRequired(false);
|
||||||
|
_logger->info("RU: %s, dlspd=%u", (*peerIter)->ipaddr.c_str(), (*peerIter)->calculateDownloadSpeed(now));
|
||||||
|
if((*peerIter)->optUnchoking()) {
|
||||||
|
fastOptUnchoker = true;
|
||||||
|
(*peerIter)->optUnchoking(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(fastOptUnchoker) {
|
||||||
|
std::random_shuffle(peerIter, peers.end());
|
||||||
|
for(std::deque<Peer*>::iterator i = peerIter; i != peers.end(); ++i) {
|
||||||
|
if((*i)->peerInterested()) {
|
||||||
|
(*i)->optUnchoking(true);
|
||||||
|
_logger->info("OU: %s", (*i)->ipaddr.c_str());
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
(*i)->chokingRequired(false);
|
||||||
|
_logger->info("OU: %s", (*i)->ipaddr.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
BtLeecherStateChoke::executeChoke(const std::deque<SharedHandle<Peer> >& peerSet)
|
||||||
|
{
|
||||||
|
_logger->info("Leecher state, %d choke round started", _round);
|
||||||
|
_lastRound.reset();
|
||||||
|
|
||||||
|
std::deque<Peer*> peers;
|
||||||
|
std::transform(peerSet.begin(), peerSet.end(), std::back_inserter(peers),
|
||||||
|
std::mem_fun_ref(&SharedHandle<Peer>::get));
|
||||||
|
|
||||||
|
peers.erase(std::remove_if(peers.begin(), peers.end(), SnubbedPeer()),
|
||||||
|
peers.end());
|
||||||
|
|
||||||
|
std::for_each(peers.begin(), peers.end(),
|
||||||
|
std::bind2nd(std::mem_fun((void (Peer::*)(bool))&Peer::chokingRequired), true));
|
||||||
|
|
||||||
|
// planned optimistic unchoke
|
||||||
|
if(_round == 0) {
|
||||||
|
plannedOptimisticUnchoke(peers);
|
||||||
|
}
|
||||||
|
regularUnchoke(peers);
|
||||||
|
|
||||||
|
if(++_round == 3) {
|
||||||
|
_round = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const Time& BtLeecherStateChoke::getLastRound() const
|
||||||
|
{
|
||||||
|
return _lastRound;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace aria2
|
|
@ -0,0 +1,72 @@
|
||||||
|
/* <!-- copyright */
|
||||||
|
/*
|
||||||
|
* aria2 - The high speed download utility
|
||||||
|
*
|
||||||
|
* Copyright (C) 2006 Tatsuhiro Tsujikawa
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* In addition, as a special exception, the copyright holders give
|
||||||
|
* permission to link the code of portions of this program with the
|
||||||
|
* OpenSSL library under certain conditions as described in each
|
||||||
|
* individual source file, and distribute linked combinations
|
||||||
|
* including the two.
|
||||||
|
* You must obey the GNU General Public License in all respects
|
||||||
|
* for all of the code used other than OpenSSL. If you modify
|
||||||
|
* file(s) with this exception, you may extend this exception to your
|
||||||
|
* version of the file(s), but you are not obligated to do so. If you
|
||||||
|
* do not wish to do so, delete this exception statement from your
|
||||||
|
* version. If you delete this exception statement from all source
|
||||||
|
* files in the program, then also delete it here.
|
||||||
|
*/
|
||||||
|
/* copyright --> */
|
||||||
|
#ifndef _D_BT_LEECHER_STATE_CHOKE_H_
|
||||||
|
#define _D_BT_LEECHER_STATE_CHOKE_H_
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
#include "SharedHandle.h"
|
||||||
|
#include "TimeA2.h"
|
||||||
|
#include <deque>
|
||||||
|
|
||||||
|
namespace aria2 {
|
||||||
|
|
||||||
|
class Peer;
|
||||||
|
class Logger;
|
||||||
|
|
||||||
|
class BtLeecherStateChoke {
|
||||||
|
private:
|
||||||
|
int _round;
|
||||||
|
|
||||||
|
Time _lastRound;
|
||||||
|
|
||||||
|
const Logger* _logger;
|
||||||
|
|
||||||
|
void plannedOptimisticUnchoke(std::deque<Peer*>& peers);
|
||||||
|
|
||||||
|
void regularUnchoke(std::deque<Peer*>& peers);
|
||||||
|
|
||||||
|
public:
|
||||||
|
BtLeecherStateChoke();
|
||||||
|
|
||||||
|
~BtLeecherStateChoke();
|
||||||
|
|
||||||
|
void executeChoke(const std::deque<SharedHandle<Peer> >& peerSet);
|
||||||
|
|
||||||
|
const Time& getLastRound() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace aria2
|
||||||
|
|
||||||
|
#endif // _D_BT_LEECHER_STATE_CHOKE_H_
|
|
@ -81,6 +81,8 @@ public:
|
||||||
virtual void removeOutstandingRequest(const RequestSlot& slot) = 0;
|
virtual void removeOutstandingRequest(const RequestSlot& slot) = 0;
|
||||||
|
|
||||||
virtual void addOutstandingRequest(const RequestSlot& slot) = 0;
|
virtual void addOutstandingRequest(const RequestSlot& slot) = 0;
|
||||||
|
|
||||||
|
virtual size_t countOutstandingUpload() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef SharedHandle<BtMessageDispatcher> BtMessageDispatcherHandle;
|
typedef SharedHandle<BtMessageDispatcher> BtMessageDispatcherHandle;
|
||||||
|
|
|
@ -37,6 +37,9 @@
|
||||||
#include "DlAbortEx.h"
|
#include "DlAbortEx.h"
|
||||||
#include "message.h"
|
#include "message.h"
|
||||||
#include "Peer.h"
|
#include "Peer.h"
|
||||||
|
#include "BtRegistry.h"
|
||||||
|
#include "BtContext.h"
|
||||||
|
#include "PeerStorage.h"
|
||||||
|
|
||||||
namespace aria2 {
|
namespace aria2 {
|
||||||
|
|
||||||
|
@ -54,6 +57,9 @@ BtNotInterestedMessageHandle BtNotInterestedMessage::create(const unsigned char*
|
||||||
|
|
||||||
void BtNotInterestedMessage::doReceivedAction() {
|
void BtNotInterestedMessage::doReceivedAction() {
|
||||||
peer->peerInterested(false);
|
peer->peerInterested(false);
|
||||||
|
if(!peer->amChoking()) {
|
||||||
|
PEER_STORAGE(btContext)->executeChoke();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BtNotInterestedMessage::sendPredicate() const {
|
bool BtNotInterestedMessage::sendPredicate() const {
|
||||||
|
|
|
@ -0,0 +1,151 @@
|
||||||
|
/* <!-- copyright */
|
||||||
|
/*
|
||||||
|
* aria2 - The high speed download utility
|
||||||
|
*
|
||||||
|
* Copyright (C) 2006 Tatsuhiro Tsujikawa
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* In addition, as a special exception, the copyright holders give
|
||||||
|
* permission to link the code of portions of this program with the
|
||||||
|
* OpenSSL library under certain conditions as described in each
|
||||||
|
* individual source file, and distribute linked combinations
|
||||||
|
* including the two.
|
||||||
|
* You must obey the GNU General Public License in all respects
|
||||||
|
* for all of the code used other than OpenSSL. If you modify
|
||||||
|
* file(s) with this exception, you may extend this exception to your
|
||||||
|
* version of the file(s), but you are not obligated to do so. If you
|
||||||
|
* do not wish to do so, delete this exception statement from your
|
||||||
|
* version. If you delete this exception statement from all source
|
||||||
|
* files in the program, then also delete it here.
|
||||||
|
*/
|
||||||
|
/* copyright --> */
|
||||||
|
#include "BtSeederStateChoke.h"
|
||||||
|
#include "BtContext.h"
|
||||||
|
#include "Peer.h"
|
||||||
|
#include "BtRegistry.h"
|
||||||
|
#include "PeerObject.h"
|
||||||
|
#include "BtMessageDispatcher.h"
|
||||||
|
#include "BtMessageFactory.h"
|
||||||
|
#include "BtRequestFactory.h"
|
||||||
|
#include "BtMessageReceiver.h"
|
||||||
|
#include "PeerConnection.h"
|
||||||
|
#include "ExtensionMessageFactory.h"
|
||||||
|
#include "Logger.h"
|
||||||
|
#include "LogFactory.h"
|
||||||
|
#include "a2time.h"
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
namespace aria2 {
|
||||||
|
|
||||||
|
BtSeederStateChoke::BtSeederStateChoke(const SharedHandle<BtContext>& btContext):
|
||||||
|
_btContext(btContext),
|
||||||
|
_round(0),
|
||||||
|
_lastRound(0),
|
||||||
|
_logger(LogFactory::getInstance()) {}
|
||||||
|
|
||||||
|
BtSeederStateChoke::~BtSeederStateChoke() {}
|
||||||
|
|
||||||
|
class RecentUnchoke {
|
||||||
|
private:
|
||||||
|
SharedHandle<BtContext> _btContext;
|
||||||
|
|
||||||
|
const struct timeval _now;
|
||||||
|
public:
|
||||||
|
RecentUnchoke(const SharedHandle<BtContext>& btContext,
|
||||||
|
const struct timeval& now):
|
||||||
|
_btContext(btContext), _now(now) {}
|
||||||
|
|
||||||
|
bool operator()(Peer* left, Peer* right) const
|
||||||
|
{
|
||||||
|
size_t leftUpload = BT_MESSAGE_DISPATCHER(_btContext, left)->countOutstandingRequest();
|
||||||
|
size_t rightUpload = BT_MESSAGE_DISPATCHER(_btContext, right)->countOutstandingRequest();
|
||||||
|
if(leftUpload && !rightUpload) {
|
||||||
|
return true;
|
||||||
|
} else if(!leftUpload && rightUpload) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const int TIME_FRAME = 20;
|
||||||
|
if(!left->getLastAmUnchoking().elapsed(TIME_FRAME) &&
|
||||||
|
left->getLastAmUnchoking().isNewer(right->getLastAmUnchoking())) {
|
||||||
|
return true;
|
||||||
|
} else if(!right->getLastAmUnchoking().elapsed(TIME_FRAME) &&
|
||||||
|
right->getLastAmUnchoking().isNewer(left->getLastAmUnchoking())) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return left->calculateUploadSpeed(_now) > right->calculateUploadSpeed(_now);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class NotInterestedPeer {
|
||||||
|
public:
|
||||||
|
bool operator()(const Peer* peer) const
|
||||||
|
{
|
||||||
|
return !peer->peerInterested();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void BtSeederStateChoke::unchoke(std::deque<Peer*>& peers)
|
||||||
|
{
|
||||||
|
int count = (_round == 2) ? 4 : 3;
|
||||||
|
|
||||||
|
struct timeval now;
|
||||||
|
gettimeofday(&now, 0);
|
||||||
|
|
||||||
|
std::sort(peers.begin(), peers.end(), RecentUnchoke(_btContext, now));
|
||||||
|
|
||||||
|
std::deque<Peer*>::iterator r = peers.begin();
|
||||||
|
for(; r != peers.end() && count; ++r, --count) {
|
||||||
|
(*r)->chokingRequired(false);
|
||||||
|
_logger->info("RU: %s, ulspd=%u", (*r)->ipaddr.c_str(),
|
||||||
|
(*r)->calculateUploadSpeed(now));
|
||||||
|
}
|
||||||
|
if(_round == 2 && r != peers.end()) {
|
||||||
|
std::random_shuffle(r, peers.end());
|
||||||
|
(*r)->optUnchoking(true);
|
||||||
|
_logger->info("POU: %s", (*r)->ipaddr.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
BtSeederStateChoke::executeChoke(const std::deque<SharedHandle<Peer> >& peerSet)
|
||||||
|
{
|
||||||
|
_logger->info("Seeder state, %d choke round started", _round);
|
||||||
|
_lastRound.reset();
|
||||||
|
|
||||||
|
std::deque<Peer*> peers;
|
||||||
|
std::transform(peerSet.begin(), peerSet.end(), std::back_inserter(peers),
|
||||||
|
std::mem_fun_ref(&SharedHandle<Peer>::get));
|
||||||
|
|
||||||
|
std::for_each(peers.begin(), peers.end(),
|
||||||
|
std::bind2nd(std::mem_fun((void (Peer::*)(bool))&Peer::chokingRequired), true));
|
||||||
|
|
||||||
|
peers.erase(std::remove_if(peers.begin(), peers.end(), NotInterestedPeer()),
|
||||||
|
peers.end());
|
||||||
|
|
||||||
|
unchoke(peers);
|
||||||
|
|
||||||
|
if(++_round == 3) {
|
||||||
|
_round = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const Time& BtSeederStateChoke::getLastRound() const
|
||||||
|
{
|
||||||
|
return _lastRound;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace aria2
|
|
@ -0,0 +1,72 @@
|
||||||
|
/* <!-- copyright */
|
||||||
|
/*
|
||||||
|
* aria2 - The high speed download utility
|
||||||
|
*
|
||||||
|
* Copyright (C) 2006 Tatsuhiro Tsujikawa
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* In addition, as a special exception, the copyright holders give
|
||||||
|
* permission to link the code of portions of this program with the
|
||||||
|
* OpenSSL library under certain conditions as described in each
|
||||||
|
* individual source file, and distribute linked combinations
|
||||||
|
* including the two.
|
||||||
|
* You must obey the GNU General Public License in all respects
|
||||||
|
* for all of the code used other than OpenSSL. If you modify
|
||||||
|
* file(s) with this exception, you may extend this exception to your
|
||||||
|
* version of the file(s), but you are not obligated to do so. If you
|
||||||
|
* do not wish to do so, delete this exception statement from your
|
||||||
|
* version. If you delete this exception statement from all source
|
||||||
|
* files in the program, then also delete it here.
|
||||||
|
*/
|
||||||
|
/* copyright --> */
|
||||||
|
#ifndef _D_BT_SEEDER_STATE_CHOKE_H_
|
||||||
|
#define _D_BT_SEEDER_STATE_CHOKE_H_
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
#include "SharedHandle.h"
|
||||||
|
#include "TimeA2.h"
|
||||||
|
#include <deque>
|
||||||
|
|
||||||
|
namespace aria2 {
|
||||||
|
|
||||||
|
class BtContext;
|
||||||
|
class Peer;
|
||||||
|
class Logger;
|
||||||
|
|
||||||
|
class BtSeederStateChoke {
|
||||||
|
private:
|
||||||
|
SharedHandle<BtContext> _btContext;
|
||||||
|
|
||||||
|
int _round;
|
||||||
|
|
||||||
|
Time _lastRound;
|
||||||
|
|
||||||
|
const Logger* _logger;
|
||||||
|
|
||||||
|
void unchoke(std::deque<Peer*>& peers);
|
||||||
|
public:
|
||||||
|
BtSeederStateChoke(const SharedHandle<BtContext>& btContext);
|
||||||
|
|
||||||
|
~BtSeederStateChoke();
|
||||||
|
|
||||||
|
void executeChoke(const std::deque<SharedHandle<Peer> >& peerSet);
|
||||||
|
|
||||||
|
const Time& getLastRound() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace aria2
|
||||||
|
|
||||||
|
#endif // _D_BT_SEEDER_STATE_CHOKE_H_
|
|
@ -76,10 +76,8 @@ Commands BtSetup::setup(RequestGroup* requestGroup,
|
||||||
e,
|
e,
|
||||||
btContext));
|
btContext));
|
||||||
commands.push_back(new PeerChokeCommand(CUIDCounterSingletonHolder::instance()->newID(),
|
commands.push_back(new PeerChokeCommand(CUIDCounterSingletonHolder::instance()->newID(),
|
||||||
requestGroup,
|
|
||||||
e,
|
e,
|
||||||
btContext,
|
btContext));
|
||||||
10));
|
|
||||||
|
|
||||||
commands.push_back(new ActivePeerConnectionCommand(CUIDCounterSingletonHolder::instance()->newID(),
|
commands.push_back(new ActivePeerConnectionCommand(CUIDCounterSingletonHolder::instance()->newID(),
|
||||||
requestGroup, e, btContext, 10));
|
requestGroup, e, btContext, 10));
|
||||||
|
|
|
@ -49,6 +49,7 @@
|
||||||
#include "Piece.h"
|
#include "Piece.h"
|
||||||
#include "LogFactory.h"
|
#include "LogFactory.h"
|
||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
|
#include "a2functional.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
namespace aria2 {
|
namespace aria2 {
|
||||||
|
@ -266,6 +267,12 @@ void DefaultBtMessageDispatcher::addOutstandingRequest(const RequestSlot& reques
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t DefaultBtMessageDispatcher::countOutstandingUpload()
|
||||||
|
{
|
||||||
|
return std::count_if(messageQueue.begin(), messageQueue.end(),
|
||||||
|
mem_fun_sh(&BtMessage::isUploading));
|
||||||
|
}
|
||||||
|
|
||||||
std::deque<SharedHandle<BtMessage> >&
|
std::deque<SharedHandle<BtMessage> >&
|
||||||
DefaultBtMessageDispatcher::getMessageQueue()
|
DefaultBtMessageDispatcher::getMessageQueue()
|
||||||
{
|
{
|
||||||
|
|
|
@ -101,6 +101,8 @@ public:
|
||||||
|
|
||||||
virtual void addOutstandingRequest(const RequestSlot& requestSlot);
|
virtual void addOutstandingRequest(const RequestSlot& requestSlot);
|
||||||
|
|
||||||
|
virtual size_t countOutstandingUpload();
|
||||||
|
|
||||||
std::deque<SharedHandle<BtMessage> >& getMessageQueue();
|
std::deque<SharedHandle<BtMessage> >& getMessageQueue();
|
||||||
|
|
||||||
RequestSlots& getRequestSlots();
|
RequestSlots& getRequestSlots();
|
||||||
|
|
|
@ -41,6 +41,9 @@
|
||||||
#include "Peer.h"
|
#include "Peer.h"
|
||||||
#include "BtContext.h"
|
#include "BtContext.h"
|
||||||
#include "BtRuntime.h"
|
#include "BtRuntime.h"
|
||||||
|
#include "BtSeederStateChoke.h"
|
||||||
|
#include "BtLeecherStateChoke.h"
|
||||||
|
#include "PieceStorage.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
namespace aria2 {
|
namespace aria2 {
|
||||||
|
@ -52,12 +55,18 @@ DefaultPeerStorage::DefaultPeerStorage(const BtContextHandle& btContext,
|
||||||
maxPeerListSize(MAX_PEER_LIST_SIZE),
|
maxPeerListSize(MAX_PEER_LIST_SIZE),
|
||||||
btRuntime(BT_RUNTIME(btContext)),
|
btRuntime(BT_RUNTIME(btContext)),
|
||||||
removedPeerSessionDownloadLength(0),
|
removedPeerSessionDownloadLength(0),
|
||||||
removedPeerSessionUploadLength(0)
|
removedPeerSessionUploadLength(0),
|
||||||
|
_seederStateChoke(new BtSeederStateChoke(btContext)),
|
||||||
|
_leecherStateChoke(new BtLeecherStateChoke())
|
||||||
{
|
{
|
||||||
logger = LogFactory::getInstance();
|
logger = LogFactory::getInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
DefaultPeerStorage::~DefaultPeerStorage() {}
|
DefaultPeerStorage::~DefaultPeerStorage()
|
||||||
|
{
|
||||||
|
delete _seederStateChoke;
|
||||||
|
delete _leecherStateChoke;
|
||||||
|
}
|
||||||
|
|
||||||
class FindIdenticalPeer {
|
class FindIdenticalPeer {
|
||||||
private:
|
private:
|
||||||
|
@ -246,4 +255,23 @@ void DefaultPeerStorage::returnPeer(const PeerHandle& peer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DefaultPeerStorage::chokeRoundIntervalElapsed()
|
||||||
|
{
|
||||||
|
const time_t CHOKE_ROUND_INTERVAL = 10;
|
||||||
|
if(PIECE_STORAGE(btContext)->downloadFinished()) {
|
||||||
|
return _seederStateChoke->getLastRound().elapsed(CHOKE_ROUND_INTERVAL);
|
||||||
|
} else {
|
||||||
|
return _leecherStateChoke->getLastRound().elapsed(CHOKE_ROUND_INTERVAL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DefaultPeerStorage::executeChoke()
|
||||||
|
{
|
||||||
|
if(PIECE_STORAGE(btContext)->downloadFinished()) {
|
||||||
|
return _seederStateChoke->executeChoke(getActivePeers());
|
||||||
|
} else {
|
||||||
|
return _leecherStateChoke->executeChoke(getActivePeers());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace aria2
|
} // namespace aria2
|
||||||
|
|
|
@ -46,6 +46,8 @@ class BtContext;
|
||||||
class Option;
|
class Option;
|
||||||
class Logger;
|
class Logger;
|
||||||
class BtRuntime;
|
class BtRuntime;
|
||||||
|
class BtSeederStateChoke;
|
||||||
|
class BtLeecherStateChoke;
|
||||||
|
|
||||||
class DefaultPeerStorage : public PeerStorage {
|
class DefaultPeerStorage : public PeerStorage {
|
||||||
private:
|
private:
|
||||||
|
@ -58,6 +60,9 @@ private:
|
||||||
uint64_t removedPeerSessionDownloadLength;
|
uint64_t removedPeerSessionDownloadLength;
|
||||||
uint64_t removedPeerSessionUploadLength;
|
uint64_t removedPeerSessionUploadLength;
|
||||||
|
|
||||||
|
BtSeederStateChoke* _seederStateChoke;
|
||||||
|
BtLeecherStateChoke* _leecherStateChoke;
|
||||||
|
|
||||||
bool isPeerAlreadyAdded(const SharedHandle<Peer>& peer);
|
bool isPeerAlreadyAdded(const SharedHandle<Peer>& peer);
|
||||||
public:
|
public:
|
||||||
DefaultPeerStorage(const SharedHandle<BtContext>& btContext,
|
DefaultPeerStorage(const SharedHandle<BtContext>& btContext,
|
||||||
|
@ -91,6 +96,10 @@ public:
|
||||||
|
|
||||||
virtual void returnPeer(const SharedHandle<Peer>& peer);
|
virtual void returnPeer(const SharedHandle<Peer>& peer);
|
||||||
|
|
||||||
|
virtual bool chokeRoundIntervalElapsed();
|
||||||
|
|
||||||
|
virtual void executeChoke();
|
||||||
|
|
||||||
void setMaxPeerListSize(size_t size) { this->maxPeerListSize = size; }
|
void setMaxPeerListSize(size_t size) { this->maxPeerListSize = size; }
|
||||||
|
|
||||||
size_t getMaxPeerListSize() const { return maxPeerListSize; }
|
size_t getMaxPeerListSize() const { return maxPeerListSize; }
|
||||||
|
|
|
@ -367,7 +367,9 @@ SRCS += MetaEntry.h\
|
||||||
LibsslARC4Decryptor.h\
|
LibsslARC4Decryptor.h\
|
||||||
LibsslARC4Encryptor.h\
|
LibsslARC4Encryptor.h\
|
||||||
LibsslDHKeyExchange.h\
|
LibsslDHKeyExchange.h\
|
||||||
BtConstants.h
|
BtConstants.h\
|
||||||
|
BtLeecherStateChoke.cc BtLeecherStateChoke.h\
|
||||||
|
BtSeederStateChoke.cc BtSeederStateChoke.h
|
||||||
endif # ENABLE_BITTORRENT
|
endif # ENABLE_BITTORRENT
|
||||||
|
|
||||||
if ENABLE_METALINK
|
if ENABLE_METALINK
|
||||||
|
|
|
@ -221,7 +221,9 @@ bin_PROGRAMS = aria2c$(EXEEXT)
|
||||||
@ENABLE_BITTORRENT_TRUE@ LibsslARC4Decryptor.h\
|
@ENABLE_BITTORRENT_TRUE@ LibsslARC4Decryptor.h\
|
||||||
@ENABLE_BITTORRENT_TRUE@ LibsslARC4Encryptor.h\
|
@ENABLE_BITTORRENT_TRUE@ LibsslARC4Encryptor.h\
|
||||||
@ENABLE_BITTORRENT_TRUE@ LibsslDHKeyExchange.h\
|
@ENABLE_BITTORRENT_TRUE@ LibsslDHKeyExchange.h\
|
||||||
@ENABLE_BITTORRENT_TRUE@ BtConstants.h
|
@ENABLE_BITTORRENT_TRUE@ BtConstants.h\
|
||||||
|
@ENABLE_BITTORRENT_TRUE@ BtLeecherStateChoke.cc BtLeecherStateChoke.h\
|
||||||
|
@ENABLE_BITTORRENT_TRUE@ BtSeederStateChoke.cc BtSeederStateChoke.h
|
||||||
|
|
||||||
@ENABLE_METALINK_TRUE@am__append_3 = Metalinker.cc Metalinker.h\
|
@ENABLE_METALINK_TRUE@am__append_3 = Metalinker.cc Metalinker.h\
|
||||||
@ENABLE_METALINK_TRUE@ MetalinkEntry.cc MetalinkEntry.h\
|
@ENABLE_METALINK_TRUE@ MetalinkEntry.cc MetalinkEntry.h\
|
||||||
|
@ -522,7 +524,9 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \
|
||||||
LibgcryptARC4Decryptor.h LibgcryptARC4Encryptor.h \
|
LibgcryptARC4Decryptor.h LibgcryptARC4Encryptor.h \
|
||||||
LibgcryptDHKeyExchange.h LibsslARC4Context.h \
|
LibgcryptDHKeyExchange.h LibsslARC4Context.h \
|
||||||
LibsslARC4Decryptor.h LibsslARC4Encryptor.h \
|
LibsslARC4Decryptor.h LibsslARC4Encryptor.h \
|
||||||
LibsslDHKeyExchange.h BtConstants.h Metalinker.cc Metalinker.h \
|
LibsslDHKeyExchange.h BtConstants.h BtLeecherStateChoke.cc \
|
||||||
|
BtLeecherStateChoke.h BtSeederStateChoke.cc \
|
||||||
|
BtSeederStateChoke.h Metalinker.cc Metalinker.h \
|
||||||
MetalinkEntry.cc MetalinkEntry.h MetalinkResource.cc \
|
MetalinkEntry.cc MetalinkEntry.h MetalinkResource.cc \
|
||||||
MetalinkResource.h MetalinkProcessor.h \
|
MetalinkResource.h MetalinkProcessor.h \
|
||||||
MetalinkProcessorFactory.cc MetalinkProcessorFactory.h \
|
MetalinkProcessorFactory.cc MetalinkProcessorFactory.h \
|
||||||
|
@ -667,7 +671,9 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \
|
||||||
@ENABLE_BITTORRENT_TRUE@ DHTRegistry.$(OBJEXT) \
|
@ENABLE_BITTORRENT_TRUE@ DHTRegistry.$(OBJEXT) \
|
||||||
@ENABLE_BITTORRENT_TRUE@ InitiatorMSEHandshakeCommand.$(OBJEXT) \
|
@ENABLE_BITTORRENT_TRUE@ InitiatorMSEHandshakeCommand.$(OBJEXT) \
|
||||||
@ENABLE_BITTORRENT_TRUE@ ReceiverMSEHandshakeCommand.$(OBJEXT) \
|
@ENABLE_BITTORRENT_TRUE@ ReceiverMSEHandshakeCommand.$(OBJEXT) \
|
||||||
@ENABLE_BITTORRENT_TRUE@ MSEHandshake.$(OBJEXT)
|
@ENABLE_BITTORRENT_TRUE@ MSEHandshake.$(OBJEXT) \
|
||||||
|
@ENABLE_BITTORRENT_TRUE@ BtLeecherStateChoke.$(OBJEXT) \
|
||||||
|
@ENABLE_BITTORRENT_TRUE@ BtSeederStateChoke.$(OBJEXT)
|
||||||
@ENABLE_METALINK_TRUE@am__objects_3 = Metalinker.$(OBJEXT) \
|
@ENABLE_METALINK_TRUE@am__objects_3 = Metalinker.$(OBJEXT) \
|
||||||
@ENABLE_METALINK_TRUE@ MetalinkEntry.$(OBJEXT) \
|
@ENABLE_METALINK_TRUE@ MetalinkEntry.$(OBJEXT) \
|
||||||
@ENABLE_METALINK_TRUE@ MetalinkResource.$(OBJEXT) \
|
@ENABLE_METALINK_TRUE@ MetalinkResource.$(OBJEXT) \
|
||||||
|
@ -1234,6 +1240,7 @@ distclean-compile:
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtHaveNoneMessage.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtHaveNoneMessage.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtInterestedMessage.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtInterestedMessage.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtKeepAliveMessage.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtKeepAliveMessage.Po@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtLeecherStateChoke.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtNotInterestedMessage.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtNotInterestedMessage.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtPieceMessage.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtPieceMessage.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtPortMessage.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtPortMessage.Po@am__quote@
|
||||||
|
@ -1241,6 +1248,7 @@ distclean-compile:
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtRegistry.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtRegistry.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtRejectMessage.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtRejectMessage.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtRequestMessage.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtRequestMessage.Po@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtSeederStateChoke.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtSetup.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtSetup.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtSuggestPieceMessage.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtSuggestPieceMessage.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtUnchokeMessage.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtUnchokeMessage.Po@am__quote@
|
||||||
|
|
12
src/Peer.cc
12
src/Peer.cc
|
@ -442,4 +442,16 @@ const Time& Peer::getBadConditionStartTime() const
|
||||||
return _badConditionStartTime;
|
return _badConditionStartTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Time& Peer::getLastDownloadUpdate() const
|
||||||
|
{
|
||||||
|
assert(_res);
|
||||||
|
return _res->getLastDownloadUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
const Time& Peer::getLastAmUnchoking() const
|
||||||
|
{
|
||||||
|
assert(_res);
|
||||||
|
return _res->getLastAmUnchoking();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace aria2
|
} // namespace aria2
|
||||||
|
|
|
@ -231,6 +231,10 @@ public:
|
||||||
std::string getExtensionName(uint8_t id) const;
|
std::string getExtensionName(uint8_t id) const;
|
||||||
|
|
||||||
void setExtension(const std::string& name, uint8_t id);
|
void setExtension(const std::string& name, uint8_t id);
|
||||||
|
|
||||||
|
const Time& getLastDownloadUpdate() const;
|
||||||
|
|
||||||
|
const Time& getLastAmUnchoking() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef SharedHandle<Peer> PeerHandle;
|
typedef SharedHandle<Peer> PeerHandle;
|
||||||
|
|
|
@ -33,141 +33,29 @@
|
||||||
*/
|
*/
|
||||||
/* copyright --> */
|
/* copyright --> */
|
||||||
#include "PeerChokeCommand.h"
|
#include "PeerChokeCommand.h"
|
||||||
#include "Util.h"
|
|
||||||
#include "Peer.h"
|
|
||||||
#include "DownloadEngine.h"
|
#include "DownloadEngine.h"
|
||||||
#include "BtContext.h"
|
#include "BtContext.h"
|
||||||
#include "BtRuntime.h"
|
#include "BtRuntime.h"
|
||||||
#include "PieceStorage.h"
|
|
||||||
#include "PeerStorage.h"
|
#include "PeerStorage.h"
|
||||||
#include "Logger.h"
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
namespace aria2 {
|
namespace aria2 {
|
||||||
|
|
||||||
PeerChokeCommand::PeerChokeCommand(int32_t cuid,
|
PeerChokeCommand::PeerChokeCommand(int32_t cuid,
|
||||||
RequestGroup* requestGroup,
|
|
||||||
DownloadEngine* e,
|
DownloadEngine* e,
|
||||||
const BtContextHandle& btContext,
|
const BtContextHandle& btContext):
|
||||||
time_t interval):
|
|
||||||
Command(cuid),
|
Command(cuid),
|
||||||
BtContextAwareCommand(btContext),
|
BtContextAwareCommand(btContext),
|
||||||
RequestGroupAware(requestGroup),
|
e(e)
|
||||||
interval(interval),
|
|
||||||
e(e),
|
|
||||||
rotate(0)
|
|
||||||
{}
|
{}
|
||||||
|
|
||||||
PeerChokeCommand::~PeerChokeCommand() {}
|
PeerChokeCommand::~PeerChokeCommand() {}
|
||||||
|
|
||||||
class ChokePeer {
|
|
||||||
public:
|
|
||||||
ChokePeer() {}
|
|
||||||
void operator()(PeerHandle& peer) {
|
|
||||||
peer->chokingRequired(true);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void PeerChokeCommand::optUnchokingPeer(Peers& peers) const {
|
|
||||||
if(peers.empty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
std::random_shuffle(peers.begin(), peers.end());
|
|
||||||
unsigned int 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 {
|
|
||||||
std::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 {
|
|
||||||
std::sort(peers.begin(), peers.end(), DownloadFaster());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PeerChokeCommand::execute() {
|
bool PeerChokeCommand::execute() {
|
||||||
if(btRuntime->isHalt()) {
|
if(btRuntime->isHalt()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if(checkPoint.elapsed(interval)) {
|
if(peerStorage->chokeRoundIntervalElapsed()) {
|
||||||
checkPoint.reset();
|
peerStorage->executeChoke();
|
||||||
Peers peers = peerStorage->getActivePeers();
|
|
||||||
std::for_each(peers.begin(), peers.end(), ChokePeer());
|
|
||||||
if(pieceStorage->downloadFinished()) {
|
|
||||||
orderByUploadRate(peers);
|
|
||||||
} else {
|
|
||||||
orderByDownloadRate(peers);
|
|
||||||
}
|
|
||||||
unsigned int 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);
|
e->commands.push_back(this);
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -37,34 +37,21 @@
|
||||||
|
|
||||||
#include "Command.h"
|
#include "Command.h"
|
||||||
#include "BtContextAwareCommand.h"
|
#include "BtContextAwareCommand.h"
|
||||||
#include "RequestGroupAware.h"
|
|
||||||
#include "TimeA2.h"
|
|
||||||
|
|
||||||
namespace aria2 {
|
namespace aria2 {
|
||||||
|
|
||||||
class DownloadEngine;
|
class DownloadEngine;
|
||||||
class Peer;
|
|
||||||
|
|
||||||
class PeerChokeCommand : public Command,
|
class PeerChokeCommand : public Command,
|
||||||
public BtContextAwareCommand,
|
public BtContextAwareCommand
|
||||||
public RequestGroupAware
|
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
time_t interval;
|
|
||||||
DownloadEngine* e;
|
DownloadEngine* e;
|
||||||
unsigned int rotate;
|
|
||||||
Time checkPoint;
|
|
||||||
|
|
||||||
void orderByUploadRate(std::deque<SharedHandle<Peer> >& peers) const;
|
|
||||||
void orderByDownloadRate(std::deque<SharedHandle<Peer> >& peers) const;
|
|
||||||
void optUnchokingPeer(std::deque<SharedHandle<Peer> >& peers) const;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PeerChokeCommand(int32_t cuid,
|
PeerChokeCommand(int32_t cuid,
|
||||||
RequestGroup* requestGroup,
|
|
||||||
DownloadEngine* e,
|
DownloadEngine* e,
|
||||||
const SharedHandle<BtContext>& btContext,
|
const SharedHandle<BtContext>& btContext);
|
||||||
time_t interval);
|
|
||||||
|
|
||||||
virtual ~PeerChokeCommand();
|
virtual ~PeerChokeCommand();
|
||||||
|
|
||||||
|
|
|
@ -53,7 +53,9 @@ PeerSessionResource::PeerSessionResource(size_t pieceLength, uint64_t totalLengt
|
||||||
_dhtEnabled(false),
|
_dhtEnabled(false),
|
||||||
_latency(DEFAULT_LATENCY),
|
_latency(DEFAULT_LATENCY),
|
||||||
_uploadLength(0),
|
_uploadLength(0),
|
||||||
_downloadLength(0)
|
_downloadLength(0),
|
||||||
|
_lastDownloadUpdate(0),
|
||||||
|
_lastAmUnchoking(0)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
PeerSessionResource::~PeerSessionResource()
|
PeerSessionResource::~PeerSessionResource()
|
||||||
|
@ -69,6 +71,9 @@ bool PeerSessionResource::amChoking() const
|
||||||
void PeerSessionResource::amChoking(bool b)
|
void PeerSessionResource::amChoking(bool b)
|
||||||
{
|
{
|
||||||
_amChoking = b;
|
_amChoking = b;
|
||||||
|
if(!b) {
|
||||||
|
_lastAmUnchoking.reset();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PeerSessionResource::amInterested() const
|
bool PeerSessionResource::amInterested() const
|
||||||
|
@ -137,6 +142,10 @@ bool PeerSessionResource::snubbing() const
|
||||||
void PeerSessionResource::snubbing(bool b)
|
void PeerSessionResource::snubbing(bool b)
|
||||||
{
|
{
|
||||||
_snubbing = b;
|
_snubbing = b;
|
||||||
|
if(_snubbing) {
|
||||||
|
chokingRequired(true);
|
||||||
|
optUnchoking(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PeerSessionResource::hasAllPieces() const
|
bool PeerSessionResource::hasAllPieces() const
|
||||||
|
@ -311,6 +320,18 @@ void PeerSessionResource::updateDownloadLength(size_t bytes)
|
||||||
{
|
{
|
||||||
_peerStat.updateDownloadLength(bytes);
|
_peerStat.updateDownloadLength(bytes);
|
||||||
_downloadLength += bytes;
|
_downloadLength += bytes;
|
||||||
|
|
||||||
|
_lastDownloadUpdate.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
const Time& PeerSessionResource::getLastDownloadUpdate() const
|
||||||
|
{
|
||||||
|
return _lastDownloadUpdate;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Time& PeerSessionResource::getLastAmUnchoking() const
|
||||||
|
{
|
||||||
|
return _lastAmUnchoking;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace aria2
|
} // namespace aria2
|
||||||
|
|
|
@ -38,6 +38,7 @@
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "BtConstants.h"
|
#include "BtConstants.h"
|
||||||
#include "PeerStat.h"
|
#include "PeerStat.h"
|
||||||
|
#include "TimeA2.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
|
|
||||||
|
@ -76,6 +77,10 @@ private:
|
||||||
uint64_t _uploadLength;
|
uint64_t _uploadLength;
|
||||||
uint64_t _downloadLength;
|
uint64_t _downloadLength;
|
||||||
|
|
||||||
|
Time _lastDownloadUpdate;
|
||||||
|
|
||||||
|
Time _lastAmUnchoking;
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
bool indexIncluded(const std::deque<T>& c, T index) const;
|
bool indexIncluded(const std::deque<T>& c, T index) const;
|
||||||
public:
|
public:
|
||||||
|
@ -179,6 +184,10 @@ public:
|
||||||
uint64_t downloadLength() const;
|
uint64_t downloadLength() const;
|
||||||
|
|
||||||
void updateDownloadLength(size_t bytes);
|
void updateDownloadLength(size_t bytes);
|
||||||
|
|
||||||
|
const Time& getLastDownloadUpdate() const;
|
||||||
|
|
||||||
|
const Time& getLastAmUnchoking() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace aria2
|
} // namespace aria2
|
||||||
|
|
|
@ -89,6 +89,10 @@ public:
|
||||||
* Tells PeerStorage object that peer is no longer used in the session.
|
* Tells PeerStorage object that peer is no longer used in the session.
|
||||||
*/
|
*/
|
||||||
virtual void returnPeer(const SharedHandle<Peer>& peer) = 0;
|
virtual void returnPeer(const SharedHandle<Peer>& peer) = 0;
|
||||||
|
|
||||||
|
virtual bool chokeRoundIntervalElapsed() = 0;
|
||||||
|
|
||||||
|
virtual void executeChoke() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef SharedHandle<PeerStorage> PeerStorageHandle;
|
typedef SharedHandle<PeerStorage> PeerStorageHandle;
|
||||||
|
|
|
@ -57,6 +57,11 @@ public:
|
||||||
virtual void removeOutstandingRequest(const RequestSlot& slot) {}
|
virtual void removeOutstandingRequest(const RequestSlot& slot) {}
|
||||||
|
|
||||||
virtual void addOutstandingRequest(const RequestSlot& slot) {}
|
virtual void addOutstandingRequest(const RequestSlot& slot) {}
|
||||||
|
|
||||||
|
virtual size_t countOutstandingUpload()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace aria2
|
} // namespace aria2
|
||||||
|
|
|
@ -56,6 +56,13 @@ public:
|
||||||
virtual void returnPeer(const SharedHandle<Peer>& peer)
|
virtual void returnPeer(const SharedHandle<Peer>& peer)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual bool chokeRoundIntervalElapsed()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void executeChoke() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _D_MOCK_PEER_STORAGE_H_
|
#endif // _D_MOCK_PEER_STORAGE_H_
|
||||||
|
|
Loading…
Reference in New Issue