Browse Source

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
Tatsuhiro Tsujikawa 17 years ago
parent
commit
ec395b6a9c
4 changed files with 95 additions and 50 deletions
  1. 9 0
      ChangeLog
  2. 48 23
      src/SegmentMan.cc
  3. 5 4
      src/SegmentMan.h
  4. 33 23
      test/SegmentManTest.cc

+ 9 - 0
ChangeLog

@@ -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.

+ 48 - 23
src/SegmentMan.cc

@@ -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 {

+ 5 - 4
src/SegmentMan.h

@@ -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

+ 33 - 23
test/SegmentManTest.cc

@@ -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);
-
-  for(int32_t i = 0; i < 5; ++i) {
-    CPPUNIT_ASSERT(segmentMan.hasSegment(i));
+  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);
+
+  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