mirror of https://github.com/aria2/aria2
				
				
				
			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.ccpull/1/head
							parent
							
								
									d05d8bbddc
								
							
						
					
					
						commit
						4da631bef6
					
				
							
								
								
									
										21
									
								
								ChangeLog
								
								
								
								
							
							
						
						
									
										21
									
								
								ChangeLog
								
								
								
								
							|  | @ -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, | ||||
|  |  | |||
|  | @ -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
 | ||||
|  |  | |||
|  | @ -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; | ||||
|  |  | |||
|  | @ -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
 | ||||
|  |  | |||
|  | @ -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
 | ||||
|  |  | |||
|  | @ -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\
 | ||||
|  |  | |||
|  | @ -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 | ||||
|  |  | |||
|  | @ -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
 | ||||
|  |  | |||
|  | @ -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
 | ||||
|  | @ -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_
 | ||||
|  | @ -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
 | ||||
|  |  | |||
|  | @ -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
 | ||||
|  |  | |||
|  | @ -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)); | ||||
|  |  | |||
|  | @ -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(); | ||||
|  |  | |||
|  | @ -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_
 | ||||
|  | @ -66,6 +66,8 @@ aria2c_SOURCES = AllTest.cc\ | |||
| 	BencodeTest.cc\
 | ||||
| 	SequentialPickerTest.cc\
 | ||||
| 	RarestPieceSelectorTest.cc\
 | ||||
| 	PieceStatManTest.cc\
 | ||||
| 	InOrderPieceSelector.h\
 | ||||
| 	LongestSequencePieceSelectorTest.cc\
 | ||||
| 	a2algoTest.cc\
 | ||||
| 	bitfieldTest.cc\
 | ||||
|  |  | |||
|  | @ -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; \
 | ||||
|  |  | |||
|  | @ -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
 | ||||
|  | @ -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())); | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Tatsuhiro Tsujikawa
						Tatsuhiro Tsujikawa