diff options
| author | Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com> | 2010-07-15 11:39:21 +0000 |
|---|---|---|
| committer | Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com> | 2010-07-15 11:39:21 +0000 |
| commit | 1ddaaf7614a413947b59b9be4ee2c4c52d463e4a (patch) | |
| tree | 81103314dcf6cde0f205d11b76004a20ffa36d43 /src | |
| parent | 55748de7268ac073a7e76d133996d229cf26b190 (diff) | |
2010-07-15 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
Added --min-split-size=SIZE option. aria2 does not split less
than 2*SIZE byte range. For example, let's consider downloading
20MiB file. If SIZE is 10M, aria2 can split file into 2 range
[0-10MiB) and [10MiB-20MiB) and download it using 2 sources(if
--split >= 2, of course). If SIZE is 15M, since 2*15M > 20MiB,
aria2 does not split file and download it using 1 source.
* src/BitfieldMan.cc
* src/BitfieldMan.h
* src/DefaultPieceStorage.cc
* src/DefaultPieceStorage.h
* src/OptionHandlerFactory.cc
* src/RequestGroup.cc
* src/prefs.cc
* src/prefs.h
* src/usage_text.h
* test/BitfieldManTest.cc
* test/SegmentManTest.cc
Diffstat (limited to 'src')
| -rw-r--r-- | src/BitfieldMan.cc | 68 | ||||
| -rw-r--r-- | src/BitfieldMan.h | 6 | ||||
| -rw-r--r-- | src/DefaultPieceStorage.cc | 6 | ||||
| -rw-r--r-- | src/DefaultPieceStorage.h | 8 | ||||
| -rw-r--r-- | src/OptionHandlerFactory.cc | 11 | ||||
| -rw-r--r-- | src/RequestGroup.cc | 1 | ||||
| -rw-r--r-- | src/prefs.cc | 2 | ||||
| -rw-r--r-- | src/prefs.h | 2 | ||||
| -rw-r--r-- | src/usage_text.h | 8 |
9 files changed, 88 insertions, 24 deletions
diff --git a/src/BitfieldMan.cc b/src/BitfieldMan.cc index 907a05ce..427e02de 100644 --- a/src/BitfieldMan.cc +++ b/src/BitfieldMan.cc @@ -221,37 +221,59 @@ static size_t getEndIndex(size_t index, const Array& bitfield, size_t blocks) { template<typename Array> static bool getSparseMissingUnusedIndex (size_t& index, + size_t minSplitSize, const Array& bitfield, const unsigned char* useBitfield, + size_t blockLength_, size_t blocks) { BitfieldMan::Range maxRange; BitfieldMan::Range currentRange; - { - size_t nextIndex = 0; - while(nextIndex < blocks) { - currentRange.startIndex = - getStartIndex(nextIndex, bitfield, blocks); - if(currentRange.startIndex == blocks) { - break; - } - currentRange.endIndex = - getEndIndex(currentRange.startIndex, bitfield, blocks); - if(maxRange < currentRange) { - maxRange = currentRange; + size_t nextIndex = 0; + while(nextIndex < blocks) { + currentRange.startIndex = + getStartIndex(nextIndex, bitfield, blocks); + if(currentRange.startIndex == blocks) { + break; + } + currentRange.endIndex = + getEndIndex(currentRange.startIndex, bitfield, blocks); + + if(currentRange.startIndex > 0) { + if(bitfield::test(useBitfield, blocks, currentRange.startIndex-1)) { + currentRange.startIndex = currentRange.getMidIndex(); } - nextIndex = currentRange.endIndex; } + // If range is equal, choose a range where its startIndex-1 is + // set. + if(maxRange < currentRange || + (maxRange == currentRange && + maxRange.startIndex > 0 && currentRange.startIndex > 0 && + (!bitfield::test(bitfield, blocks, maxRange.startIndex-1) || + bitfield::test(useBitfield, blocks, maxRange.startIndex-1)) + && + bitfield::test(bitfield, blocks, currentRange.startIndex-1) && + !bitfield::test(useBitfield, blocks, currentRange.startIndex-1))) { + maxRange = currentRange; + } + nextIndex = currentRange.endIndex; + } if(maxRange.getSize()) { if(maxRange.startIndex == 0) { index = 0; - } else if(bitfield::test(useBitfield, blocks, maxRange.startIndex-1)) { - index = maxRange.getMidIndex(); + return true; } else { - index = maxRange.startIndex; + if((!bitfield::test(useBitfield, blocks, maxRange.startIndex-1) && + bitfield::test(bitfield, blocks, maxRange.startIndex-1)) || + ((uint64_t)(maxRange.endIndex-maxRange.startIndex)*blockLength_ + >= minSplitSize)) { + index = maxRange.startIndex; + return true; + } else { + return false; + } } - return true; } else { return false; } @@ -259,17 +281,21 @@ static bool getSparseMissingUnusedIndex bool BitfieldMan::getSparseMissingUnusedIndex (size_t& index, + size_t minSplitSize, const unsigned char* ignoreBitfield, size_t ignoreBitfieldLength) const { if(filterEnabled_) { return aria2::getSparseMissingUnusedIndex - (index, array(ignoreBitfield)|~array(filterBitfield_)|array(bitfield_)|array(useBitfield_), - useBitfield_, blocks_); + (index, minSplitSize, + array(ignoreBitfield)|~array(filterBitfield_)| + array(bitfield_)|array(useBitfield_), + useBitfield_, blockLength_, blocks_); } else { return aria2::getSparseMissingUnusedIndex - (index, array(ignoreBitfield)|array(bitfield_)|array(useBitfield_), - useBitfield_, blocks_); + (index, minSplitSize, + array(ignoreBitfield)|array(bitfield_)|array(useBitfield_), + useBitfield_, blockLength_, blocks_); } } diff --git a/src/BitfieldMan.h b/src/BitfieldMan.h index c08812e8..912702e2 100644 --- a/src/BitfieldMan.h +++ b/src/BitfieldMan.h @@ -92,6 +92,11 @@ public: bool operator<(const Range& range) const { return getSize() < range.getSize(); } + + bool operator==(const Range& range) const + { + return getSize() == range.getSize(); + } }; public: BitfieldMan(size_t blockLength, uint64_t totalLength); @@ -144,6 +149,7 @@ public: // affected by filter bool getSparseMissingUnusedIndex (size_t& index, + size_t minSplitSize, const unsigned char* ignoreBitfield, size_t ignoreBitfieldLength) const; diff --git a/src/DefaultPieceStorage.cc b/src/DefaultPieceStorage.cc index 901e5a42..a0b0d415 100644 --- a/src/DefaultPieceStorage.cc +++ b/src/DefaultPieceStorage.cc @@ -72,7 +72,8 @@ DefaultPieceStorage::DefaultPieceStorage logger_(LogFactory::getInstance()), option_(option), pieceStatMan_(new PieceStatMan(downloadContext->getNumPieces(), true)), - pieceSelector_(new RarestPieceSelector(pieceStatMan_)) + pieceSelector_(new RarestPieceSelector(pieceStatMan_)), + minSplitSize_(1024*1024) {} DefaultPieceStorage::~DefaultPieceStorage() { @@ -272,7 +273,8 @@ SharedHandle<Piece> DefaultPieceStorage::getSparseMissingUnusedPiece (const unsigned char* ignoreBitfield, size_t length) { size_t index; - if(bitfieldMan_->getSparseMissingUnusedIndex(index, ignoreBitfield, length)) { + if(bitfieldMan_->getSparseMissingUnusedIndex + (index, minSplitSize_, ignoreBitfield, length)) { return checkOutPiece(index); } else { return SharedHandle<Piece>(); diff --git a/src/DefaultPieceStorage.h b/src/DefaultPieceStorage.h index 06fc64ae..dce56c5f 100644 --- a/src/DefaultPieceStorage.h +++ b/src/DefaultPieceStorage.h @@ -87,6 +87,8 @@ private: SharedHandle<PieceSelector> pieceSelector_; + size_t minSplitSize_; + bool getMissingPieceIndex(size_t& index, const unsigned char* bitfield, size_t length); @@ -251,7 +253,11 @@ public: { return pieceSelector_; } - + + void setMinSplitSize(size_t minSplitSize) + { + minSplitSize_ = minSplitSize; + } }; typedef SharedHandle<DefaultPieceStorage> DefaultPieceStorageHandle; diff --git a/src/OptionHandlerFactory.cc b/src/OptionHandlerFactory.cc index 4884cd84..97d9bdfa 100644 --- a/src/OptionHandlerFactory.cc +++ b/src/OptionHandlerFactory.cc @@ -367,6 +367,17 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers() handlers.push_back(op); } { + SharedHandle<OptionHandler> op(new UnitNumberOptionHandler + (PREF_MIN_SPLIT_SIZE, + TEXT_MIN_SPLIT_SIZE, + "20M", + 1024*1024, 1024*1024*1024)); + op->addTag(TAG_ADVANCED); + op->addTag(TAG_FTP); + op->addTag(TAG_HTTP); + handlers.push_back(op); + } + { SharedHandle<OptionHandler> op(new BooleanOptionHandler (PREF_NO_CONF, TEXT_NO_CONF, diff --git a/src/RequestGroup.cc b/src/RequestGroup.cc index 612fe1fd..148b2e12 100644 --- a/src/RequestGroup.cc +++ b/src/RequestGroup.cc @@ -534,6 +534,7 @@ void RequestGroup::initPieceStorage() if(!diskWriterFactory_.isNull()) { ps->setDiskWriterFactory(diskWriterFactory_); } + ps->setMinSplitSize(option_->getAsInt(PREF_MIN_SPLIT_SIZE)); tempPieceStorage = ps; } else { UnknownLengthPieceStorageHandle ps diff --git a/src/prefs.cc b/src/prefs.cc index 95afc73d..c9db428f 100644 --- a/src/prefs.cc +++ b/src/prefs.cc @@ -192,6 +192,8 @@ const std::string PREF_MAX_RESUME_FAILURE_TRIES("max-resume-failure-tries"); const std::string PREF_SAVE_SESSION("save-session"); // value: 1*digit const std::string PREF_MAX_CONNECTION_PER_SERVER("max-connection-per-server"); +// value: 1*digit +const std::string PREF_MIN_SPLIT_SIZE("min-split-size"); /** * FTP related preferences diff --git a/src/prefs.h b/src/prefs.h index 2a59453a..a270ec9a 100644 --- a/src/prefs.h +++ b/src/prefs.h @@ -196,6 +196,8 @@ extern const std::string PREF_MAX_RESUME_FAILURE_TRIES; extern const std::string PREF_SAVE_SESSION; // value: 1*digit extern const std::string PREF_MAX_CONNECTION_PER_SERVER; +// value: 1*digit +extern const std::string PREF_MIN_SPLIT_SIZE; /** * FTP related preferences diff --git a/src/usage_text.h b/src/usage_text.h index 8e9b3517..a9fda018 100644 --- a/src/usage_text.h +++ b/src/usage_text.h @@ -686,3 +686,11 @@ #define TEXT_MAX_CONNECTION_PER_SERVER \ _(" --max-connection-per-server=NUM The maximum number of connections to one server\n"\ " for each download.") +#define TEXT_MIN_SPLIT_SIZE \ + _(" --min-split-size=SIZE aria2 does not split less than 2*SIZE byte range.\n" \ + " For example, let's consider downloading 20MiB\n" \ + " file. If SIZE is 10M, aria2 can split file into 2\n" \ + " range [0-10MiB) and [10MiB-20MiB) and download it\n" \ + " using 2 sources(if --split >= 2, of course).\n" \ + " If SIZE is 15M, since 2*15M > 20MiB, aria2 does\n" \ + " not split file and download it using 1 source.") |
