summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>2014-07-12 16:52:01 +0900
committerTatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>2014-07-12 17:01:46 +0900
commit3aaa5a7344ef631998df9a9c2bd6cf4fbca11ac8 (patch)
treea2cb25784f084529ca1eac1db2d04bb2fdc2635c
parent620be59b1e04670fed73f0a914065f7df2ec3535 (diff)
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.
-rw-r--r--src/Piece.cc20
-rw-r--r--src/Piece.h16
-rw-r--r--test/DefaultBtProgressInfoFileTest.cc8
-rw-r--r--test/PieceTest.cc2
4 files changed, 26 insertions, 20 deletions
diff --git a/src/Piece.cc b/src/Piece.cc
index 55b5a64b..8ab439f8 100644
--- a/src/Piece.cc
+++ b/src/Piece.cc
@@ -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_);
}
diff --git a/src/Piece.h b/src/Piece.h
index 2389c3ac..c5252b67 100644
--- a/src/Piece.h
+++ b/src/Piece.h
@@ -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);
diff --git a/test/DefaultBtProgressInfoFileTest.cc b/test/DefaultBtProgressInfoFileTest.cc
index 974c0555..2754a7f7 100644
--- a/test/DefaultBtProgressInfoFileTest.cc
+++ b/test/DefaultBtProgressInfoFileTest.cc
@@ -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()
diff --git a/test/PieceTest.cc b/test/PieceTest.cc
index 3a7c7b17..5dd48f43 100644
--- a/test/PieceTest.cc
+++ b/test/PieceTest.cc
@@ -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()