Don't sum in-flight piece which does not intersect filtered ranges

When calculating completed length, don't sum the completed length of
piece which does not intersect filtered ranges.
pull/22/head
Tatsuhiro Tsujikawa 2012-06-27 23:28:57 +09:00
parent 68f225de0b
commit c30ea8adeb
6 changed files with 81 additions and 7 deletions

View File

@ -609,6 +609,14 @@ bool BitfieldMan::isAllFilterBitSet() const
return testAllBitSet(filterBitfield_, bitfieldLength_, blocks_); return testAllBitSet(filterBitfield_, bitfieldLength_, blocks_);
} }
bool BitfieldMan::isFilterBitSet(size_t index) const {
if(filterBitfield_) {
return bitfield::test(filterBitfield_, blocks_, index);
} else {
return false;
}
}
bool BitfieldMan::isBitSet(size_t index) const bool BitfieldMan::isBitSet(size_t index) const
{ {
return bitfield::test(bitfield_, blocks_, index); return bitfield::test(bitfield_, blocks_, index);

View File

@ -200,6 +200,9 @@ public:
bool isAllBitSet() const; bool isAllBitSet() const;
bool isAllFilterBitSet() const; bool isAllFilterBitSet() const;
// Returns true if index bit is set in filterBitfield_. If
// filterBitfield_ is NULL, returns false.
bool isFilterBitSet(size_t index) const;
const unsigned char* getBitfield() const const unsigned char* getBitfield() const
{ {

View File

@ -537,14 +537,29 @@ int64_t DefaultPieceStorage::getCompletedLength()
int64_t DefaultPieceStorage::getFilteredCompletedLength() int64_t DefaultPieceStorage::getFilteredCompletedLength()
{ {
return bitfieldMan_->getFilteredCompletedLength()+ return bitfieldMan_->getFilteredCompletedLength()+
getInFlightPieceCompletedLength(); getInFlightPieceFilteredCompletedLength();
} }
size_t DefaultPieceStorage::getInFlightPieceCompletedLength() const int64_t DefaultPieceStorage::getInFlightPieceCompletedLength() const
{ {
return std::accumulate(usedPieces_.begin(), usedPieces_.end(), int64_t len = 0;
0, adopt2nd(std::plus<size_t>(), for(UsedPieceSet::const_iterator i = usedPieces_.begin(),
mem_fun_sh(&Piece::getCompletedLength))); eoi = usedPieces_.end(); i != eoi; ++i) {
len += (*i)->getCompletedLength();
}
return len;
}
int64_t DefaultPieceStorage::getInFlightPieceFilteredCompletedLength() const
{
int64_t len = 0;
for(UsedPieceSet::const_iterator i = usedPieces_.begin(),
eoi = usedPieces_.end(); i != eoi; ++i) {
if(bitfieldMan_->isFilterBitSet((*i)->getIndex())) {
len += (*i)->getCompletedLength();
}
}
return len;
} }
// not unittested // not unittested

View File

@ -110,8 +110,11 @@ private:
void deleteUsedPiece(const SharedHandle<Piece>& piece); void deleteUsedPiece(const SharedHandle<Piece>& piece);
SharedHandle<Piece> findUsedPiece(size_t index) const; SharedHandle<Piece> findUsedPiece(size_t index) const;
size_t getInFlightPieceCompletedLength() const; // Returns the sum of completed length of in-flight pieces
int64_t getInFlightPieceCompletedLength() const;
// Returns the sum of completed length of in-flight pieces
// intersecting filter ranges.
int64_t getInFlightPieceFilteredCompletedLength() const;
public: public:
// Setting randomPieceStatsOrdering to true means a piece is chosen in // Setting randomPieceStatsOrdering to true means a piece is chosen in
// random when more than 2 pieces has the same rarity. // random when more than 2 pieces has the same rarity.

View File

@ -18,6 +18,7 @@ class BitfieldManTest:public CppUnit::TestFixture {
CPPUNIT_TEST(testGetFirstMissingIndex); CPPUNIT_TEST(testGetFirstMissingIndex);
CPPUNIT_TEST(testIsAllBitSet); CPPUNIT_TEST(testIsAllBitSet);
CPPUNIT_TEST(testFilter); CPPUNIT_TEST(testFilter);
CPPUNIT_TEST(testIsFilterBitSet);
CPPUNIT_TEST(testAddFilter_zeroLength); CPPUNIT_TEST(testAddFilter_zeroLength);
CPPUNIT_TEST(testAddNotFilter); CPPUNIT_TEST(testAddNotFilter);
CPPUNIT_TEST(testAddNotFilter_zeroLength); CPPUNIT_TEST(testAddNotFilter_zeroLength);
@ -51,6 +52,7 @@ public:
void testIsAllBitSet(); void testIsAllBitSet();
void testFilter(); void testFilter();
void testIsFilterBitSet();
void testAddFilter_zeroLength(); void testAddFilter_zeroLength();
void testAddNotFilter(); void testAddNotFilter();
void testAddNotFilter_zeroLength(); void testAddNotFilter_zeroLength();
@ -244,6 +246,17 @@ void BitfieldManTest::testFilter()
CPPUNIT_ASSERT_EQUAL((int64_t)31ULL, btman2.getFilteredTotalLength()); CPPUNIT_ASSERT_EQUAL((int64_t)31ULL, btman2.getFilteredTotalLength());
} }
void BitfieldManTest::testIsFilterBitSet()
{
BitfieldMan btman(2, 32);
CPPUNIT_ASSERT(!btman.isFilterBitSet(0));
btman.addFilter(0, 2);
CPPUNIT_ASSERT(btman.isFilterBitSet(0));
CPPUNIT_ASSERT(!btman.isFilterBitSet(1));
btman.addFilter(2, 4);
CPPUNIT_ASSERT(btman.isFilterBitSet(1));
}
void BitfieldManTest::testAddFilter_zeroLength() void BitfieldManTest::testAddFilter_zeroLength()
{ {
BitfieldMan bits(1024, 1024*1024); BitfieldMan bits(1024, 1024*1024);

View File

@ -37,6 +37,7 @@ class DefaultPieceStorageTest:public CppUnit::TestFixture {
CPPUNIT_TEST(testCancelPiece); CPPUNIT_TEST(testCancelPiece);
CPPUNIT_TEST(testMarkPiecesDone); CPPUNIT_TEST(testMarkPiecesDone);
CPPUNIT_TEST(testGetCompletedLength); CPPUNIT_TEST(testGetCompletedLength);
CPPUNIT_TEST(testGetFilteredCompletedLength);
CPPUNIT_TEST(testGetNextUsedIndex); CPPUNIT_TEST(testGetNextUsedIndex);
CPPUNIT_TEST_SUITE_END(); CPPUNIT_TEST_SUITE_END();
private: private:
@ -71,6 +72,7 @@ public:
void testCancelPiece(); void testCancelPiece();
void testMarkPiecesDone(); void testMarkPiecesDone();
void testGetCompletedLength(); void testGetCompletedLength();
void testGetFilteredCompletedLength();
void testGetNextUsedIndex(); void testGetNextUsedIndex();
}; };
@ -345,6 +347,36 @@ void DefaultPieceStorageTest::testGetCompletedLength()
CPPUNIT_ASSERT_EQUAL((int64_t)256*1024*1024, ps.getCompletedLength()); CPPUNIT_ASSERT_EQUAL((int64_t)256*1024*1024, ps.getCompletedLength());
} }
void DefaultPieceStorageTest::testGetFilteredCompletedLength()
{
const size_t pieceLength = 1024*1024;
SharedHandle<DownloadContext> dctx(new DownloadContext());
dctx->setPieceLength(pieceLength);
SharedHandle<FileEntry> files[] = {
SharedHandle<FileEntry>(new FileEntry("foo", 2*pieceLength, 0)),
SharedHandle<FileEntry>(new FileEntry("bar", 4*pieceLength, 2*pieceLength))
};
files[1]->setRequested(false);
dctx->setFileEntries(&files[0], &files[2]);
DefaultPieceStorage ps(dctx, option_.get());
std::vector<SharedHandle<Piece> > inflightPieces(2);
inflightPieces[0] = SharedHandle<Piece>(new Piece(1, pieceLength));
inflightPieces[0]->completeBlock(0);
inflightPieces[1] = SharedHandle<Piece>(new Piece(2, pieceLength));
inflightPieces[1]->completeBlock(1);
inflightPieces[1]->completeBlock(2);
ps.addInFlightPiece(inflightPieces);
ps.setupFileFilter();
SharedHandle<Piece> piece = ps.getMissingPiece(0, 1);
ps.completePiece(piece);
CPPUNIT_ASSERT_EQUAL((int64_t)pieceLength+16*1024,
ps.getFilteredCompletedLength());
}
void DefaultPieceStorageTest::testGetNextUsedIndex() void DefaultPieceStorageTest::testGetNextUsedIndex()
{ {
DefaultPieceStorage pss(dctx_, option_.get()); DefaultPieceStorage pss(dctx_, option_.get());