diff --git a/ChangeLog b/ChangeLog index 65180fa9..4999e639 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2008-08-14 Tatsuhiro Tsujikawa + + Fixed occasional assertion failure in PieceSegment. + Calling PieceStorage::getMissingPiece(size_t) was missing after + canceling segments in SegmentMan::getSegment(int32_t). This resulted in + creation of duplicate segments and one of the segment was finished then + assertion failure was caused. + * src/SegmentMan.cc + * test/SegmentManTest.cc + 2008-08-11 Tatsuhiro Tsujikawa Added options to load/save the server's performance/status to a file diff --git a/src/SegmentMan.cc b/src/SegmentMan.cc index 0d3f8a15..9383ec0a 100644 --- a/src/SegmentMan.cc +++ b/src/SegmentMan.cc @@ -46,6 +46,7 @@ #include "DownloadContext.h" #include "Piece.h" #include +#include namespace aria2 { @@ -186,7 +187,12 @@ SegmentHandle SegmentMan::getSegment(int32_t cuid) { PeerStatHandle slowPeerStat = getPeerStat(slowSegmentEntry->cuid); slowPeerStat->requestIdle(); cancelSegment(slowSegmentEntry->cuid); - return checkoutSegment(cuid, slowSegmentEntry->segment->getPiece()); + + SharedHandle piece = + _pieceStorage->getMissingPiece(slowSegmentEntry->segment->getIndex()); + assert(!piece.isNull()); + + return checkoutSegment(cuid, piece); } else { return SharedHandle(); } diff --git a/test/SegmentManTest.cc b/test/SegmentManTest.cc index be4d8f89..33e9f95b 100644 --- a/test/SegmentManTest.cc +++ b/test/SegmentManTest.cc @@ -20,6 +20,7 @@ class SegmentManTest:public CppUnit::TestFixture { CPPUNIT_TEST(testNullBitfield); CPPUNIT_TEST(testCompleteSegment); CPPUNIT_TEST(testGetPeerStat); + CPPUNIT_TEST(testGetSegment_segmentForward); CPPUNIT_TEST_SUITE_END(); private: @@ -30,6 +31,7 @@ public: void testNullBitfield(); void testCompleteSegment(); void testGetPeerStat(); + void testGetSegment_segmentForward(); }; @@ -118,4 +120,30 @@ void SegmentManTest::testGetPeerStat() } } +void SegmentManTest::testGetSegment_segmentForward() +{ + Option op; + size_t pieceLength = 1; + uint64_t totalLength = 1; + SharedHandle dctx + (new SingleFileDownloadContext(pieceLength, totalLength, "aria2.tar.bz2")); + SharedHandle ps(new DefaultPieceStorage(dctx, &op)); + SegmentMan segmentMan(&op, dctx, ps); + + SharedHandle segment = segmentMan.getSegment(1); + CPPUNIT_ASSERT(!segment.isNull()); + CPPUNIT_ASSERT_EQUAL((size_t)0, segment->getIndex()); + + SharedHandle cuid2_ps(new PeerStat(2)); + CPPUNIT_ASSERT(segmentMan.registerPeerStat(cuid2_ps)); + + SharedHandle segment_forwarded = segmentMan.getSegment(2); + CPPUNIT_ASSERT(!segment_forwarded.isNull()); + CPPUNIT_ASSERT_EQUAL((size_t)0, segment_forwarded->getIndex()); + + // SegmentMan::getSegmetn(3) returns null because CUID#3's PeerStat is not + // registered and all segment(total 1 in this case) are used. + CPPUNIT_ASSERT(segmentMan.getSegment(3).isNull()); +} + } // namespace aria2