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> 2008-07-20 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
Cache last calculated average download/upload speed. Cache last calculated average download/upload speed.

View File

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

View File

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

View File

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