mirror of https://github.com/aria2/aria2
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.ccpull/1/head
parent
fc0fa4203a
commit
e57a070a3f
|
@ -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.
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
91
src/Piece.cc
91
src/Piece.cc
|
@ -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
|
||||
|
|
15
src/Piece.h
15
src/Piece.h
|
@ -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();
|
||||
|
||||
/**
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue