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
pull/1/head
Tatsuhiro Tsujikawa 2009-11-29 06:43:38 +00:00
parent 30ba476e9d
commit e208302947
19 changed files with 464 additions and 17 deletions

View File

@ -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

View File

@ -239,6 +239,12 @@ public:
{
_pieceSelector = pieceSelector;
}
SharedHandle<PieceSelector> getPieceSelector() const
{
return _pieceSelector;
}
};
typedef SharedHandle<DefaultPieceStorage> DefaultPieceStorageHandle;

View File

@ -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

View File

@ -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@

View File

@ -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,

View File

@ -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_

View File

@ -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

View File

@ -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_

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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).")

View File

@ -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);

View File

@ -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>

View File

@ -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

View File

@ -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@

19
test/MockPieceSelector.h Normal file
View File

@ -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_

View File

@ -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

View File

@ -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