mirror of https://github.com/aria2/aria2
2009-11-29 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
Added option --bt-prioritize-piece. This option instruct aria2 to try to download first and last pieces of each file first. The argument can contain 2 keywords:head and tail. To include both keywords, they must be separated by comma. These keywords can take one parameter, SIZE. For example , if head=SIZE is specified, pieces in the range of first SIZE bytes of each file get higher priority. tail=SIZE means the range of last SIZE bytes of each file. SIZE can include K or M(1K = 1024, 1M = 1024K). * src/DefaultPieceStorage.h * src/Makefile.am * src/OptionHandlerFactory.cc * src/OptionHandlerImpl.h * src/PriorityPieceSelector.cc * src/PriorityPieceSelector.h * src/RequestGroup.cc * src/prefs.cc * src/prefs.h * src/usage_text.h * src/util.cc * src/util.h * test/Makefile.am * test/MockPieceSelector.h * test/PriorityPieceSelectorTest.cc * test/UtilTest.ccpull/1/head
parent
30ba476e9d
commit
e208302947
27
ChangeLog
27
ChangeLog
|
@ -1,3 +1,30 @@
|
||||||
|
2009-11-29 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
|
||||||
|
|
||||||
|
Added option --bt-prioritize-piece. This option instruct aria2 to
|
||||||
|
try to download first and last pieces of each file first. The
|
||||||
|
argument can contain 2 keywords:head and tail. To include both
|
||||||
|
keywords, they must be separated by comma. These keywords can take
|
||||||
|
one parameter, SIZE. For example , if head=SIZE is specified,
|
||||||
|
pieces in the range of first SIZE bytes of each file get higher
|
||||||
|
priority. tail=SIZE means the range of last SIZE bytes of each
|
||||||
|
file. SIZE can include K or M(1K = 1024, 1M = 1024K).
|
||||||
|
* src/DefaultPieceStorage.h
|
||||||
|
* src/Makefile.am
|
||||||
|
* src/OptionHandlerFactory.cc
|
||||||
|
* src/OptionHandlerImpl.h
|
||||||
|
* src/PriorityPieceSelector.cc
|
||||||
|
* src/PriorityPieceSelector.h
|
||||||
|
* src/RequestGroup.cc
|
||||||
|
* src/prefs.cc
|
||||||
|
* src/prefs.h
|
||||||
|
* src/usage_text.h
|
||||||
|
* src/util.cc
|
||||||
|
* src/util.h
|
||||||
|
* test/Makefile.am
|
||||||
|
* test/MockPieceSelector.h
|
||||||
|
* test/PriorityPieceSelectorTest.cc
|
||||||
|
* test/UtilTest.cc
|
||||||
|
|
||||||
2009-11-29 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
|
2009-11-29 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
|
||||||
|
|
||||||
Fixed typo
|
Fixed typo
|
||||||
|
|
|
@ -239,6 +239,12 @@ public:
|
||||||
{
|
{
|
||||||
_pieceSelector = pieceSelector;
|
_pieceSelector = pieceSelector;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SharedHandle<PieceSelector> getPieceSelector() const
|
||||||
|
{
|
||||||
|
return _pieceSelector;
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef SharedHandle<DefaultPieceStorage> DefaultPieceStorageHandle;
|
typedef SharedHandle<DefaultPieceStorage> DefaultPieceStorageHandle;
|
||||||
|
|
|
@ -442,7 +442,8 @@ SRCS += PeerAbstractCommand.cc PeerAbstractCommand.h\
|
||||||
ExtensionMessageRegistry.h\
|
ExtensionMessageRegistry.h\
|
||||||
bencode.cc bencode.h\
|
bencode.cc bencode.h\
|
||||||
bittorrent_helper.cc bittorrent_helper.h\
|
bittorrent_helper.cc bittorrent_helper.h\
|
||||||
BtStopDownloadCommand.cc BtStopDownloadCommand.h
|
BtStopDownloadCommand.cc BtStopDownloadCommand.h\
|
||||||
|
PriorityPieceSelector.cc PriorityPieceSelector.h
|
||||||
endif # ENABLE_BITTORRENT
|
endif # ENABLE_BITTORRENT
|
||||||
|
|
||||||
if ENABLE_METALINK
|
if ENABLE_METALINK
|
||||||
|
|
|
@ -240,7 +240,8 @@ bin_PROGRAMS = aria2c$(EXEEXT)
|
||||||
@ENABLE_BITTORRENT_TRUE@ ExtensionMessageRegistry.h\
|
@ENABLE_BITTORRENT_TRUE@ ExtensionMessageRegistry.h\
|
||||||
@ENABLE_BITTORRENT_TRUE@ bencode.cc bencode.h\
|
@ENABLE_BITTORRENT_TRUE@ bencode.cc bencode.h\
|
||||||
@ENABLE_BITTORRENT_TRUE@ bittorrent_helper.cc bittorrent_helper.h\
|
@ENABLE_BITTORRENT_TRUE@ bittorrent_helper.cc bittorrent_helper.h\
|
||||||
@ENABLE_BITTORRENT_TRUE@ BtStopDownloadCommand.cc BtStopDownloadCommand.h
|
@ENABLE_BITTORRENT_TRUE@ BtStopDownloadCommand.cc BtStopDownloadCommand.h\
|
||||||
|
@ENABLE_BITTORRENT_TRUE@ PriorityPieceSelector.cc PriorityPieceSelector.h
|
||||||
|
|
||||||
@ENABLE_METALINK_TRUE@am__append_14 = Metalinker.cc Metalinker.h\
|
@ENABLE_METALINK_TRUE@am__append_14 = Metalinker.cc Metalinker.h\
|
||||||
@ENABLE_METALINK_TRUE@ MetalinkEntry.cc MetalinkEntry.h\
|
@ENABLE_METALINK_TRUE@ MetalinkEntry.cc MetalinkEntry.h\
|
||||||
|
@ -568,7 +569,8 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \
|
||||||
ZeroBtMessage.h RangeBtMessageValidator.h \
|
ZeroBtMessage.h RangeBtMessageValidator.h \
|
||||||
IndexBtMessageValidator.h ExtensionMessageRegistry.h \
|
IndexBtMessageValidator.h ExtensionMessageRegistry.h \
|
||||||
bencode.cc bencode.h bittorrent_helper.cc bittorrent_helper.h \
|
bencode.cc bencode.h bittorrent_helper.cc bittorrent_helper.h \
|
||||||
BtStopDownloadCommand.cc BtStopDownloadCommand.h Metalinker.cc \
|
BtStopDownloadCommand.cc BtStopDownloadCommand.h \
|
||||||
|
PriorityPieceSelector.cc PriorityPieceSelector.h Metalinker.cc \
|
||||||
Metalinker.h MetalinkEntry.cc MetalinkEntry.h \
|
Metalinker.h MetalinkEntry.cc MetalinkEntry.h \
|
||||||
MetalinkResource.cc MetalinkResource.h MetalinkProcessor.h \
|
MetalinkResource.cc MetalinkResource.h MetalinkProcessor.h \
|
||||||
MetalinkParserController.cc MetalinkParserController.h \
|
MetalinkParserController.cc MetalinkParserController.h \
|
||||||
|
@ -730,7 +732,8 @@ am__objects_6 =
|
||||||
@ENABLE_BITTORRENT_TRUE@ ZeroBtMessage.$(OBJEXT) \
|
@ENABLE_BITTORRENT_TRUE@ ZeroBtMessage.$(OBJEXT) \
|
||||||
@ENABLE_BITTORRENT_TRUE@ bencode.$(OBJEXT) \
|
@ENABLE_BITTORRENT_TRUE@ bencode.$(OBJEXT) \
|
||||||
@ENABLE_BITTORRENT_TRUE@ bittorrent_helper.$(OBJEXT) \
|
@ENABLE_BITTORRENT_TRUE@ bittorrent_helper.$(OBJEXT) \
|
||||||
@ENABLE_BITTORRENT_TRUE@ BtStopDownloadCommand.$(OBJEXT)
|
@ENABLE_BITTORRENT_TRUE@ BtStopDownloadCommand.$(OBJEXT) \
|
||||||
|
@ENABLE_BITTORRENT_TRUE@ PriorityPieceSelector.$(OBJEXT)
|
||||||
@ENABLE_METALINK_TRUE@am__objects_14 = Metalinker.$(OBJEXT) \
|
@ENABLE_METALINK_TRUE@am__objects_14 = Metalinker.$(OBJEXT) \
|
||||||
@ENABLE_METALINK_TRUE@ MetalinkEntry.$(OBJEXT) \
|
@ENABLE_METALINK_TRUE@ MetalinkEntry.$(OBJEXT) \
|
||||||
@ENABLE_METALINK_TRUE@ MetalinkResource.$(OBJEXT) \
|
@ENABLE_METALINK_TRUE@ MetalinkResource.$(OBJEXT) \
|
||||||
|
@ -1507,6 +1510,7 @@ distclean-compile:
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PieceStatMan.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PieceStatMan.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PiecedSegment.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PiecedSegment.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Platform.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Platform.Po@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PriorityPieceSelector.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ProtocolDetector.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ProtocolDetector.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/RangeBtMessage.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/RangeBtMessage.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/RarestPieceSelector.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/RarestPieceSelector.Po@am__quote@
|
||||||
|
|
|
@ -969,6 +969,13 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
|
||||||
op->addTag(TAG_BITTORRENT);
|
op->addTag(TAG_BITTORRENT);
|
||||||
handlers.push_back(op);
|
handlers.push_back(op);
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
SharedHandle<OptionHandler> op(new PrioritizePieceOptionHandler
|
||||||
|
(PREF_BT_PRIORITIZE_PIECE,
|
||||||
|
TEXT_BT_PRIORITIZE_PIECE));
|
||||||
|
op->addTag(TAG_BITTORRENT);
|
||||||
|
handlers.push_back(op);
|
||||||
|
}
|
||||||
{
|
{
|
||||||
SharedHandle<OptionHandler> op(new UnitNumberOptionHandler
|
SharedHandle<OptionHandler> op(new UnitNumberOptionHandler
|
||||||
(PREF_BT_REQUEST_PEER_SPEED_LIMIT,
|
(PREF_BT_REQUEST_PEER_SPEED_LIMIT,
|
||||||
|
|
|
@ -55,6 +55,7 @@
|
||||||
#include "a2functional.h"
|
#include "a2functional.h"
|
||||||
#include "message.h"
|
#include "message.h"
|
||||||
#include "File.h"
|
#include "File.h"
|
||||||
|
#include "FileEntry.h"
|
||||||
|
|
||||||
namespace aria2 {
|
namespace aria2 {
|
||||||
|
|
||||||
|
@ -601,6 +602,32 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class PrioritizePieceOptionHandler:public NameMatchOptionHandler {
|
||||||
|
public:
|
||||||
|
PrioritizePieceOptionHandler
|
||||||
|
(const std::string& optName,
|
||||||
|
const std::string& description = NO_DESCRIPTION,
|
||||||
|
const std::string& defaultValue = NO_DEFAULT_VALUE,
|
||||||
|
char shortName = 0):
|
||||||
|
NameMatchOptionHandler(optName, description, defaultValue,
|
||||||
|
OptionHandler::REQ_ARG, shortName) {}
|
||||||
|
|
||||||
|
virtual void parseArg(Option& option, const std::string& optarg)
|
||||||
|
{
|
||||||
|
// Parse optarg against empty FileEntry list to detect syntax
|
||||||
|
// error.
|
||||||
|
std::vector<size_t> result;
|
||||||
|
util::parsePrioritizePieceRange
|
||||||
|
(result, optarg, std::vector<SharedHandle<FileEntry> >(), 1024);
|
||||||
|
option.put(_optName, optarg);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual std::string createPossibleValuesString() const
|
||||||
|
{
|
||||||
|
return "head[=SIZE],tail[=SIZE]";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace aria2
|
} // namespace aria2
|
||||||
|
|
||||||
#endif // _D_OPTION_HANDLER_IMPL_H_
|
#endif // _D_OPTION_HANDLER_IMPL_H_
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
/* <!-- copyright */
|
||||||
|
/*
|
||||||
|
* aria2 - The high speed download utility
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 Tatsuhiro Tsujikawa
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* In addition, as a special exception, the copyright holders give
|
||||||
|
* permission to link the code of portions of this program with the
|
||||||
|
* OpenSSL library under certain conditions as described in each
|
||||||
|
* individual source file, and distribute linked combinations
|
||||||
|
* including the two.
|
||||||
|
* You must obey the GNU General Public License in all respects
|
||||||
|
* for all of the code used other than OpenSSL. If you modify
|
||||||
|
* file(s) with this exception, you may extend this exception to your
|
||||||
|
* version of the file(s), but you are not obligated to do so. If you
|
||||||
|
* do not wish to do so, delete this exception statement from your
|
||||||
|
* version. If you delete this exception statement from all source
|
||||||
|
* files in the program, then also delete it here.
|
||||||
|
*/
|
||||||
|
/* copyright --> */
|
||||||
|
#include "PriorityPieceSelector.h"
|
||||||
|
#include "bitfield.h"
|
||||||
|
|
||||||
|
namespace aria2 {
|
||||||
|
|
||||||
|
PriorityPieceSelector::PriorityPieceSelector
|
||||||
|
(const SharedHandle<PieceSelector>& selector):
|
||||||
|
_selector(selector) {}
|
||||||
|
|
||||||
|
bool PriorityPieceSelector::select
|
||||||
|
(size_t& index, const unsigned char* bitfield, size_t nbits) const
|
||||||
|
{
|
||||||
|
for(std::vector<size_t>::const_iterator i = _prioritizedPieces.begin();
|
||||||
|
i != _prioritizedPieces.end(); ++i) {
|
||||||
|
if(bitfield::test(bitfield, nbits, *i)) {
|
||||||
|
index = *i;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return _selector->select(index, bitfield, nbits);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace aria2
|
|
@ -0,0 +1,67 @@
|
||||||
|
/* <!-- copyright */
|
||||||
|
/*
|
||||||
|
* aria2 - The high speed download utility
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 Tatsuhiro Tsujikawa
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* In addition, as a special exception, the copyright holders give
|
||||||
|
* permission to link the code of portions of this program with the
|
||||||
|
* OpenSSL library under certain conditions as described in each
|
||||||
|
* individual source file, and distribute linked combinations
|
||||||
|
* including the two.
|
||||||
|
* You must obey the GNU General Public License in all respects
|
||||||
|
* for all of the code used other than OpenSSL. If you modify
|
||||||
|
* file(s) with this exception, you may extend this exception to your
|
||||||
|
* version of the file(s), but you are not obligated to do so. If you
|
||||||
|
* do not wish to do so, delete this exception statement from your
|
||||||
|
* version. If you delete this exception statement from all source
|
||||||
|
* files in the program, then also delete it here.
|
||||||
|
*/
|
||||||
|
/* copyright --> */
|
||||||
|
#ifndef _D_PRIORITY_PIECE_SELECTOR_H_
|
||||||
|
#define _D_PRIORITY_PIECE_SELECTOR_H_
|
||||||
|
|
||||||
|
#include "PieceSelector.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "SharedHandle.h"
|
||||||
|
|
||||||
|
namespace aria2 {
|
||||||
|
|
||||||
|
class PriorityPieceSelector:public PieceSelector {
|
||||||
|
private:
|
||||||
|
std::vector<size_t> _prioritizedPieces;
|
||||||
|
|
||||||
|
SharedHandle<PieceSelector> _selector;
|
||||||
|
public:
|
||||||
|
PriorityPieceSelector(const SharedHandle<PieceSelector>& selector);
|
||||||
|
|
||||||
|
virtual bool select
|
||||||
|
(size_t& index, const unsigned char* bitfield, size_t nbits) const;
|
||||||
|
|
||||||
|
template<typename InputIterator>
|
||||||
|
void setPriorityPiece(InputIterator first, InputIterator last)
|
||||||
|
{
|
||||||
|
std::vector<size_t> t(first, last);
|
||||||
|
_prioritizedPieces.swap(t);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace aria2
|
||||||
|
|
||||||
|
#endif // _D_PRIORITY_PIECE_SELECTOR_H_
|
|
@ -76,6 +76,7 @@
|
||||||
#include "PieceSelector.h"
|
#include "PieceSelector.h"
|
||||||
#include "a2functional.h"
|
#include "a2functional.h"
|
||||||
#include "SocketCore.h"
|
#include "SocketCore.h"
|
||||||
|
#include "SimpleRandomizer.h"
|
||||||
#ifdef ENABLE_MESSAGE_DIGEST
|
#ifdef ENABLE_MESSAGE_DIGEST
|
||||||
# include "CheckIntegrityCommand.h"
|
# include "CheckIntegrityCommand.h"
|
||||||
#endif // ENABLE_MESSAGE_DIGEST
|
#endif // ENABLE_MESSAGE_DIGEST
|
||||||
|
@ -100,6 +101,7 @@
|
||||||
# include "DHTPeerAnnounceStorage.h"
|
# include "DHTPeerAnnounceStorage.h"
|
||||||
# include "DHTEntryPointNameResolveCommand.h"
|
# include "DHTEntryPointNameResolveCommand.h"
|
||||||
# include "LongestSequencePieceSelector.h"
|
# include "LongestSequencePieceSelector.h"
|
||||||
|
# include "PriorityPieceSelector.h"
|
||||||
#endif // ENABLE_BITTORRENT
|
#endif // ENABLE_BITTORRENT
|
||||||
#ifdef ENABLE_METALINK
|
#ifdef ENABLE_METALINK
|
||||||
# include "MetalinkPostDownloadHandler.h"
|
# include "MetalinkPostDownloadHandler.h"
|
||||||
|
@ -440,16 +442,33 @@ void RequestGroup::initPieceStorage()
|
||||||
#ifdef ENABLE_BITTORRENT
|
#ifdef ENABLE_BITTORRENT
|
||||||
SharedHandle<DefaultPieceStorage> ps
|
SharedHandle<DefaultPieceStorage> ps
|
||||||
(new DefaultPieceStorage(_downloadContext, _option.get()));
|
(new DefaultPieceStorage(_downloadContext, _option.get()));
|
||||||
// Use LongestSequencePieceSelector when HTTP/FTP/BitTorrent integrated
|
if(_downloadContext->hasAttribute(bittorrent::BITTORRENT)) {
|
||||||
// downloads. Currently multi-file integrated download is not supported.
|
if(isUriSuppliedForRequsetFileEntry
|
||||||
if(_downloadContext->hasAttribute(bittorrent::BITTORRENT) &&
|
|
||||||
isUriSuppliedForRequsetFileEntry
|
|
||||||
(_downloadContext->getFileEntries().begin(),
|
(_downloadContext->getFileEntries().begin(),
|
||||||
_downloadContext->getFileEntries().end())) {
|
_downloadContext->getFileEntries().end())) {
|
||||||
|
// Use LongestSequencePieceSelector when HTTP/FTP/BitTorrent
|
||||||
|
// integrated downloads. Currently multi-file integrated
|
||||||
|
// download is not supported.
|
||||||
_logger->debug("Using LongestSequencePieceSelector");
|
_logger->debug("Using LongestSequencePieceSelector");
|
||||||
ps->setPieceSelector
|
ps->setPieceSelector
|
||||||
(SharedHandle<PieceSelector>(new LongestSequencePieceSelector()));
|
(SharedHandle<PieceSelector>(new LongestSequencePieceSelector()));
|
||||||
}
|
}
|
||||||
|
if(_option->defined(PREF_BT_PRIORITIZE_PIECE)) {
|
||||||
|
std::vector<size_t> result;
|
||||||
|
util::parsePrioritizePieceRange
|
||||||
|
(result, _option->get(PREF_BT_PRIORITIZE_PIECE),
|
||||||
|
_downloadContext->getFileEntries(),
|
||||||
|
_downloadContext->getPieceLength());
|
||||||
|
if(!result.empty()) {
|
||||||
|
std::random_shuffle(result.begin(), result.end(),
|
||||||
|
*(SimpleRandomizer::getInstance().get()));
|
||||||
|
SharedHandle<PriorityPieceSelector> priSelector
|
||||||
|
(new PriorityPieceSelector(ps->getPieceSelector()));
|
||||||
|
priSelector->setPriorityPiece(result.begin(), result.end());
|
||||||
|
ps->setPieceSelector(priSelector);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
#else // !ENABLE_BITTORRENT
|
#else // !ENABLE_BITTORRENT
|
||||||
SharedHandle<DefaultPieceStorage> ps
|
SharedHandle<DefaultPieceStorage> ps
|
||||||
(new DefaultPieceStorage(_downloadContext, _option.get()));
|
(new DefaultPieceStorage(_downloadContext, _option.get()));
|
||||||
|
|
|
@ -305,6 +305,8 @@ const std::string PREF_INDEX_OUT("index-out");
|
||||||
const std::string PREF_BT_TRACKER_INTERVAL("bt-tracker-interval");
|
const std::string PREF_BT_TRACKER_INTERVAL("bt-tracker-interval");
|
||||||
// values: 1*digit
|
// values: 1*digit
|
||||||
const std::string PREF_BT_STOP_TIMEOUT("bt-stop-timeout");
|
const std::string PREF_BT_STOP_TIMEOUT("bt-stop-timeout");
|
||||||
|
// values: head[=SIZE]|tail[=SIZE], ...
|
||||||
|
const std::string PREF_BT_PRIORITIZE_PIECE("bt-prioritize-piece");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Metalink related preferences
|
* Metalink related preferences
|
||||||
|
|
|
@ -309,6 +309,8 @@ extern const std::string PREF_INDEX_OUT;
|
||||||
extern const std::string PREF_BT_TRACKER_INTERVAL;
|
extern const std::string PREF_BT_TRACKER_INTERVAL;
|
||||||
// values: 1*digit
|
// values: 1*digit
|
||||||
extern const std::string PREF_BT_STOP_TIMEOUT;
|
extern const std::string PREF_BT_STOP_TIMEOUT;
|
||||||
|
// values: head[=SIZE]|tail[=SIZE], ...
|
||||||
|
extern const std::string PREF_BT_PRIORITIZE_PIECE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Metalink related preferences
|
* Metalink related preferences
|
||||||
|
|
|
@ -567,3 +567,14 @@ _(" --bt-stop-timeout=SEC Stop BitTorrent download if download speed is 0
|
||||||
_(" --xml-rpc-listen-all[=true|false] Listen incoming XML-RPC requests on all\n"\
|
_(" --xml-rpc-listen-all[=true|false] Listen incoming XML-RPC requests on all\n"\
|
||||||
" network interfaces. If false is given, listen only\n"\
|
" network interfaces. If false is given, listen only\n"\
|
||||||
" on local loopback interface.")
|
" on local loopback interface.")
|
||||||
|
#define TEXT_BT_PRIORITIZE_PIECE \
|
||||||
|
_(" --bt-prioritize-piece=head[=SIZE],tail[=SIZE] Try to download first and last\n"\
|
||||||
|
" pieces of each file first. The argument can\n"\
|
||||||
|
" contain 2 keywords:head and tail. To include both\n"\
|
||||||
|
" keywords, they must be separated by comma. These\n"\
|
||||||
|
" keywords can take one parameter, SIZE. For example\n"\
|
||||||
|
" , if head=SIZE is specified, pieces in the range\n"\
|
||||||
|
" of first SIZE bytes of each file get higher\n"\
|
||||||
|
" priority. tail=SIZE means the range of last SIZE\n"\
|
||||||
|
" bytes of each file. SIZE can include K or M(1K =\n"\
|
||||||
|
" 1024, 1M = 1024K).")
|
||||||
|
|
64
src/util.cc
64
src/util.cc
|
@ -525,6 +525,70 @@ IntSequence parseIntRange(const std::string& src)
|
||||||
return values;
|
return values;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void parsePrioritizePieceRange
|
||||||
|
(std::vector<size_t>& result, const std::string& src,
|
||||||
|
const std::vector<SharedHandle<FileEntry> >& fileEntries,
|
||||||
|
size_t pieceLength)
|
||||||
|
{
|
||||||
|
std::vector<size_t> indexes;
|
||||||
|
std::vector<std::string> parts;
|
||||||
|
split(src, std::back_inserter(parts), ",", true);
|
||||||
|
for(std::vector<std::string>::const_iterator i = parts.begin();
|
||||||
|
i != parts.end(); ++i) {
|
||||||
|
if((*i) == "head") {
|
||||||
|
for(std::vector<SharedHandle<FileEntry> >::const_iterator fi =
|
||||||
|
fileEntries.begin(); fi != fileEntries.end(); ++fi) {
|
||||||
|
indexes.push_back((*fi)->getOffset()/pieceLength);
|
||||||
|
}
|
||||||
|
} else if(util::startsWith(*i, "head=")) {
|
||||||
|
std::string sizestr = std::string((*i).begin()+(*i).find("=")+1,
|
||||||
|
(*i).end());
|
||||||
|
uint64_t head = std::max((int64_t)0, getRealSize(sizestr));
|
||||||
|
for(std::vector<SharedHandle<FileEntry> >::const_iterator fi =
|
||||||
|
fileEntries.begin(); fi != fileEntries.end(); ++fi) {
|
||||||
|
if((*fi)->getLength() == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
size_t lastIndex =
|
||||||
|
((*fi)->getOffset()+std::min(head, (*fi)->getLength())-1)/pieceLength;
|
||||||
|
for(size_t index = (*fi)->getOffset()/pieceLength;
|
||||||
|
index <= lastIndex; ++index) {
|
||||||
|
indexes.push_back(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if((*i) == "tail") {
|
||||||
|
for(std::vector<SharedHandle<FileEntry> >::const_iterator fi =
|
||||||
|
fileEntries.begin(); fi != fileEntries.end(); ++fi) {
|
||||||
|
indexes.push_back
|
||||||
|
(((*fi)->getOffset()+(*fi)->getLength()-1)/pieceLength);
|
||||||
|
}
|
||||||
|
} else if(util::startsWith(*i, "tail=")) {
|
||||||
|
std::string sizestr = std::string((*i).begin()+(*i).find("=")+1,
|
||||||
|
(*i).end());
|
||||||
|
size_t tail = std::max((int64_t)0, getRealSize(sizestr));
|
||||||
|
for(std::vector<SharedHandle<FileEntry> >::const_iterator fi =
|
||||||
|
fileEntries.begin(); fi != fileEntries.end(); ++fi) {
|
||||||
|
if((*fi)->getLength() == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
uint64_t endOffset = (*fi)->getLastOffset();
|
||||||
|
size_t fromIndex =
|
||||||
|
(endOffset-1-(std::min(tail, (*fi)->getLength())-1))/pieceLength;
|
||||||
|
for(size_t index = fromIndex; index <= (endOffset-1)/pieceLength;
|
||||||
|
++index) {
|
||||||
|
indexes.push_back(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw DL_ABORT_EX
|
||||||
|
(StringFormat("Unrecognized token %s", (*i).c_str()).str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::sort(indexes.begin(), indexes.end());
|
||||||
|
indexes.erase(std::unique(indexes.begin(), indexes.end()), indexes.end());
|
||||||
|
result.insert(result.end(), indexes.begin(), indexes.end());
|
||||||
|
}
|
||||||
|
|
||||||
std::string getContentDispositionFilename(const std::string& header) {
|
std::string getContentDispositionFilename(const std::string& header) {
|
||||||
static const std::string keyName = "filename=";
|
static const std::string keyName = "filename=";
|
||||||
std::string::size_type attributesp = header.find(keyName);
|
std::string::size_type attributesp = header.find(keyName);
|
||||||
|
|
19
src/util.h
19
src/util.h
|
@ -48,6 +48,7 @@
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "SharedHandle.h"
|
#include "SharedHandle.h"
|
||||||
#include "IntSequence.h"
|
#include "IntSequence.h"
|
||||||
|
@ -193,6 +194,22 @@ uint64_t parseULLInt(const std::string& s, int base = 10);
|
||||||
|
|
||||||
IntSequence parseIntRange(const std::string& src);
|
IntSequence parseIntRange(const std::string& src);
|
||||||
|
|
||||||
|
// Parses string which specifies the range of piece index for higher
|
||||||
|
// priority and appends those indexes into result. The input string
|
||||||
|
// src can contain 2 keywords "head" and "tail". To include both
|
||||||
|
// keywords, they must be separated by comma. "head" means the pieces
|
||||||
|
// where the first byte of each file sits. "tail" means the pieces
|
||||||
|
// where the last byte of each file sits. These keywords can take one
|
||||||
|
// parameter, SIZE. For example, if "head=SIZE" is specified, pieces
|
||||||
|
// in the range of first SIZE bytes of each file get higher
|
||||||
|
// priority. SIZE can include K or M(1K = 1024, 1M = 1024K).
|
||||||
|
//
|
||||||
|
// sample: head=512K,tail=512K
|
||||||
|
void parsePrioritizePieceRange
|
||||||
|
(std::vector<size_t>& result, const std::string& src,
|
||||||
|
const std::vector<SharedHandle<FileEntry> >& fileEntries,
|
||||||
|
size_t pieceLength);
|
||||||
|
|
||||||
// this function temporarily put here
|
// this function temporarily put here
|
||||||
std::string getContentDispositionFilename(const std::string& header);
|
std::string getContentDispositionFilename(const std::string& header);
|
||||||
|
|
||||||
|
@ -293,7 +310,7 @@ parseIndexPath(const std::string& line);
|
||||||
std::map<size_t, std::string> createIndexPathMap(std::istream& i);
|
std::map<size_t, std::string> createIndexPathMap(std::istream& i);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Take a string src which is a deliminated list and add its elements
|
* Take a string src which is a delimited list and add its elements
|
||||||
* into result. result is stored in out.
|
* into result. result is stored in out.
|
||||||
*/
|
*/
|
||||||
template<typename OutputIterator>
|
template<typename OutputIterator>
|
||||||
|
|
|
@ -187,7 +187,9 @@ aria2c_SOURCES += BtAllowedFastMessageTest.cc\
|
||||||
MockExtensionMessageFactory.h\
|
MockExtensionMessageFactory.h\
|
||||||
MockPieceStorage.h\
|
MockPieceStorage.h\
|
||||||
BencodeTest.cc\
|
BencodeTest.cc\
|
||||||
BittorrentHelperTest.cc
|
BittorrentHelperTest.cc\
|
||||||
|
PriorityPieceSelectorTest.cc\
|
||||||
|
MockPieceSelector.h
|
||||||
endif # ENABLE_BITTORRENT
|
endif # ENABLE_BITTORRENT
|
||||||
|
|
||||||
if ENABLE_METALINK
|
if ENABLE_METALINK
|
||||||
|
|
|
@ -136,7 +136,9 @@ check_PROGRAMS = $(am__EXEEXT_1)
|
||||||
@ENABLE_BITTORRENT_TRUE@ MockExtensionMessageFactory.h\
|
@ENABLE_BITTORRENT_TRUE@ MockExtensionMessageFactory.h\
|
||||||
@ENABLE_BITTORRENT_TRUE@ MockPieceStorage.h\
|
@ENABLE_BITTORRENT_TRUE@ MockPieceStorage.h\
|
||||||
@ENABLE_BITTORRENT_TRUE@ BencodeTest.cc\
|
@ENABLE_BITTORRENT_TRUE@ BencodeTest.cc\
|
||||||
@ENABLE_BITTORRENT_TRUE@ BittorrentHelperTest.cc
|
@ENABLE_BITTORRENT_TRUE@ BittorrentHelperTest.cc\
|
||||||
|
@ENABLE_BITTORRENT_TRUE@ PriorityPieceSelectorTest.cc\
|
||||||
|
@ENABLE_BITTORRENT_TRUE@ MockPieceSelector.h
|
||||||
|
|
||||||
@ENABLE_METALINK_TRUE@am__append_7 = MetalinkerTest.cc\
|
@ENABLE_METALINK_TRUE@am__append_7 = MetalinkerTest.cc\
|
||||||
@ENABLE_METALINK_TRUE@ MetalinkEntryTest.cc\
|
@ENABLE_METALINK_TRUE@ MetalinkEntryTest.cc\
|
||||||
|
@ -259,6 +261,7 @@ am__aria2c_SOURCES_DIST = AllTest.cc TestUtil.cc TestUtil.h \
|
||||||
MockDHTTask.h MockDHTTaskFactory.h MockDHTTaskQueue.h \
|
MockDHTTask.h MockDHTTaskFactory.h MockDHTTaskQueue.h \
|
||||||
MockExtensionMessage.h MockExtensionMessageFactory.h \
|
MockExtensionMessage.h MockExtensionMessageFactory.h \
|
||||||
MockPieceStorage.h BencodeTest.cc BittorrentHelperTest.cc \
|
MockPieceStorage.h BencodeTest.cc BittorrentHelperTest.cc \
|
||||||
|
PriorityPieceSelectorTest.cc MockPieceSelector.h \
|
||||||
MetalinkerTest.cc MetalinkEntryTest.cc \
|
MetalinkerTest.cc MetalinkEntryTest.cc \
|
||||||
Metalink2RequestGroupTest.cc \
|
Metalink2RequestGroupTest.cc \
|
||||||
MetalinkPostDownloadHandlerTest.cc MetalinkHelperTest.cc \
|
MetalinkPostDownloadHandlerTest.cc MetalinkHelperTest.cc \
|
||||||
|
@ -347,7 +350,8 @@ am__aria2c_SOURCES_DIST = AllTest.cc TestUtil.cc TestUtil.h \
|
||||||
@ENABLE_BITTORRENT_TRUE@ ARC4Test.$(OBJEXT) \
|
@ENABLE_BITTORRENT_TRUE@ ARC4Test.$(OBJEXT) \
|
||||||
@ENABLE_BITTORRENT_TRUE@ MSEHandshakeTest.$(OBJEXT) \
|
@ENABLE_BITTORRENT_TRUE@ MSEHandshakeTest.$(OBJEXT) \
|
||||||
@ENABLE_BITTORRENT_TRUE@ BencodeTest.$(OBJEXT) \
|
@ENABLE_BITTORRENT_TRUE@ BencodeTest.$(OBJEXT) \
|
||||||
@ENABLE_BITTORRENT_TRUE@ BittorrentHelperTest.$(OBJEXT)
|
@ENABLE_BITTORRENT_TRUE@ BittorrentHelperTest.$(OBJEXT) \
|
||||||
|
@ENABLE_BITTORRENT_TRUE@ PriorityPieceSelectorTest.$(OBJEXT)
|
||||||
@ENABLE_METALINK_TRUE@am__objects_7 = MetalinkerTest.$(OBJEXT) \
|
@ENABLE_METALINK_TRUE@am__objects_7 = MetalinkerTest.$(OBJEXT) \
|
||||||
@ENABLE_METALINK_TRUE@ MetalinkEntryTest.$(OBJEXT) \
|
@ENABLE_METALINK_TRUE@ MetalinkEntryTest.$(OBJEXT) \
|
||||||
@ENABLE_METALINK_TRUE@ Metalink2RequestGroupTest.$(OBJEXT) \
|
@ENABLE_METALINK_TRUE@ Metalink2RequestGroupTest.$(OBJEXT) \
|
||||||
|
@ -840,6 +844,7 @@ distclean-compile:
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PeerTest.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PeerTest.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PieceStatManTest.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PieceStatManTest.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PieceTest.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PieceTest.Po@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PriorityPieceSelectorTest.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ProtocolDetectorTest.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ProtocolDetectorTest.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/RarestPieceSelectorTest.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/RarestPieceSelectorTest.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/RequestGroupManTest.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/RequestGroupManTest.Po@am__quote@
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
#ifndef _D_MOCK_PIECE_SELECTOR_H_
|
||||||
|
#define _D_MOCK_PIECE_SELECTOR_H_
|
||||||
|
|
||||||
|
#include "PieceSelector.h"
|
||||||
|
|
||||||
|
namespace aria2 {
|
||||||
|
|
||||||
|
class MockPieceSelector:public PieceSelector {
|
||||||
|
public:
|
||||||
|
virtual bool select
|
||||||
|
(size_t& index, const unsigned char* bitfield, size_t nbits) const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace aria2
|
||||||
|
|
||||||
|
#endif // _D_MOCK_PIECE_SELECTOR_H_
|
|
@ -0,0 +1,45 @@
|
||||||
|
#include "PriorityPieceSelector.h"
|
||||||
|
|
||||||
|
#include <cppunit/extensions/HelperMacros.h>
|
||||||
|
|
||||||
|
#include "array_fun.h"
|
||||||
|
#include "BitfieldMan.h"
|
||||||
|
#include "MockPieceSelector.h"
|
||||||
|
|
||||||
|
namespace aria2 {
|
||||||
|
|
||||||
|
class PriorityPieceSelectorTest:public CppUnit::TestFixture {
|
||||||
|
|
||||||
|
CPPUNIT_TEST_SUITE(PriorityPieceSelectorTest);
|
||||||
|
CPPUNIT_TEST(testSelect);
|
||||||
|
CPPUNIT_TEST_SUITE_END();
|
||||||
|
public:
|
||||||
|
void testSelect();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
CPPUNIT_TEST_SUITE_REGISTRATION(PriorityPieceSelectorTest);
|
||||||
|
|
||||||
|
void PriorityPieceSelectorTest::testSelect()
|
||||||
|
{
|
||||||
|
size_t pieceLength = 1024;
|
||||||
|
size_t A[] = { 1,200};
|
||||||
|
BitfieldMan bf(pieceLength, pieceLength*256);
|
||||||
|
for(size_t i = 0; i < arrayLength(A); ++i) {
|
||||||
|
bf.setBit(A[i]);
|
||||||
|
}
|
||||||
|
PriorityPieceSelector selector
|
||||||
|
(SharedHandle<PieceSelector>(new MockPieceSelector()));
|
||||||
|
selector.setPriorityPiece(&A[0], &A[arrayLength(A)]);
|
||||||
|
|
||||||
|
size_t index;
|
||||||
|
CPPUNIT_ASSERT(selector.select(index, bf.getBitfield(), bf.countBlock()));
|
||||||
|
CPPUNIT_ASSERT_EQUAL((size_t)1, index);
|
||||||
|
bf.unsetBit(1);
|
||||||
|
CPPUNIT_ASSERT(selector.select(index, bf.getBitfield(), bf.countBlock()));
|
||||||
|
CPPUNIT_ASSERT_EQUAL((size_t)200, index);
|
||||||
|
bf.unsetBit(200);
|
||||||
|
CPPUNIT_ASSERT(!selector.select(index, bf.getBitfield(), bf.countBlock()));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace aria2
|
|
@ -57,6 +57,7 @@ class UtilTest:public CppUnit::TestFixture {
|
||||||
CPPUNIT_TEST(testCreateIndexPathMap);
|
CPPUNIT_TEST(testCreateIndexPathMap);
|
||||||
CPPUNIT_TEST(testGenerateRandomData);
|
CPPUNIT_TEST(testGenerateRandomData);
|
||||||
CPPUNIT_TEST(testFromHex);
|
CPPUNIT_TEST(testFromHex);
|
||||||
|
CPPUNIT_TEST(testParsePrioritizePieceRange);
|
||||||
CPPUNIT_TEST_SUITE_END();
|
CPPUNIT_TEST_SUITE_END();
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -102,6 +103,7 @@ public:
|
||||||
void testCreateIndexPathMap();
|
void testCreateIndexPathMap();
|
||||||
void testGenerateRandomData();
|
void testGenerateRandomData();
|
||||||
void testFromHex();
|
void testFromHex();
|
||||||
|
void testParsePrioritizePieceRange();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -821,4 +823,67 @@ void UtilTest::testFromHex()
|
||||||
CPPUNIT_ASSERT(util::fromHex(src).empty());
|
CPPUNIT_ASSERT(util::fromHex(src).empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UtilTest::testParsePrioritizePieceRange()
|
||||||
|
{
|
||||||
|
// piece index
|
||||||
|
// 0 1 2 3 4 5 6 7
|
||||||
|
// | | | |
|
||||||
|
// file1 | | |
|
||||||
|
// | | |
|
||||||
|
// file2 | |
|
||||||
|
// file3 |
|
||||||
|
// | |
|
||||||
|
// file4 |
|
||||||
|
size_t pieceLength = 1024;
|
||||||
|
std::vector<SharedHandle<FileEntry> > entries(4, SharedHandle<FileEntry>());
|
||||||
|
entries[0].reset(new FileEntry("file1", 1024, 0));
|
||||||
|
entries[1].reset(new FileEntry("file2",2560,entries[0]->getLastOffset()));
|
||||||
|
entries[2].reset(new FileEntry("file3",0,entries[1]->getLastOffset()));
|
||||||
|
entries[3].reset(new FileEntry("file4",3584,entries[2]->getLastOffset()));
|
||||||
|
|
||||||
|
std::vector<size_t> result;
|
||||||
|
util::parsePrioritizePieceRange(result, "head", entries, pieceLength);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((size_t)3, result.size());
|
||||||
|
CPPUNIT_ASSERT_EQUAL((size_t)0, result[0]);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((size_t)1, result[1]);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((size_t)3, result[2]);
|
||||||
|
result.clear();
|
||||||
|
util::parsePrioritizePieceRange(result, "tail", entries, pieceLength);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((size_t)3, result.size());
|
||||||
|
CPPUNIT_ASSERT_EQUAL((size_t)0, result[0]);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((size_t)3, result[1]);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((size_t)6, result[2]);
|
||||||
|
result.clear();
|
||||||
|
util::parsePrioritizePieceRange(result, "head=1K", entries, pieceLength);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((size_t)4, result.size());
|
||||||
|
CPPUNIT_ASSERT_EQUAL((size_t)0, result[0]);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((size_t)1, result[1]);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((size_t)3, result[2]);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((size_t)4, result[3]);
|
||||||
|
result.clear();
|
||||||
|
util::parsePrioritizePieceRange(result, "tail=1K", entries, pieceLength);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((size_t)4, result.size());
|
||||||
|
CPPUNIT_ASSERT_EQUAL((size_t)0, result[0]);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((size_t)2, result[1]);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((size_t)3, result[2]);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((size_t)6, result[3]);
|
||||||
|
result.clear();
|
||||||
|
util::parsePrioritizePieceRange(result, "head,tail", entries, pieceLength);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((size_t)4, result.size());
|
||||||
|
CPPUNIT_ASSERT_EQUAL((size_t)0, result[0]);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((size_t)1, result[1]);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((size_t)3, result[2]);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((size_t)6, result[3]);
|
||||||
|
result.clear();
|
||||||
|
util::parsePrioritizePieceRange
|
||||||
|
(result, "head=300M,tail=300M", entries, pieceLength);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((size_t)7, result.size());
|
||||||
|
for(size_t i = 0; i < 7; ++i) {
|
||||||
|
CPPUNIT_ASSERT_EQUAL(i, result[i]);
|
||||||
|
}
|
||||||
|
result.clear();
|
||||||
|
util::parsePrioritizePieceRange(result, "", entries, pieceLength);
|
||||||
|
CPPUNIT_ASSERT(result.empty());
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace aria2
|
} // namespace aria2
|
||||||
|
|
Loading…
Reference in New Issue