mirror of https://github.com/aria2/aria2
Fix file length information in RPC response when length > 2GB is unknown
This commit fixes the bug that aria2.tellStopped RPC method returns total length and completedLength as 0 when file size is unknown in advance and turns out > 2GB in the end. This commit and addresses the performance degradation in this case.pull/253/head
parent
620be59b1e
commit
3aaa5a7344
20
src/Piece.cc
20
src/Piece.cc
|
@ -60,7 +60,7 @@ Piece::Piece()
|
||||||
usedBySegment_(false)
|
usedBySegment_(false)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
Piece::Piece(size_t index, int32_t length, int32_t blockLength)
|
Piece::Piece(size_t index, int64_t length, int32_t blockLength)
|
||||||
: bitfield_(new BitfieldMan(blockLength, length)),
|
: bitfield_(new BitfieldMan(blockLength, length)),
|
||||||
wrCache_(nullptr),
|
wrCache_(nullptr),
|
||||||
index_(index),
|
index_(index),
|
||||||
|
@ -181,15 +181,21 @@ bool Piece::getAllMissingBlockIndexes
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Piece::toString() const {
|
std::string Piece::toString() const {
|
||||||
return fmt("piece: index=%lu, length=%d",
|
return fmt("piece: index=%lu, length=%" PRId64,
|
||||||
static_cast<unsigned long>(index_), length_);
|
static_cast<unsigned long>(index_), length_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Piece::reconfigure(int32_t length)
|
void Piece::reconfigure(int64_t length)
|
||||||
{
|
{
|
||||||
delete bitfield_;
|
delete bitfield_;
|
||||||
length_ = length;
|
length_ = length;
|
||||||
bitfield_ = new BitfieldMan(blockLength_, length_);
|
// TODO currently, this function is only called from
|
||||||
|
// GrowSegment::updateWrittenLength(). If we use default block
|
||||||
|
// length (16K), and length_ gets large (e.g., 4GB), creating
|
||||||
|
// BitfieldMan for each call is very expensive. Therefore, we use
|
||||||
|
// maximum block length for now to reduce the overhead. Ideally, we
|
||||||
|
// check the code thoroughly and remove bitfield_ if we can.
|
||||||
|
bitfield_ = new BitfieldMan(std::numeric_limits<int32_t>::max(), length_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Piece::setBitfield(const unsigned char* bitfield, size_t len)
|
void Piece::setBitfield(const unsigned char* bitfield, size_t len)
|
||||||
|
@ -197,7 +203,7 @@ void Piece::setBitfield(const unsigned char* bitfield, size_t len)
|
||||||
bitfield_->setBitfield(bitfield, len);
|
bitfield_->setBitfield(bitfield, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t Piece::getCompletedLength()
|
int64_t Piece::getCompletedLength()
|
||||||
{
|
{
|
||||||
return bitfield_->getCompletedLength();
|
return bitfield_->getCompletedLength();
|
||||||
}
|
}
|
||||||
|
@ -208,13 +214,13 @@ void Piece::setHashType(const std::string& hashType)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Piece::updateHash
|
bool Piece::updateHash
|
||||||
(int32_t begin, const unsigned char* data, size_t dataLength)
|
(int64_t begin, const unsigned char* data, size_t dataLength)
|
||||||
{
|
{
|
||||||
if(hashType_.empty()) {
|
if(hashType_.empty()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if(begin == nextBegin_ &&
|
if(begin == nextBegin_ &&
|
||||||
nextBegin_+dataLength <= static_cast<size_t>(length_)) {
|
nextBegin_ + static_cast<int64_t>(dataLength) <= length_) {
|
||||||
if(!mdctx_) {
|
if(!mdctx_) {
|
||||||
mdctx_ = MessageDigest::create(hashType_);
|
mdctx_ = MessageDigest::create(hashType_);
|
||||||
}
|
}
|
||||||
|
|
16
src/Piece.h
16
src/Piece.h
|
@ -62,9 +62,9 @@ private:
|
||||||
|
|
||||||
size_t index_;
|
size_t index_;
|
||||||
|
|
||||||
int32_t length_;
|
int64_t length_;
|
||||||
int32_t blockLength_;
|
int32_t blockLength_;
|
||||||
int32_t nextBegin_;
|
int64_t nextBegin_;
|
||||||
|
|
||||||
bool usedBySegment_;
|
bool usedBySegment_;
|
||||||
|
|
||||||
|
@ -75,7 +75,7 @@ public:
|
||||||
static const int32_t BLOCK_LENGTH = 16*1024;
|
static const int32_t BLOCK_LENGTH = 16*1024;
|
||||||
|
|
||||||
Piece();
|
Piece();
|
||||||
Piece(size_t index, int32_t length, int32_t blockLength = BLOCK_LENGTH);
|
Piece(size_t index, int64_t length, int32_t blockLength = BLOCK_LENGTH);
|
||||||
|
|
||||||
~Piece();
|
~Piece();
|
||||||
|
|
||||||
|
@ -127,9 +127,9 @@ public:
|
||||||
|
|
||||||
void setIndex(size_t index) { index_ = index; }
|
void setIndex(size_t index) { index_ = index; }
|
||||||
|
|
||||||
int32_t getLength() const { return length_; }
|
int64_t getLength() const { return length_; }
|
||||||
|
|
||||||
void setLength(int32_t length) { length_ = length; }
|
void setLength(int64_t length) { length_ = length; }
|
||||||
|
|
||||||
const unsigned char* getBitfield() const;
|
const unsigned char* getBitfield() const;
|
||||||
|
|
||||||
|
@ -145,14 +145,14 @@ public:
|
||||||
bool isBlockUsed(size_t index) const;
|
bool isBlockUsed(size_t index) const;
|
||||||
|
|
||||||
// Calculates completed length
|
// Calculates completed length
|
||||||
int32_t getCompletedLength();
|
int64_t getCompletedLength();
|
||||||
|
|
||||||
void setHashType(const std::string& hashType);
|
void setHashType(const std::string& hashType);
|
||||||
|
|
||||||
// Updates hash value. This function compares begin and private variable
|
// Updates hash value. This function compares begin and private variable
|
||||||
// nextBegin_ and only when they are equal, hash is updated eating data and
|
// nextBegin_ and only when they are equal, hash is updated eating data and
|
||||||
// returns true. Otherwise returns false.
|
// returns true. Otherwise returns false.
|
||||||
bool updateHash(int32_t begin, const unsigned char* data, size_t dataLength);
|
bool updateHash(int64_t begin, const unsigned char* data, size_t dataLength);
|
||||||
|
|
||||||
bool isHashCalculated() const;
|
bool isHashCalculated() const;
|
||||||
|
|
||||||
|
@ -171,7 +171,7 @@ public:
|
||||||
/**
|
/**
|
||||||
* Loses current bitfield state.
|
* Loses current bitfield state.
|
||||||
*/
|
*/
|
||||||
void reconfigure(int32_t length);
|
void reconfigure(int64_t length);
|
||||||
|
|
||||||
void addUser(cuid_t cuid);
|
void addUser(cuid_t cuid);
|
||||||
void removeUser(cuid_t cuid);
|
void removeUser(cuid_t cuid);
|
||||||
|
|
|
@ -361,7 +361,7 @@ void DefaultBtProgressInfoFileTest::testLoad_nonBt_compat()
|
||||||
|
|
||||||
std::shared_ptr<Piece> piece1 = inFlightPieces[0];
|
std::shared_ptr<Piece> piece1 = inFlightPieces[0];
|
||||||
CPPUNIT_ASSERT_EQUAL((size_t)1, piece1->getIndex());
|
CPPUNIT_ASSERT_EQUAL((size_t)1, piece1->getIndex());
|
||||||
CPPUNIT_ASSERT_EQUAL(1024, piece1->getLength());
|
CPPUNIT_ASSERT_EQUAL((int64_t)1024, piece1->getLength());
|
||||||
CPPUNIT_ASSERT_EQUAL((size_t)1, piece1->getBitfieldLength());
|
CPPUNIT_ASSERT_EQUAL((size_t)1, piece1->getBitfieldLength());
|
||||||
CPPUNIT_ASSERT_EQUAL(std::string("00"), util::toHex(piece1->getBitfield(),
|
CPPUNIT_ASSERT_EQUAL(std::string("00"), util::toHex(piece1->getBitfield(),
|
||||||
piece1->getBitfieldLength()));
|
piece1->getBitfieldLength()));
|
||||||
|
@ -369,7 +369,7 @@ void DefaultBtProgressInfoFileTest::testLoad_nonBt_compat()
|
||||||
// piece index 2
|
// piece index 2
|
||||||
std::shared_ptr<Piece> piece2 = inFlightPieces[1];
|
std::shared_ptr<Piece> piece2 = inFlightPieces[1];
|
||||||
CPPUNIT_ASSERT_EQUAL((size_t)2, piece2->getIndex());
|
CPPUNIT_ASSERT_EQUAL((size_t)2, piece2->getIndex());
|
||||||
CPPUNIT_ASSERT_EQUAL(512, piece2->getLength());
|
CPPUNIT_ASSERT_EQUAL((int64_t)512, piece2->getLength());
|
||||||
}
|
}
|
||||||
#endif // !WORDS_BIGENDIAN
|
#endif // !WORDS_BIGENDIAN
|
||||||
|
|
||||||
|
@ -406,7 +406,7 @@ void DefaultBtProgressInfoFileTest::testLoad_nonBt()
|
||||||
|
|
||||||
std::shared_ptr<Piece> piece1 = inFlightPieces[0];
|
std::shared_ptr<Piece> piece1 = inFlightPieces[0];
|
||||||
CPPUNIT_ASSERT_EQUAL((size_t)1, piece1->getIndex());
|
CPPUNIT_ASSERT_EQUAL((size_t)1, piece1->getIndex());
|
||||||
CPPUNIT_ASSERT_EQUAL(1024, piece1->getLength());
|
CPPUNIT_ASSERT_EQUAL((int64_t)1024, piece1->getLength());
|
||||||
CPPUNIT_ASSERT_EQUAL((size_t)1, piece1->getBitfieldLength());
|
CPPUNIT_ASSERT_EQUAL((size_t)1, piece1->getBitfieldLength());
|
||||||
CPPUNIT_ASSERT_EQUAL(std::string("00"), util::toHex(piece1->getBitfield(),
|
CPPUNIT_ASSERT_EQUAL(std::string("00"), util::toHex(piece1->getBitfield(),
|
||||||
piece1->getBitfieldLength()));
|
piece1->getBitfieldLength()));
|
||||||
|
@ -414,7 +414,7 @@ void DefaultBtProgressInfoFileTest::testLoad_nonBt()
|
||||||
// piece index 2
|
// piece index 2
|
||||||
std::shared_ptr<Piece> piece2 = inFlightPieces[1];
|
std::shared_ptr<Piece> piece2 = inFlightPieces[1];
|
||||||
CPPUNIT_ASSERT_EQUAL((size_t)2, piece2->getIndex());
|
CPPUNIT_ASSERT_EQUAL((size_t)2, piece2->getIndex());
|
||||||
CPPUNIT_ASSERT_EQUAL(512, piece2->getLength());
|
CPPUNIT_ASSERT_EQUAL((int64_t)512, piece2->getLength());
|
||||||
}
|
}
|
||||||
|
|
||||||
void DefaultBtProgressInfoFileTest::testLoad_nonBt_pieceLengthShorter()
|
void DefaultBtProgressInfoFileTest::testLoad_nonBt_pieceLengthShorter()
|
||||||
|
|
|
@ -67,7 +67,7 @@ void PieceTest::testGetCompletedLength()
|
||||||
p.completeBlock(9);
|
p.completeBlock(9);
|
||||||
p.completeBlock(10); // <-- 100 bytes
|
p.completeBlock(10); // <-- 100 bytes
|
||||||
|
|
||||||
CPPUNIT_ASSERT_EQUAL(blockLength*3+100, p.getCompletedLength());
|
CPPUNIT_ASSERT_EQUAL((int64_t)(blockLength*3+100), p.getCompletedLength());
|
||||||
}
|
}
|
||||||
|
|
||||||
void PieceTest::testFlushWrCache()
|
void PieceTest::testFlushWrCache()
|
||||||
|
|
Loading…
Reference in New Issue