summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>2010-07-15 11:39:21 +0000
committerTatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>2010-07-15 11:39:21 +0000
commit1ddaaf7614a413947b59b9be4ee2c4c52d463e4a (patch)
tree81103314dcf6cde0f205d11b76004a20ffa36d43 /src
parent55748de7268ac073a7e76d133996d229cf26b190 (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.cc68
-rw-r--r--src/BitfieldMan.h6
-rw-r--r--src/DefaultPieceStorage.cc6
-rw-r--r--src/DefaultPieceStorage.h8
-rw-r--r--src/OptionHandlerFactory.cc11
-rw-r--r--src/RequestGroup.cc1
-rw-r--r--src/prefs.cc2
-rw-r--r--src/prefs.h2
-rw-r--r--src/usage_text.h8
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.")