diff --git a/ChangeLog b/ChangeLog index 6ab9b2adda..a6e8dde64b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2008-05-11 Tatsuhiro Tsujikawa + + In piece selection functions, Pass std::deque<...> by reference rather + than returning it. + * src/BitfieldMan.cc + * src/BitfieldMan.h + * src/DefaultBtRequestFactory.cc + * src/DefaultPieceStorage.cc + * src/Piece.cc + * src/Piece.h + * test/BitfieldManTest.cc + 2008-05-11 Tatsuhiro Tsujikawa Implemented rarest piece first piece selection strategy. diff --git a/src/BitfieldMan.cc b/src/BitfieldMan.cc index d89deb2903..cf3c233398 100644 --- a/src/BitfieldMan.cc +++ b/src/BitfieldMan.cc @@ -388,45 +388,52 @@ bool BitfieldMan::getSparseMissingUnusedIndex(size_t& index) const { } template -std::deque -BitfieldMan::getAllMissingIndexes(const Array& bitfield, size_t bitfieldLength) const +bool BitfieldMan::getAllMissingIndexes(std::deque& indexes, + const Array& bitfield, + size_t bitfieldLength) const { - std::deque missingIndexes; for(size_t i = 0; i < bitfieldLength; ++i) { size_t base = i*8; for(size_t bi = 0; bi < 8 && base+bi < blocks; ++bi) { unsigned char mask = 128 >> bi; if(bitfield[i] & mask) { - missingIndexes.push_back(base+bi); + indexes.push_back(base+bi); } } } - return missingIndexes; + return !indexes.empty(); } -std::deque BitfieldMan::getAllMissingIndexes() const { +bool BitfieldMan::getAllMissingIndexes(std::deque& indexes) const +{ array_fun bf = array_negate(bitfield); if(filterEnabled) { bf = array_and(bf, filterBitfield); } - return getAllMissingIndexes(bf, bitfieldLength); + return getAllMissingIndexes(indexes, bf, bitfieldLength); } -std::deque BitfieldMan::getAllMissingIndexes(const unsigned char* peerBitfield, size_t peerBitfieldLength) const { +bool BitfieldMan::getAllMissingIndexes(std::deque& indexes, + const unsigned char* peerBitfield, + size_t peerBitfieldLength) const +{ if(bitfieldLength != peerBitfieldLength) { - return std::deque(); + return false; } array_fun bf = array_and(array_negate(bitfield), peerBitfield); if(filterEnabled) { bf = array_and(bf, filterBitfield); } - return getAllMissingIndexes(bf, bitfieldLength); + return getAllMissingIndexes(indexes, bf, bitfieldLength); } -std::deque BitfieldMan::getAllMissingUnusedIndexes(const unsigned char* peerBitfield, size_t peerBitfieldLength) const { +bool BitfieldMan::getAllMissingUnusedIndexes(std::deque& indexes, + const unsigned char* peerBitfield, + size_t peerBitfieldLength) const +{ if(bitfieldLength != peerBitfieldLength) { - return std::deque(); + return false; } array_fun bf = array_and(array_and(array_negate(bitfield), array_negate(useBitfield)), @@ -434,7 +441,7 @@ std::deque BitfieldMan::getAllMissingUnusedIndexes(const unsigned char* if(filterEnabled) { bf = array_and(bf, filterBitfield); } - return getAllMissingIndexes(bf, bitfieldLength); + return getAllMissingIndexes(indexes, bf, bitfieldLength); } size_t BitfieldMan::countMissingBlock() const { diff --git a/src/BitfieldMan.h b/src/BitfieldMan.h index 9e8ea0e067..7150337d25 100644 --- a/src/BitfieldMan.h +++ b/src/BitfieldMan.h @@ -73,7 +73,9 @@ class BitfieldMan { bool getFirstMissingIndex(size_t& index, const Array& bitfield, size_t bitfieldLength) const; template - std::deque getAllMissingIndexes(const Array& bitfield, size_t bitfieldLength) const; + bool getAllMissingIndexes(std::deque& indexes, + const Array& bitfield, + size_t bitfieldLength) const; bool isBitSetInternal(const unsigned char* bitfield, size_t index) const; bool setBitInternal(unsigned char* bitfield, size_t index, bool on); @@ -137,16 +139,18 @@ class BitfieldMan { /** * affected by filter */ - std::deque getAllMissingIndexes() const; + bool getAllMissingIndexes(std::deque&indexes) const; /** * affected by filter */ - std::deque getAllMissingIndexes(const unsigned char* bitfield, size_t len) const; + bool getAllMissingIndexes(std::deque& indexes, + const unsigned char* bitfield, size_t len) const; /** * affected by filter */ - std::deque getAllMissingUnusedIndexes(const unsigned char* bitfield, - size_t len) const; + bool getAllMissingUnusedIndexes(std::deque& indexes, + const unsigned char* bitfield, + size_t len) const; /** * affected by filter */ diff --git a/src/DefaultBtRequestFactory.cc b/src/DefaultBtRequestFactory.cc index 74825494b9..22e13868d2 100644 --- a/src/DefaultBtRequestFactory.cc +++ b/src/DefaultBtRequestFactory.cc @@ -126,7 +126,8 @@ BtMessages DefaultBtRequestFactory::createRequestMessagesOnEndGame(size_t max) for(Pieces::iterator itr = pieces.begin(); itr != pieces.end() && requests.size() < max; itr++) { PieceHandle& piece = *itr; - std::deque missingBlockIndexes = piece->getAllMissingBlockIndexes(); + std::deque missingBlockIndexes; + piece->getAllMissingBlockIndexes(missingBlockIndexes); random_shuffle(missingBlockIndexes.begin(), missingBlockIndexes.end()); for(std::deque::const_iterator bitr = missingBlockIndexes.begin(); bitr != missingBlockIndexes.end() && requests.size() < max; bitr++) { diff --git a/src/DefaultPieceStorage.cc b/src/DefaultPieceStorage.cc index c52840ad15..75eb5fd436 100644 --- a/src/DefaultPieceStorage.cc +++ b/src/DefaultPieceStorage.cc @@ -142,23 +142,26 @@ class FindRarestPiece bool DefaultPieceStorage::getMissingPieceIndex(size_t& index, const PeerHandle& peer) { + std::deque indexes; + bool r; if(isEndGame()) { - return bitfieldMan->getMissingIndex(index, peer->getBitfield(), - peer->getBitfieldLength()); + r = bitfieldMan->getAllMissingIndexes(indexes, peer->getBitfield(), + peer->getBitfieldLength()); } else { - std::deque indexes = - bitfieldMan->getAllMissingUnusedIndexes(peer->getBitfield(), - peer->getBitfieldLength()); - if(indexes.empty()) { - return false; - } else { - std::sort(indexes.begin(), indexes.end()); - std::deque >::const_iterator i = - std::find_if(_sortedPieceStats.begin(), _sortedPieceStats.end(), - FindRarestPiece(indexes)); - index = (*i)->getIndex(); - return true; - } + r = bitfieldMan->getAllMissingUnusedIndexes(indexes, + peer->getBitfield(), + peer->getBitfieldLength()); + } + if(r) { + // We assume indexes is sorted using comparator less. + //std::sort(indexes.begin(), indexes.end()); + std::deque >::const_iterator i = + std::find_if(_sortedPieceStats.begin(), _sortedPieceStats.end(), + FindRarestPiece(indexes)); + index = (*i)->getIndex(); + return true; + } else { + return false; } } diff --git a/src/Piece.cc b/src/Piece.cc index aa56401e33..f35520a3bf 100644 --- a/src/Piece.cc +++ b/src/Piece.cc @@ -169,8 +169,8 @@ bool Piece::getFirstMissingBlockIndexWithoutLock(size_t& index) const return bitfield->getFirstMissingIndex(index); } -std::deque Piece::getAllMissingBlockIndexes() const { - return bitfield->getAllMissingIndexes(); +bool Piece::getAllMissingBlockIndexes(std::deque& indexes) const { + return bitfield->getAllMissingIndexes(indexes); } std::string Piece::toString() const { diff --git a/src/Piece.h b/src/Piece.h index 67e61f430e..c978f45175 100644 --- a/src/Piece.h +++ b/src/Piece.h @@ -70,7 +70,7 @@ class Piece { bool getMissingUnusedBlockIndex(size_t& index) const; bool getMissingBlockIndex(size_t& index) const; bool getFirstMissingBlockIndexWithoutLock(size_t& index) const; - std::deque getAllMissingBlockIndexes() const; + bool getAllMissingBlockIndexes(std::deque& indexes) const; void completeBlock(size_t blockIndex); void cancelBlock(size_t blockIndex); diff --git a/test/BitfieldManTest.cc b/test/BitfieldManTest.cc index 00451fbcb2..2ab8e93634 100644 --- a/test/BitfieldManTest.cc +++ b/test/BitfieldManTest.cc @@ -21,6 +21,7 @@ class BitfieldManTest:public CppUnit::TestFixture { CPPUNIT_TEST(testSetBitRange); CPPUNIT_TEST(testGetAllMissingIndexes); CPPUNIT_TEST(testGetAllMissingIndexes_noarg); + CPPUNIT_TEST(testGetAllMissingUnusedIndexes); CPPUNIT_TEST(testGetMissingUnusedIndex); CPPUNIT_TEST(testGetMissingIndex_noarg); CPPUNIT_TEST(testGetMissingUnusedIndex_noarg); @@ -48,7 +49,8 @@ class BitfieldManTest:public CppUnit::TestFixture { void testGetMissingUnusedIndex_noarg(); void testGetAllMissingIndexes(); void testGetAllMissingIndexes_noarg(); - + void testGetAllMissingUnusedIndexes(); + void testIsAllBitSet(); void testFilter(); void testGetSparceMissingUnusedIndex(); @@ -594,12 +596,20 @@ void BitfieldManTest::testGetAllMissingIndexes_noarg() uint64_t totalLength = 1024*1024; BitfieldMan bf(blockLength, totalLength); - CPPUNIT_ASSERT_EQUAL((size_t)64, bf.getAllMissingIndexes().size()); + { + std::deque indexes; + CPPUNIT_ASSERT(bf.getAllMissingIndexes(indexes)); + CPPUNIT_ASSERT_EQUAL((size_t)64, indexes.size()); + } for(size_t i = 0; i < 63; ++i) { bf.setBit(i); } - CPPUNIT_ASSERT_EQUAL((size_t)1, bf.getAllMissingIndexes().size()); - CPPUNIT_ASSERT_EQUAL((size_t)63, bf.getAllMissingIndexes().front()); + { + std::deque indexes; + CPPUNIT_ASSERT(bf.getAllMissingIndexes(indexes)); + CPPUNIT_ASSERT_EQUAL((size_t)1, indexes.size()); + CPPUNIT_ASSERT_EQUAL((size_t)63, indexes.front()); + } } void BitfieldManTest::testGetAllMissingIndexes() @@ -610,16 +620,53 @@ void BitfieldManTest::testGetAllMissingIndexes() BitfieldMan peerBf(blockLength, totalLength); peerBf.setAllBit(); - CPPUNIT_ASSERT_EQUAL((size_t)64, bf.getAllMissingIndexes(peerBf.getBitfield(), - peerBf.getBitfieldLength()).size()); + { + std::deque indexes; + CPPUNIT_ASSERT(bf.getAllMissingIndexes(indexes, + peerBf.getBitfield(), + peerBf.getBitfieldLength())); + CPPUNIT_ASSERT_EQUAL((size_t)64, indexes.size()); + } for(size_t i = 0; i < 62; ++i) { bf.setBit(i); } peerBf.unsetBit(62); + { + std::deque indexes; + CPPUNIT_ASSERT(bf.getAllMissingIndexes(indexes, + peerBf.getBitfield(), + peerBf.getBitfieldLength())); + + CPPUNIT_ASSERT_EQUAL((size_t)1, indexes.size()); + CPPUNIT_ASSERT_EQUAL((size_t)63, indexes.front()); + } +} + +void BitfieldManTest::testGetAllMissingUnusedIndexes() +{ + size_t blockLength = 16*1024; + uint64_t totalLength = 1024*1024; + BitfieldMan bf(blockLength, totalLength); + BitfieldMan peerBf(blockLength, totalLength); + peerBf.setAllBit(); { - std::deque indexes = bf.getAllMissingIndexes(peerBf.getBitfield(), - peerBf.getBitfieldLength()); + std::deque indexes; + CPPUNIT_ASSERT(bf.getAllMissingUnusedIndexes(indexes, + peerBf.getBitfield(), + peerBf.getBitfieldLength())); + CPPUNIT_ASSERT_EQUAL((size_t)64, indexes.size()); + } + for(size_t i = 0; i < 61; ++i) { + bf.setBit(i); + } + bf.setUseBit(61); + peerBf.unsetBit(62); + { + std::deque indexes; + CPPUNIT_ASSERT(bf.getAllMissingUnusedIndexes(indexes, + peerBf.getBitfield(), + peerBf.getBitfieldLength())); CPPUNIT_ASSERT_EQUAL((size_t)1, indexes.size()); CPPUNIT_ASSERT_EQUAL((size_t)63, indexes.front());