2008-03-07 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>

Removed subPiece related functions.
	* src/Piece.{h, cc} : Also rewritten getCompletedLength().
	* src/DefaultPieceStorage.{h, cc}
	* test/PieceTest.cc
	* test/DefaultPieceStorageTest.cc
pull/1/head
Tatsuhiro Tsujikawa 2008-03-07 12:44:20 +00:00
parent fc0fa4203a
commit e57a070a3f
7 changed files with 18 additions and 278 deletions

View File

@ -1,3 +1,11 @@
2008-03-07 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
Removed subPiece related functions.
* src/Piece.{h, cc} : Also rewritten getCompletedLength().
* src/DefaultPieceStorage.{h, cc}
* test/PieceTest.cc
* test/DefaultPieceStorageTest.cc
2008-03-07 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
Use unsigned char for data store.

View File

@ -204,36 +204,6 @@ PieceHandle DefaultPieceStorage::getMissingPiece()
return checkOutPiece(bitfieldMan->getSparseMissingUnusedIndex());
}
PieceHandle DefaultPieceStorage::getMissingPiece(const FileEntryHandle& fileEntry)
{
BitfieldMan temp(*bitfieldMan);
temp.clearFilter();
temp.addFilter(fileEntry->getOffset(), fileEntry->getLength());
temp.enableFilter();
int32_t firstPieceIndex = START_INDEX(fileEntry->getOffset(), downloadContext->getPieceLength());
int32_t endPieceIndex = END_INDEX(fileEntry->getOffset(), fileEntry->getLength(), downloadContext->getPieceLength());
if(!temp.isBitSet(firstPieceIndex) && !temp.isUseBitSet(firstPieceIndex)) {
PieceHandle piece = findUsedPiece(firstPieceIndex);
if(!piece.isNull()) {
if(piece->isRangeComplete(fileEntry->getOffset()-firstPieceIndex*downloadContext->getPieceLength(),
fileEntry->getLength() > downloadContext->getPieceLength() ?
downloadContext->getPieceLength():fileEntry->getLength())) {
temp.setBit(firstPieceIndex);
}
}
}
if(firstPieceIndex != endPieceIndex && !temp.isBitSet(endPieceIndex) && !temp.isUseBitSet(endPieceIndex)) {
PieceHandle piece = findUsedPiece(endPieceIndex);
if(!piece.isNull()) {
if(piece->isRangeComplete(0, fileEntry->getOffset()+fileEntry->getLength()-endPieceIndex*downloadContext->getPieceLength())) {
temp.setBit(endPieceIndex);
}
}
}
return checkOutPiece(temp.getSparseMissingUnusedIndex());
}
PieceHandle DefaultPieceStorage::getMissingPiece(int32_t index)
{
if(hasPiece(index) || isPieceUsed(index)) {

View File

@ -100,7 +100,6 @@ public:
virtual SharedHandle<Piece> getMissingFastPiece(const SharedHandle<Peer>& peer);
virtual SharedHandle<Piece> getMissingPiece();
virtual SharedHandle<Piece> getMissingPiece(const SharedHandle<FileEntry>& fileEntry);
virtual SharedHandle<Piece> getMissingPiece(int32_t index);

View File

@ -85,7 +85,6 @@ bool Piece::operator==(const Piece& piece) const
void Piece::completeBlock(int32_t blockIndex) {
bitfield->setBit(blockIndex);
bitfield->unsetUseBit(blockIndex);
removeSubPiece(blockIndex);
}
void Piece::clearAllBlock() {
@ -189,97 +188,9 @@ void Piece::setBitfield(const unsigned char* bitfield, int32_t len)
this->bitfield->setBitfield(bitfield, len);
}
void Piece::addSubPiece(const PieceHandle& subPiece)
{
_subPieces.push_back(subPiece);
}
PieceHandle Piece::getSubPiece(int32_t blockIndex)
{
Pieces::iterator itr = getSubPieceIterator(blockIndex);
if(itr == _subPieces.end()) {
return 0;
} else {
return *itr;
}
}
void Piece::removeSubPiece(int32_t blockIndex)
{
Pieces::iterator itr = getSubPieceIterator(blockIndex);
if(itr != _subPieces.end()) {
_subPieces.erase(itr);
}
}
Pieces::iterator Piece::getSubPieceIterator(int32_t blockIndex)
{
for(Pieces::iterator itr = _subPieces.begin(); itr != _subPieces.end(); ++itr) {
if((*itr)->getIndex() == blockIndex) {
return itr;
}
}
return _subPieces.end();
}
bool Piece::isRangeComplete(int32_t offset, int32_t length)
{
int32_t startIndex = START_INDEX(offset, _blockLength);
int32_t endIndex = END_INDEX(offset, length, _blockLength);
if(countBlock() <= endIndex) {
endIndex = countBlock()-1;
}
if(startIndex+1 < endIndex) {
if(!bitfield->isBitRangeSet(startIndex+1, endIndex-1)) {
return false;
}
}
if(startIndex == endIndex) {
if(hasBlock(startIndex)) {
return true;
}
PieceHandle subPiece = getSubPiece(startIndex);
if(subPiece.isNull()) {
return false;
}
return subPiece->isRangeComplete(offset, length);
} else {
if(!hasBlock(startIndex)) {
PieceHandle subPiece = getSubPiece(startIndex);
if(subPiece.isNull()) {
return false;
}
if(!subPiece->isRangeComplete(offset-startIndex*_blockLength, length)) {
return false;
}
}
if(!hasBlock(endIndex)) {
PieceHandle subPiece = getSubPiece(endIndex);
if(subPiece.isNull()) {
return false;
}
if(!subPiece->isRangeComplete(0, offset+length-endIndex*_blockLength)) {
return false;
}
}
return true;
}
}
int32_t Piece::getCompletedLength()
{
int32_t length = 0;
for(int32_t i = 0; i < countBlock(); ++i) {
if(hasBlock(i)) {
length += getBlockLength(i);
} else {
PieceHandle subPiece = getSubPiece(i);
if(!subPiece.isNull()) {
length += subPiece->getCompletedLength();
}
}
}
return length;
return bitfield->getCompletedLength();
}
} // namespace aria2

View File

@ -51,8 +51,6 @@ private:
int32_t length;
int32_t _blockLength;
BitfieldMan* bitfield;
std::deque<SharedHandle<Piece> > _subPieces;
public:
static const int32_t BLOCK_LENGTH = 16*1024;
@ -113,18 +111,7 @@ public:
bool isBlockUsed(int32_t index) const;
void addSubPiece(const SharedHandle<Piece>& subPiece);
SharedHandle<Piece> getSubPiece(int32_t blockIndex);
void removeSubPiece(int32_t blockIndex);
std::deque<SharedHandle<Piece> >::iterator
getSubPieceIterator(int32_t blockIndex);
bool isRangeComplete(int32_t offset, int32_t length);
// Calculates completed length, taking into account SubPieces
// Calculates completed length
int32_t getCompletedLength();
/**

View File

@ -24,7 +24,6 @@ class DefaultPieceStorageTest:public CppUnit::TestFixture {
CPPUNIT_TEST(testGetPiece);
CPPUNIT_TEST(testGetPieceInUsedPieces);
CPPUNIT_TEST(testGetPieceCompletedPiece);
CPPUNIT_TEST(testGetMissingPiece_fileEntry);
CPPUNIT_TEST(testCancelPiece);
CPPUNIT_TEST(testMarkPiecesDone);
CPPUNIT_TEST_SUITE_END();
@ -62,7 +61,6 @@ public:
void testGetPiece();
void testGetPieceInUsedPieces();
void testGetPieceCompletedPiece();
void testGetMissingPiece_fileEntry();
void testCancelPiece();
void testMarkPiecesDone();
};
@ -172,79 +170,10 @@ void DefaultPieceStorageTest::testGetPieceCompletedPiece() {
CPPUNIT_ASSERT_EQUAL(true, pieceGot->pieceComplete());
}
void DefaultPieceStorageTest::testGetMissingPiece_fileEntry()
{
// - 32KB
// +--------+
// |11111222|
int32_t pieceLength = 256*1024;
int64_t totalLength = 1*pieceLength;
int32_t blockLength = 16*1024;
std::deque<std::string> uris1;
uris1.push_back("http://localhost/src/file1.txt");
std::deque<std::string> uris2;
uris2.push_back("http://localhost/src/file2.txt");
SharedHandle<FileEntry> file1 = new FileEntry("src/file1.txt", 150*1024, 0/*, uris1*/);
SharedHandle<FileEntry> file2 = new FileEntry("src/file2.txt", 106*1024, file1->getLength() /*, uris2*/);
SharedHandle<MockBtContext> dctx = new MockBtContext();
dctx->setPieceLength(pieceLength);
dctx->setTotalLength(totalLength);
dctx->addFileEntry(file1);
dctx->addFileEntry(file2);
SharedHandle<DefaultPieceStorage> ps = new DefaultPieceStorage(dctx, option);
SharedHandle<Piece> p = ps->getMissingPiece(file1);
CPPUNIT_ASSERT(!p.isNull());
CPPUNIT_ASSERT_EQUAL((int32_t)0, p->getIndex());
for(int32_t i = 0; i < 9; ++i) {
p->completeBlock(i);
}
SharedHandle<Piece> subPiece = new Piece(9, blockLength, 1);
p->addSubPiece(subPiece);
ps->cancelPiece(p);
// Piece index = 0 should be retrieved again because the part of file1 is
// not complete
SharedHandle<Piece> p2 = ps->getMissingPiece(file1);
CPPUNIT_ASSERT(!p2.isNull());
CPPUNIT_ASSERT_EQUAL((int32_t)0, p2->getIndex());
// Make the part of file1 complete
for(int32_t i = 0; i < 6*1024; ++i) {
p2->getSubPiece(9)->completeBlock(i);
}
ps->cancelPiece(p2);
// Null Piece should be retrieved
CPPUNIT_ASSERT(ps->getMissingPiece(file1).isNull());
// Next, I retrive the piece giving file2
SharedHandle<Piece> p3 = ps->getMissingPiece(file2);
CPPUNIT_ASSERT(!p3.isNull());
CPPUNIT_ASSERT_EQUAL((int32_t)0, p3->getIndex());
// Make the part of file2 complete
for(int32_t i = 6*1024; i < 16*1024; ++i) {
p3->getSubPiece(9)->completeBlock(i);
}
for(int32_t i = 10; i < 16; ++i) {
p3->completeBlock(i);
}
ps->cancelPiece(p3);
// Null Piece should be retrieved
CPPUNIT_ASSERT(ps->getMissingPiece(file2).isNull());
}
void DefaultPieceStorageTest::testCancelPiece()
{
int32_t pieceLength = 256*1024;
int64_t totalLength = 32*pieceLength; // <-- make the number of piece greater than END_GAME_PIECE_NUM
int32_t blockLength = 16*1024;
std::deque<std::string> uris1;
uris1.push_back("http://localhost/src/file1.txt");
SharedHandle<FileEntry> file1 = new FileEntry("src/file1.txt", totalLength, 0 /*, uris1*/);
@ -256,18 +185,14 @@ void DefaultPieceStorageTest::testCancelPiece()
SharedHandle<DefaultPieceStorage> ps = new DefaultPieceStorage(dctx, option);
SharedHandle<Piece> p = ps->getMissingPiece(file1);
SharedHandle<Piece> p = ps->getMissingPiece();
p->completeBlock(0);
SharedHandle<Piece> subPiece = new Piece(0, blockLength, 1);
subPiece->completeBlock(0);
p->addSubPiece(subPiece);
ps->cancelPiece(p);
// See the sub piece is also hibernated...
SharedHandle<Piece> p2 = ps->getMissingPiece(file1);
SharedHandle<Piece> p2 = ps->getMissingPiece();
CPPUNIT_ASSERT(!p2->getSubPiece(0).isNull());
CPPUNIT_ASSERT(p2->hasBlock(0));
}
void DefaultPieceStorageTest::testMarkPiecesDone()

View File

@ -8,8 +8,6 @@ class PieceTest:public CppUnit::TestFixture {
CPPUNIT_TEST_SUITE(PieceTest);
CPPUNIT_TEST(testCompleteBlock);
CPPUNIT_TEST(testIsRangeComplete);
CPPUNIT_TEST(testIsRangeComplete_subPiece);
CPPUNIT_TEST(testGetCompletedLength);
CPPUNIT_TEST_SUITE_END();
private:
@ -18,8 +16,6 @@ public:
void setUp() {}
void testCompleteBlock();
void testIsRangeComplete();
void testIsRangeComplete_subPiece();
void testGetCompletedLength();
};
@ -31,78 +27,22 @@ void PieceTest::testCompleteBlock()
int32_t blockLength = 32*1024;
Piece p(0, blockLength*10, blockLength);
// 5 is a block index inside the Piece p.
SharedHandle<Piece> subPiece = new Piece(5, blockLength, 1);
p.addSubPiece(subPiece);
CPPUNIT_ASSERT(!p.getSubPiece(5).isNull());
// When block is complete, then its associated sub piece must be deleted.
p.completeBlock(5);
CPPUNIT_ASSERT(p.getSubPiece(5).isNull());
}
void PieceTest::testIsRangeComplete()
{
int32_t blockLength = 16*1024;
Piece p(0, blockLength*10, blockLength);
CPPUNIT_ASSERT(!p.isRangeComplete(8*1024, 16*1024));
p.completeBlock(0);
CPPUNIT_ASSERT(!p.isRangeComplete(8*1024, 16*1024));
CPPUNIT_ASSERT(p.isRangeComplete(8*1024, 8*1024));
p.completeBlock(1);
CPPUNIT_ASSERT(p.isRangeComplete(8*1024, 16*1024));
}
void PieceTest::testIsRangeComplete_subPiece()
{
int32_t blockLength = 16*1024;
Piece p(0, blockLength*10, blockLength);
CPPUNIT_ASSERT(!p.isRangeComplete(8*1024, 32*1024));
SharedHandle<Piece> startSubPiece = new Piece(0, blockLength, 1);
p.addSubPiece(startSubPiece);
SharedHandle<Piece> endSubPiece = new Piece(2, blockLength, 1);
p.addSubPiece(endSubPiece);
p.completeBlock(1);
CPPUNIT_ASSERT(!p.isRangeComplete(8*1024, 32*1024));
for(int32_t i = 8*1024; i < blockLength; ++i) {
startSubPiece->completeBlock(i);
}
CPPUNIT_ASSERT(!p.isRangeComplete(8*1024, 32*1024));
for(int32_t i = 0; i < 8*1024; ++i) {
endSubPiece->completeBlock(i);
}
CPPUNIT_ASSERT(p.isRangeComplete(8*1024, 32*1024));
CPPUNIT_ASSERT(p.hasBlock(5));
}
void PieceTest::testGetCompletedLength()
{
int32_t blockLength = 16*1024;
Piece p(0, blockLength*10, blockLength);
Piece p(0, blockLength*10+100, blockLength);
SharedHandle<Piece> subPiece = new Piece(0, blockLength, 1);
for(int32_t i = 0; i < blockLength-1; ++i) {
subPiece->completeBlock(i);
}
p.addSubPiece(subPiece);
p.completeBlock(1);
p.completeBlock(2);
p.completeBlock(9);
p.completeBlock(10); // <-- 100 bytes
CPPUNIT_ASSERT_EQUAL(blockLength*3+blockLength-1, p.getCompletedLength());
CPPUNIT_ASSERT_EQUAL(blockLength*3+100, p.getCompletedLength());
}
} // namespace aria2