mirror of https://github.com/aria2/aria2
				
				
				
			2008-05-17 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
Put piece selection strategy algorithm to RarestPieceSelector class, Added a switch to choose whether randomized selection so that unit tests emit same results in, possibly, win32. * src/DefaultPieceStorage.cc * src/DefaultPieceStorage.h * src/RarestPieceSelector.cc * src/RarestPieceSelector.h * test/DefaultPieceStorageTest.cc * test/RarestPieceSelectorTest.ccpull/1/head
							parent
							
								
									77d892d7f2
								
							
						
					
					
						commit
						ef02915d82
					
				
							
								
								
									
										12
									
								
								ChangeLog
								
								
								
								
							
							
						
						
									
										12
									
								
								ChangeLog
								
								
								
								
							| 
						 | 
				
			
			@ -1,3 +1,15 @@
 | 
			
		|||
2008-05-17  Tatsuhiro Tsujikawa  <tujikawa at rednoah dot com>
 | 
			
		||||
 | 
			
		||||
	Put piece selection strategy algorithm to RarestPieceSelector class,
 | 
			
		||||
	Added a switch to choose whether randomized selection so that unit
 | 
			
		||||
	tests emit same results in, possibly, win32.
 | 
			
		||||
	* src/DefaultPieceStorage.cc
 | 
			
		||||
	* src/DefaultPieceStorage.h
 | 
			
		||||
	* src/RarestPieceSelector.cc
 | 
			
		||||
	* src/RarestPieceSelector.h
 | 
			
		||||
	* test/DefaultPieceStorageTest.cc
 | 
			
		||||
	* test/RarestPieceSelectorTest.cc
 | 
			
		||||
 | 
			
		||||
2008-05-17  Tatsuhiro Tsujikawa  <tujikawa at rednoah dot com>
 | 
			
		||||
 | 
			
		||||
	Don't pool connection if HTTP proxy is enabled.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -53,63 +53,24 @@
 | 
			
		|||
#include "a2functional.h"
 | 
			
		||||
#include "Option.h"
 | 
			
		||||
#include "StringFormat.h"
 | 
			
		||||
#include "RarestPieceSelector.h"
 | 
			
		||||
#include <numeric>
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
 | 
			
		||||
namespace aria2 {
 | 
			
		||||
 | 
			
		||||
class GenPieceStat {
 | 
			
		||||
private:
 | 
			
		||||
  size_t _index;
 | 
			
		||||
public:
 | 
			
		||||
  GenPieceStat():_index(0) {}
 | 
			
		||||
 | 
			
		||||
  SharedHandle<PieceStat> operator()()
 | 
			
		||||
  {
 | 
			
		||||
    return SharedHandle<PieceStat>(new PieceStat(_index++));
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class PieceRarer
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
  bool operator()(const SharedHandle<PieceStat>& left,
 | 
			
		||||
		  const SharedHandle<PieceStat>& right)
 | 
			
		||||
  {
 | 
			
		||||
    if(left->getCount() == right->getCount()) {
 | 
			
		||||
      return left->getOrder() < right->getOrder();
 | 
			
		||||
    } else {
 | 
			
		||||
      return left->getCount() < right->getCount();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
DefaultPieceStorage::DefaultPieceStorage(const DownloadContextHandle& downloadContext, const Option* option):
 | 
			
		||||
DefaultPieceStorage::DefaultPieceStorage(const DownloadContextHandle& downloadContext, const Option* option, bool randomPieceStatsOrdering):
 | 
			
		||||
  downloadContext(downloadContext),
 | 
			
		||||
  bitfieldMan(BitfieldManFactory::getFactoryInstance()->
 | 
			
		||||
	      createBitfieldMan(downloadContext->getPieceLength(),
 | 
			
		||||
				downloadContext->getTotalLength())),
 | 
			
		||||
  _diskWriterFactory(new DefaultDiskWriterFactory()),
 | 
			
		||||
  endGamePieceNum(END_GAME_PIECE_NUM),
 | 
			
		||||
  logger(LogFactory::getInstance()),
 | 
			
		||||
  option(option),
 | 
			
		||||
  _pieceStats(downloadContext->getNumPieces())
 | 
			
		||||
{
 | 
			
		||||
  bitfieldMan =
 | 
			
		||||
    BitfieldManFactory::getFactoryInstance()->
 | 
			
		||||
    createBitfieldMan(downloadContext->getPieceLength(),
 | 
			
		||||
		      downloadContext->getTotalLength());
 | 
			
		||||
 | 
			
		||||
  std::generate(_pieceStats.begin(), _pieceStats.end(), GenPieceStat());
 | 
			
		||||
  _sortedPieceStats = _pieceStats;
 | 
			
		||||
  // we need some randomness in ordering.
 | 
			
		||||
  std::random_shuffle(_sortedPieceStats.begin(), _sortedPieceStats.end());
 | 
			
		||||
  {
 | 
			
		||||
    size_t order = 0;
 | 
			
		||||
    for(std::deque<SharedHandle<PieceStat> >::iterator i = _sortedPieceStats.begin();
 | 
			
		||||
	i != _sortedPieceStats.end(); ++i) {
 | 
			
		||||
      (*i)->setOrder(order++);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  logger = LogFactory::getInstance();
 | 
			
		||||
}
 | 
			
		||||
  _pieceSelector(new RarestPieceSelector(downloadContext->getNumPieces(),
 | 
			
		||||
					 randomPieceStatsOrdering))
 | 
			
		||||
{}
 | 
			
		||||
 | 
			
		||||
DefaultPieceStorage::~DefaultPieceStorage() {
 | 
			
		||||
  delete bitfieldMan;
 | 
			
		||||
| 
						 | 
				
			
			@ -126,19 +87,6 @@ bool DefaultPieceStorage::isEndGame()
 | 
			
		|||
  return bitfieldMan->countMissingBlock() <= endGamePieceNum;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class FindRarestPiece
 | 
			
		||||
{
 | 
			
		||||
private:
 | 
			
		||||
  const std::deque<size_t>& _indexes;
 | 
			
		||||
public:
 | 
			
		||||
  FindRarestPiece(const std::deque<size_t>& indexes):_indexes(indexes) {}
 | 
			
		||||
 | 
			
		||||
  bool operator()(const SharedHandle<PieceStat>& pieceStat)
 | 
			
		||||
  {
 | 
			
		||||
    return std::binary_search(_indexes.begin(), _indexes.end(), pieceStat->getIndex());
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
bool DefaultPieceStorage::getMissingPieceIndex(size_t& index, const PeerHandle& peer)
 | 
			
		||||
{
 | 
			
		||||
  std::deque<size_t> indexes;
 | 
			
		||||
| 
						 | 
				
			
			@ -153,11 +101,7 @@ bool DefaultPieceStorage::getMissingPieceIndex(size_t& index, const PeerHandle&
 | 
			
		|||
  }
 | 
			
		||||
  if(r) {
 | 
			
		||||
    // We assume indexes is sorted using comparator less.
 | 
			
		||||
    //std::sort(indexes.begin(), indexes.end());
 | 
			
		||||
    std::deque<SharedHandle<PieceStat> >::const_iterator i =
 | 
			
		||||
      std::find_if(_sortedPieceStats.begin(), _sortedPieceStats.end(),
 | 
			
		||||
		   FindRarestPiece(indexes));
 | 
			
		||||
    index = (*i)->getIndex();
 | 
			
		||||
    _pieceSelector->select(index, indexes);
 | 
			
		||||
    return true;
 | 
			
		||||
  } else {
 | 
			
		||||
    return false;
 | 
			
		||||
| 
						 | 
				
			
			@ -647,113 +591,26 @@ void DefaultPieceStorage::setDiskWriterFactory(const DiskWriterFactoryHandle& di
 | 
			
		|||
void DefaultPieceStorage::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(_sortedPieceStats.begin(), _sortedPieceStats.end(), PieceRarer());
 | 
			
		||||
  _pieceSelector->addPieceStats(bitfield, bitfieldLength);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DefaultPieceStorage::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(_sortedPieceStats.begin(), _sortedPieceStats.end(), PieceRarer());
 | 
			
		||||
  _pieceSelector->subtractPieceStats(bitfield, bitfieldLength);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DefaultPieceStorage::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(_sortedPieceStats.begin(), _sortedPieceStats.end(), PieceRarer());
 | 
			
		||||
  _pieceSelector->updatePieceStats(newBitfield, newBitfieldLength,
 | 
			
		||||
				   oldBitfield);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DefaultPieceStorage::addPieceStats(size_t index)
 | 
			
		||||
{
 | 
			
		||||
  SharedHandle<PieceStat> pieceStat(_pieceStats[index]);
 | 
			
		||||
  {
 | 
			
		||||
    std::deque<SharedHandle<PieceStat> >::iterator cur =
 | 
			
		||||
      std::lower_bound(_sortedPieceStats.begin(), _sortedPieceStats.end(),
 | 
			
		||||
		       pieceStat, PieceRarer());
 | 
			
		||||
    _sortedPieceStats.erase(cur);
 | 
			
		||||
  }
 | 
			
		||||
  pieceStat->addCount();
 | 
			
		||||
 | 
			
		||||
  std::deque<SharedHandle<PieceStat> >::iterator to =
 | 
			
		||||
    std::lower_bound(_sortedPieceStats.begin(), _sortedPieceStats.end(),
 | 
			
		||||
		     pieceStat, PieceRarer());
 | 
			
		||||
 | 
			
		||||
  _sortedPieceStats.insert(to, pieceStat);
 | 
			
		||||
 | 
			
		||||
//    for(std::deque<SharedHandle<PieceStat> >::const_iterator i = _sortedPieceStats.begin(); i != _sortedPieceStats.end(); ++i) {
 | 
			
		||||
//      logger->debug("index = %u, count = %u", (*i)->getIndex(), (*i)->getCount());
 | 
			
		||||
//    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PieceStat::PieceStat(size_t index):_order(0), _index(index), _count(0) {}
 | 
			
		||||
 | 
			
		||||
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;
 | 
			
		||||
  _pieceSelector->addPieceStats(index);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace aria2
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -45,6 +45,7 @@ class Logger;
 | 
			
		|||
class Option;
 | 
			
		||||
class DiskWriterFactory;
 | 
			
		||||
class FileEntry;
 | 
			
		||||
class RarestPieceSelector;
 | 
			
		||||
 | 
			
		||||
#define END_GAME_PIECE_NUM 20
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -67,23 +68,6 @@ public:
 | 
			
		|||
 | 
			
		||||
typedef std::deque<HaveEntry> Haves;
 | 
			
		||||
 | 
			
		||||
class PieceStat {
 | 
			
		||||
private:
 | 
			
		||||
  size_t _order;
 | 
			
		||||
  size_t _index;
 | 
			
		||||
  size_t _count;
 | 
			
		||||
public:
 | 
			
		||||
  PieceStat(size_t index);
 | 
			
		||||
 | 
			
		||||
  void addCount();
 | 
			
		||||
  void subCount();
 | 
			
		||||
 | 
			
		||||
  size_t getOrder() const;
 | 
			
		||||
  void setOrder(size_t order);
 | 
			
		||||
  size_t getIndex() const;
 | 
			
		||||
  size_t getCount() const;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class DefaultPieceStorage : public PieceStorage {
 | 
			
		||||
private:
 | 
			
		||||
  SharedHandle<DownloadContext> downloadContext;
 | 
			
		||||
| 
						 | 
				
			
			@ -97,9 +81,8 @@ private:
 | 
			
		|||
  const Option* option;
 | 
			
		||||
  Haves haves;
 | 
			
		||||
 | 
			
		||||
  std::deque<SharedHandle<PieceStat> > _pieceStats;
 | 
			
		||||
  std::deque<SharedHandle<PieceStat> > _sortedPieceStats;
 | 
			
		||||
  
 | 
			
		||||
  SharedHandle<RarestPieceSelector> _pieceSelector;
 | 
			
		||||
 | 
			
		||||
  bool getMissingPieceIndex(size_t& index, const SharedHandle<Peer>& peer);
 | 
			
		||||
  bool getMissingFastPieceIndex(size_t& index, const SharedHandle<Peer>& peer);
 | 
			
		||||
  SharedHandle<Piece> checkOutPiece(size_t index);
 | 
			
		||||
| 
						 | 
				
			
			@ -111,7 +94,13 @@ private:
 | 
			
		|||
  size_t getInFlightPieceCompletedLength() const;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
  DefaultPieceStorage(const SharedHandle<DownloadContext>& downloadContext, const Option* option);
 | 
			
		||||
  // Setting randomPieceStatsOrdering to true means a piece is chosen in
 | 
			
		||||
  // random when more than 2 pieces has the same rarity.
 | 
			
		||||
  // If it is set to false, a piece whose index is smallest has the highest
 | 
			
		||||
  // priority.
 | 
			
		||||
  DefaultPieceStorage(const SharedHandle<DownloadContext>& downloadContext,
 | 
			
		||||
		      const Option* option,
 | 
			
		||||
		      bool randomPieceStatsOrdering = true);
 | 
			
		||||
  virtual ~DefaultPieceStorage();
 | 
			
		||||
 | 
			
		||||
  virtual bool hasMissingPiece(const SharedHandle<Peer>& peer);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -187,7 +187,8 @@ SRCS =  Socket.h\
 | 
			
		|||
	HttpSkipResponseCommand.cc HttpSkipResponseCommand.h\
 | 
			
		||||
	InitiateConnectionCommand.cc InitiateConnectionCommand.h\
 | 
			
		||||
	FtpFinishDownloadCommand.cc FtpFinishDownloadCommand.h\
 | 
			
		||||
	A2STR.cc A2STR.h
 | 
			
		||||
	A2STR.cc A2STR.h\
 | 
			
		||||
	RarestPieceSelector.cc RarestPieceSelector.h
 | 
			
		||||
 | 
			
		||||
if ENABLE_ASYNC_DNS
 | 
			
		||||
SRCS += AsyncNameResolver.cc AsyncNameResolver.h
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -409,7 +409,8 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \
 | 
			
		|||
	HttpSkipResponseCommand.cc HttpSkipResponseCommand.h \
 | 
			
		||||
	InitiateConnectionCommand.cc InitiateConnectionCommand.h \
 | 
			
		||||
	FtpFinishDownloadCommand.cc FtpFinishDownloadCommand.h \
 | 
			
		||||
	A2STR.cc A2STR.h AsyncNameResolver.cc AsyncNameResolver.h \
 | 
			
		||||
	A2STR.cc A2STR.h RarestPieceSelector.cc RarestPieceSelector.h \
 | 
			
		||||
	AsyncNameResolver.cc AsyncNameResolver.h \
 | 
			
		||||
	IteratableChunkChecksumValidator.cc \
 | 
			
		||||
	IteratableChunkChecksumValidator.h \
 | 
			
		||||
	IteratableChecksumValidator.cc IteratableChecksumValidator.h \
 | 
			
		||||
| 
						 | 
				
			
			@ -793,11 +794,12 @@ am__objects_15 = SocketCore.$(OBJEXT) Command.$(OBJEXT) \
 | 
			
		|||
	StringFormat.$(OBJEXT) HttpSkipResponseCommand.$(OBJEXT) \
 | 
			
		||||
	InitiateConnectionCommand.$(OBJEXT) \
 | 
			
		||||
	FtpFinishDownloadCommand.$(OBJEXT) A2STR.$(OBJEXT) \
 | 
			
		||||
	$(am__objects_1) $(am__objects_2) $(am__objects_3) \
 | 
			
		||||
	$(am__objects_4) $(am__objects_5) $(am__objects_6) \
 | 
			
		||||
	$(am__objects_7) $(am__objects_8) $(am__objects_9) \
 | 
			
		||||
	$(am__objects_10) $(am__objects_11) $(am__objects_12) \
 | 
			
		||||
	$(am__objects_13) $(am__objects_14)
 | 
			
		||||
	RarestPieceSelector.$(OBJEXT) $(am__objects_1) \
 | 
			
		||||
	$(am__objects_2) $(am__objects_3) $(am__objects_4) \
 | 
			
		||||
	$(am__objects_5) $(am__objects_6) $(am__objects_7) \
 | 
			
		||||
	$(am__objects_8) $(am__objects_9) $(am__objects_10) \
 | 
			
		||||
	$(am__objects_11) $(am__objects_12) $(am__objects_13) \
 | 
			
		||||
	$(am__objects_14)
 | 
			
		||||
am_libaria2c_a_OBJECTS = $(am__objects_15)
 | 
			
		||||
libaria2c_a_OBJECTS = $(am_libaria2c_a_OBJECTS)
 | 
			
		||||
am__installdirs = "$(DESTDIR)$(bindir)"
 | 
			
		||||
| 
						 | 
				
			
			@ -1136,11 +1138,12 @@ SRCS = Socket.h SocketCore.cc SocketCore.h BinaryStream.h Command.cc \
 | 
			
		|||
	HttpSkipResponseCommand.cc HttpSkipResponseCommand.h \
 | 
			
		||||
	InitiateConnectionCommand.cc InitiateConnectionCommand.h \
 | 
			
		||||
	FtpFinishDownloadCommand.cc FtpFinishDownloadCommand.h \
 | 
			
		||||
	A2STR.cc A2STR.h $(am__append_1) $(am__append_2) \
 | 
			
		||||
	$(am__append_3) $(am__append_4) $(am__append_5) \
 | 
			
		||||
	$(am__append_6) $(am__append_7) $(am__append_8) \
 | 
			
		||||
	$(am__append_9) $(am__append_10) $(am__append_11) \
 | 
			
		||||
	$(am__append_12) $(am__append_13) $(am__append_14)
 | 
			
		||||
	A2STR.cc A2STR.h RarestPieceSelector.cc RarestPieceSelector.h \
 | 
			
		||||
	$(am__append_1) $(am__append_2) $(am__append_3) \
 | 
			
		||||
	$(am__append_4) $(am__append_5) $(am__append_6) \
 | 
			
		||||
	$(am__append_7) $(am__append_8) $(am__append_9) \
 | 
			
		||||
	$(am__append_10) $(am__append_11) $(am__append_12) \
 | 
			
		||||
	$(am__append_13) $(am__append_14)
 | 
			
		||||
noinst_LIBRARIES = libaria2c.a
 | 
			
		||||
libaria2c_a_SOURCES = $(SRCS)
 | 
			
		||||
aria2c_LDADD = libaria2c.a @LIBINTL@ @ALLOCA@ @LIBGNUTLS_LIBS@\
 | 
			
		||||
| 
						 | 
				
			
			@ -1459,6 +1462,7 @@ distclean-compile:
 | 
			
		|||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PiecesMetalinkParserState.Po@am__quote@
 | 
			
		||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Platform.Po@am__quote@
 | 
			
		||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ProtocolDetector.Po@am__quote@
 | 
			
		||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/RarestPieceSelector.Po@am__quote@
 | 
			
		||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/RealtimeCommand.Po@am__quote@
 | 
			
		||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ReceiverMSEHandshakeCommand.Po@am__quote@
 | 
			
		||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Request.Po@am__quote@
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,221 @@
 | 
			
		|||
/* <!-- copyright */
 | 
			
		||||
/*
 | 
			
		||||
 * aria2 - The high speed download utility
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (C) 2006 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 "RarestPieceSelector.h"
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
 | 
			
		||||
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)
 | 
			
		||||
{
 | 
			
		||||
  std::generate(_pieceStats.begin(), _pieceStats.end(), GenPieceStat());
 | 
			
		||||
  _sortedPieceStats = _pieceStats;
 | 
			
		||||
  // we need some randomness in ordering.
 | 
			
		||||
  if(randomShuffle) {
 | 
			
		||||
    std::random_shuffle(_sortedPieceStats.begin(), _sortedPieceStats.end());
 | 
			
		||||
  }
 | 
			
		||||
  {
 | 
			
		||||
    size_t order = 0;
 | 
			
		||||
    for(std::deque<SharedHandle<PieceStat> >::iterator i = _sortedPieceStats.begin();
 | 
			
		||||
	i != _sortedPieceStats.end(); ++i) {
 | 
			
		||||
      (*i)->setOrder(order++);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class FindRarestPiece
 | 
			
		||||
{
 | 
			
		||||
private:
 | 
			
		||||
  const std::deque<size_t>& _indexes;
 | 
			
		||||
public:
 | 
			
		||||
  FindRarestPiece(const std::deque<size_t>& indexes):_indexes(indexes) {}
 | 
			
		||||
 | 
			
		||||
  bool operator()(const SharedHandle<PieceStat>& pieceStat)
 | 
			
		||||
  {
 | 
			
		||||
    return std::binary_search(_indexes.begin(), _indexes.end(), pieceStat->getIndex());
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
bool RarestPieceSelector::select
 | 
			
		||||
(size_t& index,
 | 
			
		||||
 const std::deque<size_t>& candidateIndexes) const
 | 
			
		||||
{
 | 
			
		||||
  std::deque<SharedHandle<PieceStat> >::const_iterator i =
 | 
			
		||||
    std::find_if(_sortedPieceStats.begin(), _sortedPieceStats.end(),
 | 
			
		||||
		 FindRarestPiece(candidateIndexes));
 | 
			
		||||
  if(i == _sortedPieceStats.end()) {
 | 
			
		||||
    return false;
 | 
			
		||||
  } else {
 | 
			
		||||
    index = (*i)->getIndex();
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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(_sortedPieceStats.begin(), _sortedPieceStats.end());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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(_sortedPieceStats.begin(), _sortedPieceStats.end());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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(_sortedPieceStats.begin(), _sortedPieceStats.end());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RarestPieceSelector::addPieceStats(size_t index)
 | 
			
		||||
{
 | 
			
		||||
  SharedHandle<PieceStat> pieceStat(_pieceStats[index]);
 | 
			
		||||
  {
 | 
			
		||||
    std::deque<SharedHandle<PieceStat> >::iterator cur =
 | 
			
		||||
      std::lower_bound(_sortedPieceStats.begin(), _sortedPieceStats.end(),
 | 
			
		||||
		       pieceStat);
 | 
			
		||||
    _sortedPieceStats.erase(cur);
 | 
			
		||||
  }
 | 
			
		||||
  pieceStat->addCount();
 | 
			
		||||
 | 
			
		||||
  std::deque<SharedHandle<PieceStat> >::iterator to =
 | 
			
		||||
    std::lower_bound(_sortedPieceStats.begin(), _sortedPieceStats.end(),
 | 
			
		||||
		     pieceStat);
 | 
			
		||||
 | 
			
		||||
  _sortedPieceStats.insert(to, pieceStat);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const std::deque<SharedHandle<PieceStat> >&
 | 
			
		||||
RarestPieceSelector::getSortedPieceStats() const
 | 
			
		||||
{
 | 
			
		||||
  return _sortedPieceStats;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace aria2
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,91 @@
 | 
			
		|||
/* <!-- copyright */
 | 
			
		||||
/*
 | 
			
		||||
 * aria2 - The high speed download utility
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (C) 2006 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_RAREST_PIECE_SELECTOR_H_
 | 
			
		||||
#define _D_RAREST_PIECE_SELECTOR_H_
 | 
			
		||||
 | 
			
		||||
#include "common.h"
 | 
			
		||||
#include "SharedHandle.h"
 | 
			
		||||
#include <deque>
 | 
			
		||||
 | 
			
		||||
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 RarestPieceSelector {
 | 
			
		||||
private:
 | 
			
		||||
  std::deque<SharedHandle<PieceStat> > _pieceStats;
 | 
			
		||||
 | 
			
		||||
  std::deque<SharedHandle<PieceStat> > _sortedPieceStats;
 | 
			
		||||
public:
 | 
			
		||||
  RarestPieceSelector(size_t pieceNum, bool randomShuffle);
 | 
			
		||||
 | 
			
		||||
  bool select(size_t& index, const std::deque<size_t>& candidateIndexes) const;
 | 
			
		||||
 | 
			
		||||
  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);
 | 
			
		||||
 | 
			
		||||
  const std::deque<SharedHandle<PieceStat> >& getSortedPieceStats() const;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // namespace aria2
 | 
			
		||||
 | 
			
		||||
#endif // _D_RAREST_PIECE_SELECTOR_H_
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -76,20 +76,19 @@ void DefaultPieceStorageTest::testGetTotalLength() {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
void DefaultPieceStorageTest::testGetMissingPiece() {
 | 
			
		||||
  DefaultPieceStorage pss(btContext, option);
 | 
			
		||||
  DefaultPieceStorage pss(btContext, option, false);
 | 
			
		||||
  pss.setEndGamePieceNum(0);
 | 
			
		||||
 | 
			
		||||
  peer->setAllBitfield();
 | 
			
		||||
  // TODO the ordering of piece may vary depending on the system, so the test
 | 
			
		||||
  // may fail.
 | 
			
		||||
 | 
			
		||||
  SharedHandle<Piece> piece = pss.getMissingPiece(peer);
 | 
			
		||||
  CPPUNIT_ASSERT_EQUAL(std::string("piece: index=2, length=128"),
 | 
			
		||||
  CPPUNIT_ASSERT_EQUAL(std::string("piece: index=0, length=128"),
 | 
			
		||||
		       piece->toString());
 | 
			
		||||
  piece = pss.getMissingPiece(peer);
 | 
			
		||||
  CPPUNIT_ASSERT_EQUAL(std::string("piece: index=1, length=128"),
 | 
			
		||||
		       piece->toString());
 | 
			
		||||
  piece = pss.getMissingPiece(peer);
 | 
			
		||||
  CPPUNIT_ASSERT_EQUAL(std::string("piece: index=0, length=128"),
 | 
			
		||||
  CPPUNIT_ASSERT_EQUAL(std::string("piece: index=2, length=128"),
 | 
			
		||||
		       piece->toString());
 | 
			
		||||
  piece = pss.getMissingPiece(peer);
 | 
			
		||||
  CPPUNIT_ASSERT(piece.isNull());
 | 
			
		||||
| 
						 | 
				
			
			@ -119,15 +118,13 @@ void DefaultPieceStorageTest::testHasMissingPiece() {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
void DefaultPieceStorageTest::testCompletePiece() {
 | 
			
		||||
  DefaultPieceStorage pss(btContext, option);
 | 
			
		||||
  DefaultPieceStorage pss(btContext, option, true);
 | 
			
		||||
  pss.setEndGamePieceNum(0);
 | 
			
		||||
 | 
			
		||||
  peer->setAllBitfield();
 | 
			
		||||
 | 
			
		||||
  // TODO the ordering of piece may vary depending on the system, so the test
 | 
			
		||||
  // may fail.
 | 
			
		||||
  SharedHandle<Piece> piece = pss.getMissingPiece(peer);
 | 
			
		||||
  CPPUNIT_ASSERT_EQUAL(std::string("piece: index=2, length=128"),
 | 
			
		||||
  CPPUNIT_ASSERT_EQUAL(std::string("piece: index=0, length=128"),
 | 
			
		||||
		       piece->toString());
 | 
			
		||||
 | 
			
		||||
  CPPUNIT_ASSERT_EQUAL(0ULL, pss.getCompletedLength());
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,179 @@
 | 
			
		|||
#include "RarestPieceSelector.h"
 | 
			
		||||
#include "Exception.h"
 | 
			
		||||
#include "Util.h"
 | 
			
		||||
#include <cstring>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <cppunit/extensions/HelperMacros.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_SUITE_END();
 | 
			
		||||
public:
 | 
			
		||||
  void setUp() {}
 | 
			
		||||
 | 
			
		||||
  void tearDown() {}
 | 
			
		||||
 | 
			
		||||
  void testAddPieceStats_index();
 | 
			
		||||
  void testAddPieceStats_bitfield();
 | 
			
		||||
  void testUpdatePieceStats();
 | 
			
		||||
  void testSubtractPieceStats();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
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::deque<SharedHandle<PieceStat> >& stats(selector.getSortedPieceStats());
 | 
			
		||||
    CPPUNIT_ASSERT_EQUAL((size_t)10, stats.size());
 | 
			
		||||
    
 | 
			
		||||
    for(size_t i = 0; i < 10; ++i) {
 | 
			
		||||
      CPPUNIT_ASSERT_EQUAL(indexes[i], stats[i]->getIndex());
 | 
			
		||||
      CPPUNIT_ASSERT_EQUAL(counts[i], stats[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::deque<SharedHandle<PieceStat> >& stats(selector.getSortedPieceStats());
 | 
			
		||||
 | 
			
		||||
    for(size_t i = 0; i < 10; ++i) {
 | 
			
		||||
      CPPUNIT_ASSERT_EQUAL(indexes[i], stats[i]->getIndex());
 | 
			
		||||
      CPPUNIT_ASSERT_EQUAL(counts[i], stats[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::deque<SharedHandle<PieceStat> >& stats(selector.getSortedPieceStats());
 | 
			
		||||
 | 
			
		||||
    for(size_t i = 0; i < 10; ++i) {
 | 
			
		||||
      CPPUNIT_ASSERT_EQUAL(indexes[i], stats[i]->getIndex());
 | 
			
		||||
      CPPUNIT_ASSERT_EQUAL(counts[i], stats[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::deque<SharedHandle<PieceStat> >& stats(selector.getSortedPieceStats());
 | 
			
		||||
    CPPUNIT_ASSERT_EQUAL((size_t)10, stats.size());
 | 
			
		||||
    
 | 
			
		||||
    for(size_t i = 0; i < 10; ++i) {
 | 
			
		||||
      CPPUNIT_ASSERT_EQUAL(indexes[i], stats[i]->getIndex());
 | 
			
		||||
      CPPUNIT_ASSERT_EQUAL(counts[i], stats[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::deque<SharedHandle<PieceStat> >& stats(selector.getSortedPieceStats());
 | 
			
		||||
    CPPUNIT_ASSERT_EQUAL((size_t)10, stats.size());
 | 
			
		||||
    
 | 
			
		||||
    for(size_t i = 0; i < 10; ++i) {
 | 
			
		||||
      CPPUNIT_ASSERT_EQUAL(indexes[i], stats[i]->getIndex());
 | 
			
		||||
      CPPUNIT_ASSERT_EQUAL(counts[i], stats[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::deque<SharedHandle<PieceStat> >& stats(selector.getSortedPieceStats());
 | 
			
		||||
    CPPUNIT_ASSERT_EQUAL((size_t)10, stats.size());
 | 
			
		||||
    
 | 
			
		||||
    for(size_t i = 0; i < 10; ++i) {
 | 
			
		||||
      CPPUNIT_ASSERT_EQUAL(indexes[i], stats[i]->getIndex());
 | 
			
		||||
      CPPUNIT_ASSERT_EQUAL(counts[i], stats[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::deque<SharedHandle<PieceStat> >& stats(selector.getSortedPieceStats());
 | 
			
		||||
    CPPUNIT_ASSERT_EQUAL((size_t)10, stats.size());
 | 
			
		||||
    
 | 
			
		||||
    for(size_t i = 0; i < 10; ++i) {
 | 
			
		||||
      CPPUNIT_ASSERT_EQUAL(indexes[i], stats[i]->getIndex());
 | 
			
		||||
      CPPUNIT_ASSERT_EQUAL(counts[i], stats[i]->getCount());
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
} // namespace aria2
 | 
			
		||||
		Loading…
	
		Reference in New Issue