mirror of https://github.com/aria2/aria2
2007-11-13 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
Recalculates download progress when loading a control file, if the piece length of DownloadContext is different from the one saved in the control file. Currently in-flight pieces are ignored. * src/DefaultBtProgressInfoFile.cc * test/DefaultBtProgressInfoFileTest.cc * src/Util.{h, cc} * test/UtilTest.ccpull/1/head
parent
aef50efed0
commit
d6686a5e29
10
ChangeLog
10
ChangeLog
|
@ -1,3 +1,13 @@
|
|||
2007-11-13 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
|
||||
|
||||
Recalculates download progress when loading a control file,
|
||||
if the piece length of DownloadContext is different from the one saved
|
||||
in the control file. Currently in-flight pieces are ignored.
|
||||
* src/DefaultBtProgressInfoFile.cc
|
||||
* test/DefaultBtProgressInfoFileTest.cc
|
||||
* src/Util.{h, cc}
|
||||
* test/UtilTest.cc
|
||||
|
||||
2007-11-12 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
|
||||
|
||||
Do not rotate tiers in announce-list.
|
||||
|
|
3
TODO
3
TODO
|
@ -56,6 +56,5 @@
|
|||
FatalException .... Program should abort.
|
||||
|
||||
-- remaining features to be implemented for 0.12.0 release
|
||||
* Implement duplicate download checking in Bt
|
||||
* Implement duplicate download checking
|
||||
* improve --metalink-location field
|
||||
* Piece length conversion when loading file
|
|
@ -190,13 +190,8 @@ void DefaultBtProgressInfoFile::load()
|
|||
savedInfoHash = 0;
|
||||
}
|
||||
|
||||
// TODO implement the conversion mechanism between different piece length.
|
||||
int32_t pieceLength;
|
||||
in.read(reinterpret_cast<char*>(&pieceLength), sizeof(pieceLength));
|
||||
if(pieceLength != _dctx->getPieceLength()) {
|
||||
throw new DlAbortEx("piece length mismatch. expected: %d, actual: %d",
|
||||
_dctx->getPieceLength(), pieceLength);
|
||||
}
|
||||
|
||||
int64_t totalLength;
|
||||
in.read(reinterpret_cast<char*>(&totalLength), sizeof(totalLength));
|
||||
|
@ -214,51 +209,61 @@ void DefaultBtProgressInfoFile::load()
|
|||
// TODO implement the conversion mechanism between different piece length.
|
||||
int32_t bitfieldLength;
|
||||
in.read(reinterpret_cast<char*>(&bitfieldLength), sizeof(bitfieldLength));
|
||||
if(_pieceStorage->getBitfieldLength() != bitfieldLength) {
|
||||
int32_t expectedBitfieldLength = ((totalLength+pieceLength-1)/pieceLength+7)/8;
|
||||
if(expectedBitfieldLength != bitfieldLength) {
|
||||
throw new DlAbortEx("bitfield length mismatch. expected: %d, actual: %d",
|
||||
_pieceStorage->getBitfieldLength(),
|
||||
expectedBitfieldLength,
|
||||
bitfieldLength);
|
||||
}
|
||||
|
||||
// TODO implement the conversion mechanism between different piece length.
|
||||
savedBitfield = new unsigned char[bitfieldLength];
|
||||
in.read(reinterpret_cast<char*>(savedBitfield), bitfieldLength);
|
||||
_pieceStorage->setBitfield(savedBitfield, bitfieldLength);
|
||||
delete [] savedBitfield;
|
||||
savedBitfield = 0;
|
||||
|
||||
int32_t numInFlightPiece;
|
||||
in.read(reinterpret_cast<char*>(&numInFlightPiece), sizeof(numInFlightPiece));
|
||||
|
||||
Pieces inFlightPieces;
|
||||
while(numInFlightPiece--) {
|
||||
int32_t index;
|
||||
in.read(reinterpret_cast<char*>(&index), sizeof(index));
|
||||
if(!(0 <= index && index < _dctx->getNumPieces())) {
|
||||
throw new DlAbortEx("piece index out of range: %d", index);
|
||||
}
|
||||
int32_t length;
|
||||
in.read(reinterpret_cast<char*>(&length), sizeof(length));
|
||||
if(!(0 < length && length <=_dctx->getPieceLength())) {
|
||||
throw new DlAbortEx("piece length out of range: %d", length);
|
||||
}
|
||||
PieceHandle piece = new Piece(index, length);
|
||||
int32_t bitfieldLength;
|
||||
in.read(reinterpret_cast<char*>(&bitfieldLength), sizeof(bitfieldLength));
|
||||
if(piece->getBitfieldLength() != bitfieldLength) {
|
||||
throw new DlAbortEx("piece bitfield length mismatch. expected: %d actual: %d",
|
||||
piece->getBitfieldLength(), bitfieldLength);
|
||||
}
|
||||
savedBitfield = new unsigned char[bitfieldLength];
|
||||
in.read(reinterpret_cast<char*>(savedBitfield), bitfieldLength);
|
||||
piece->setBitfield(savedBitfield, bitfieldLength);
|
||||
if(pieceLength == _dctx->getPieceLength()) {
|
||||
_pieceStorage->setBitfield(savedBitfield, bitfieldLength);
|
||||
delete [] savedBitfield;
|
||||
savedBitfield = 0;
|
||||
|
||||
inFlightPieces.push_back(piece);
|
||||
}
|
||||
_pieceStorage->addInFlightPiece(inFlightPieces);
|
||||
|
||||
int32_t numInFlightPiece;
|
||||
in.read(reinterpret_cast<char*>(&numInFlightPiece), sizeof(numInFlightPiece));
|
||||
|
||||
Pieces inFlightPieces;
|
||||
while(numInFlightPiece--) {
|
||||
int32_t index;
|
||||
in.read(reinterpret_cast<char*>(&index), sizeof(index));
|
||||
if(!(0 <= index && index < _dctx->getNumPieces())) {
|
||||
throw new DlAbortEx("piece index out of range: %d", index);
|
||||
}
|
||||
int32_t length;
|
||||
in.read(reinterpret_cast<char*>(&length), sizeof(length));
|
||||
if(!(0 < length && length <=_dctx->getPieceLength())) {
|
||||
throw new DlAbortEx("piece length out of range: %d", length);
|
||||
}
|
||||
PieceHandle piece = new Piece(index, length);
|
||||
int32_t bitfieldLength;
|
||||
in.read(reinterpret_cast<char*>(&bitfieldLength), sizeof(bitfieldLength));
|
||||
if(piece->getBitfieldLength() != bitfieldLength) {
|
||||
throw new DlAbortEx("piece bitfield length mismatch. expected: %d actual: %d",
|
||||
piece->getBitfieldLength(), bitfieldLength);
|
||||
}
|
||||
savedBitfield = new unsigned char[bitfieldLength];
|
||||
in.read(reinterpret_cast<char*>(savedBitfield), bitfieldLength);
|
||||
piece->setBitfield(savedBitfield, bitfieldLength);
|
||||
delete [] savedBitfield;
|
||||
savedBitfield = 0;
|
||||
|
||||
inFlightPieces.push_back(piece);
|
||||
}
|
||||
_pieceStorage->addInFlightPiece(inFlightPieces);
|
||||
} else {
|
||||
BitfieldMan src(pieceLength, totalLength);
|
||||
src.setBitfield(savedBitfield, bitfieldLength);
|
||||
BitfieldMan dest(_dctx->getPieceLength(), totalLength);
|
||||
Util::convertBitfield(&dest, &src);
|
||||
_pieceStorage->setBitfield(dest.getBitfield(), dest.getBitfieldLength());
|
||||
delete [] savedBitfield;
|
||||
savedBitfield = 0;
|
||||
}
|
||||
_logger->info(MSG_LOADED_SEGMENT_FILE);
|
||||
} catch(ios::failure const& exception) {
|
||||
delete [] savedBitfield;
|
||||
|
|
11
src/Util.cc
11
src/Util.cc
|
@ -39,6 +39,7 @@
|
|||
#include "a2netcompat.h"
|
||||
#include "a2time.h"
|
||||
#include "DlAbortEx.h"
|
||||
#include "BitfieldMan.h"
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
|
@ -782,3 +783,13 @@ void Util::mkdirs(const string& dirpath)
|
|||
throw new DlAbortEx(EX_MAKE_DIR, dir.getPath().c_str(), strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
void Util::convertBitfield(BitfieldMan* dest, const BitfieldMan* src)
|
||||
{
|
||||
for(int32_t index = 0; index < dest->countBlock(); ++index) {
|
||||
if(src->isBitSetOffsetRange((int64_t)index*dest->getBlockLength(),
|
||||
dest->getBlockLength())) {
|
||||
dest->setBit(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
|
||||
class Randomizer;
|
||||
extern typedef SharedHandle<Randomizer> RandomizerHandle;
|
||||
class BitfieldMan;
|
||||
|
||||
#define STRTOLL(X) strtoll(X, (char**)NULL, 10)
|
||||
|
||||
|
@ -153,6 +154,8 @@ public:
|
|||
static int32_t alphaToNum(const string& alphabets);
|
||||
|
||||
static void mkdirs(const string& dirpath);
|
||||
|
||||
static void convertBitfield(BitfieldMan* dest, const BitfieldMan* src);
|
||||
};
|
||||
|
||||
#endif // _D_UTIL_H_
|
||||
|
|
|
@ -24,6 +24,7 @@ class DefaultBtProgressInfoFileTest:public CppUnit::TestFixture {
|
|||
CPPUNIT_TEST(testSave_nonBt);
|
||||
CPPUNIT_TEST(testLoad);
|
||||
CPPUNIT_TEST(testLoad_nonBt);
|
||||
CPPUNIT_TEST(testLoad_nonBt_pieceLengthShorter);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
private:
|
||||
MockBtContextHandle _btContext;
|
||||
|
@ -35,19 +36,22 @@ public:
|
|||
|
||||
void setUp() {
|
||||
BtRegistry::unregisterAll();
|
||||
|
||||
}
|
||||
|
||||
void initializeMembers(int32_t pieceLength, int64_t totalLength)
|
||||
{
|
||||
static unsigned char infoHash[] = {
|
||||
0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa,
|
||||
0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff,
|
||||
};
|
||||
|
||||
|
||||
_option = new Option();
|
||||
_option->put(PREF_DIR, ".");
|
||||
|
||||
_btContext = new MockBtContext();
|
||||
_btContext->setInfoHash(infoHash);
|
||||
|
||||
_bitfield = new BitfieldMan(1024, 80*1024);
|
||||
_bitfield = new BitfieldMan(pieceLength, totalLength);
|
||||
|
||||
_pieceStorage = new MockPieceStorage();
|
||||
_pieceStorage->setBitfield(_bitfield.get());
|
||||
|
@ -75,6 +79,7 @@ public:
|
|||
void testLoad();
|
||||
void testSave_nonBt();
|
||||
void testLoad_nonBt();
|
||||
void testLoad_nonBt_pieceLengthShorter();
|
||||
};
|
||||
|
||||
#undef BLOCK_LENGTH
|
||||
|
@ -84,7 +89,8 @@ CPPUNIT_TEST_SUITE_REGISTRATION(DefaultBtProgressInfoFileTest);
|
|||
|
||||
void DefaultBtProgressInfoFileTest::testLoad()
|
||||
{
|
||||
try {
|
||||
initializeMembers(1024, 81920);
|
||||
|
||||
_btContext->setName("load");
|
||||
_btContext->setPieceLength(1024);
|
||||
_btContext->setTotalLength(81920);
|
||||
|
@ -121,16 +127,11 @@ void DefaultBtProgressInfoFileTest::testLoad()
|
|||
PieceHandle piece2 = inFlightPieces[1];
|
||||
CPPUNIT_ASSERT_EQUAL((int32_t)2, piece2->getIndex());
|
||||
CPPUNIT_ASSERT_EQUAL((int32_t)512, piece2->getLength());
|
||||
|
||||
} catch(Exception* e) {
|
||||
cerr << e->getMsg() << endl;
|
||||
delete e;
|
||||
}
|
||||
}
|
||||
|
||||
void DefaultBtProgressInfoFileTest::testLoad_nonBt()
|
||||
{
|
||||
BtRegistry::unregisterAll();
|
||||
initializeMembers(1024, 81920);
|
||||
|
||||
SingleFileDownloadContextHandle dctx =
|
||||
new SingleFileDownloadContext(1024, 81920, "load-nonBt");
|
||||
|
@ -165,9 +166,31 @@ void DefaultBtProgressInfoFileTest::testLoad_nonBt()
|
|||
|
||||
}
|
||||
|
||||
void DefaultBtProgressInfoFileTest::testLoad_nonBt_pieceLengthShorter()
|
||||
{
|
||||
initializeMembers(512, 81920);
|
||||
|
||||
SingleFileDownloadContextHandle dctx =
|
||||
new SingleFileDownloadContext(512, 81920, "load-nonBt");
|
||||
|
||||
DefaultBtProgressInfoFile infoFile(dctx, _pieceStorage, _option.get());
|
||||
CPPUNIT_ASSERT_EQUAL(string("./load-nonBt.aria2"), infoFile.getFilename());
|
||||
infoFile.load();
|
||||
|
||||
// check the contents of objects
|
||||
|
||||
// bitfield
|
||||
CPPUNIT_ASSERT_EQUAL(string("fffffffffffffffffffffffffffffffffffffffc"),
|
||||
Util::toHex(_bitfield->getBitfield(), _bitfield->getBitfieldLength()));
|
||||
|
||||
// the number of in-flight pieces
|
||||
CPPUNIT_ASSERT_EQUAL((int32_t)0,
|
||||
_pieceStorage->countInFlightPiece());
|
||||
}
|
||||
|
||||
void DefaultBtProgressInfoFileTest::testSave_nonBt()
|
||||
{
|
||||
BtRegistry::unregisterAll();
|
||||
initializeMembers(1024, 81920);
|
||||
|
||||
SingleFileDownloadContextHandle dctx =
|
||||
new SingleFileDownloadContext(1024, 81920, "save-temp");
|
||||
|
@ -261,6 +284,8 @@ void DefaultBtProgressInfoFileTest::testSave_nonBt()
|
|||
|
||||
void DefaultBtProgressInfoFileTest::testSave()
|
||||
{
|
||||
initializeMembers(1024, 81920);
|
||||
|
||||
_btContext->setName("save-temp");
|
||||
_btContext->setPieceLength(1024);
|
||||
_btContext->setTotalLength(81920);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "Util.h"
|
||||
#include "FixedNumberRandomizer.h"
|
||||
#include "DlAbortEx.h"
|
||||
#include "BitfieldMan.h"
|
||||
#include <string>
|
||||
#include <cppunit/extensions/HelperMacros.h>
|
||||
|
||||
|
@ -30,6 +31,7 @@ class UtilTest:public CppUnit::TestFixture {
|
|||
CPPUNIT_TEST(testIsUppercase);
|
||||
CPPUNIT_TEST(testAlphaToNum);
|
||||
CPPUNIT_TEST(testMkdirs);
|
||||
CPPUNIT_TEST(testConvertBitfield);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
private:
|
||||
|
||||
|
@ -58,6 +60,7 @@ public:
|
|||
void testIsUppercase();
|
||||
void testAlphaToNum();
|
||||
void testMkdirs();
|
||||
void testConvertBitfield();
|
||||
};
|
||||
|
||||
|
||||
|
@ -390,3 +393,17 @@ void UtilTest::testMkdirs()
|
|||
delete ex;
|
||||
}
|
||||
}
|
||||
|
||||
void UtilTest::testConvertBitfield()
|
||||
{
|
||||
BitfieldMan srcBitfield(384*1024, 256*1024*256+1);
|
||||
BitfieldMan destBitfield(512*1024, srcBitfield.getTotalLength());
|
||||
srcBitfield.setAllBit();
|
||||
srcBitfield.unsetBit(2);// <- range [768, 1152)
|
||||
// which corresponds to the index [1,2] in destBitfield
|
||||
Util::convertBitfield(&destBitfield, &srcBitfield);
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(string("9fffffffffffffffffffffffffffffff80"),
|
||||
Util::toHex(destBitfield.getBitfield(),
|
||||
destBitfield.getBitfieldLength()));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue