2009-05-06 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>

Moved piece statistics stuff to new PieceStatMan class.
	Refactored PieceSelector interface.
	* src/DefaultPieceStorage.cc
	* src/DefaultPieceStorage.h
	* src/LongestSequencePieceSelector.cc
	* src/LongestSequencePieceSelector.h
	* src/Makefile.am
	* src/PieceSelector.h
	* src/PieceStatMan.cc
	* src/PieceStatMan.h
	* src/RarestPieceSelector.cc
	* src/RarestPieceSelector.h
	* src/RequestGroup.cc
	* test/DefaultPieceStorageTest.cc
	* test/InOrderPieceSelector.h
	* test/Makefile.am
	* test/PieceStatManTest.cc
	* test/RarestPieceSelectorTest.cc
pull/1/head
Tatsuhiro Tsujikawa 2009-05-06 07:49:22 +00:00
parent d05d8bbddc
commit 4da631bef6
19 changed files with 655 additions and 477 deletions

View File

@ -1,3 +1,24 @@
2009-05-06 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
Moved piece statistics stuff to new PieceStatMan class.
Refactored PieceSelector interface.
* src/DefaultPieceStorage.cc
* src/DefaultPieceStorage.h
* src/LongestSequencePieceSelector.cc
* src/LongestSequencePieceSelector.h
* src/Makefile.am
* src/PieceSelector.h
* src/PieceStatMan.cc
* src/PieceStatMan.h
* src/RarestPieceSelector.cc
* src/RarestPieceSelector.h
* src/RequestGroup.cc
* test/DefaultPieceStorageTest.cc
* test/InOrderPieceSelector.h
* test/Makefile.am
* test/PieceStatManTest.cc
* test/RarestPieceSelectorTest.cc
2009-05-06 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
Added static member _protocolFamily to SocketCore. By default,

View File

@ -58,13 +58,12 @@
#include "StringFormat.h"
#include "RarestPieceSelector.h"
#include "array_fun.h"
#include "PieceStatMan.h"
namespace aria2 {
DefaultPieceStorage::DefaultPieceStorage
(const DownloadContextHandle& downloadContext,
const Option* option,
const SharedHandle<PieceSelector>& pieceSelector):
(const DownloadContextHandle& downloadContext, const Option* option):
downloadContext(downloadContext),
bitfieldMan(BitfieldManFactory::getFactoryInstance()->
createBitfieldMan(downloadContext->getPieceLength(),
@ -73,13 +72,9 @@ DefaultPieceStorage::DefaultPieceStorage
endGamePieceNum(END_GAME_PIECE_NUM),
logger(LogFactory::getInstance()),
option(option),
_pieceSelector(pieceSelector)
{
if(_pieceSelector.isNull()) {
_pieceSelector.reset
(new RarestPieceSelector(downloadContext->getNumPieces(), true));
}
}
_pieceStatMan(new PieceStatMan(downloadContext->getNumPieces(), true)),
_pieceSelector(new RarestPieceSelector(_pieceStatMan))
{}
DefaultPieceStorage::~DefaultPieceStorage() {
delete bitfieldMan;
@ -653,26 +648,26 @@ void DefaultPieceStorage::setDiskWriterFactory(const DiskWriterFactoryHandle& di
void DefaultPieceStorage::addPieceStats(const unsigned char* bitfield,
size_t bitfieldLength)
{
_pieceSelector->addPieceStats(bitfield, bitfieldLength);
_pieceStatMan->addPieceStats(bitfield, bitfieldLength);
}
void DefaultPieceStorage::subtractPieceStats(const unsigned char* bitfield,
size_t bitfieldLength)
{
_pieceSelector->subtractPieceStats(bitfield, bitfieldLength);
_pieceStatMan->subtractPieceStats(bitfield, bitfieldLength);
}
void DefaultPieceStorage::updatePieceStats(const unsigned char* newBitfield,
size_t newBitfieldLength,
const unsigned char* oldBitfield)
{
_pieceSelector->updatePieceStats(newBitfield, newBitfieldLength,
_pieceStatMan->updatePieceStats(newBitfield, newBitfieldLength,
oldBitfield);
}
void DefaultPieceStorage::addPieceStats(size_t index)
{
_pieceSelector->addPieceStats(index);
_pieceStatMan->addPieceStats(index);
}
} // namespace aria2

View File

@ -45,6 +45,7 @@ class Logger;
class Option;
class DiskWriterFactory;
class FileEntry;
class PieceStatMan;
class PieceSelector;
#define END_GAME_PIECE_NUM 20
@ -81,6 +82,8 @@ private:
const Option* option;
Haves haves;
SharedHandle<PieceStatMan> _pieceStatMan;
SharedHandle<PieceSelector> _pieceSelector;
bool getMissingPieceIndex(size_t& index,
@ -108,9 +111,7 @@ public:
// If it is set to false, a piece whose index is smallest has the highest
// priority.
DefaultPieceStorage(const SharedHandle<DownloadContext>& downloadContext,
const Option* option,
const SharedHandle<PieceSelector>& pieceSelector
= SharedHandle<PieceSelector>());
const Option* option);
virtual ~DefaultPieceStorage();
@ -223,6 +224,16 @@ public:
void addUsedPiece(const SharedHandle<Piece>& piece);
void setDiskWriterFactory(const SharedHandle<DiskWriterFactory>& diskWriterFactory);
const SharedHandle<PieceStatMan>& getPieceStatMan() const
{
return _pieceStatMan;
}
void setPieceSelector(const SharedHandle<PieceSelector>& pieceSelector)
{
_pieceSelector = pieceSelector;
}
};
typedef SharedHandle<DefaultPieceStorage> DefaultPieceStorageHandle;

View File

@ -85,16 +85,4 @@ bool LongestSequencePieceSelector::select
}
}
void LongestSequencePieceSelector::addPieceStats
(const unsigned char* bitfield, size_t bitfieldLength) {}
void LongestSequencePieceSelector::subtractPieceStats
(const unsigned char* bitfield, size_t bitfieldLength) {}
void LongestSequencePieceSelector::updatePieceStats
(const unsigned char* newBitfield, size_t newBitfieldLength,
const unsigned char* oldBitfield) {}
void LongestSequencePieceSelector::addPieceStats(size_t index) {}
} // namespace aria2

View File

@ -47,18 +47,6 @@ public:
// returns 15 because { 10, 11, 12, 13, 14, 15 } is the longest sequence.
virtual bool select
(size_t& index, const unsigned char* bitfield, size_t nbits) const;
virtual void addPieceStats(size_t index);
virtual void addPieceStats(const unsigned char* bitfield,
size_t bitfieldLength);
virtual void subtractPieceStats(const unsigned char* bitfield,
size_t bitfieldLength);
virtual void updatePieceStats(const unsigned char* newBitfield,
size_t newBitfieldLength,
const unsigned char* oldBitfield);
};
} // namespace aria2

View File

@ -117,6 +117,7 @@ SRCS = Socket.h\
PieceStorage.h\
DefaultPieceStorage.cc DefaultPieceStorage.h\
UnknownLengthPieceStorage.cc UnknownLengthPieceStorage.h\
PieceStatMan.cc PieceStatMan.h\
StatCalc.h\
ConsoleStatCalc.cc ConsoleStatCalc.h\
TransferStat.cc TransferStat.h\

View File

@ -1,4 +1,4 @@
# Makefile.in generated by automake 1.10.1 from Makefile.am.
# Makefile.in generated by automake 1.10.2 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
@ -355,8 +355,8 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \
AutoSaveCommand.cc AutoSaveCommand.h PieceStorage.h \
DefaultPieceStorage.cc DefaultPieceStorage.h \
UnknownLengthPieceStorage.cc UnknownLengthPieceStorage.h \
StatCalc.h ConsoleStatCalc.cc ConsoleStatCalc.h \
TransferStat.cc TransferStat.h Dependency.h \
PieceStatMan.cc PieceStatMan.h StatCalc.h ConsoleStatCalc.cc \
ConsoleStatCalc.h TransferStat.cc TransferStat.h Dependency.h \
BtProgressInfoFile.h DefaultBtProgressInfoFile.cc \
DefaultBtProgressInfoFile.h NullProgressInfoFile.h \
FileAllocationIterator.h SingleFileAllocationIterator.cc \
@ -768,8 +768,9 @@ am__objects_23 = SocketCore.$(OBJEXT) Command.$(OBJEXT) \
PStringSegment.$(OBJEXT) PStringBuildVisitor.$(OBJEXT) \
ParameterizedStringParser.$(OBJEXT) TimeBasedCommand.$(OBJEXT) \
AutoSaveCommand.$(OBJEXT) DefaultPieceStorage.$(OBJEXT) \
UnknownLengthPieceStorage.$(OBJEXT) ConsoleStatCalc.$(OBJEXT) \
TransferStat.$(OBJEXT) DefaultBtProgressInfoFile.$(OBJEXT) \
UnknownLengthPieceStorage.$(OBJEXT) PieceStatMan.$(OBJEXT) \
ConsoleStatCalc.$(OBJEXT) TransferStat.$(OBJEXT) \
DefaultBtProgressInfoFile.$(OBJEXT) \
SingleFileAllocationIterator.$(OBJEXT) \
ContentTypeRequestGroupCriteria.$(OBJEXT) \
DownloadHandler.$(OBJEXT) DownloadHandlerConstants.$(OBJEXT) \
@ -1008,6 +1009,7 @@ target_alias = @target_alias@
target_cpu = @target_cpu@
target_os = @target_os@
target_vendor = @target_vendor@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
aria2c_SOURCES = main.cc\
@ -1084,8 +1086,8 @@ SRCS = Socket.h SocketCore.cc SocketCore.h BinaryStream.h Command.cc \
AutoSaveCommand.cc AutoSaveCommand.h PieceStorage.h \
DefaultPieceStorage.cc DefaultPieceStorage.h \
UnknownLengthPieceStorage.cc UnknownLengthPieceStorage.h \
StatCalc.h ConsoleStatCalc.cc ConsoleStatCalc.h \
TransferStat.cc TransferStat.h Dependency.h \
PieceStatMan.cc PieceStatMan.h StatCalc.h ConsoleStatCalc.cc \
ConsoleStatCalc.h TransferStat.cc TransferStat.h Dependency.h \
BtProgressInfoFile.h DefaultBtProgressInfoFile.cc \
DefaultBtProgressInfoFile.h NullProgressInfoFile.h \
FileAllocationIterator.h SingleFileAllocationIterator.cc \
@ -1169,8 +1171,8 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
&& exit 0; \
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
&& { if test -f $@; then exit 0; else break; fi; }; \
exit 1;; \
esac; \
done; \
@ -1466,6 +1468,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Piece.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PieceHashCheckIntegrityEntry.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PieceHashMetalinkParserState.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)/PiecesMetalinkParserState.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Platform.Po@am__quote@
@ -1568,7 +1571,7 @@ ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
mkid -fID $$unique
tags: TAGS

View File

@ -37,9 +37,7 @@
#include "common.h"
#include <deque>
#include "SharedHandle.h"
#include <cstdlib>
namespace aria2 {
@ -49,18 +47,6 @@ public:
virtual bool select
(size_t& index, const unsigned char* bitfield, size_t nbits) const = 0;
virtual void addPieceStats(size_t index) = 0;
virtual void addPieceStats(const unsigned char* bitfield,
size_t bitfieldLength) = 0;
virtual void subtractPieceStats(const unsigned char* bitfield,
size_t bitfieldLength) = 0;
virtual void updatePieceStats(const unsigned char* newBitfield,
size_t newBitfieldLength,
const unsigned char* oldBitfield) = 0;
};
} // namespace aria2

218
src/PieceStatMan.cc Normal file
View File

@ -0,0 +1,218 @@
/* <!-- 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 "PieceStatMan.h"
#include <algorithm>
#include "SimpleRandomizer.h"
namespace aria2 {
PieceStat::PieceStat(size_t index):_order(0), _index(index), _count(0) {}
bool PieceStat::operator<(const PieceStat& pieceStat) const
{
if(_count == pieceStat._count) {
return _order < pieceStat._order;
} else {
return _count < pieceStat._count;
}
}
void PieceStat::addCount()
{
if(_count < SIZE_MAX) {
++_count;
}
}
void PieceStat::subCount()
{
if(_count > 0) {
--_count;
}
}
size_t PieceStat::getIndex() const
{
return _index;
}
size_t PieceStat::getCount() const
{
return _count;
}
void PieceStat::setOrder(size_t order)
{
_order = order;
}
size_t PieceStat::getOrder() const
{
return _order;
}
class GenPieceStat {
private:
size_t _index;
public:
GenPieceStat():_index(0) {}
SharedHandle<PieceStat> operator()()
{
return SharedHandle<PieceStat>(new PieceStat(_index++));
}
};
PieceStatMan::PieceStatMan(size_t pieceNum, bool randomShuffle):
_pieceStats(pieceNum),
_sortedPieceStatIndexes(pieceNum)
{
std::generate(_pieceStats.begin(), _pieceStats.end(), GenPieceStat());
std::vector<SharedHandle<PieceStat> > sortedPieceStats(_pieceStats);
// we need some randomness in ordering.
if(randomShuffle) {
std::random_shuffle(sortedPieceStats.begin(), sortedPieceStats.end(),
*(SimpleRandomizer::getInstance().get()));
}
{
size_t order = 0;
for(std::vector<SharedHandle<PieceStat> >::iterator i =
sortedPieceStats.begin(); i != sortedPieceStats.end(); ++i) {
_sortedPieceStatIndexes[order] = (*i)->getIndex();
(*i)->setOrder(order++);
}
}
}
class PieceStatRarer {
private:
const std::vector<SharedHandle<PieceStat> >& _pieceStats;
public:
PieceStatRarer(const std::vector<SharedHandle<PieceStat> >& ps):
_pieceStats(ps) {}
bool operator()(size_t lhs, size_t rhs) const
{
return _pieceStats[lhs] < _pieceStats[rhs];
}
};
void PieceStatMan::addPieceStats(const unsigned char* bitfield,
size_t bitfieldLength)
{
size_t index = 0;
for(size_t bi = 0; bi < bitfieldLength; ++bi) {
for(size_t i = 0; i < 8; ++i, ++index) {
unsigned char mask = 128 >> i;
if(bitfield[bi]&mask) {
_pieceStats[index]->addCount();
}
}
}
std::sort(_sortedPieceStatIndexes.begin(), _sortedPieceStatIndexes.end(),
PieceStatRarer(_pieceStats));
}
void PieceStatMan::subtractPieceStats(const unsigned char* bitfield,
size_t bitfieldLength)
{
size_t index = 0;
for(size_t bi = 0; bi < bitfieldLength; ++bi) {
for(size_t i = 0; i < 8; ++i, ++index) {
unsigned char mask = 128 >> i;
if(bitfield[bi]&mask) {
_pieceStats[index]->subCount();
}
}
}
std::sort(_sortedPieceStatIndexes.begin(), _sortedPieceStatIndexes.end(),
PieceStatRarer(_pieceStats));
}
void PieceStatMan::updatePieceStats(const unsigned char* newBitfield,
size_t newBitfieldLength,
const unsigned char* oldBitfield)
{
size_t index = 0;
for(size_t bi = 0; bi < newBitfieldLength; ++bi) {
for(size_t i = 0; i < 8; ++i, ++index) {
unsigned char mask = 128 >> i;
if((newBitfield[bi]&mask) && !(oldBitfield[bi]&mask)) {
_pieceStats[index]->addCount();
} else if(!(newBitfield[bi]&mask) && (oldBitfield[bi]&mask)) {
_pieceStats[index]->subCount();
}
}
}
std::sort(_sortedPieceStatIndexes.begin(), _sortedPieceStatIndexes.end(),
PieceStatRarer(_pieceStats));
}
void PieceStatMan::addPieceStats(size_t index)
{
std::vector<size_t>::iterator cur =
std::lower_bound(_sortedPieceStatIndexes.begin(),
_sortedPieceStatIndexes.end(),
index, PieceStatRarer(_pieceStats));
_pieceStats[index]->addCount();
std::vector<size_t>::iterator to =
std::upper_bound(cur+1, _sortedPieceStatIndexes.end(),
index, PieceStatRarer(_pieceStats));
std::rotate(cur, cur+1, to);
}
const std::vector<size_t>& PieceStatMan::getRarerPieceIndexes() const
{
return _sortedPieceStatIndexes;
}
const std::vector<SharedHandle<PieceStat> >&
PieceStatMan::getPieceStats() const
{
return _pieceStats;
}
} // namespace aria2

93
src/PieceStatMan.h Normal file
View File

@ -0,0 +1,93 @@
/* <!-- 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_PIECE_STAT_MAN_H_
#define _D_PIECE_STAT_MAN_H_
#include "common.h"
#include <vector>
#include "SharedHandle.h"
namespace aria2 {
class PieceStat {
private:
size_t _order;
size_t _index;
size_t _count;
public:
PieceStat(size_t index);
bool operator<(const PieceStat& pieceStat) const;
void addCount();
void subCount();
size_t getOrder() const;
void setOrder(size_t order);
size_t getIndex() const;
size_t getCount() const;
};
class PieceStatMan {
private:
std::vector<SharedHandle<PieceStat> > _pieceStats;
std::vector<size_t> _sortedPieceStatIndexes;
public:
PieceStatMan(size_t pieceNum, bool randomShuffle);
void addPieceStats(size_t index);
void addPieceStats(const unsigned char* bitfield,
size_t bitfieldLength);
void subtractPieceStats(const unsigned char* bitfield,
size_t bitfieldLength);
void updatePieceStats(const unsigned char* newBitfield,
size_t newBitfieldLength,
const unsigned char* oldBitfield);
// Returns piece index in rarest first order.
const std::vector<size_t>& getRarerPieceIndexes() const;
const std::vector<SharedHandle<PieceStat> >& getPieceStats() const;
};
} // namespace aria2
#endif // _D_PIECE_STAT_MAN_H_

View File

@ -37,87 +37,12 @@
#include <cassert>
#include <algorithm>
#include "SimpleRandomizer.h"
#include "PieceStatMan.h"
namespace aria2 {
PieceStat::PieceStat(size_t index):_order(0), _index(index), _count(0) {}
bool PieceStat::operator<(const PieceStat& pieceStat) const
{
if(_count == pieceStat._count) {
return _order < pieceStat._order;
} else {
return _count < pieceStat._count;
}
}
void PieceStat::addCount()
{
if(_count < SIZE_MAX) {
++_count;
}
}
void PieceStat::subCount()
{
if(_count > 0) {
--_count;
}
}
size_t PieceStat::getIndex() const
{
return _index;
}
size_t PieceStat::getCount() const
{
return _count;
}
void PieceStat::setOrder(size_t order)
{
_order = order;
}
size_t PieceStat::getOrder() const
{
return _order;
}
class GenPieceStat {
private:
size_t _index;
public:
GenPieceStat():_index(0) {}
SharedHandle<PieceStat> operator()()
{
return SharedHandle<PieceStat>(new PieceStat(_index++));
}
};
RarestPieceSelector::RarestPieceSelector(size_t pieceNum, bool randomShuffle):
_pieceStats(pieceNum),
_sortedPieceStatIndexes(pieceNum)
{
std::generate(_pieceStats.begin(), _pieceStats.end(), GenPieceStat());
std::vector<SharedHandle<PieceStat> > sortedPieceStats(_pieceStats);
// we need some randomness in ordering.
if(randomShuffle) {
std::random_shuffle(sortedPieceStats.begin(), sortedPieceStats.end(),
*(SimpleRandomizer::getInstance().get()));
}
{
size_t order = 0;
for(std::vector<SharedHandle<PieceStat> >::iterator i =
sortedPieceStats.begin(); i != sortedPieceStats.end(); ++i) {
_sortedPieceStatIndexes[order] = (*i)->getIndex();
(*i)->setOrder(order++);
}
}
}
RarestPieceSelector::RarestPieceSelector
(const SharedHandle<PieceStatMan>& pieceStatMan):_pieceStatMan(pieceStatMan) {}
class FindRarestPiece
{
@ -139,10 +64,12 @@ public:
bool RarestPieceSelector::select
(size_t& index, const unsigned char* bitfield, size_t nbits) const
{
const std::vector<size_t>& pieceIndexes =
_pieceStatMan->getRarerPieceIndexes();
std::vector<size_t>::const_iterator i =
std::find_if(_sortedPieceStatIndexes.begin(), _sortedPieceStatIndexes.end(),
std::find_if(pieceIndexes.begin(), pieceIndexes.end(),
FindRarestPiece(bitfield, nbits));
if(i == _sortedPieceStatIndexes.end()) {
if(i == pieceIndexes.end()) {
return false;
} else {
index = *i;
@ -150,102 +77,4 @@ bool RarestPieceSelector::select
}
}
class PieceStatRarer {
private:
const std::vector<SharedHandle<PieceStat> >& _pieceStats;
public:
PieceStatRarer(const std::vector<SharedHandle<PieceStat> >& ps):
_pieceStats(ps) {}
bool operator()(size_t lhs, size_t rhs) const
{
return _pieceStats[lhs] < _pieceStats[rhs];
}
};
void RarestPieceSelector::addPieceStats(const unsigned char* bitfield,
size_t bitfieldLength)
{
size_t index = 0;
for(size_t bi = 0; bi < bitfieldLength; ++bi) {
for(size_t i = 0; i < 8; ++i, ++index) {
unsigned char mask = 128 >> i;
if(bitfield[bi]&mask) {
_pieceStats[index]->addCount();
}
}
}
std::sort(_sortedPieceStatIndexes.begin(), _sortedPieceStatIndexes.end(),
PieceStatRarer(_pieceStats));
}
void RarestPieceSelector::subtractPieceStats(const unsigned char* bitfield,
size_t bitfieldLength)
{
size_t index = 0;
for(size_t bi = 0; bi < bitfieldLength; ++bi) {
for(size_t i = 0; i < 8; ++i, ++index) {
unsigned char mask = 128 >> i;
if(bitfield[bi]&mask) {
_pieceStats[index]->subCount();
}
}
}
std::sort(_sortedPieceStatIndexes.begin(), _sortedPieceStatIndexes.end(),
PieceStatRarer(_pieceStats));
}
void RarestPieceSelector::updatePieceStats(const unsigned char* newBitfield,
size_t newBitfieldLength,
const unsigned char* oldBitfield)
{
size_t index = 0;
for(size_t bi = 0; bi < newBitfieldLength; ++bi) {
for(size_t i = 0; i < 8; ++i, ++index) {
unsigned char mask = 128 >> i;
if((newBitfield[bi]&mask) && !(oldBitfield[bi]&mask)) {
_pieceStats[index]->addCount();
} else if(!(newBitfield[bi]&mask) && (oldBitfield[bi]&mask)) {
_pieceStats[index]->subCount();
}
}
}
std::sort(_sortedPieceStatIndexes.begin(), _sortedPieceStatIndexes.end(),
PieceStatRarer(_pieceStats));
}
void RarestPieceSelector::addPieceStats(size_t index)
{
std::vector<size_t>::iterator cur =
std::lower_bound(_sortedPieceStatIndexes.begin(),
_sortedPieceStatIndexes.end(),
index, PieceStatRarer(_pieceStats));
_pieceStats[index]->addCount();
std::vector<size_t>::iterator to =
std::upper_bound(cur+1, _sortedPieceStatIndexes.end(),
index, PieceStatRarer(_pieceStats));
std::rotate(cur, cur+1, to);
}
const std::vector<size_t>&
RarestPieceSelector::getSortedPieceStatIndexes() const
{
return _sortedPieceStatIndexes;
}
const std::vector<SharedHandle<PieceStat> >&
RarestPieceSelector::getPieceStats() const
{
return _pieceStats;
}
} // namespace aria2

View File

@ -36,56 +36,20 @@
#define _D_RAREST_PIECE_SELECTOR_H_
#include "PieceSelector.h"
#include <vector>
#include "SharedHandle.h"
namespace aria2 {
class PieceStat {
private:
size_t _order;
size_t _index;
size_t _count;
public:
PieceStat(size_t index);
bool operator<(const PieceStat& pieceStat) const;
void addCount();
void subCount();
size_t getOrder() const;
void setOrder(size_t order);
size_t getIndex() const;
size_t getCount() const;
};
class PieceStatMan;
class RarestPieceSelector:public PieceSelector {
private:
std::vector<SharedHandle<PieceStat> > _pieceStats;
std::vector<size_t> _sortedPieceStatIndexes;
SharedHandle<PieceStatMan> _pieceStatMan;
public:
RarestPieceSelector(size_t pieceNum, bool randomShuffle);
RarestPieceSelector(const SharedHandle<PieceStatMan>& pieceStatMan);
virtual bool select
(size_t& index, const unsigned char* bitfield, size_t nbits) const;
virtual void addPieceStats(size_t index);
virtual void addPieceStats(const unsigned char* bitfield,
size_t bitfieldLength);
virtual void subtractPieceStats(const unsigned char* bitfield,
size_t bitfieldLength);
virtual void updatePieceStats(const unsigned char* newBitfield,
size_t newBitfieldLength,
const unsigned char* oldBitfield);
const std::vector<size_t>& getSortedPieceStatIndexes() const;
const std::vector<SharedHandle<PieceStat> >& getPieceStats() const;
};
} // namespace aria2

View File

@ -396,17 +396,17 @@ void RequestGroup::initPieceStorage()
{
if(_downloadContext->knowsTotalLength()) {
#ifdef ENABLE_BITTORRENT
SharedHandle<DefaultPieceStorage> ps;
SharedHandle<PieceSelector> selector;
SharedHandle<DefaultPieceStorage> ps
(new DefaultPieceStorage(_downloadContext, _option));
// Use LongestSequencePieceSelector when HTTP/FTP/BitTorrent integrated
// downloads. Currently multi-file integrated download is not supported.
if(!_uris.empty() &&
_downloadContext->getFileEntries().size() == 1 &&
!dynamic_pointer_cast<BtContext>(_downloadContext).isNull()) {
_logger->debug("Using LongestSequencePieceSelector");
selector.reset(new LongestSequencePieceSelector());
ps->setPieceSelector
(SharedHandle<PieceSelector>(new LongestSequencePieceSelector()));
}
ps.reset(new DefaultPieceStorage(_downloadContext, _option, selector));
#else // !ENABLE_BITTORRENT
SharedHandle<DefaultPieceStorage> ps
(new DefaultPieceStorage(_downloadContext, _option));

View File

@ -13,6 +13,7 @@
#include "FileEntry.h"
#include "MockBtContext.h"
#include "RarestPieceSelector.h"
#include "InOrderPieceSelector.h"
namespace aria2 {
@ -37,7 +38,7 @@ private:
SharedHandle<BtContext> btContext;
SharedHandle<Peer> peer;
Option* option;
SharedHandle<RarestPieceSelector> _selector;
SharedHandle<PieceSelector> _pieceSelector;
public:
DefaultPieceStorageTest() {
SharedHandle<FixedNumberRandomizer> randomizer
@ -53,7 +54,7 @@ public:
peer->allocateSessionResource(btContext->getPieceLength(),
btContext->getTotalLength());
option = new Option();
_selector.reset(new RarestPieceSelector(btContext->getNumPieces(), false));
_pieceSelector.reset(new InOrderPieceSelector());
}
void tearDown()
@ -87,7 +88,8 @@ void DefaultPieceStorageTest::testGetTotalLength() {
}
void DefaultPieceStorageTest::testGetMissingPiece() {
DefaultPieceStorage pss(btContext, option, _selector);
DefaultPieceStorage pss(btContext, option);
pss.setPieceSelector(_pieceSelector);
pss.setEndGamePieceNum(0);
peer->setAllBitfield();
@ -107,7 +109,8 @@ void DefaultPieceStorageTest::testGetMissingPiece() {
void DefaultPieceStorageTest::testGetMissingPiece_excludedIndexes()
{
DefaultPieceStorage pss(btContext, option, _selector);
DefaultPieceStorage pss(btContext, option);
pss.setPieceSelector(_pieceSelector);
pss.setEndGamePieceNum(0);
peer->setAllBitfield();
@ -128,7 +131,8 @@ void DefaultPieceStorageTest::testGetMissingPiece_excludedIndexes()
}
void DefaultPieceStorageTest::testGetMissingFastPiece() {
DefaultPieceStorage pss(btContext, option, _selector);
DefaultPieceStorage pss(btContext, option);
pss.setPieceSelector(_pieceSelector);
pss.setEndGamePieceNum(0);
peer->setAllBitfield();
@ -144,7 +148,8 @@ void DefaultPieceStorageTest::testGetMissingFastPiece() {
void DefaultPieceStorageTest::testGetMissingFastPiece_excludedIndexes()
{
DefaultPieceStorage pss(btContext, option, _selector);
DefaultPieceStorage pss(btContext, option);
pss.setPieceSelector(_pieceSelector);
pss.setEndGamePieceNum(0);
peer->setAllBitfield();
@ -173,7 +178,8 @@ void DefaultPieceStorageTest::testHasMissingPiece() {
}
void DefaultPieceStorageTest::testCompletePiece() {
DefaultPieceStorage pss(btContext, option, _selector);
DefaultPieceStorage pss(btContext, option);
pss.setPieceSelector(_pieceSelector);
pss.setEndGamePieceNum(0);
peer->setAllBitfield();

View File

@ -0,0 +1,26 @@
#ifndef _D_IN_ORDER_PIECE_SELECTOR_H_
#define _D_IN_ORDER_PIECE_SELECTOR_H_
#include "PieceSelector.h"
#include "bitfield.h"
namespace aria2 {
class InOrderPieceSelector:public PieceSelector {
public:
virtual bool select
(size_t& index, const unsigned char* bitfield, size_t nbits) const
{
for(size_t i = 0; i < nbits; ++i) {
if(bitfield::test(bitfield, nbits, i)) {
index = i;
return true;
}
}
return false;
}
};
} // namespace aria2
#endif // _D_IN_ORDER_PIECE_SELECTOR_H_

View File

@ -66,6 +66,8 @@ aria2c_SOURCES = AllTest.cc\
BencodeTest.cc\
SequentialPickerTest.cc\
RarestPieceSelectorTest.cc\
PieceStatManTest.cc\
InOrderPieceSelector.h\
LongestSequencePieceSelectorTest.cc\
a2algoTest.cc\
bitfieldTest.cc\

View File

@ -1,4 +1,4 @@
# Makefile.in generated by automake 1.10.1 from Makefile.am.
# Makefile.in generated by automake 1.10.2 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
@ -193,6 +193,7 @@ am__aria2c_SOURCES_DIST = AllTest.cc TestUtil.cc TestUtil.h \
TimeTest.cc FtpConnectionTest.cc OptionParserTest.cc \
SimpleDNSCacheTest.cc DownloadHelperTest.cc BencodeTest.cc \
SequentialPickerTest.cc RarestPieceSelectorTest.cc \
PieceStatManTest.cc InOrderPieceSelector.h \
LongestSequencePieceSelectorTest.cc a2algoTest.cc \
bitfieldTest.cc BDETest.cc FallocFileAllocationIteratorTest.cc \
GZipDecoderTest.cc Sqlite3MozCookieParserTest.cc \
@ -363,7 +364,7 @@ am_aria2c_OBJECTS = AllTest.$(OBJEXT) TestUtil.$(OBJEXT) \
OptionParserTest.$(OBJEXT) SimpleDNSCacheTest.$(OBJEXT) \
DownloadHelperTest.$(OBJEXT) BencodeTest.$(OBJEXT) \
SequentialPickerTest.$(OBJEXT) \
RarestPieceSelectorTest.$(OBJEXT) \
RarestPieceSelectorTest.$(OBJEXT) PieceStatManTest.$(OBJEXT) \
LongestSequencePieceSelectorTest.$(OBJEXT) \
a2algoTest.$(OBJEXT) bitfieldTest.$(OBJEXT) BDETest.$(OBJEXT) \
$(am__objects_1) $(am__objects_2) $(am__objects_3) \
@ -561,6 +562,7 @@ target_alias = @target_alias@
target_cpu = @target_cpu@
target_os = @target_os@
target_vendor = @target_vendor@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
aria2c_SOURCES = AllTest.cc TestUtil.cc TestUtil.h SocketCoreTest.cc \
@ -591,6 +593,7 @@ aria2c_SOURCES = AllTest.cc TestUtil.cc TestUtil.h SocketCoreTest.cc \
TimeTest.cc FtpConnectionTest.cc OptionParserTest.cc \
SimpleDNSCacheTest.cc DownloadHelperTest.cc BencodeTest.cc \
SequentialPickerTest.cc RarestPieceSelectorTest.cc \
PieceStatManTest.cc InOrderPieceSelector.h \
LongestSequencePieceSelectorTest.cc a2algoTest.cc \
bitfieldTest.cc BDETest.cc $(am__append_1) $(am__append_2) \
$(am__append_3) $(am__append_4) $(am__append_5) \
@ -646,8 +649,8 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
&& exit 0; \
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
&& { if test -f $@; then exit 0; else break; fi; }; \
exit 1;; \
esac; \
done; \
@ -799,6 +802,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PeerMessageUtilTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PeerSessionResourceTest.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)/PieceTest.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@
@ -853,7 +857,7 @@ ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
mkid -fID $$unique
tags: TAGS
@ -896,7 +900,7 @@ distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
check-TESTS: $(TESTS)
@failed=0; all=0; xfail=0; xpass=0; skip=0; ws='[ ]'; \
@failed=0; all=0; xfail=0; xpass=0; skip=0; \
srcdir=$(srcdir); export srcdir; \
list=' $(TESTS) '; \
if test -n "$$list"; then \
@ -907,7 +911,7 @@ check-TESTS: $(TESTS)
if $(TESTS_ENVIRONMENT) $${dir}$$tst; then \
all=`expr $$all + 1`; \
case " $(XFAIL_TESTS) " in \
*$$ws$$tst$$ws*) \
*[\ \ ]$$tst[\ \ ]*) \
xpass=`expr $$xpass + 1`; \
failed=`expr $$failed + 1`; \
echo "XPASS: $$tst"; \
@ -919,7 +923,7 @@ check-TESTS: $(TESTS)
elif test $$? -ne 77; then \
all=`expr $$all + 1`; \
case " $(XFAIL_TESTS) " in \
*$$ws$$tst$$ws*) \
*[\ \ ]$$tst[\ \ ]*) \
xfail=`expr $$xfail + 1`; \
echo "XFAIL: $$tst"; \
;; \
@ -933,23 +937,36 @@ check-TESTS: $(TESTS)
echo "SKIP: $$tst"; \
fi; \
done; \
if test "$$all" -eq 1; then \
tests="test"; \
All=""; \
else \
tests="tests"; \
All="All "; \
fi; \
if test "$$failed" -eq 0; then \
if test "$$xfail" -eq 0; then \
banner="All $$all tests passed"; \
banner="$$All$$all $$tests passed"; \
else \
banner="All $$all tests behaved as expected ($$xfail expected failures)"; \
if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \
banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \
fi; \
else \
if test "$$xpass" -eq 0; then \
banner="$$failed of $$all tests failed"; \
banner="$$failed of $$all $$tests failed"; \
else \
banner="$$failed of $$all tests did not behave as expected ($$xpass unexpected passes)"; \
if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \
banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \
fi; \
fi; \
dashes="$$banner"; \
skipped=""; \
if test "$$skip" -ne 0; then \
skipped="($$skip tests were not run)"; \
if test "$$skip" -eq 1; then \
skipped="($$skip test was not run)"; \
else \
skipped="($$skip tests were not run)"; \
fi; \
test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \
dashes="$$skipped"; \
fi; \

194
test/PieceStatManTest.cc Normal file
View File

@ -0,0 +1,194 @@
#include "PieceStatMan.h"
#include <cppunit/extensions/HelperMacros.h>
namespace aria2 {
class PieceStatManTest:public CppUnit::TestFixture {
CPPUNIT_TEST_SUITE(PieceStatManTest);
CPPUNIT_TEST(testAddPieceStats_index);
CPPUNIT_TEST(testAddPieceStats_bitfield);
CPPUNIT_TEST(testUpdatePieceStats);
CPPUNIT_TEST(testSubtractPieceStats);
CPPUNIT_TEST_SUITE_END();
public:
void setUp() {}
void tearDown() {}
void testAddPieceStats_index();
void testAddPieceStats_bitfield();
void testUpdatePieceStats();
void testSubtractPieceStats();
};
CPPUNIT_TEST_SUITE_REGISTRATION(PieceStatManTest);
void PieceStatManTest::testAddPieceStats_index()
{
PieceStatMan pieceStatMan(10, false);
pieceStatMan.addPieceStats(1);
{
size_t indexes[] = { 0, 2, 3, 4, 5, 6, 7, 8, 9, 1 };
size_t counts[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
const std::vector<size_t>& statsidx(pieceStatMan.getRarerPieceIndexes());
const std::vector<SharedHandle<PieceStat> >& stats
(pieceStatMan.getPieceStats());
CPPUNIT_ASSERT_EQUAL((size_t)10, stats.size());
for(size_t i = 0; i < 10; ++i) {
CPPUNIT_ASSERT_EQUAL(indexes[i], statsidx[i]);
CPPUNIT_ASSERT_EQUAL(counts[i], stats[statsidx[i]]->getCount());
}
}
pieceStatMan.addPieceStats(1);
{
size_t indexes[] = { 0, 2, 3, 4, 5, 6, 7, 8, 9, 1 };
size_t counts[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 };
const std::vector<size_t>& statsidx(pieceStatMan.getRarerPieceIndexes());
const std::vector<SharedHandle<PieceStat> >& stats
(pieceStatMan.getPieceStats());
for(size_t i = 0; i < 10; ++i) {
CPPUNIT_ASSERT_EQUAL(indexes[i], statsidx[i]);
CPPUNIT_ASSERT_EQUAL(counts[i], stats[statsidx[i]]->getCount());
}
}
pieceStatMan.addPieceStats(3);
pieceStatMan.addPieceStats(9);
pieceStatMan.addPieceStats(3);
pieceStatMan.addPieceStats(0);
{
size_t indexes[] = { 2, 4, 5, 6, 7, 8, 0, 9, 1, 3 };
size_t counts[] = { 0, 0, 0, 0, 0, 0, 1, 1, 2, 2 };
const std::vector<size_t>& statsidx(pieceStatMan.getRarerPieceIndexes());
const std::vector<SharedHandle<PieceStat> >& stats
(pieceStatMan.getPieceStats());
for(size_t i = 0; i < 10; ++i) {
CPPUNIT_ASSERT_EQUAL(indexes[i], statsidx[i]);
CPPUNIT_ASSERT_EQUAL(counts[i], stats[statsidx[i]]->getCount());
}
}
}
void PieceStatManTest::testAddPieceStats_bitfield()
{
PieceStatMan pieceStatMan(10, false);
const unsigned char bitfield[] = { 0xaa, 0x80 };
pieceStatMan.addPieceStats(bitfield, sizeof(bitfield));
{
size_t indexes[] = { 1, 3, 5, 7, 9, 0, 2, 4, 6, 8 };
size_t counts[] = { 0, 0, 0, 0, 0, 1, 1, 1, 1, 1 };
const std::vector<size_t>& statsidx(pieceStatMan.getRarerPieceIndexes());
const std::vector<SharedHandle<PieceStat> >& stats
(pieceStatMan.getPieceStats());
CPPUNIT_ASSERT_EQUAL((size_t)10, stats.size());
for(size_t i = 0; i < 10; ++i) {
CPPUNIT_ASSERT_EQUAL(indexes[i], statsidx[i]);
CPPUNIT_ASSERT_EQUAL(counts[i], stats[statsidx[i]]->getCount());
}
}
pieceStatMan.addPieceStats(bitfield, sizeof(bitfield));
{
size_t indexes[] = { 1, 3, 5, 7, 9, 0, 2, 4, 6, 8 };
size_t counts[] = { 0, 0, 0, 0, 0, 2, 2, 2, 2, 2 };
const std::vector<size_t>& statsidx(pieceStatMan.getRarerPieceIndexes());
const std::vector<SharedHandle<PieceStat> >& stats
(pieceStatMan.getPieceStats());
CPPUNIT_ASSERT_EQUAL((size_t)10, stats.size());
for(size_t i = 0; i < 10; ++i) {
CPPUNIT_ASSERT_EQUAL(indexes[i], statsidx[i]);
CPPUNIT_ASSERT_EQUAL(counts[i], stats[statsidx[i]]->getCount());
}
}
}
void PieceStatManTest::testUpdatePieceStats()
{
PieceStatMan pieceStatMan(10, false);
const unsigned char bitfield[] = { 0xff, 0xc0 };
pieceStatMan.addPieceStats(bitfield, sizeof(bitfield));
const unsigned char oldBitfield[] = { 0xf0, 0x00 };
const unsigned char newBitfield[] = { 0x1f, 0x00 };
pieceStatMan.updatePieceStats(newBitfield, sizeof(newBitfield), oldBitfield);
{
// idx: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
// bf : 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
// old: 1, 1, 1, 1, 0, 0, 0, 0, 0, 0
// new: 0, 0, 0, 1, 1, 1, 1, 1, 0, 0
// ---------------------------------
// res: 0, 0, 0, 1, 2, 2, 2, 2, 1, 1
size_t indexes[] = { 0, 1, 2, 3, 8, 9, 4, 5, 6, 7 };
size_t counts[] = { 0, 0, 0, 1, 1, 1, 2, 2, 2, 2 };
const std::vector<size_t>& statsidx(pieceStatMan.getRarerPieceIndexes());
const std::vector<SharedHandle<PieceStat> >& stats
(pieceStatMan.getPieceStats());
CPPUNIT_ASSERT_EQUAL((size_t)10, stats.size());
for(size_t i = 0; i < 10; ++i) {
CPPUNIT_ASSERT_EQUAL(indexes[i], statsidx[i]);
CPPUNIT_ASSERT_EQUAL(counts[i], stats[statsidx[i]]->getCount());
}
}
}
void PieceStatManTest::testSubtractPieceStats()
{
PieceStatMan pieceStatMan(10, false);
const unsigned char bitfield[] = { 0xf0, 0x00 };
pieceStatMan.addPieceStats(bitfield, sizeof(bitfield));
const unsigned char newBitfield[] = { 0x3f, 0x00 };
pieceStatMan.subtractPieceStats(newBitfield, sizeof(newBitfield));
{
// idx: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
// bf : 1, 1, 1, 1, 0, 0, 0, 0, 0, 0
// new: 0, 0, 1, 1, 1, 1, 1, 1, 0, 0
// ---------------------------------
// res: 1, 1, 0, 0, 0, 0, 0, 0, 0, 0
size_t indexes[] = { 2, 3, 4, 5, 6, 7, 8, 9, 0, 1 };
size_t counts[] = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1 };
const std::vector<size_t>& statsidx(pieceStatMan.getRarerPieceIndexes());
const std::vector<SharedHandle<PieceStat> >& stats
(pieceStatMan.getPieceStats());
CPPUNIT_ASSERT_EQUAL((size_t)10, stats.size());
for(size_t i = 0; i < 10; ++i) {
CPPUNIT_ASSERT_EQUAL(indexes[i], statsidx[i]);
CPPUNIT_ASSERT_EQUAL(counts[i], stats[statsidx[i]]->getCount());
}
}
}
} // namespace aria2

View File

@ -1,23 +1,15 @@
#include "RarestPieceSelector.h"
#include <cstring>
#include <iostream>
#include <cppunit/extensions/HelperMacros.h>
#include "Exception.h"
#include "Util.h"
#include "BitfieldMan.h"
#include "PieceStatMan.h"
namespace aria2 {
class RarestPieceSelectorTest:public CppUnit::TestFixture {
CPPUNIT_TEST_SUITE(RarestPieceSelectorTest);
CPPUNIT_TEST(testAddPieceStats_index);
CPPUNIT_TEST(testAddPieceStats_bitfield);
CPPUNIT_TEST(testUpdatePieceStats);
CPPUNIT_TEST(testSubtractPieceStats);
CPPUNIT_TEST(testSelect);
CPPUNIT_TEST_SUITE_END();
public:
@ -35,177 +27,21 @@ public:
CPPUNIT_TEST_SUITE_REGISTRATION(RarestPieceSelectorTest);
void RarestPieceSelectorTest::testAddPieceStats_index()
{
RarestPieceSelector selector(10, false);
selector.addPieceStats(1);
{
size_t indexes[] = { 0, 2, 3, 4, 5, 6, 7, 8, 9, 1 };
size_t counts[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
const std::vector<size_t>& statsidx(selector.getSortedPieceStatIndexes());
const std::vector<SharedHandle<PieceStat> >& stats(selector.getPieceStats());
CPPUNIT_ASSERT_EQUAL((size_t)10, stats.size());
for(size_t i = 0; i < 10; ++i) {
CPPUNIT_ASSERT_EQUAL(indexes[i], statsidx[i]);
CPPUNIT_ASSERT_EQUAL(counts[i], stats[statsidx[i]]->getCount());
}
}
selector.addPieceStats(1);
{
size_t indexes[] = { 0, 2, 3, 4, 5, 6, 7, 8, 9, 1 };
size_t counts[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 };
const std::vector<size_t>& statsidx(selector.getSortedPieceStatIndexes());
const std::vector<SharedHandle<PieceStat> >& stats(selector.getPieceStats());
for(size_t i = 0; i < 10; ++i) {
CPPUNIT_ASSERT_EQUAL(indexes[i], statsidx[i]);
CPPUNIT_ASSERT_EQUAL(counts[i], stats[statsidx[i]]->getCount());
}
}
selector.addPieceStats(3);
selector.addPieceStats(9);
selector.addPieceStats(3);
selector.addPieceStats(0);
{
size_t indexes[] = { 2, 4, 5, 6, 7, 8, 0, 9, 1, 3 };
size_t counts[] = { 0, 0, 0, 0, 0, 0, 1, 1, 2, 2 };
const std::vector<size_t>& statsidx(selector.getSortedPieceStatIndexes());
const std::vector<SharedHandle<PieceStat> >& stats(selector.getPieceStats());
for(size_t i = 0; i < 10; ++i) {
CPPUNIT_ASSERT_EQUAL(indexes[i], statsidx[i]);
CPPUNIT_ASSERT_EQUAL(counts[i], stats[statsidx[i]]->getCount());
}
}
}
void RarestPieceSelectorTest::testAddPieceStats_bitfield()
{
RarestPieceSelector selector(10, false);
const unsigned char bitfield[] = { 0xaa, 0x80 };
selector.addPieceStats(bitfield, sizeof(bitfield));
{
size_t indexes[] = { 1, 3, 5, 7, 9, 0, 2, 4, 6, 8 };
size_t counts[] = { 0, 0, 0, 0, 0, 1, 1, 1, 1, 1 };
const std::vector<size_t>& statsidx(selector.getSortedPieceStatIndexes());
const std::vector<SharedHandle<PieceStat> >& stats(selector.getPieceStats());
CPPUNIT_ASSERT_EQUAL((size_t)10, stats.size());
for(size_t i = 0; i < 10; ++i) {
CPPUNIT_ASSERT_EQUAL(indexes[i], statsidx[i]);
CPPUNIT_ASSERT_EQUAL(counts[i], stats[statsidx[i]]->getCount());
}
}
selector.addPieceStats(bitfield, sizeof(bitfield));
{
size_t indexes[] = { 1, 3, 5, 7, 9, 0, 2, 4, 6, 8 };
size_t counts[] = { 0, 0, 0, 0, 0, 2, 2, 2, 2, 2 };
const std::vector<size_t>& statsidx(selector.getSortedPieceStatIndexes());
const std::vector<SharedHandle<PieceStat> >& stats(selector.getPieceStats());
CPPUNIT_ASSERT_EQUAL((size_t)10, stats.size());
for(size_t i = 0; i < 10; ++i) {
CPPUNIT_ASSERT_EQUAL(indexes[i], statsidx[i]);
CPPUNIT_ASSERT_EQUAL(counts[i], stats[statsidx[i]]->getCount());
}
}
}
void RarestPieceSelectorTest::testUpdatePieceStats()
{
RarestPieceSelector selector(10, false);
const unsigned char bitfield[] = { 0xff, 0xc0 };
selector.addPieceStats(bitfield, sizeof(bitfield));
const unsigned char oldBitfield[] = { 0xf0, 0x00 };
const unsigned char newBitfield[] = { 0x1f, 0x00 };
selector.updatePieceStats(newBitfield, sizeof(newBitfield), oldBitfield);
{
// idx: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
// bf : 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
// old: 1, 1, 1, 1, 0, 0, 0, 0, 0, 0
// new: 0, 0, 0, 1, 1, 1, 1, 1, 0, 0
// ---------------------------------
// res: 0, 0, 0, 1, 2, 2, 2, 2, 1, 1
size_t indexes[] = { 0, 1, 2, 3, 8, 9, 4, 5, 6, 7 };
size_t counts[] = { 0, 0, 0, 1, 1, 1, 2, 2, 2, 2 };
const std::vector<size_t>& statsidx(selector.getSortedPieceStatIndexes());
const std::vector<SharedHandle<PieceStat> >& stats(selector.getPieceStats());
CPPUNIT_ASSERT_EQUAL((size_t)10, stats.size());
for(size_t i = 0; i < 10; ++i) {
CPPUNIT_ASSERT_EQUAL(indexes[i], statsidx[i]);
CPPUNIT_ASSERT_EQUAL(counts[i], stats[statsidx[i]]->getCount());
}
}
}
void RarestPieceSelectorTest::testSubtractPieceStats()
{
RarestPieceSelector selector(10, false);
const unsigned char bitfield[] = { 0xf0, 0x00 };
selector.addPieceStats(bitfield, sizeof(bitfield));
const unsigned char newBitfield[] = { 0x3f, 0x00 };
selector.subtractPieceStats(newBitfield, sizeof(newBitfield));
{
// idx: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
// bf : 1, 1, 1, 1, 0, 0, 0, 0, 0, 0
// new: 0, 0, 1, 1, 1, 1, 1, 1, 0, 0
// ---------------------------------
// res: 1, 1, 0, 0, 0, 0, 0, 0, 0, 0
size_t indexes[] = { 2, 3, 4, 5, 6, 7, 8, 9, 0, 1 };
size_t counts[] = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1 };
const std::vector<size_t>& statsidx(selector.getSortedPieceStatIndexes());
const std::vector<SharedHandle<PieceStat> >& stats(selector.getPieceStats());
CPPUNIT_ASSERT_EQUAL((size_t)10, stats.size());
for(size_t i = 0; i < 10; ++i) {
CPPUNIT_ASSERT_EQUAL(indexes[i], statsidx[i]);
CPPUNIT_ASSERT_EQUAL(counts[i], stats[statsidx[i]]->getCount());
}
}
}
void RarestPieceSelectorTest::testSelect()
{
RarestPieceSelector selector(10, false);
SharedHandle<PieceStatMan> pieceStatMan(new PieceStatMan(10, false));
RarestPieceSelector selector(pieceStatMan);
BitfieldMan bf(1024, 10*1024);
bf.setBitRange(0, 2);
size_t index;
selector.addPieceStats(0);
pieceStatMan->addPieceStats(0);
CPPUNIT_ASSERT(selector.select(index, bf.getBitfield(),
bf.countBlock()));
CPPUNIT_ASSERT_EQUAL((size_t)1, index);
selector.addPieceStats(1);
pieceStatMan->addPieceStats(1);
CPPUNIT_ASSERT(selector.select(index, bf.getBitfield(),
bf.countBlock()));