mirror of https://github.com/aria2/aria2
2009-07-03 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
Rewritten PeerStats handling in SegmentMan.cc. Now we have 2 list of PeerStat in SegmentMan. peerStats is used for calculating download speed. Therefore all active PeerStats should be in there. Another one is _fastestPeerStats and it only contains fastest PeerStat for each hostname/protocol pair. They are used for updating ServerStat. * src/DownloadCommand.cc * src/Request.h * src/RequestGroupMan.cc * src/SegmentMan.cc * src/SegmentMan.h * test/SegmentManTest.ccpull/1/head
parent
01fdb2aaeb
commit
ffaeb271f9
15
ChangeLog
15
ChangeLog
|
@ -1,3 +1,18 @@
|
||||||
|
2009-07-03 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
|
||||||
|
|
||||||
|
Rewritten PeerStats handling in SegmentMan.cc. Now we have 2 list
|
||||||
|
of PeerStat in SegmentMan. peerStats is used for calculating
|
||||||
|
download speed. Therefore all active PeerStats should be in
|
||||||
|
there. Another one is _fastestPeerStats and it only contains
|
||||||
|
fastest PeerStat for each hostname/protocol pair. They are used
|
||||||
|
for updating ServerStat.
|
||||||
|
* src/DownloadCommand.cc
|
||||||
|
* src/Request.h
|
||||||
|
* src/RequestGroupMan.cc
|
||||||
|
* src/SegmentMan.cc
|
||||||
|
* src/SegmentMan.h
|
||||||
|
* test/SegmentManTest.cc
|
||||||
|
|
||||||
2009-07-03 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
|
2009-07-03 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
|
||||||
|
|
||||||
Try all available addresses returned by DNS until it gets
|
Try all available addresses returned by DNS until it gets
|
||||||
|
|
|
@ -89,18 +89,15 @@ DownloadCommand::DownloadCommand(int cuid,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // ENABLE_MESSAGE_DIGEST
|
#endif // ENABLE_MESSAGE_DIGEST
|
||||||
peerStat = req->getPeerStat();
|
|
||||||
if(peerStat.isNull()) {
|
peerStat = req->initPeerStat();
|
||||||
peerStat = req->initPeerStat();
|
|
||||||
_requestGroup->getSegmentMan()->registerPeerStat(peerStat);
|
|
||||||
}
|
|
||||||
peerStat->downloadStart();
|
peerStat->downloadStart();
|
||||||
|
_requestGroup->getSegmentMan()->registerPeerStat(peerStat);
|
||||||
}
|
}
|
||||||
|
|
||||||
DownloadCommand::~DownloadCommand() {
|
DownloadCommand::~DownloadCommand() {
|
||||||
assert(peerStat.get());
|
|
||||||
peerStat->downloadStop();
|
peerStat->downloadStop();
|
||||||
req->purgePeerStat();
|
_requestGroup->getSegmentMan()->updateFastestPeerStat(peerStat);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DownloadCommand::executeInternal() {
|
bool DownloadCommand::executeInternal() {
|
||||||
|
|
|
@ -185,8 +185,6 @@ public:
|
||||||
|
|
||||||
const SharedHandle<PeerStat>& initPeerStat();
|
const SharedHandle<PeerStat>& initPeerStat();
|
||||||
|
|
||||||
void purgePeerStat() { _peerStat.reset(); }
|
|
||||||
|
|
||||||
static const std::string METHOD_GET;
|
static const std::string METHOD_GET;
|
||||||
static const std::string METHOD_HEAD;
|
static const std::string METHOD_HEAD;
|
||||||
|
|
||||||
|
|
|
@ -329,34 +329,6 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class PeerStatFaster {
|
|
||||||
public:
|
|
||||||
bool operator()(const SharedHandle<PeerStat>& lhs,
|
|
||||||
const SharedHandle<PeerStat>& rhs) const
|
|
||||||
{
|
|
||||||
int r;
|
|
||||||
r = lhs->getHostname().compare(rhs->getHostname());
|
|
||||||
if(r != 0) {
|
|
||||||
return r < 0;
|
|
||||||
}
|
|
||||||
r = lhs->getProtocol().compare(rhs->getProtocol());
|
|
||||||
if(r != 0) {
|
|
||||||
return r < 0;
|
|
||||||
}
|
|
||||||
return lhs->getAvgDownloadSpeed() > rhs->getAvgDownloadSpeed();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class PeerStatHostProtoEqual {
|
|
||||||
public:
|
|
||||||
bool operator()(const SharedHandle<PeerStat>& lhs,
|
|
||||||
const SharedHandle<PeerStat>& rhs) const
|
|
||||||
{
|
|
||||||
return lhs->getHostname() == rhs->getHostname() &&
|
|
||||||
lhs->getProtocol() == rhs->getProtocol();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class CollectServerStat {
|
class CollectServerStat {
|
||||||
private:
|
private:
|
||||||
RequestGroupMan* _requestGroupMan;
|
RequestGroupMan* _requestGroupMan;
|
||||||
|
@ -370,16 +342,12 @@ public:
|
||||||
// Collect statistics during download in PeerStats and update/register
|
// Collect statistics during download in PeerStats and update/register
|
||||||
// ServerStatMan
|
// ServerStatMan
|
||||||
if(!group->getSegmentMan().isNull()) {
|
if(!group->getSegmentMan().isNull()) {
|
||||||
|
bool singleConnection =
|
||||||
std::deque<SharedHandle<PeerStat> > peerStats =
|
group->getSegmentMan()->getPeerStats().size() == 1;
|
||||||
group->getSegmentMan()->getPeerStats();
|
const std::deque<SharedHandle<PeerStat> >& peerStats =
|
||||||
std::sort(peerStats.begin(), peerStats.end(), PeerStatFaster());
|
group->getSegmentMan()->getFastestPeerStats();
|
||||||
// Use fastest PeerStat for each hostname/protocol pair.
|
|
||||||
for(std::deque<SharedHandle<PeerStat> >::const_iterator i =
|
for(std::deque<SharedHandle<PeerStat> >::const_iterator i =
|
||||||
peerStats.begin(),
|
peerStats.begin(); i != peerStats.end(); ++i) {
|
||||||
last = std::unique(peerStats.begin(), peerStats.end(),
|
|
||||||
PeerStatHostProtoEqual());
|
|
||||||
i != last; ++i) {
|
|
||||||
if((*i)->getHostname().empty() || (*i)->getProtocol().empty()) {
|
if((*i)->getHostname().empty() || (*i)->getProtocol().empty()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -391,7 +359,7 @@ public:
|
||||||
(*i)->getProtocol());
|
(*i)->getProtocol());
|
||||||
ss->increaseCounter();
|
ss->increaseCounter();
|
||||||
ss->updateDownloadSpeed(speed);
|
ss->updateDownloadSpeed(speed);
|
||||||
if(peerStats.size() == 1) {
|
if(singleConnection) {
|
||||||
ss->updateSingleConnectionAvgSpeed(speed);
|
ss->updateSingleConnectionAvgSpeed(speed);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -282,9 +282,42 @@ uint64_t SegmentMan::getDownloadLength() const {
|
||||||
|
|
||||||
void SegmentMan::registerPeerStat(const SharedHandle<PeerStat>& peerStat)
|
void SegmentMan::registerPeerStat(const SharedHandle<PeerStat>& peerStat)
|
||||||
{
|
{
|
||||||
|
for(std::deque<SharedHandle<PeerStat> >::iterator i = peerStats.begin();
|
||||||
|
i != peerStats.end(); ++i) {
|
||||||
|
if((*i)->getStatus() == PeerStat::IDLE) {
|
||||||
|
*i = peerStat;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
peerStats.push_back(peerStat);
|
peerStats.push_back(peerStat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class PeerStatHostProtoEqual {
|
||||||
|
private:
|
||||||
|
const SharedHandle<PeerStat>& _peerStat;
|
||||||
|
public:
|
||||||
|
PeerStatHostProtoEqual(const SharedHandle<PeerStat>& peerStat):
|
||||||
|
_peerStat(peerStat) {}
|
||||||
|
|
||||||
|
bool operator()(const SharedHandle<PeerStat>& p) const
|
||||||
|
{
|
||||||
|
return _peerStat->getHostname() == p->getHostname() &&
|
||||||
|
_peerStat->getProtocol() == p->getProtocol();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void SegmentMan::updateFastestPeerStat(const SharedHandle<PeerStat>& peerStat)
|
||||||
|
{
|
||||||
|
std::deque<SharedHandle<PeerStat> >::iterator i =
|
||||||
|
std::find_if(_fastestPeerStats.begin(), _fastestPeerStats.end(),
|
||||||
|
PeerStatHostProtoEqual(peerStat));
|
||||||
|
if(i == _fastestPeerStats.end()) {
|
||||||
|
_fastestPeerStats.push_back(peerStat);
|
||||||
|
} else if((*i)->getAvgDownloadSpeed() < peerStat->getAvgDownloadSpeed()) {
|
||||||
|
*i = peerStat;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
unsigned int SegmentMan::calculateDownloadSpeed()
|
unsigned int SegmentMan::calculateDownloadSpeed()
|
||||||
{
|
{
|
||||||
unsigned int speed = 0;
|
unsigned int speed = 0;
|
||||||
|
|
|
@ -88,8 +88,12 @@ private:
|
||||||
// segment. The value is writtenLength for that segment.
|
// segment. The value is writtenLength for that segment.
|
||||||
std::map<size_t, size_t> _segmentWrittenLengthMemo;
|
std::map<size_t, size_t> _segmentWrittenLengthMemo;
|
||||||
|
|
||||||
|
// Used for calculating download speed.
|
||||||
std::deque<SharedHandle<PeerStat> > peerStats;
|
std::deque<SharedHandle<PeerStat> > peerStats;
|
||||||
|
|
||||||
|
// Keep track of fastest PeerStat for each server
|
||||||
|
std::deque<SharedHandle<PeerStat> > _fastestPeerStats;
|
||||||
|
|
||||||
// key: PeerStat's cuid, value: its download speed
|
// key: PeerStat's cuid, value: its download speed
|
||||||
std::map<cuid_t, unsigned int> _peerStatDlspdMap;
|
std::map<cuid_t, unsigned int> _peerStatDlspdMap;
|
||||||
|
|
||||||
|
@ -188,10 +192,10 @@ public:
|
||||||
*/
|
*/
|
||||||
uint64_t getDownloadLength() const;
|
uint64_t getDownloadLength() const;
|
||||||
|
|
||||||
/**
|
|
||||||
* Registers given peerStat if it has not been registerd and returns true.
|
// If there is inactive PeerStat in peerStats, it is replaced with
|
||||||
* Otherwise does nothing and returns false.
|
// given peerStat. If no such PeerStat exist, the given peerStat is
|
||||||
*/
|
// inserted.
|
||||||
void registerPeerStat(const SharedHandle<PeerStat>& peerStat);
|
void registerPeerStat(const SharedHandle<PeerStat>& peerStat);
|
||||||
|
|
||||||
const std::deque<SharedHandle<PeerStat> >& getPeerStats() const
|
const std::deque<SharedHandle<PeerStat> >& getPeerStats() const
|
||||||
|
@ -199,6 +203,17 @@ public:
|
||||||
return peerStats;
|
return peerStats;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If there is slower PeerStat than given peerStat for the same
|
||||||
|
// hostname and protocol in _fastestPeerStats, the former is
|
||||||
|
// replaced with latter. If there are no PeerStat with same hostname
|
||||||
|
// and protocol with given peerStat, given peerStat is inserted.
|
||||||
|
void updateFastestPeerStat(const SharedHandle<PeerStat>& peerStat);
|
||||||
|
|
||||||
|
const std::deque<SharedHandle<PeerStat> >& getFastestPeerStats() const
|
||||||
|
{
|
||||||
|
return _fastestPeerStats;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns current download speed in bytes per sec.
|
* Returns current download speed in bytes per sec.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -17,6 +17,7 @@ class SegmentManTest:public CppUnit::TestFixture {
|
||||||
CPPUNIT_TEST(testNullBitfield);
|
CPPUNIT_TEST(testNullBitfield);
|
||||||
CPPUNIT_TEST(testCompleteSegment);
|
CPPUNIT_TEST(testCompleteSegment);
|
||||||
CPPUNIT_TEST(testGetSegment_sameFileEntry);
|
CPPUNIT_TEST(testGetSegment_sameFileEntry);
|
||||||
|
CPPUNIT_TEST(testRegisterPeerStat);
|
||||||
CPPUNIT_TEST_SUITE_END();
|
CPPUNIT_TEST_SUITE_END();
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -28,6 +29,7 @@ public:
|
||||||
void testCompleteSegment();
|
void testCompleteSegment();
|
||||||
void testGetPeerStat();
|
void testGetPeerStat();
|
||||||
void testGetSegment_sameFileEntry();
|
void testGetSegment_sameFileEntry();
|
||||||
|
void testRegisterPeerStat();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -124,4 +126,22 @@ void SegmentManTest::testGetSegment_sameFileEntry()
|
||||||
CPPUNIT_ASSERT_EQUAL((size_t)3, segments.size());
|
CPPUNIT_ASSERT_EQUAL((size_t)3, segments.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SegmentManTest::testRegisterPeerStat()
|
||||||
|
{
|
||||||
|
Option op;
|
||||||
|
SharedHandle<DownloadContext> dctx(new DownloadContext());
|
||||||
|
SharedHandle<DefaultPieceStorage> ps(new DefaultPieceStorage(dctx, &op));
|
||||||
|
SegmentMan segman(&op, dctx, ps);
|
||||||
|
|
||||||
|
SharedHandle<PeerStat> p1(new PeerStat(0, "host1", "http"));
|
||||||
|
segman.registerPeerStat(p1);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((size_t)1, segman.getPeerStats().size());
|
||||||
|
SharedHandle<PeerStat> p2(new PeerStat(0, "host2", "http"));
|
||||||
|
segman.registerPeerStat(p2);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((size_t)1, segman.getPeerStats().size());
|
||||||
|
p2->downloadStart();
|
||||||
|
segman.registerPeerStat(p1);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((size_t)2, segman.getPeerStats().size());
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace aria2
|
} // namespace aria2
|
||||||
|
|
Loading…
Reference in New Issue