2008-07-20 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>

Now SegmentMan::findSlowerSegmentEntry() picks up the segment 
for which
	the transfer has not yet started.
	Rewritten SegmentMan::registerPeerStat() and 
SegmentMan::getPeerStat().
	* src/SegmentMan.cc
	* src/SegmentMan.h
	* test/SegmentManTest.cc
pull/1/head
Tatsuhiro Tsujikawa 2008-07-20 07:55:10 +00:00
parent 52979168f3
commit ec395b6a9c
4 changed files with 94 additions and 49 deletions

View File

@ -1,3 +1,12 @@
2008-07-20 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
Now SegmentMan::findSlowerSegmentEntry() picks up the segment for which
the transfer has not yet started.
Rewritten SegmentMan::registerPeerStat() and SegmentMan::getPeerStat().
* src/SegmentMan.cc
* src/SegmentMan.h
* test/SegmentManTest.cc
2008-07-20 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
Cache last calculated average download/upload speed.

View File

@ -123,25 +123,36 @@ SegmentHandle SegmentMan::checkoutSegment(int32_t cuid,
return segment;
}
SegmentEntryHandle SegmentMan::findSlowerSegmentEntry(const PeerStatHandle& peerStat) const {
SegmentEntryHandle SegmentMan::findSlowerSegmentEntry
(const PeerStatHandle& peerStat)
{
unsigned int speed = peerStat->getAvgDownloadSpeed()*0.8;
SegmentEntryHandle slowSegmentEntry;
for(SegmentEntries::const_iterator itr = usedSegmentEntries.begin();
itr != usedSegmentEntries.end(); ++itr) {
const SegmentEntryHandle& segmentEntry = *itr;
int startupIdleTime = _option->getAsInt(PREF_STARTUP_IDLE_TIME);
for(std::deque<SharedHandle<SegmentEntry> >::const_iterator itr =
usedSegmentEntries.begin(); itr != usedSegmentEntries.end(); ++itr) {
const SharedHandle<SegmentEntry>& segmentEntry = *itr;
if(segmentEntry->cuid == 0) {
continue;
}
PeerStatHandle p = getPeerStat(segmentEntry->cuid);
if(!p.get() || p->getCuid() == peerStat->getCuid() ||
p->getStatus() != PeerStat::ACTIVE ||
!p->getDownloadStartTime().elapsed(_option->getAsInt(PREF_STARTUP_IDLE_TIME))) {
continue;
}
unsigned int pSpeed = p->calculateDownloadSpeed();
if(pSpeed < speed) {
speed = pSpeed;
SharedHandle<PeerStat> p = getPeerStat(segmentEntry->cuid);
if(p.isNull()) {
// "p is null" means that it hasn't used DownloadCommand yet, i.e. waiting
// response from HTTP server after sending HTTP request.
p.reset(new PeerStat(segmentEntry->cuid));
registerPeerStat(p);
slowSegmentEntry = segmentEntry;
} else {
if(p->getCuid() == peerStat->getCuid() ||
(p->getStatus() == PeerStat::ACTIVE &&
!p->getDownloadStartTime().elapsed(startupIdleTime))) {
continue;
}
unsigned int pSpeed = p->calculateDownloadSpeed();
if(pSpeed < speed) {
speed = pSpeed;
slowSegmentEntry = segmentEntry;
}
}
}
return slowSegmentEntry;
@ -241,22 +252,36 @@ uint64_t SegmentMan::getDownloadLength() const {
}
}
void SegmentMan::registerPeerStat(const PeerStatHandle& peerStat) {
PeerStatHandle temp = getPeerStat(peerStat->getCuid());
if(!temp.get()) {
peerStats.push_back(peerStat);
class FindPeerStat {
public:
bool operator()(const SharedHandle<PeerStat>& peerStat, int32_t cuid) const
{
return peerStat->getCuid() < cuid;
}
};
bool SegmentMan::registerPeerStat(const SharedHandle<PeerStat>& peerStat)
{
std::deque<SharedHandle<PeerStat> >::iterator i =
std::lower_bound(peerStats.begin(), peerStats.end(),peerStat->getCuid(),
FindPeerStat());
if(i == peerStats.end() || (*i)->getCuid() != peerStat->getCuid()) {
peerStats.insert(i, peerStat);
return true ;
} else {
return false;
}
}
PeerStatHandle SegmentMan::getPeerStat(int32_t cuid) const
{
for(std::deque<SharedHandle<PeerStat> >::const_iterator itr = peerStats.begin(); itr != peerStats.end(); ++itr) {
const PeerStatHandle& peerStat = *itr;
if(peerStat->getCuid() == cuid) {
return peerStat;
}
std::deque<SharedHandle<PeerStat> >::const_iterator i =
std::lower_bound(peerStats.begin(), peerStats.end(), cuid, FindPeerStat());
if(i != peerStats.end() && (*i)->getCuid() == cuid) {
return *i;
} else {
return SharedHandle<PeerStat>();
}
return SharedHandle<PeerStat>();
}
unsigned int SegmentMan::calculateDownloadSpeed() const {

View File

@ -82,7 +82,8 @@ private:
SharedHandle<Segment> checkoutSegment(int32_t cuid,
const SharedHandle<Piece>& piece);
SegmentEntryHandle findSlowerSegmentEntry(const SharedHandle<PeerStat>& peerStat) const;
SharedHandle<SegmentEntry> findSlowerSegmentEntry
(const SharedHandle<PeerStat>& peerStat);
public:
SegmentMan(const Option* option,
const SharedHandle<DownloadContext>& downloadContext,
@ -159,10 +160,10 @@ public:
uint64_t getDownloadLength() const;
/**
* Registers given peerStat if it has not been registerd.
* Otherwise does nothing.
* Registers given peerStat if it has not been registerd and returns true.
* Otherwise does nothing and returns false.
*/
void registerPeerStat(const SharedHandle<PeerStat>& peerStat);
bool registerPeerStat(const SharedHandle<PeerStat>& peerStat);
/**
* Returns peerStat whose cuid is given cuid. If it is not found, returns

View File

@ -8,6 +8,8 @@
#include "Segment.h"
#include "Option.h"
#include "FileEntry.h"
#include "MockPieceStorage.h"
#include "PeerStat.h"
#include <cppunit/extensions/HelperMacros.h>
namespace aria2 {
@ -17,7 +19,7 @@ class SegmentManTest:public CppUnit::TestFixture {
CPPUNIT_TEST_SUITE(SegmentManTest);
CPPUNIT_TEST(testNullBitfield);
CPPUNIT_TEST(testCompleteSegment);
CPPUNIT_TEST(testMarkPieceDone_usedSegment);
CPPUNIT_TEST(testGetPeerStat);
CPPUNIT_TEST_SUITE_END();
private:
@ -27,7 +29,7 @@ public:
void testNullBitfield();
void testCompleteSegment();
void testMarkPieceDone_usedSegment();
void testGetPeerStat();
};
@ -82,30 +84,38 @@ void SegmentManTest::testCompleteSegment()
CPPUNIT_ASSERT_EQUAL((size_t)2, segments[1]->getIndex());
}
void SegmentManTest::testMarkPieceDone_usedSegment()
void SegmentManTest::testGetPeerStat()
{
// TODO implement this later
/*
SegmentMan segmentMan;
int32_t pieceLength = 1024*1024;
int64_t totalLength = 10*pieceLength;
segmentMan.initBitfield(pieceLength, totalLength);
segmentMan.markPieceDone(5*pieceLength+100);
Option op;
size_t pieceLength = 1;
uint64_t totalLength = 1;
SharedHandle<SingleFileDownloadContext> dctx
(new SingleFileDownloadContext(pieceLength, totalLength, "aria2.tar.bz2"));
SharedHandle<PieceStorage> ps(new MockPieceStorage());
SegmentMan segmentMan(&op, dctx, ps);
for(int32_t i = 0; i < 5; ++i) {
CPPUNIT_ASSERT(segmentMan.hasSegment(i));
CPPUNIT_ASSERT(segmentMan.getPeerStat(1).isNull());
SharedHandle<PeerStat> ps1(new PeerStat(1));
CPPUNIT_ASSERT(segmentMan.registerPeerStat(ps1));
{
SharedHandle<PeerStat> ps = segmentMan.getPeerStat(1);
CPPUNIT_ASSERT(!ps.isNull());
CPPUNIT_ASSERT_EQUAL(1, ps->getCuid());
}
for(int32_t i = 5; i < 10; ++i) {
CPPUNIT_ASSERT(!segmentMan.hasSegment(i));
// Duplicate registering is not allowed.
SharedHandle<PeerStat> ps1d(new PeerStat(1));
CPPUNIT_ASSERT(!segmentMan.registerPeerStat(ps1d));
// See whether it can work on several entries.
SharedHandle<PeerStat> ps2(new PeerStat(2));
SharedHandle<PeerStat> ps3(new PeerStat(3));
CPPUNIT_ASSERT(segmentMan.registerPeerStat(ps3));
CPPUNIT_ASSERT(segmentMan.registerPeerStat(ps2));
{
SharedHandle<PeerStat> ps = segmentMan.getPeerStat(2);
CPPUNIT_ASSERT(!ps.isNull());
CPPUNIT_ASSERT_EQUAL(2, ps->getCuid());
}
SharedHandle<Segment> segment = segmentMan.getSegment(0, 5);
CPPUNIT_ASSERT(!segment.isNull());
CPPUNIT_ASSERT_EQUAL((int32_t)5, segment->index);
CPPUNIT_ASSERT_EQUAL(pieceLength, (int32_t) segment->length);
CPPUNIT_ASSERT_EQUAL(pieceLength, (int32_t) segment->segmentLength);
CPPUNIT_ASSERT_EQUAL((int32_t)100, segment->writtenLength);
*/
}
} // namespace aria2