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>
|
||||
|
||||
Fixed typo
|
||||
|
|
|
@ -239,6 +239,12 @@ public:
|
|||
{
|
||||
_pieceSelector = pieceSelector;
|
||||
}
|
||||
|
||||
SharedHandle<PieceSelector> getPieceSelector() const
|
||||
{
|
||||
return _pieceSelector;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
typedef SharedHandle<DefaultPieceStorage> DefaultPieceStorageHandle;
|
||||
|
|
|
@ -442,7 +442,8 @@ SRCS += PeerAbstractCommand.cc PeerAbstractCommand.h\
|
|||
ExtensionMessageRegistry.h\
|
||||
bencode.cc bencode.h\
|
||||
bittorrent_helper.cc bittorrent_helper.h\
|
||||
BtStopDownloadCommand.cc BtStopDownloadCommand.h
|
||||
BtStopDownloadCommand.cc BtStopDownloadCommand.h\
|
||||
PriorityPieceSelector.cc PriorityPieceSelector.h
|
||||
endif # ENABLE_BITTORRENT
|
||||
|
||||
if ENABLE_METALINK
|
||||
|
|
|
@ -240,7 +240,8 @@ bin_PROGRAMS = aria2c$(EXEEXT)
|
|||
@ENABLE_BITTORRENT_TRUE@ ExtensionMessageRegistry.h\
|
||||
@ENABLE_BITTORRENT_TRUE@ bencode.cc bencode.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@ MetalinkEntry.cc MetalinkEntry.h\
|
||||
|
@ -568,7 +569,8 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \
|
|||
ZeroBtMessage.h RangeBtMessageValidator.h \
|
||||
IndexBtMessageValidator.h ExtensionMessageRegistry.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 \
|
||||
MetalinkResource.cc MetalinkResource.h MetalinkProcessor.h \
|
||||
MetalinkParserController.cc MetalinkParserController.h \
|
||||
|
@ -730,7 +732,8 @@ am__objects_6 =
|
|||
@ENABLE_BITTORRENT_TRUE@ ZeroBtMessage.$(OBJEXT) \
|
||||
@ENABLE_BITTORRENT_TRUE@ bencode.$(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@ MetalinkEntry.$(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)/PiecedSegment.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)/RangeBtMessage.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);
|
||||
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
|
||||
(PREF_BT_REQUEST_PEER_SPEED_LIMIT,
|
||||
|
|
|
@ -55,6 +55,7 @@
|
|||
#include "a2functional.h"
|
||||
#include "message.h"
|
||||
#include "File.h"
|
||||
#include "FileEntry.h"
|
||||
|
||||
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
|
||||
|
||||
#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 "a2functional.h"
|
||||
#include "SocketCore.h"
|
||||
#include "SimpleRandomizer.h"
|
||||
#ifdef ENABLE_MESSAGE_DIGEST
|
||||
# include "CheckIntegrityCommand.h"
|
||||
#endif // ENABLE_MESSAGE_DIGEST
|
||||
|
@ -100,6 +101,7 @@
|
|||
# include "DHTPeerAnnounceStorage.h"
|
||||
# include "DHTEntryPointNameResolveCommand.h"
|
||||
# include "LongestSequencePieceSelector.h"
|
||||
# include "PriorityPieceSelector.h"
|
||||
#endif // ENABLE_BITTORRENT
|
||||
#ifdef ENABLE_METALINK
|
||||
# include "MetalinkPostDownloadHandler.h"
|
||||
|
@ -440,15 +442,32 @@ void RequestGroup::initPieceStorage()
|
|||
#ifdef ENABLE_BITTORRENT
|
||||
SharedHandle<DefaultPieceStorage> ps
|
||||
(new DefaultPieceStorage(_downloadContext, _option.get()));
|
||||
// Use LongestSequencePieceSelector when HTTP/FTP/BitTorrent integrated
|
||||
// downloads. Currently multi-file integrated download is not supported.
|
||||
if(_downloadContext->hasAttribute(bittorrent::BITTORRENT) &&
|
||||
isUriSuppliedForRequsetFileEntry
|
||||
(_downloadContext->getFileEntries().begin(),
|
||||
_downloadContext->getFileEntries().end())) {
|
||||
_logger->debug("Using LongestSequencePieceSelector");
|
||||
ps->setPieceSelector
|
||||
(SharedHandle<PieceSelector>(new LongestSequencePieceSelector()));
|
||||
if(_downloadContext->hasAttribute(bittorrent::BITTORRENT)) {
|
||||
if(isUriSuppliedForRequsetFileEntry
|
||||
(_downloadContext->getFileEntries().begin(),
|
||||
_downloadContext->getFileEntries().end())) {
|
||||
// Use LongestSequencePieceSelector when HTTP/FTP/BitTorrent
|
||||
// integrated downloads. Currently multi-file integrated
|
||||
// download is not supported.
|
||||
_logger->debug("Using LongestSequencePieceSelector");
|
||||
ps->setPieceSelector
|
||||
(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
|
||||
SharedHandle<DefaultPieceStorage> ps
|
||||
|
|
|
@ -305,6 +305,8 @@ const std::string PREF_INDEX_OUT("index-out");
|
|||
const std::string PREF_BT_TRACKER_INTERVAL("bt-tracker-interval");
|
||||
// values: 1*digit
|
||||
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
|
||||
|
|
|
@ -309,6 +309,8 @@ extern const std::string PREF_INDEX_OUT;
|
|||
extern const std::string PREF_BT_TRACKER_INTERVAL;
|
||||
// values: 1*digit
|
||||
extern const std::string PREF_BT_STOP_TIMEOUT;
|
||||
// values: head[=SIZE]|tail[=SIZE], ...
|
||||
extern const std::string PREF_BT_PRIORITIZE_PIECE;
|
||||
|
||||
/**
|
||||
* 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"\
|
||||
" network interfaces. If false is given, listen only\n"\
|
||||
" 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;
|
||||
}
|
||||
|
||||
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) {
|
||||
static const std::string keyName = "filename=";
|
||||
std::string::size_type attributesp = header.find(keyName);
|
||||
|
|
19
src/util.h
19
src/util.h
|
@ -48,6 +48,7 @@
|
|||
#include <map>
|
||||
#include <iomanip>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
#include "SharedHandle.h"
|
||||
#include "IntSequence.h"
|
||||
|
@ -193,6 +194,22 @@ uint64_t parseULLInt(const std::string& s, int base = 10);
|
|||
|
||||
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
|
||||
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);
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
template<typename OutputIterator>
|
||||
|
|
|
@ -187,7 +187,9 @@ aria2c_SOURCES += BtAllowedFastMessageTest.cc\
|
|||
MockExtensionMessageFactory.h\
|
||||
MockPieceStorage.h\
|
||||
BencodeTest.cc\
|
||||
BittorrentHelperTest.cc
|
||||
BittorrentHelperTest.cc\
|
||||
PriorityPieceSelectorTest.cc\
|
||||
MockPieceSelector.h
|
||||
endif # ENABLE_BITTORRENT
|
||||
|
||||
if ENABLE_METALINK
|
||||
|
|
|
@ -136,7 +136,9 @@ check_PROGRAMS = $(am__EXEEXT_1)
|
|||
@ENABLE_BITTORRENT_TRUE@ MockExtensionMessageFactory.h\
|
||||
@ENABLE_BITTORRENT_TRUE@ MockPieceStorage.h\
|
||||
@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@ MetalinkEntryTest.cc\
|
||||
|
@ -259,6 +261,7 @@ am__aria2c_SOURCES_DIST = AllTest.cc TestUtil.cc TestUtil.h \
|
|||
MockDHTTask.h MockDHTTaskFactory.h MockDHTTaskQueue.h \
|
||||
MockExtensionMessage.h MockExtensionMessageFactory.h \
|
||||
MockPieceStorage.h BencodeTest.cc BittorrentHelperTest.cc \
|
||||
PriorityPieceSelectorTest.cc MockPieceSelector.h \
|
||||
MetalinkerTest.cc MetalinkEntryTest.cc \
|
||||
Metalink2RequestGroupTest.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@ MSEHandshakeTest.$(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@ MetalinkEntryTest.$(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)/PieceStatManTest.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)/RarestPieceSelectorTest.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(testGenerateRandomData);
|
||||
CPPUNIT_TEST(testFromHex);
|
||||
CPPUNIT_TEST(testParsePrioritizePieceRange);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
private:
|
||||
|
||||
|
@ -102,6 +103,7 @@ public:
|
|||
void testCreateIndexPathMap();
|
||||
void testGenerateRandomData();
|
||||
void testFromHex();
|
||||
void testParsePrioritizePieceRange();
|
||||
};
|
||||
|
||||
|
||||
|
@ -821,4 +823,67 @@ void UtilTest::testFromHex()
|
|||
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
|
||||
|
|
Loading…
Reference in New Issue