2008-09-19 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>

Fixed the bug that a block in a piece is requested when same 
block is
	already requested to the same peer in end game mode.
	* src/BtRequestFactory.h
	* src/DefaultBtInteractive.cc
	* src/DefaultBtRequestFactory.cc
	* src/DefaultBtRequestFactory.h
	* src/DefaultPieceStorage.cc
	* src/DefaultPieceStorage.h
	* src/PieceStorage.h
	* src/UnknownLengthPieceStorage.cc
	* src/UnknownLengthPieceStorage.h
	* test/DefaultBtRequestFactoryTest.cc
	* test/DefaultPieceStorageTest.cc
	* test/MockBtRequestFactory.h
	* test/MockPieceStorage.h
pull/1/head
Tatsuhiro Tsujikawa 2008-09-19 14:11:41 +00:00
parent cdaafd8c8c
commit 67767e2f61
14 changed files with 242 additions and 36 deletions

View File

@ -1,3 +1,21 @@
2008-09-19 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
Fixed the bug that a block in a piece is requested when same block is
already requested to the same peer in end game mode.
* src/BtRequestFactory.h
* src/DefaultBtInteractive.cc
* src/DefaultBtRequestFactory.cc
* src/DefaultBtRequestFactory.h
* src/DefaultPieceStorage.cc
* src/DefaultPieceStorage.h
* src/PieceStorage.h
* src/UnknownLengthPieceStorage.cc
* src/UnknownLengthPieceStorage.h
* test/DefaultBtRequestFactoryTest.cc
* test/DefaultPieceStorageTest.cc
* test/MockBtRequestFactory.h
* test/MockPieceStorage.h
2008-09-19 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
Removed _uploadLength and _downloadLength from PeerSessionResource

View File

@ -76,6 +76,13 @@ public:
*/
virtual void createRequestMessagesOnEndGame
(std::deque<SharedHandle<BtMessage> >& requests, size_t max) = 0;
/**
* Stores the list of index of pieces added using addTargetPiece() into
* indexes.
*/
virtual void getTargetPieceIndexes(std::deque<size_t>& indexes) const = 0;
};
typedef SharedHandle<BtRequestFactory> BtRequestFactoryHandle;

View File

@ -295,25 +295,32 @@ void DefaultBtInteractive::fillPiece(size_t maxMissingBlock) {
if(peer->peerChoking()) {
if(peer->isFastExtensionEnabled()) {
std::deque<size_t> excludedIndexes;
btRequestFactory->getTargetPieceIndexes(excludedIndexes);
while(numMissingBlock < maxMissingBlock) {
PieceHandle piece = pieceStorage->getMissingFastPiece(peer);
SharedHandle<Piece> piece =
pieceStorage->getMissingFastPiece(peer, excludedIndexes);
if(piece.isNull()) {
break;
} else {
btRequestFactory->addTargetPiece(piece);
numMissingBlock += piece->countMissingBlock();
excludedIndexes.push_back(piece->getIndex());
}
}
}
} else {
std::deque<size_t> excludedIndexes;
btRequestFactory->getTargetPieceIndexes(excludedIndexes);
while(numMissingBlock < maxMissingBlock) {
PieceHandle piece = pieceStorage->getMissingPiece(peer);
SharedHandle<Piece> piece =
pieceStorage->getMissingPiece(peer, excludedIndexes);
if(piece.isNull()) {
break;
} else {
btRequestFactory->addTargetPiece(piece);
numMissingBlock += piece->countMissingBlock();
excludedIndexes.push_back(piece->getIndex());
}
}
}

View File

@ -210,6 +210,13 @@ size_t DefaultBtRequestFactory::countMissingBlock()
CountMissingBlock()).getNumMissingBlock();
}
void DefaultBtRequestFactory::getTargetPieceIndexes
(std::deque<size_t>& indexes) const
{
std::transform(pieces.begin(), pieces.end(), std::back_inserter(indexes),
mem_fun_sh(&Piece::getIndex));
}
std::deque<SharedHandle<Piece> >& DefaultBtRequestFactory::getTargetPieces()
{
return pieces;

View File

@ -84,6 +84,8 @@ public:
virtual void createRequestMessagesOnEndGame
(std::deque<SharedHandle<BtMessage> >& requests, size_t max);
virtual void getTargetPieceIndexes(std::deque<size_t>& indexes) const;
std::deque<SharedHandle<Piece> >& getTargetPieces();
void setCuid(int32_t cuid)

View File

@ -87,22 +87,20 @@ bool DefaultPieceStorage::isEndGame()
return bitfieldMan->countMissingBlock() <= endGamePieceNum;
}
bool DefaultPieceStorage::getMissingPieceIndex(size_t& index, const PeerHandle& peer)
bool DefaultPieceStorage::getMissingPieceIndex(size_t& index,
const unsigned char* bitfield,
size_t& length)
{
std::deque<size_t> indexes;
bool r;
if(isEndGame()) {
r = bitfieldMan->getAllMissingIndexes(indexes, peer->getBitfield(),
peer->getBitfieldLength());
r = bitfieldMan->getAllMissingIndexes(indexes, bitfield, length);
} else {
r = bitfieldMan->getAllMissingUnusedIndexes(indexes,
peer->getBitfield(),
peer->getBitfieldLength());
r = bitfieldMan->getAllMissingUnusedIndexes(indexes, bitfield, length);
}
if(r) {
// We assume indexes is sorted using comparator less.
_pieceSelector->select(index, indexes);
return true;
return _pieceSelector->select(index, indexes);
} else {
return false;
}
@ -171,45 +169,81 @@ PieceHandle DefaultPieceStorage::findUsedPiece(size_t index) const
}
}
PieceHandle DefaultPieceStorage::getMissingPiece(const PeerHandle& peer)
SharedHandle<Piece> DefaultPieceStorage::getMissingPiece
(const unsigned char* bitfield, size_t length)
{
size_t index;
if(getMissingPieceIndex(index, peer)) {
if(getMissingPieceIndex(index, bitfield, length)) {
return checkOutPiece(index);
} else {
return SharedHandle<Piece>();
}
}
bool DefaultPieceStorage::getMissingFastPieceIndex(size_t& index,
const PeerHandle& peer)
SharedHandle<Piece> DefaultPieceStorage::getMissingPiece
(const BitfieldMan& bitfield)
{
return getMissingPiece(bitfield.getBitfield(), bitfield.getBitfieldLength());
}
PieceHandle DefaultPieceStorage::getMissingPiece(const SharedHandle<Peer>& peer)
{
return getMissingPiece(peer->getBitfield(), peer->getBitfieldLength());
}
void DefaultPieceStorage::createFastIndexBitfield
(BitfieldMan& bitfield, const SharedHandle<Peer>& peer)
{
for(std::deque<size_t>::const_iterator itr =
peer->getPeerAllowedIndexSet().begin();
itr != peer->getPeerAllowedIndexSet().end(); ++itr) {
if(!bitfieldMan->isBitSet(*itr) && peer->hasPiece(*itr)) {
bitfield.setBit(*itr);
}
}
}
PieceHandle DefaultPieceStorage::getMissingFastPiece
(const SharedHandle<Peer>& peer)
{
if(peer->isFastExtensionEnabled() && peer->countPeerAllowedIndexSet() > 0) {
BitfieldMan tempBitfield(bitfieldMan->getBlockLength(),
bitfieldMan->getTotalLength());
for(std::deque<size_t>::const_iterator itr = peer->getPeerAllowedIndexSet().begin();
itr != peer->getPeerAllowedIndexSet().end(); itr++) {
if(!bitfieldMan->isBitSet(*itr) && peer->hasPiece(*itr)) {
tempBitfield.setBit(*itr);
}
}
if(isEndGame()) {
return bitfieldMan->getMissingIndex(index, tempBitfield.getBitfield(),
tempBitfield.getBitfieldLength());
} else {
return bitfieldMan->getMissingUnusedIndex(index,
tempBitfield.getBitfield(),
tempBitfield.getBitfieldLength());
}
createFastIndexBitfield(tempBitfield, peer);
return getMissingPiece(tempBitfield);
} else {
return SharedHandle<Piece>();
}
return false;
}
PieceHandle DefaultPieceStorage::getMissingFastPiece(const PeerHandle& peer)
static void unsetExcludedIndexes(BitfieldMan& bitfield,
const std::deque<size_t>& excludedIndexes)
{
size_t index;
if(getMissingFastPieceIndex(index, peer)) {
return checkOutPiece(index);
for(std::deque<size_t>::const_iterator i = excludedIndexes.begin();
i != excludedIndexes.end(); ++i) {
bitfield.unsetBit(*i);
}
}
SharedHandle<Piece> DefaultPieceStorage::getMissingPiece
(const SharedHandle<Peer>& peer, const std::deque<size_t>& excludedIndexes)
{
BitfieldMan tempBitfield(bitfieldMan->getBlockLength(),
bitfieldMan->getTotalLength());
tempBitfield.setBitfield(peer->getBitfield(), peer->getBitfieldLength());
unsetExcludedIndexes(tempBitfield, excludedIndexes);
return getMissingPiece(tempBitfield);
}
SharedHandle<Piece> DefaultPieceStorage::getMissingFastPiece
(const SharedHandle<Peer>& peer, const std::deque<size_t>& excludedIndexes)
{
if(peer->isFastExtensionEnabled() && peer->countPeerAllowedIndexSet() > 0) {
BitfieldMan tempBitfield(bitfieldMan->getBlockLength(),
bitfieldMan->getTotalLength());
createFastIndexBitfield(tempBitfield, peer);
unsetExcludedIndexes(tempBitfield, excludedIndexes);
return getMissingPiece(tempBitfield);
} else {
return SharedHandle<Piece>();
}

View File

@ -83,8 +83,17 @@ private:
SharedHandle<RarestPieceSelector> _pieceSelector;
bool getMissingPieceIndex(size_t& index, const SharedHandle<Peer>& peer);
bool getMissingFastPieceIndex(size_t& index, const SharedHandle<Peer>& peer);
bool getMissingPieceIndex(size_t& index,
const unsigned char* bitfield, size_t& length);
SharedHandle<Piece> getMissingPiece(const unsigned char* bitfield,
size_t length);
SharedHandle<Piece> getMissingPiece(const BitfieldMan& bitfield);
void createFastIndexBitfield(BitfieldMan& bitfield,
const SharedHandle<Peer>& peer);
SharedHandle<Piece> checkOutPiece(size_t index);
// size_t deleteUsedPiecesByFillRate(int fillRate, size_t toDelete);
// void reduceUsedPieces(size_t upperBound);
@ -109,6 +118,12 @@ public:
virtual SharedHandle<Piece> getMissingFastPiece(const SharedHandle<Peer>& peer);
virtual SharedHandle<Piece> getMissingPiece
(const SharedHandle<Peer>& peer, const std::deque<size_t>& excludedIndexes);
virtual SharedHandle<Piece> getMissingFastPiece
(const SharedHandle<Peer>& peer, const std::deque<size_t>& excludedIndexes);
virtual SharedHandle<Piece> getMissingPiece();
virtual SharedHandle<Piece> getMissingPiece(size_t index);

View File

@ -67,6 +67,14 @@ public:
virtual SharedHandle<Piece>
getMissingPiece(const SharedHandle<Peer>& peer) = 0;
/**
* Same as getMissingPiece(const SharedHandle<Peer>& peer), but the indexes in
* excludedIndexes are excluded.
*/
virtual SharedHandle<Piece> getMissingPiece
(const SharedHandle<Peer>& peer,
const std::deque<size_t>& excludedIndexes) = 0;
/**
* Returns a piece that the peer has but localhost doesn't.
* Only pieces that declared as "fast" are returned.
@ -76,6 +84,14 @@ public:
*/
virtual SharedHandle<Piece>
getMissingFastPiece(const SharedHandle<Peer>& peer) = 0;
/**
* Same as getMissingFastPiece(const SharedHandle<Peer>& peer), but the
* indexes in excludedIndexes are excluded.
*/
virtual SharedHandle<Piece> getMissingFastPiece
(const SharedHandle<Peer>& peer,
const std::deque<size_t>& excludedIndexes) = 0;
/**
* Returns a missing piece if available. Otherwise returns 0;

View File

@ -79,11 +79,23 @@ SharedHandle<Piece> UnknownLengthPieceStorage::getMissingPiece(const SharedHandl
abort();
}
SharedHandle<Piece> UnknownLengthPieceStorage::getMissingPiece
(const SharedHandle<Peer>& peer, const std::deque<size_t>& excludedIndexes)
{
abort();
}
SharedHandle<Piece> UnknownLengthPieceStorage::getMissingFastPiece(const SharedHandle<Peer>& peer)
{
abort();
}
SharedHandle<Piece> UnknownLengthPieceStorage::getMissingFastPiece
(const SharedHandle<Peer>& peer, const std::deque<size_t>& excludedIndexes)
{
abort();
}
PieceHandle UnknownLengthPieceStorage::getMissingPiece()
{
if(_downloadFinished) {

View File

@ -79,6 +79,9 @@ public:
*/
virtual SharedHandle<Piece> getMissingPiece(const SharedHandle<Peer>& peer);
virtual SharedHandle<Piece> getMissingPiece
(const SharedHandle<Peer>& peer, const std::deque<size_t>& excludedIndexes);
/**
* Returns a piece that the peer has but localhost doesn't.
* Only pieces that declared as "fast" are returned.
@ -88,6 +91,9 @@ public:
*/
virtual SharedHandle<Piece> getMissingFastPiece(const SharedHandle<Peer>& peer);
virtual SharedHandle<Piece> getMissingFastPiece
(const SharedHandle<Peer>& peer, const std::deque<size_t>& excludedIndexes);
/**
* Returns a missing piece if available. Otherwise returns 0;
*/

View File

@ -25,6 +25,7 @@ class DefaultBtRequestFactoryTest:public CppUnit::TestFixture {
CPPUNIT_TEST(testCreateRequestMessages);
CPPUNIT_TEST(testCreateRequestMessages_onEndGame);
CPPUNIT_TEST(testRemoveTargetPiece);
CPPUNIT_TEST(testGetTargetPieceIndexes);
CPPUNIT_TEST_SUITE_END();
private:
SharedHandle<DefaultBtRequestFactory> btRequestFactory;
@ -35,6 +36,7 @@ public:
void testCreateRequestMessages();
void testCreateRequestMessages_onEndGame();
void testRemoveTargetPiece();
void testGetTargetPieceIndexes();
class MockBtRequestMessage : public MockBtMessage {
public:
@ -234,4 +236,22 @@ void DefaultBtRequestFactoryTest::testRemoveTargetPiece() {
piece1) == btRequestFactory->getTargetPieces().end());
}
void DefaultBtRequestFactoryTest::testGetTargetPieceIndexes()
{
SharedHandle<Piece> piece1(new Piece(1, btContext->getPieceLength()));
SharedHandle<Piece> piece3(new Piece(3, btContext->getPieceLength()));
SharedHandle<Piece> piece5(new Piece(5, btContext->getPieceLength()));
btRequestFactory->addTargetPiece(piece3);
btRequestFactory->addTargetPiece(piece1);
btRequestFactory->addTargetPiece(piece5);
std::deque<size_t> indexes;
btRequestFactory->getTargetPieceIndexes(indexes);
CPPUNIT_ASSERT_EQUAL((size_t)3, indexes.size());
CPPUNIT_ASSERT_EQUAL((size_t)3, indexes[0]);
CPPUNIT_ASSERT_EQUAL((size_t)1, indexes[1]);
CPPUNIT_ASSERT_EQUAL((size_t)5, indexes[2]);
}
} // namespace aria2

View File

@ -18,7 +18,9 @@ class DefaultPieceStorageTest:public CppUnit::TestFixture {
CPPUNIT_TEST_SUITE(DefaultPieceStorageTest);
CPPUNIT_TEST(testGetTotalLength);
CPPUNIT_TEST(testGetMissingPiece);
CPPUNIT_TEST(testGetMissingPiece_excludedIndexes);
CPPUNIT_TEST(testGetMissingFastPiece);
CPPUNIT_TEST(testGetMissingFastPiece_excludedIndexes);
CPPUNIT_TEST(testHasMissingPiece);
CPPUNIT_TEST(testCompletePiece);
CPPUNIT_TEST(testGetPiece);
@ -56,7 +58,9 @@ public:
void testGetTotalLength();
void testGetMissingPiece();
void testGetMissingPiece_excludedIndexes();
void testGetMissingFastPiece();
void testGetMissingFastPiece_excludedIndexes();
void testHasMissingPiece();
void testCompletePiece();
void testGetPiece();
@ -94,6 +98,28 @@ void DefaultPieceStorageTest::testGetMissingPiece() {
CPPUNIT_ASSERT(piece.isNull());
}
void DefaultPieceStorageTest::testGetMissingPiece_excludedIndexes()
{
DefaultPieceStorage pss(btContext, option, false);
pss.setEndGamePieceNum(0);
peer->setAllBitfield();
std::deque<size_t> excludedIndexes;
excludedIndexes.push_back(1);
SharedHandle<Piece> piece = pss.getMissingPiece(peer, excludedIndexes);
CPPUNIT_ASSERT_EQUAL(std::string("piece: index=0, length=128"),
piece->toString());
piece = pss.getMissingPiece(peer, excludedIndexes);
CPPUNIT_ASSERT_EQUAL(std::string("piece: index=2, length=128"),
piece->toString());
piece = pss.getMissingPiece(peer, excludedIndexes);
CPPUNIT_ASSERT(piece.isNull());
}
void DefaultPieceStorageTest::testGetMissingFastPiece() {
DefaultPieceStorage pss(btContext, option, false);
pss.setEndGamePieceNum(0);
@ -105,6 +131,28 @@ void DefaultPieceStorageTest::testGetMissingFastPiece() {
SharedHandle<Piece> piece = pss.getMissingFastPiece(peer);
CPPUNIT_ASSERT_EQUAL(std::string("piece: index=2, length=128"),
piece->toString());
CPPUNIT_ASSERT(pss.getMissingFastPiece(peer).isNull());
}
void DefaultPieceStorageTest::testGetMissingFastPiece_excludedIndexes()
{
DefaultPieceStorage pss(btContext, option, false);
pss.setEndGamePieceNum(0);
peer->setAllBitfield();
peer->setFastExtensionEnabled(true);
peer->addPeerAllowedIndex(1);
peer->addPeerAllowedIndex(2);
std::deque<size_t> excludedIndexes;
excludedIndexes.push_back(2);
SharedHandle<Piece> piece = pss.getMissingFastPiece(peer, excludedIndexes);
CPPUNIT_ASSERT_EQUAL(std::string("piece: index=1, length=128"),
piece->toString());
CPPUNIT_ASSERT(pss.getMissingFastPiece(peer, excludedIndexes).isNull());
}
void DefaultPieceStorageTest::testHasMissingPiece() {

View File

@ -28,6 +28,8 @@ public:
virtual void createRequestMessagesOnEndGame
(std::deque<SharedHandle<BtMessage> >& requests, size_t max) {}
virtual void getTargetPieceIndexes(std::deque<size_t>& indexes) const {}
};
} // namespace aria2

View File

@ -42,10 +42,22 @@ public:
return SharedHandle<Piece>(new Piece());
}
virtual SharedHandle<Piece> getMissingPiece
(const SharedHandle<Peer>& peer, const std::deque<size_t>& excludedIndexes)
{
return SharedHandle<Piece>(new Piece());
}
virtual SharedHandle<Piece> getMissingFastPiece(const SharedHandle<Peer>& peer) {
return SharedHandle<Piece>(new Piece());
}
virtual SharedHandle<Piece> getMissingFastPiece
(const SharedHandle<Peer>& peer, const std::deque<size_t>& excludedIndexes)
{
return SharedHandle<Piece>(new Piece());
}
virtual SharedHandle<Piece> getMissingPiece()
{
return SharedHandle<Piece>(new Piece());