2010-08-29 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>

Added a sets of overloaded functions for
	PieceStorage::getMissingPiece() and getMissingFastPiece() to get
	multiple pieces more efficiently.
	* src/DefaultBtInteractive.cc
	* src/DefaultPieceStorage.cc
	* src/DefaultPieceStorage.h
	* src/PieceStorage.h
	* src/UnknownLengthPieceStorage.cc
	* src/UnknownLengthPieceStorage.h
	* test/DefaultPieceStorageTest.cc
	* test/MockPieceStorage.h
pull/1/head
Tatsuhiro Tsujikawa 2010-08-29 08:53:19 +00:00
parent b49081340d
commit e997903e5d
9 changed files with 351 additions and 104 deletions

View File

@ -1,3 +1,17 @@
2010-08-29 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
Added a sets of overloaded functions for
PieceStorage::getMissingPiece() and getMissingFastPiece() to get
multiple pieces more efficiently.
* src/DefaultBtInteractive.cc
* src/DefaultPieceStorage.cc
* src/DefaultPieceStorage.h
* src/PieceStorage.h
* src/UnknownLengthPieceStorage.cc
* src/UnknownLengthPieceStorage.h
* test/DefaultPieceStorageTest.cc
* test/MockPieceStorage.h
2010-08-28 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
Changed signature of util::executeHook().

View File

@ -355,42 +355,41 @@ void DefaultBtInteractive::decideInterest() {
void DefaultBtInteractive::fillPiece(size_t maxMissingBlock) {
if(pieceStorage_->hasMissingPiece(peer_)) {
size_t numMissingBlock = btRequestFactory_->countMissingBlock();
if(numMissingBlock >= maxMissingBlock) {
return;
}
size_t diffMissingBlock = maxMissingBlock-numMissingBlock;
std::vector<SharedHandle<Piece> > pieces;
if(peer_->peerChoking()) {
if(peer_->isFastExtensionEnabled()) {
std::vector<size_t> excludedIndexes;
excludedIndexes.reserve(btRequestFactory_->countTargetPiece());
btRequestFactory_->getTargetPieceIndexes(excludedIndexes);
while(numMissingBlock < maxMissingBlock) {
SharedHandle<Piece> piece =
pieceStorage_->getMissingFastPiece(peer_, excludedIndexes);
if(piece.isNull()) {
break;
} else {
btRequestFactory_->addTargetPiece(piece);
numMissingBlock += piece->countMissingBlock();
excludedIndexes.push_back(piece->getIndex());
}
if(pieceStorage_->isEndGame()) {
std::vector<size_t> excludedIndexes;
excludedIndexes.reserve(btRequestFactory_->countTargetPiece());
btRequestFactory_->getTargetPieceIndexes(excludedIndexes);
pieceStorage_->getMissingFastPiece
(pieces, diffMissingBlock, peer_, excludedIndexes);
} else {
pieces.reserve(diffMissingBlock);
pieceStorage_->getMissingFastPiece(pieces, diffMissingBlock, peer_);
}
}
} else {
std::vector<size_t> excludedIndexes;
excludedIndexes.reserve(btRequestFactory_->countTargetPiece());
btRequestFactory_->getTargetPieceIndexes(excludedIndexes);
while(numMissingBlock < maxMissingBlock) {
SharedHandle<Piece> piece =
pieceStorage_->getMissingPiece(peer_, excludedIndexes);
if(piece.isNull()) {
break;
} else {
btRequestFactory_->addTargetPiece(piece);
numMissingBlock += piece->countMissingBlock();
excludedIndexes.push_back(piece->getIndex());
}
if(pieceStorage_->isEndGame()) {
std::vector<size_t> excludedIndexes;
excludedIndexes.reserve(btRequestFactory_->countTargetPiece());
btRequestFactory_->getTargetPieceIndexes(excludedIndexes);
pieceStorage_->getMissingPiece
(pieces, diffMissingBlock, peer_, excludedIndexes);
} else {
pieces.reserve(diffMissingBlock);
pieceStorage_->getMissingPiece(pieces, diffMissingBlock, peer_);
}
}
for(std::vector<SharedHandle<Piece> >::const_iterator i =
pieces.begin(), eoi = pieces.end(); i != eoi; ++i) {
btRequestFactory_->addTargetPiece(*i);
}
}
}

View File

@ -59,6 +59,7 @@
#include "array_fun.h"
#include "PieceStatMan.h"
#include "wallclock.h"
#include "bitfield.h"
#ifdef ENABLE_BITTORRENT
# include "bittorrent_helper.h"
#endif // ENABLE_BITTORRENT
@ -83,29 +84,6 @@ DefaultPieceStorage::~DefaultPieceStorage() {
delete bitfieldMan_;
}
bool DefaultPieceStorage::getMissingPieceIndex(size_t& index,
const unsigned char* bitfield,
size_t length)
{
const size_t mislen = bitfieldMan_->getBitfieldLength();
array_ptr<unsigned char> misbitfield(new unsigned char[mislen]);
bool r;
if(isEndGame()) {
r = bitfieldMan_->getAllMissingIndexes(misbitfield, mislen,
bitfield, length);
} else {
r = bitfieldMan_->getAllMissingUnusedIndexes(misbitfield, mislen,
bitfield, length);
}
if(r) {
// We assume indexes is sorted using comparator less.
return
pieceSelector_->select(index, misbitfield,bitfieldMan_->countBlock());
} else {
return false;
}
}
SharedHandle<Piece> DefaultPieceStorage::checkOutPiece(size_t index)
{
bitfieldMan_->setUseBit(index);
@ -172,23 +150,6 @@ SharedHandle<Piece> DefaultPieceStorage::findUsedPiece(size_t index) const
}
}
SharedHandle<Piece> DefaultPieceStorage::getMissingPiece
(const unsigned char* bitfield, size_t length)
{
size_t index;
if(getMissingPieceIndex(index, bitfield, length)) {
return checkOutPiece(index);
} else {
return SharedHandle<Piece>();
}
}
SharedHandle<Piece> DefaultPieceStorage::getMissingPiece
(const BitfieldMan& bitfield)
{
return getMissingPiece(bitfield.getBitfield(), bitfield.getBitfieldLength());
}
#ifdef ENABLE_BITTORRENT
bool DefaultPieceStorage::hasMissingPiece(const SharedHandle<Peer>& peer)
@ -197,10 +158,58 @@ bool DefaultPieceStorage::hasMissingPiece(const SharedHandle<Peer>& peer)
peer->getBitfieldLength());
}
SharedHandle<Piece>
DefaultPieceStorage::getMissingPiece(const SharedHandle<Peer>& peer)
void DefaultPieceStorage::getMissingPiece
(std::vector<SharedHandle<Piece> >& pieces,
size_t minMissingBlocks,
const unsigned char* bitfield,
size_t length)
{
return getMissingPiece(peer->getBitfield(), peer->getBitfieldLength());
const size_t mislen = bitfieldMan_->getBitfieldLength();
array_ptr<unsigned char> misbitfield(new unsigned char[mislen]);
size_t blocks = bitfieldMan_->countBlock();
size_t misBlock = 0;
if(isEndGame()) {
bool r = bitfieldMan_->getAllMissingIndexes
(misbitfield, mislen, bitfield, length);
if(!r) {
return;
}
std::vector<size_t> indexes;
for(size_t i = 0; i < blocks; ++i) {
if(bitfield::test(misbitfield, blocks, i)) {
indexes.push_back(i);
}
}
std::random_shuffle(indexes.begin(), indexes.end());
for(std::vector<size_t>::const_iterator i = indexes.begin(),
eoi = indexes.end(); i != eoi && misBlock < minMissingBlocks; ++i) {
pieces.push_back(checkOutPiece(*i));
misBlock += pieces.back()->countMissingBlock();
}
} else {
bool r = bitfieldMan_->getAllMissingUnusedIndexes
(misbitfield, mislen, bitfield, length);
if(!r) {
return;
}
while(misBlock < minMissingBlocks) {
size_t index;
if(pieceSelector_->select(index, misbitfield, blocks)) {
pieces.push_back(checkOutPiece(index));
bitfield::flipBit(misbitfield, blocks, index);
misBlock += pieces.back()->countMissingBlock();
} else {
break;
}
}
}
}
static void unsetExcludedIndexes(BitfieldMan& bitfield,
const std::vector<size_t>& excludedIndexes)
{
std::for_each(excludedIndexes.begin(), excludedIndexes.end(),
std::bind1st(std::mem_fun(&BitfieldMan::unsetBit), &bitfield));
}
void DefaultPieceStorage::createFastIndexBitfield
@ -215,47 +224,107 @@ void DefaultPieceStorage::createFastIndexBitfield
}
}
SharedHandle<Piece> DefaultPieceStorage::getMissingFastPiece
(const SharedHandle<Peer>& peer)
void DefaultPieceStorage::getMissingPiece
(std::vector<SharedHandle<Piece> >& pieces,
size_t minMissingBlocks,
const SharedHandle<Peer>& peer)
{
if(peer->isFastExtensionEnabled() && peer->countPeerAllowedIndexSet() > 0) {
BitfieldMan tempBitfield(bitfieldMan_->getBlockLength(),
bitfieldMan_->getTotalLength());
createFastIndexBitfield(tempBitfield, peer);
return getMissingPiece(tempBitfield);
} else {
return SharedHandle<Piece>();
}
getMissingPiece(pieces, minMissingBlocks,
peer->getBitfield(), peer->getBitfieldLength());
}
static void unsetExcludedIndexes(BitfieldMan& bitfield,
const std::vector<size_t>& excludedIndexes)
{
std::for_each(excludedIndexes.begin(), excludedIndexes.end(),
std::bind1st(std::mem_fun(&BitfieldMan::unsetBit), &bitfield));
}
SharedHandle<Piece> DefaultPieceStorage::getMissingPiece
(const SharedHandle<Peer>& peer, const std::vector<size_t>& excludedIndexes)
void DefaultPieceStorage::getMissingPiece
(std::vector<SharedHandle<Piece> >& pieces,
size_t minMissingBlocks,
const SharedHandle<Peer>& peer,
const std::vector<size_t>& excludedIndexes)
{
BitfieldMan tempBitfield(bitfieldMan_->getBlockLength(),
bitfieldMan_->getTotalLength());
tempBitfield.setBitfield(peer->getBitfield(), peer->getBitfieldLength());
unsetExcludedIndexes(tempBitfield, excludedIndexes);
return getMissingPiece(tempBitfield);
getMissingPiece(pieces, minMissingBlocks,
tempBitfield.getBitfield(), tempBitfield.getBitfieldLength());
}
SharedHandle<Piece> DefaultPieceStorage::getMissingFastPiece
(const SharedHandle<Peer>& peer, const std::vector<size_t>& excludedIndexes)
void DefaultPieceStorage::getMissingFastPiece
(std::vector<SharedHandle<Piece> >& pieces,
size_t minMissingBlocks,
const SharedHandle<Peer>& peer)
{
if(peer->isFastExtensionEnabled() && peer->countPeerAllowedIndexSet() > 0) {
BitfieldMan tempBitfield(bitfieldMan_->getBlockLength(),
bitfieldMan_->getTotalLength());
createFastIndexBitfield(tempBitfield, peer);
getMissingPiece(pieces, minMissingBlocks,
tempBitfield.getBitfield(),
tempBitfield.getBitfieldLength());
}
}
void DefaultPieceStorage::getMissingFastPiece
(std::vector<SharedHandle<Piece> >& pieces,
size_t minMissingBlocks,
const SharedHandle<Peer>& peer,
const std::vector<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 {
getMissingPiece(pieces, minMissingBlocks,
tempBitfield.getBitfield(),
tempBitfield.getBitfieldLength());
}
}
SharedHandle<Piece>
DefaultPieceStorage::getMissingPiece(const SharedHandle<Peer>& peer)
{
std::vector<SharedHandle<Piece> > pieces;
getMissingPiece(pieces, 1, peer);
if(pieces.empty()) {
return SharedHandle<Piece>();
} else {
return pieces.front();
}
}
SharedHandle<Piece> DefaultPieceStorage::getMissingPiece
(const SharedHandle<Peer>& peer, const std::vector<size_t>& excludedIndexes)
{
std::vector<SharedHandle<Piece> > pieces;
getMissingPiece(pieces, 1, peer, excludedIndexes);
if(pieces.empty()) {
return SharedHandle<Piece>();
} else {
return pieces.front();
}
}
SharedHandle<Piece> DefaultPieceStorage::getMissingFastPiece
(const SharedHandle<Peer>& peer)
{
std::vector<SharedHandle<Piece> > pieces;
getMissingFastPiece(pieces, 1, peer);
if(pieces.empty()) {
return SharedHandle<Piece>();
} else {
return pieces.front();
}
}
SharedHandle<Piece> DefaultPieceStorage::getMissingFastPiece
(const SharedHandle<Peer>& peer, const std::vector<size_t>& excludedIndexes)
{
std::vector<SharedHandle<Piece> > pieces;
getMissingFastPiece(pieces, 1, peer, excludedIndexes);
if(pieces.empty()) {
return SharedHandle<Piece>();
} else {
return pieces.front();
}
}

View File

@ -88,15 +88,13 @@ private:
SharedHandle<PieceSelector> pieceSelector_;
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);
#ifdef ENABLE_BITTORRENT
void getMissingPiece
(std::vector<SharedHandle<Piece> >& pieces,
size_t minMissingBlocks,
const unsigned char* bitfield,
size_t length);
void createFastIndexBitfield(BitfieldMan& bitfield,
const SharedHandle<Peer>& peer);
#endif // ENABLE_BITTORRENT
@ -123,6 +121,28 @@ public:
virtual bool hasMissingPiece(const SharedHandle<Peer>& peer);
virtual void getMissingPiece
(std::vector<SharedHandle<Piece> >& pieces,
size_t minMissingBlocks,
const SharedHandle<Peer>& peer,
const std::vector<size_t>& excludedIndexes);
virtual void getMissingPiece
(std::vector<SharedHandle<Piece> >& pieces,
size_t minMissingBlocks,
const SharedHandle<Peer>& peer);
virtual void getMissingFastPiece
(std::vector<SharedHandle<Piece> >& pieces,
size_t minMissingBlocks,
const SharedHandle<Peer>& peer,
const std::vector<size_t>& excludedIndexes);
virtual void getMissingFastPiece
(std::vector<SharedHandle<Piece> >& pieces,
size_t minMissingBlocks,
const SharedHandle<Peer>& peer);
virtual SharedHandle<Piece> getMissingPiece(const SharedHandle<Peer>& peer);
virtual SharedHandle<Piece> getMissingFastPiece

View File

@ -63,6 +63,28 @@ public:
*/
virtual bool hasMissingPiece(const SharedHandle<Peer>& peer) = 0;
virtual void getMissingPiece
(std::vector<SharedHandle<Piece> >& pieces,
size_t minMissingBlocks,
const SharedHandle<Peer>& peer,
const std::vector<size_t>& excludedIndexes) = 0;
virtual void getMissingPiece
(std::vector<SharedHandle<Piece> >& pieces,
size_t minMissingBlocks,
const SharedHandle<Peer>& peer) = 0;
virtual void getMissingFastPiece
(std::vector<SharedHandle<Piece> >& pieces,
size_t minMissingBlocks,
const SharedHandle<Peer>& peer,
const std::vector<size_t>& excludedIndexes) = 0;
virtual void getMissingFastPiece
(std::vector<SharedHandle<Piece> >& pieces,
size_t minMissingBlocks,
const SharedHandle<Peer>& peer) = 0;
/**
* Returns a piece that the peer has but localhost doesn't.
* The piece will be marked "used" status in order to prevent other command

View File

@ -78,6 +78,40 @@ bool UnknownLengthPieceStorage::hasMissingPiece(const SharedHandle<Peer>& peer)
abort();
}
void UnknownLengthPieceStorage::getMissingPiece
(std::vector<SharedHandle<Piece> >& pieces,
size_t minMissingBlocks,
const SharedHandle<Peer>& peer,
const std::vector<size_t>& excludedIndexes)
{
abort();
}
void UnknownLengthPieceStorage::getMissingPiece
(std::vector<SharedHandle<Piece> >& pieces,
size_t minMissingBlocks,
const SharedHandle<Peer>& peer)
{
abort();
}
void UnknownLengthPieceStorage::getMissingFastPiece
(std::vector<SharedHandle<Piece> >& pieces,
size_t minMissingBlocks,
const SharedHandle<Peer>& peer,
const std::vector<size_t>& excludedIndexes)
{
abort();
}
void UnknownLengthPieceStorage::getMissingFastPiece
(std::vector<SharedHandle<Piece> >& pieces,
size_t minMissingBlocks,
const SharedHandle<Peer>& peer)
{
abort();
}
SharedHandle<Piece> UnknownLengthPieceStorage::getMissingPiece(const SharedHandle<Peer>& peer)
{
abort();

View File

@ -73,6 +73,28 @@ public:
*/
virtual bool hasMissingPiece(const SharedHandle<Peer>& peer);
virtual void getMissingPiece
(std::vector<SharedHandle<Piece> >& pieces,
size_t minMissingBlocks,
const SharedHandle<Peer>& peer,
const std::vector<size_t>& excludedIndexes);
virtual void getMissingPiece
(std::vector<SharedHandle<Piece> >& pieces,
size_t minMissingBlocks,
const SharedHandle<Peer>& peer);
virtual void getMissingFastPiece
(std::vector<SharedHandle<Piece> >& pieces,
size_t minMissingBlocks,
const SharedHandle<Peer>& peer,
const std::vector<size_t>& excludedIndexes);
virtual void getMissingFastPiece
(std::vector<SharedHandle<Piece> >& pieces,
size_t minMissingBlocks,
const SharedHandle<Peer>& peer);
/**
* Returns a piece that the peer has but localhost doesn't.
* The piece will be marked "used" status in order to prevent other command

View File

@ -12,6 +12,9 @@
#include "InOrderPieceSelector.h"
#include "DownloadContext.h"
#include "bittorrent_helper.h"
#include "DiskAdaptor.h"
#include "DiskWriterFactory.h"
#include "PieceStatMan.h"
namespace aria2 {
@ -20,7 +23,9 @@ class DefaultPieceStorageTest:public CppUnit::TestFixture {
CPPUNIT_TEST_SUITE(DefaultPieceStorageTest);
CPPUNIT_TEST(testGetTotalLength);
CPPUNIT_TEST(testGetMissingPiece);
CPPUNIT_TEST(testGetMissingPiece_many);
CPPUNIT_TEST(testGetMissingPiece_excludedIndexes);
CPPUNIT_TEST(testGetMissingPiece_manyWithExcludedIndexes);
CPPUNIT_TEST(testGetMissingFastPiece);
CPPUNIT_TEST(testGetMissingFastPiece_excludedIndexes);
CPPUNIT_TEST(testHasMissingPiece);
@ -57,7 +62,9 @@ public:
void testGetTotalLength();
void testGetMissingPiece();
void testGetMissingPiece_many();
void testGetMissingPiece_excludedIndexes();
void testGetMissingPiece_manyWithExcludedIndexes();
void testGetMissingFastPiece();
void testGetMissingFastPiece_excludedIndexes();
void testHasMissingPiece();
@ -83,8 +90,6 @@ void DefaultPieceStorageTest::testGetTotalLength() {
void DefaultPieceStorageTest::testGetMissingPiece() {
DefaultPieceStorage pss(dctx_, option);
pss.setPieceSelector(pieceSelector_);
pss.setEndGamePieceNum(0);
peer->setAllBitfield();
SharedHandle<Piece> piece = pss.getMissingPiece(peer);
@ -100,6 +105,24 @@ void DefaultPieceStorageTest::testGetMissingPiece() {
CPPUNIT_ASSERT(piece.isNull());
}
void DefaultPieceStorageTest::testGetMissingPiece_many() {
DefaultPieceStorage pss(dctx_, option);
pss.setPieceSelector(pieceSelector_);
peer->setAllBitfield();
std::vector<SharedHandle<Piece> > pieces;
pss.getMissingPiece(pieces, 2, peer);
CPPUNIT_ASSERT_EQUAL((size_t)2, pieces.size());
CPPUNIT_ASSERT_EQUAL(std::string("piece: index=0, length=128"),
pieces[0]->toString());
CPPUNIT_ASSERT_EQUAL(std::string("piece: index=1, length=128"),
pieces[1]->toString());
pieces.clear();
pss.getMissingPiece(pieces, 2, peer);
CPPUNIT_ASSERT_EQUAL((size_t)1, pieces.size());
CPPUNIT_ASSERT_EQUAL(std::string("piece: index=2, length=128"),
pieces[0]->toString());
}
void DefaultPieceStorageTest::testGetMissingPiece_excludedIndexes()
{
DefaultPieceStorage pss(dctx_, option);
@ -123,6 +146,24 @@ void DefaultPieceStorageTest::testGetMissingPiece_excludedIndexes()
CPPUNIT_ASSERT(piece.isNull());
}
void DefaultPieceStorageTest::testGetMissingPiece_manyWithExcludedIndexes() {
DefaultPieceStorage pss(dctx_, option);
pss.setPieceSelector(pieceSelector_);
peer->setAllBitfield();
std::vector<size_t> excludedIndexes;
excludedIndexes.push_back(1);
std::vector<SharedHandle<Piece> > pieces;
pss.getMissingPiece(pieces, 2, peer, excludedIndexes);
CPPUNIT_ASSERT_EQUAL((size_t)2, pieces.size());
CPPUNIT_ASSERT_EQUAL(std::string("piece: index=0, length=128"),
pieces[0]->toString());
CPPUNIT_ASSERT_EQUAL(std::string("piece: index=2, length=128"),
pieces[1]->toString());
pieces.clear();
pss.getMissingPiece(pieces, 2, peer, excludedIndexes);
CPPUNIT_ASSERT(pieces.empty());
}
void DefaultPieceStorageTest::testGetMissingFastPiece() {
DefaultPieceStorage pss(dctx_, option);
pss.setPieceSelector(pieceSelector_);

View File

@ -48,6 +48,32 @@ public:
return SharedHandle<Piece>(new Piece());
}
virtual void getMissingPiece
(std::vector<SharedHandle<Piece> >& pieces,
size_t minMissingBlocks,
const SharedHandle<Peer>& peer,
const std::vector<size_t>& excludedIndexes)
{}
virtual void getMissingPiece
(std::vector<SharedHandle<Piece> >& pieces,
size_t minMissingBlocks,
const SharedHandle<Peer>& peer)
{}
virtual void getMissingFastPiece
(std::vector<SharedHandle<Piece> >& pieces,
size_t minMissingBlocks,
const SharedHandle<Peer>& peer,
const std::vector<size_t>& excludedIndexes)
{}
virtual void getMissingFastPiece
(std::vector<SharedHandle<Piece> >& pieces,
size_t minMissingBlocks,
const SharedHandle<Peer>& peer)
{}
virtual SharedHandle<Piece> getMissingPiece
(const SharedHandle<Peer>& peer, const std::vector<size_t>& excludedIndexes)
{