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
Tatsuhiro Tsujikawa 2014-07-12 16:52:01 +09:00
parent 620be59b1e
commit 3aaa5a7344
4 changed files with 26 additions and 20 deletions

View File

@ -60,7 +60,7 @@ Piece::Piece()
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)),
wrCache_(nullptr),
index_(index),
@ -181,15 +181,21 @@ bool Piece::getAllMissingBlockIndexes
}
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_);
}
void Piece::reconfigure(int32_t length)
void Piece::reconfigure(int64_t length)
{
delete bitfield_;
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)
@ -197,7 +203,7 @@ void Piece::setBitfield(const unsigned char* bitfield, size_t len)
bitfield_->setBitfield(bitfield, len);
}
int32_t Piece::getCompletedLength()
int64_t Piece::getCompletedLength()
{
return bitfield_->getCompletedLength();
}
@ -208,13 +214,13 @@ void Piece::setHashType(const std::string& hashType)
}
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()) {
return false;
}
if(begin == nextBegin_ &&
nextBegin_+dataLength <= static_cast<size_t>(length_)) {
nextBegin_ + static_cast<int64_t>(dataLength) <= length_) {
if(!mdctx_) {
mdctx_ = MessageDigest::create(hashType_);
}

View File

@ -62,9 +62,9 @@ private:
size_t index_;
int32_t length_;
int64_t length_;
int32_t blockLength_;
int32_t nextBegin_;
int64_t nextBegin_;
bool usedBySegment_;
@ -75,7 +75,7 @@ public:
static const int32_t BLOCK_LENGTH = 16*1024;
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();
@ -127,9 +127,9 @@ public:
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;
@ -145,14 +145,14 @@ public:
bool isBlockUsed(size_t index) const;
// Calculates completed length
int32_t getCompletedLength();
int64_t getCompletedLength();
void setHashType(const std::string& hashType);
// Updates hash value. This function compares begin and private variable
// nextBegin_ and only when they are equal, hash is updated eating data and
// 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;
@ -171,7 +171,7 @@ public:
/**
* Loses current bitfield state.
*/
void reconfigure(int32_t length);
void reconfigure(int64_t length);
void addUser(cuid_t cuid);
void removeUser(cuid_t cuid);

View File

@ -361,7 +361,7 @@ void DefaultBtProgressInfoFileTest::testLoad_nonBt_compat()
std::shared_ptr<Piece> piece1 = inFlightPieces[0];
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(std::string("00"), util::toHex(piece1->getBitfield(),
piece1->getBitfieldLength()));
@ -369,7 +369,7 @@ void DefaultBtProgressInfoFileTest::testLoad_nonBt_compat()
// piece index 2
std::shared_ptr<Piece> piece2 = inFlightPieces[1];
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
@ -406,7 +406,7 @@ void DefaultBtProgressInfoFileTest::testLoad_nonBt()
std::shared_ptr<Piece> piece1 = inFlightPieces[0];
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(std::string("00"), util::toHex(piece1->getBitfield(),
piece1->getBitfieldLength()));
@ -414,7 +414,7 @@ void DefaultBtProgressInfoFileTest::testLoad_nonBt()
// piece index 2
std::shared_ptr<Piece> piece2 = inFlightPieces[1];
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()

View File

@ -67,7 +67,7 @@ void PieceTest::testGetCompletedLength()
p.completeBlock(9);
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()