2009-03-28 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>

BitfieldMan::getMissingIndexes family functions now takes
	unsigned char* bitfield instead of stl container for efficiency.
	PieceSelector::select now takes this
	bitfield. RarestPieceSelector::select now also performs
	efficiently for this change.  bitfield namespace is introduced
	and it has several helper functions to handle basic bitfield
	operations such as test, count set bits, etc.
	* src/BitfieldMan.cc
	* src/BitfieldMan.h
	* src/DefaultBtRequestFactory.cc
	* src/DefaultPieceStorage.cc
	* src/DefaultPieceStorage.h
	* src/LongestSequencePieceSelector.cc
	* src/LongestSequencePieceSelector.h
	* src/Makefile.am
	* src/Piece.cc
	* src/Piece.h
	* src/PieceSelector.h
	* src/RarestPieceSelector.cc
	* src/RarestPieceSelector.h
	* src/Util.cc
	* src/Util.h
	* src/bitfield.h
	* test/BitfieldManTest.cc
	* test/LongestSequencePieceSelectorTest.cc
	* test/Makefile.am
	* test/RarestPieceSelectorTest.cc
	* test/UtilTest.cc
	* test/bitfieldTest.cc
pull/1/head
Tatsuhiro Tsujikawa 2009-03-28 13:29:38 +00:00
parent 3531d57d37
commit a6b02840fa
25 changed files with 471 additions and 227 deletions

View File

@ -1,3 +1,35 @@
2009-03-28 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
BitfieldMan::getMissingIndexes family functions now takes unsigned
char* bitfield instead of stl container for efficiency.
PieceSelector::select now takes this
bitfield. RarestPieceSelector::select now also performs
efficiently for this change. bitfield namespace is introduced and
it has several helper functions to handle basic bitfield
operations such as test, count set bits, etc.
* src/BitfieldMan.cc
* src/BitfieldMan.h
* src/DefaultBtRequestFactory.cc
* src/DefaultPieceStorage.cc
* src/DefaultPieceStorage.h
* src/LongestSequencePieceSelector.cc
* src/LongestSequencePieceSelector.h
* src/Makefile.am
* src/Piece.cc
* src/Piece.h
* src/PieceSelector.h
* src/RarestPieceSelector.cc
* src/RarestPieceSelector.h
* src/Util.cc
* src/Util.h
* src/bitfield.h
* test/BitfieldManTest.cc
* test/LongestSequencePieceSelectorTest.cc
* test/Makefile.am
* test/RarestPieceSelectorTest.cc
* test/UtilTest.cc
* test/bitfieldTest.cc
2009-03-28 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
Made accepted socket non-block.

View File

@ -34,11 +34,13 @@
/* copyright --> */
#include "BitfieldMan.h"
#include <cassert>
#include <cstring>
#include "Randomizer.h"
#include "Util.h"
#include "array_fun.h"
#include "bitfield.h"
namespace aria2 {
@ -159,19 +161,6 @@ size_t BitfieldMan::getBlockLength(size_t index) const
}
}
size_t BitfieldMan::countSetBit(const unsigned char* bitfield, size_t len) const {
size_t count = 0;
size_t size = sizeof(uint32_t);
size_t to = len/size;
for(size_t i = 0; i < to; ++i) {
count += Util::countBit(*reinterpret_cast<const uint32_t*>(&bitfield[i*size]));
}
for(size_t i = len-len%size; i < len; i++) {
count += Util::countBit(static_cast<uint32_t>(bitfield[i]));
}
return count;
}
size_t
BitfieldMan::getNthBitIndex(const unsigned char bitfield, size_t nth) const
{
@ -195,20 +184,10 @@ bool BitfieldMan::getMissingIndexRandomly(size_t& index,
size_t bitfieldLength) const
{
size_t byte = randomizer->getRandomNumber(bitfieldLength);
unsigned char lastMask = 0;
// the number of bytes in the last byte of bitfield
size_t lastByteLength = totalLength%(blockLength*8);
// the number of block in the last byte of bitfield
size_t lastBlockCount = DIV_FLOOR(lastByteLength, blockLength);
for(size_t i = 0; i < lastBlockCount; ++i) {
lastMask >>= 1;
lastMask |= 0x80;
}
for(size_t i = 0; i < bitfieldLength; ++i) {
unsigned char mask;
if(byte == bitfieldLength-1) {
mask = lastMask;
mask = bitfield::lastByteMask(blocks);
} else {
mask = 0xff;
}
@ -218,7 +197,7 @@ bool BitfieldMan::getMissingIndexRandomly(size_t& index,
index = byte*8+getNthBitIndex(bits, 1);
return true;
}
byte++;
++byte;
if(byte == bitfieldLength) {
byte = 0;
}
@ -322,27 +301,6 @@ bool BitfieldMan::getMissingUnusedIndex(size_t& index) const
return getMissingIndexRandomly(index, bf, bitfieldLength);
}
// [startIndex, endIndex)
class Range {
public:
size_t startIndex;
size_t endIndex;
Range(size_t startIndex = 0, size_t endIndex = 0):startIndex(startIndex),
endIndex(endIndex) {}
size_t getSize() const {
return endIndex-startIndex;
}
size_t getMidIndex() const {
return (endIndex-startIndex)/2+startIndex;
}
bool operator<(const Range& range) const {
return getSize() < range.getSize();
}
};
size_t BitfieldMan::getStartIndex(size_t index) const {
while(index < blocks && (isUseBitSet(index) || isBitSet(index))) {
index++;
@ -393,36 +351,35 @@ bool BitfieldMan::getSparseMissingUnusedIndex(size_t& index) const {
}
template<typename Array>
bool BitfieldMan::getAllMissingIndexes(std::deque<size_t>& indexes,
const Array& bitfield,
size_t bitfieldLength) const
static bool copyBitfield(unsigned char* dst, const Array& src, size_t blocks)
{
for(size_t i = 0; i < bitfieldLength; ++i) {
unsigned char bits = bitfield[i];
unsigned char mask = 128;
size_t index = i*8;
for(size_t bi = 0; bi < 8 && index < blocks; ++bi, mask >>= 1, ++index) {
if(bits & mask) {
indexes.push_back(index);
}
}
unsigned char bits = 0;
size_t len = (blocks+7)/8;
for(size_t i = 0; i < len-1; ++i) {
dst[i] = src[i];
bits |= dst[i];
}
return !indexes.empty();
dst[len-1] = src[len-1]&bitfield::lastByteMask(blocks);
bits |= dst[len-1];
return bits != 0;
}
bool BitfieldMan::getAllMissingIndexes(std::deque<size_t>& indexes) const
bool BitfieldMan::getAllMissingIndexes(unsigned char* misbitfield, size_t len)
const
{
assert(len == bitfieldLength);
array_fun<unsigned char> bf = array_negate(bitfield);
if(filterEnabled) {
bf = array_and(bf, filterBitfield);
}
return getAllMissingIndexes(indexes, bf, bitfieldLength);
return copyBitfield(misbitfield, bf, blocks);
}
bool BitfieldMan::getAllMissingIndexes(std::deque<size_t>& indexes,
bool BitfieldMan::getAllMissingIndexes(unsigned char* misbitfield, size_t len,
const unsigned char* peerBitfield,
size_t peerBitfieldLength) const
{
assert(len == bitfieldLength);
if(bitfieldLength != peerBitfieldLength) {
return false;
}
@ -431,13 +388,15 @@ bool BitfieldMan::getAllMissingIndexes(std::deque<size_t>& indexes,
if(filterEnabled) {
bf = array_and(bf, filterBitfield);
}
return getAllMissingIndexes(indexes, bf, bitfieldLength);
return copyBitfield(misbitfield, bf, blocks);
}
bool BitfieldMan::getAllMissingUnusedIndexes(std::deque<size_t>& indexes,
bool BitfieldMan::getAllMissingUnusedIndexes(unsigned char* misbitfield,
size_t len,
const unsigned char* peerBitfield,
size_t peerBitfieldLength) const
{
assert(len == bitfieldLength);
if(bitfieldLength != peerBitfieldLength) {
return false;
}
@ -447,7 +406,7 @@ bool BitfieldMan::getAllMissingUnusedIndexes(std::deque<size_t>& indexes,
if(filterEnabled) {
bf = array_and(bf, filterBitfield);
}
return getAllMissingIndexes(indexes, bf, bitfieldLength);
return copyBitfield(misbitfield, bf, blocks);
}
size_t BitfieldMan::countMissingBlock() const {
@ -456,16 +415,15 @@ size_t BitfieldMan::countMissingBlock() const {
size_t BitfieldMan::countMissingBlockNow() const {
if(filterEnabled) {
unsigned char* temp = new unsigned char[bitfieldLength];
array_ptr<unsigned char> temp(new unsigned char[bitfieldLength]);
for(size_t i = 0; i < bitfieldLength; ++i) {
temp[i] = bitfield[i]&filterBitfield[i];
}
size_t count = countSetBit(filterBitfield, bitfieldLength)-
countSetBit(temp, bitfieldLength);
delete [] temp;
size_t count = bitfield::countSetBit(filterBitfield, blocks)-
bitfield::countSetBit(temp, blocks);
return count;
} else {
return blocks-countSetBit(bitfield, bitfieldLength);
return blocks-bitfield::countSetBit(bitfield, blocks);
}
}
@ -479,7 +437,7 @@ size_t BitfieldMan::countBlock() const {
size_t BitfieldMan::countFilteredBlockNow() const {
if(filterEnabled) {
return countSetBit(filterBitfield, bitfieldLength);
return bitfield::countSetBit(filterBitfield, blocks);
} else {
return 0;
}
@ -550,18 +508,14 @@ bool BitfieldMan::isAllBitSet() const {
return true;
}
bool BitfieldMan::isBitSetInternal(const unsigned char* bitfield, size_t index) const {
if(index < 0 || blocks <= index) { return false; }
unsigned char mask = 128 >> index%8;
return (bitfield[index/8] & mask) != 0;
bool BitfieldMan::isBitSet(size_t index) const
{
return bitfield::test(bitfield, blocks, index);
}
bool BitfieldMan::isBitSet(size_t index) const {
return isBitSetInternal(bitfield, index);
}
bool BitfieldMan::isUseBitSet(size_t index) const {
return isBitSetInternal(useBitfield, index);
bool BitfieldMan::isUseBitSet(size_t index) const
{
return bitfield::test(useBitfield, blocks, index);
}
void BitfieldMan::setBitfield(const unsigned char* bitfield, size_t bitfieldLength) {
@ -656,11 +610,11 @@ uint64_t BitfieldMan::getFilteredTotalLengthNow() const {
if(!filterBitfield) {
return 0;
}
size_t filteredBlocks = countSetBit(filterBitfield, bitfieldLength);
size_t filteredBlocks = bitfield::countSetBit(filterBitfield, blocks);
if(filteredBlocks == 0) {
return 0;
}
if(isBitSetInternal(filterBitfield, blocks-1)) {
if(bitfield::test(filterBitfield, blocks, blocks-1)) {
return ((uint64_t)filteredBlocks-1)*blockLength+getLastBlockLength();
} else {
return ((uint64_t)filteredBlocks)*blockLength;
@ -679,12 +633,12 @@ uint64_t BitfieldMan::getCompletedLength(bool useFilter) const {
} else {
memcpy(temp, bitfield, bitfieldLength);
}
size_t completedBlocks = countSetBit(temp, bitfieldLength);
size_t completedBlocks = bitfield::countSetBit(temp, blocks);
uint64_t completedLength = 0;
if(completedBlocks == 0) {
completedLength = 0;
} else {
if(isBitSetInternal(temp, blocks-1)) {
if(bitfield::test(temp, blocks, blocks-1)) {
completedLength = ((uint64_t)completedBlocks-1)*blockLength+getLastBlockLength();
} else {
completedLength = ((uint64_t)completedBlocks)*blockLength;

View File

@ -62,7 +62,6 @@ private:
uint64_t cachedFilteredComletedLength;
uint64_t cachedFilteredTotalLength;
size_t countSetBit(const unsigned char* bitfield, size_t len) const;
size_t getNthBitIndex(const unsigned char bit, size_t nth) const;
bool getMissingIndexRandomly(size_t& index, const unsigned char* bitfield, size_t len) const;
@ -77,7 +76,6 @@ private:
const Array& bitfield,
size_t bitfieldLength) const;
bool isBitSetInternal(const unsigned char* bitfield, size_t index) const;
bool setBitInternal(unsigned char* bitfield, size_t index, bool on);
bool setFilterBit(size_t index);
@ -85,6 +83,27 @@ private:
size_t getEndIndex(size_t index) const;
uint64_t getCompletedLength(bool useFilter) const;
// [startIndex, endIndex)
class Range {
public:
size_t startIndex;
size_t endIndex;
Range(size_t startIndex = 0, size_t endIndex = 0):startIndex(startIndex),
endIndex(endIndex) {}
size_t getSize() const {
return endIndex-startIndex;
}
size_t getMidIndex() const {
return (endIndex-startIndex)/2+startIndex;
}
bool operator<(const Range& range) const {
return getSize() < range.getSize();
}
};
public:
BitfieldMan(size_t blockLength, uint64_t totalLength);
BitfieldMan(const BitfieldMan& bitfieldMan);
@ -139,16 +158,16 @@ public:
/**
* affected by filter
*/
bool getAllMissingIndexes(std::deque<size_t>&indexes) const;
bool getAllMissingIndexes(unsigned char* misbitfield, size_t mislen) const;
/**
* affected by filter
*/
bool getAllMissingIndexes(std::deque<size_t>& indexes,
bool getAllMissingIndexes(unsigned char* misbitfield, size_t mislen,
const unsigned char* bitfield, size_t len) const;
/**
* affected by filter
*/
bool getAllMissingUnusedIndexes(std::deque<size_t>& indexes,
bool getAllMissingUnusedIndexes(unsigned char* misbitfield, size_t mislen,
const unsigned char* bitfield,
size_t len) const;
/**

View File

@ -47,6 +47,7 @@
#include "BtMessage.h"
#include "a2functional.h"
#include "SimpleRandomizer.h"
#include "array_fun.h"
namespace aria2 {
@ -170,13 +171,27 @@ void DefaultBtRequestFactory::createRequestMessagesOnEndGame
for(Pieces::iterator itr = pieces.begin();
itr != pieces.end() && requests.size() < max; ++itr) {
PieceHandle& piece = *itr;
const size_t mislen = piece->getBitfieldLength();
array_ptr<unsigned char> misbitfield(new unsigned char[mislen]);
piece->getAllMissingBlockIndexes(misbitfield, mislen);
std::deque<size_t> missingBlockIndexes;
piece->getAllMissingBlockIndexes(missingBlockIndexes);
size_t blockIndex = 0;
for(size_t i = 0; i < mislen; ++i) {
unsigned char bits = misbitfield[i];
unsigned char mask = 128;
for(size_t bi = 0; bi < 8; ++bi, mask >>= 1, ++blockIndex) {
if(bits & mask) {
missingBlockIndexes.push_back(blockIndex);
}
}
}
std::random_shuffle(missingBlockIndexes.begin(), missingBlockIndexes.end(),
*(SimpleRandomizer::getInstance().get()));
for(std::deque<size_t>::const_iterator bitr = missingBlockIndexes.begin();
bitr != missingBlockIndexes.end() && requests.size() < max; bitr++) {
size_t blockIndex = *bitr;
const size_t& blockIndex = *bitr;
if(!dispatcher->isOutstandingRequest(piece->getIndex(),
blockIndex)) {
_logger->debug("Creating RequestMessage index=%u, begin=%u, blockIndex=%u",

View File

@ -57,6 +57,7 @@
#include "Option.h"
#include "StringFormat.h"
#include "RarestPieceSelector.h"
#include "array_fun.h"
namespace aria2 {
@ -97,18 +98,21 @@ bool DefaultPieceStorage::isEndGame()
bool DefaultPieceStorage::getMissingPieceIndex(size_t& index,
const unsigned char* bitfield,
size_t& length)
size_t length)
{
std::deque<size_t> indexes;
const size_t mislen = bitfieldMan->getBitfieldLength();
array_ptr<unsigned char> misbitfield(new unsigned char[mislen]);
bool r;
if(isEndGame()) {
r = bitfieldMan->getAllMissingIndexes(indexes, bitfield, length);
r = bitfieldMan->getAllMissingIndexes(misbitfield, mislen,
bitfield, length);
} else {
r = bitfieldMan->getAllMissingUnusedIndexes(indexes, bitfield, length);
r = bitfieldMan->getAllMissingUnusedIndexes(misbitfield, mislen,
bitfield, length);
}
if(r) {
// We assume indexes is sorted using comparator less.
return _pieceSelector->select(index, indexes);
return _pieceSelector->select(index, misbitfield,bitfieldMan->countBlock());
} else {
return false;
}

View File

@ -84,7 +84,7 @@ private:
SharedHandle<PieceSelector> _pieceSelector;
bool getMissingPieceIndex(size_t& index,
const unsigned char* bitfield, size_t& length);
const unsigned char* bitfield, size_t length);
SharedHandle<Piece> getMissingPiece(const unsigned char* bitfield,
size_t length);

View File

@ -33,21 +33,55 @@
*/
/* copyright --> */
#include "LongestSequencePieceSelector.h"
#include "a2algo.h"
#include "bitfield.h"
namespace aria2 {
bool LongestSequencePieceSelector::select
(size_t& index,
const std::deque<size_t>& candidateIndexes) const
static size_t getStartIndex
(size_t from, const unsigned char* bitfield, size_t nbits)
{
std::pair<std::deque<size_t>::const_iterator, size_t> p =
max_sequence(candidateIndexes.begin(), candidateIndexes.end());
if(p.second == 0) {
return false;
while(from < nbits && !bitfield::test(bitfield, nbits, from)) {
++from;
}
if(nbits <= from) {
return nbits;
} else {
index = *(p.first)+p.second-1;
return from;
}
}
static size_t getEndIndex
(size_t from, const unsigned char* bitfield, size_t nbits)
{
while(from < nbits && bitfield::test(bitfield, nbits, from)) {
++from;
}
return from;
}
bool LongestSequencePieceSelector::select
(size_t& index, const unsigned char* bitfield, size_t nbits) const
{
size_t mstartindex = 0;
size_t mendindex = 0;
size_t nextIndex = 0;
while(nextIndex < nbits) {
size_t startindex = getStartIndex(nextIndex, bitfield, nbits);
if(startindex == nbits) {
break;
}
size_t endindex = getEndIndex(startindex, bitfield, nbits);
if(mendindex-mstartindex < endindex-startindex) {
mstartindex = startindex;
mendindex = endindex;
}
nextIndex = endindex;
}
if(mendindex-mstartindex > 0) {
index = mendindex-1;
return true;
} else {
return false;
}
}

View File

@ -42,11 +42,11 @@ namespace aria2 {
class LongestSequencePieceSelector:public PieceSelector {
public:
// Returns the last index of longest continuous sequence in candidateIndexes.
// For example, if candidateIndexes is
// For example, if indexes of set bits in bitfield are
// { 1,2,3,4,7,10,11,12,13,14,15,100,112,113,114 }, then
// returns 15 because { 10, 11, 12, 13, 14, 15 } is the longest sequence.
virtual bool select
(size_t& index, const std::deque<size_t>& candidateIndexes) const;
(size_t& index, const unsigned char* bitfield, size_t nbits) const;
virtual void addPieceStats(size_t index);

View File

@ -205,7 +205,8 @@ SRCS = Socket.h\
HttpServerResponseCommand.cc HttpServerResponseCommand.h\
HttpServer.cc HttpServer.h\
PieceSelector.h\
LongestSequencePieceSelector.cc LongestSequencePieceSelector.h
LongestSequencePieceSelector.cc LongestSequencePieceSelector.h\
bitfield.h
if HAVE_POSIX_FALLOCATE
SRCS += FallocFileAllocationIterator.cc FallocFileAllocationIterator.h

View File

@ -417,11 +417,12 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \
HttpServerCommand.h HttpServerResponseCommand.cc \
HttpServerResponseCommand.h HttpServer.cc HttpServer.h \
PieceSelector.h LongestSequencePieceSelector.cc \
LongestSequencePieceSelector.h FallocFileAllocationIterator.cc \
FallocFileAllocationIterator.h EpollEventPoll.cc \
EpollEventPoll.h TLSContext.h LibgnutlsTLSContext.cc \
LibgnutlsTLSContext.h LibsslTLSContext.cc LibsslTLSContext.h \
GZipDecoder.cc GZipDecoder.h Sqlite3MozCookieParser.cc \
LongestSequencePieceSelector.h bitfield.h \
FallocFileAllocationIterator.cc FallocFileAllocationIterator.h \
EpollEventPoll.cc EpollEventPoll.h TLSContext.h \
LibgnutlsTLSContext.cc LibgnutlsTLSContext.h \
LibsslTLSContext.cc LibsslTLSContext.h GZipDecoder.cc \
GZipDecoder.h Sqlite3MozCookieParser.cc \
Sqlite3MozCookieParser.h AsyncNameResolver.cc \
AsyncNameResolver.h IteratableChunkChecksumValidator.cc \
IteratableChunkChecksumValidator.h \
@ -1157,14 +1158,14 @@ SRCS = Socket.h SocketCore.cc SocketCore.h BinaryStream.h Command.cc \
HttpServerCommand.h HttpServerResponseCommand.cc \
HttpServerResponseCommand.h HttpServer.cc HttpServer.h \
PieceSelector.h LongestSequencePieceSelector.cc \
LongestSequencePieceSelector.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) \
$(am__append_15) $(am__append_16) $(am__append_17) \
$(am__append_18) $(am__append_19) $(am__append_20) \
$(am__append_21) $(am__append_22)
LongestSequencePieceSelector.h bitfield.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) $(am__append_15) $(am__append_16) \
$(am__append_17) $(am__append_18) $(am__append_19) \
$(am__append_20) $(am__append_21) $(am__append_22)
noinst_LIBRARIES = libaria2c.a
libaria2c_a_SOURCES = $(SRCS)
aria2c_LDADD = libaria2c.a @LIBINTL@ @ALLOCA@ @LIBGNUTLS_LIBS@\

View File

@ -197,8 +197,10 @@ bool Piece::getFirstMissingBlockIndexWithoutLock(size_t& index) const
return bitfield->getFirstMissingIndex(index);
}
bool Piece::getAllMissingBlockIndexes(std::deque<size_t>& indexes) const {
return bitfield->getAllMissingIndexes(indexes);
bool Piece::getAllMissingBlockIndexes
(unsigned char* misbitfield, size_t mislen) const
{
return bitfield->getAllMissingIndexes(misbitfield, mislen);
}
std::string Piece::toString() const {

View File

@ -89,7 +89,8 @@ public:
bool getMissingUnusedBlockIndex(size_t& index) const;
bool getMissingBlockIndex(size_t& index) const;
bool getFirstMissingBlockIndexWithoutLock(size_t& index) const;
bool getAllMissingBlockIndexes(std::deque<size_t>& indexes) const;
bool getAllMissingBlockIndexes(unsigned char* misbitfield,
size_t mislen) const;
void completeBlock(size_t blockIndex);
void cancelBlock(size_t blockIndex);

View File

@ -48,7 +48,7 @@ public:
virtual ~PieceSelector() {}
virtual bool select
(size_t& index, const std::deque<size_t>& candidateIndexes) const = 0;
(size_t& index, const unsigned char* bitfield, size_t nbits) const = 0;
virtual void addPieceStats(size_t index) = 0;

View File

@ -34,6 +34,7 @@
/* copyright --> */
#include "RarestPieceSelector.h"
#include <cassert>
#include <algorithm>
#include "SimpleRandomizer.h"
@ -121,23 +122,26 @@ RarestPieceSelector::RarestPieceSelector(size_t pieceNum, bool randomShuffle):
class FindRarestPiece
{
private:
const std::deque<size_t>& _indexes;
const unsigned char* _misbitfield;
size_t _numbits;
public:
FindRarestPiece(const std::deque<size_t>& indexes):_indexes(indexes) {}
FindRarestPiece(const unsigned char* misbitfield, size_t numbits):
_misbitfield(misbitfield), _numbits(numbits) {}
bool operator()(const size_t& index)
{
return std::binary_search(_indexes.begin(), _indexes.end(), index);
assert(index < _numbits);
unsigned char mask = (128 >> (index%8));
return _misbitfield[index/8]&mask;
}
};
bool RarestPieceSelector::select
(size_t& index,
const std::deque<size_t>& candidateIndexes) const
(size_t& index, const unsigned char* bitfield, size_t nbits) const
{
std::vector<size_t>::const_iterator i =
std::find_if(_sortedPieceStatIndexes.begin(), _sortedPieceStatIndexes.end(),
FindRarestPiece(candidateIndexes));
FindRarestPiece(bitfield, nbits));
if(i == _sortedPieceStatIndexes.end()) {
return false;
} else {

View File

@ -69,7 +69,7 @@ public:
RarestPieceSelector(size_t pieceNum, bool randomShuffle);
virtual bool select
(size_t& index, const std::deque<size_t>& candidateIndexes) const;
(size_t& index, const unsigned char* bitfield, size_t nbits) const;
virtual void addPieceStats(size_t index);

View File

@ -574,33 +574,6 @@ std::string Util::getContentDispositionFilename(const std::string& header) {
}
}
static int nbits[] = {
0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8,
};
unsigned int Util::countBit(uint32_t n) {
return
nbits[n&0xffu]+
nbits[(n >> 8)&0xffu]+
nbits[(n >> 16)&0xffu]+
nbits[(n >> 24)&0xffu];
}
std::string Util::randomAlpha(size_t length, const RandomizerHandle& randomizer) {
static const char *random_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
std::string str;

View File

@ -212,8 +212,6 @@ public:
// this function temporarily put here
static std::string getContentDispositionFilename(const std::string& header);
static unsigned int countBit(uint32_t n);
static std::string randomAlpha(size_t length,
const SharedHandle<Randomizer>& randomizer);

115
src/bitfield.h Normal file
View File

@ -0,0 +1,115 @@
/* <!-- 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_BITFIELD_H_
#define _D_BITFIELD_H_
#include "common.h"
#include <cassert>
#include <cstdlib>
#include "Util.h"
namespace aria2 {
namespace bitfield {
// Returns the bit mask for the last byte. For example, nbits = 9,
// then 0x80 is returned. nbits = 12, then 0xf0 is returned.
inline unsigned char lastByteMask(size_t nbits)
{
return -256 >> (8-((nbits+7)/8*8-nbits));
}
// Returns true if index-th bits is set. Otherwise returns false.
inline bool test(const unsigned char* bitfield, size_t nbits, size_t index)
{
assert(index < nbits);
unsigned char mask = 128 >> (index%8);
return (bitfield[index/8]&mask) != 0;
}
inline size_t countBit32(uint32_t n)
{
static const int nbits[] = {
0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8,
};
return
nbits[n&0xffu]+
nbits[(n >> 8)&0xffu]+
nbits[(n >> 16)&0xffu]+
nbits[(n >> 24)&0xffu];
}
// Counts set bit in bitfield.
inline size_t countSetBit(const unsigned char* bitfield, size_t nbits)
{
size_t count = 0;
size_t size = sizeof(uint32_t);
size_t len = (nbits+7)/8;
size_t to = len/size;
for(size_t i = 0; i < to; ++i) {
count += countBit32(*reinterpret_cast<const uint32_t*>(&bitfield[i*size]));
}
for(size_t i = len-len%size; i < len-1; ++i) {
count += countBit32(static_cast<uint32_t>(bitfield[i]));
}
if(nbits%32 != 0) {
count +=
countBit32(static_cast<uint32_t>(bitfield[len-1]&lastByteMask(nbits)));
}
return count;
}
} // namespace bitfield
} // namespace aria2
#endif // _D_BITFIELD_H_

View File

@ -5,6 +5,7 @@
#include <cppunit/extensions/HelperMacros.h>
#include "FixedNumberRandomizer.h"
#include "bitfield.h"
namespace aria2 {
@ -25,6 +26,7 @@ class BitfieldManTest:public CppUnit::TestFixture {
CPPUNIT_TEST(testSetBitRange);
CPPUNIT_TEST(testGetAllMissingIndexes);
CPPUNIT_TEST(testGetAllMissingIndexes_noarg);
CPPUNIT_TEST(testGetAllMissingIndexes_checkLastByte);
CPPUNIT_TEST(testGetAllMissingUnusedIndexes);
CPPUNIT_TEST(testGetMissingUnusedIndex);
CPPUNIT_TEST(testGetMissingIndex_noarg);
@ -54,6 +56,7 @@ public:
void testGetMissingUnusedIndex_noarg();
void testGetAllMissingIndexes();
void testGetAllMissingIndexes_noarg();
void testGetAllMissingIndexes_checkLastByte();
void testGetAllMissingUnusedIndexes();
void testIsAllBitSet();
@ -607,83 +610,87 @@ void BitfieldManTest::testGetAllMissingIndexes_noarg()
{
size_t blockLength = 16*1024;
uint64_t totalLength = 1024*1024;
size_t nbits = (totalLength+blockLength-1)/blockLength;
BitfieldMan bf(blockLength, totalLength);
unsigned char misbitfield[8];
CPPUNIT_ASSERT(bf.getAllMissingIndexes(misbitfield, sizeof(misbitfield)));
CPPUNIT_ASSERT_EQUAL((size_t)64, bitfield::countSetBit(misbitfield, nbits));
{
std::deque<size_t> indexes;
CPPUNIT_ASSERT(bf.getAllMissingIndexes(indexes));
CPPUNIT_ASSERT_EQUAL((size_t)64, indexes.size());
}
for(size_t i = 0; i < 63; ++i) {
bf.setBit(i);
}
{
std::deque<size_t> indexes;
CPPUNIT_ASSERT(bf.getAllMissingIndexes(indexes));
CPPUNIT_ASSERT_EQUAL((size_t)1, indexes.size());
CPPUNIT_ASSERT_EQUAL((size_t)63, indexes.front());
}
CPPUNIT_ASSERT(bf.getAllMissingIndexes(misbitfield, sizeof(misbitfield)));
CPPUNIT_ASSERT_EQUAL((size_t)1, bitfield::countSetBit(misbitfield, nbits));
CPPUNIT_ASSERT(bitfield::test(misbitfield, nbits, 63));
}
// See garbage bits of last byte are 0
void BitfieldManTest::testGetAllMissingIndexes_checkLastByte()
{
size_t blockLength = 16*1024;
uint64_t totalLength = blockLength*2;
size_t nbits = (totalLength+blockLength-1)/blockLength;
BitfieldMan bf(blockLength, totalLength);
unsigned char misbitfield[1];
CPPUNIT_ASSERT(bf.getAllMissingIndexes(misbitfield, sizeof(misbitfield)));
CPPUNIT_ASSERT_EQUAL((size_t)2, bitfield::countSetBit(misbitfield, nbits));
CPPUNIT_ASSERT(bitfield::test(misbitfield, nbits, 0));
CPPUNIT_ASSERT(bitfield::test(misbitfield, nbits, 1));
}
void BitfieldManTest::testGetAllMissingIndexes()
{
size_t blockLength = 16*1024;
uint64_t totalLength = 1024*1024;
size_t nbits = (totalLength+blockLength-1)/blockLength;
BitfieldMan bf(blockLength, totalLength);
BitfieldMan peerBf(blockLength, totalLength);
peerBf.setAllBit();
unsigned char misbitfield[8];
{
std::deque<size_t> indexes;
CPPUNIT_ASSERT(bf.getAllMissingIndexes(indexes,
peerBf.getBitfield(),
peerBf.getBitfieldLength()));
CPPUNIT_ASSERT_EQUAL((size_t)64, indexes.size());
}
CPPUNIT_ASSERT(bf.getAllMissingIndexes(misbitfield, sizeof(misbitfield),
peerBf.getBitfield(),
peerBf.getBitfieldLength()));
CPPUNIT_ASSERT_EQUAL((size_t)64, bitfield::countSetBit(misbitfield, nbits));
for(size_t i = 0; i < 62; ++i) {
bf.setBit(i);
}
peerBf.unsetBit(62);
{
std::deque<size_t> indexes;
CPPUNIT_ASSERT(bf.getAllMissingIndexes(indexes,
peerBf.getBitfield(),
peerBf.getBitfieldLength()));
CPPUNIT_ASSERT_EQUAL((size_t)1, indexes.size());
CPPUNIT_ASSERT_EQUAL((size_t)63, indexes.front());
}
CPPUNIT_ASSERT(bf.getAllMissingIndexes(misbitfield, sizeof(misbitfield),
peerBf.getBitfield(),
peerBf.getBitfieldLength()));
CPPUNIT_ASSERT_EQUAL((size_t)1, bitfield::countSetBit(misbitfield, nbits));
CPPUNIT_ASSERT(bitfield::test(misbitfield, nbits, 63));
}
void BitfieldManTest::testGetAllMissingUnusedIndexes()
{
size_t blockLength = 16*1024;
uint64_t totalLength = 1024*1024;
size_t nbits = (totalLength+blockLength-1)/blockLength;
BitfieldMan bf(blockLength, totalLength);
BitfieldMan peerBf(blockLength, totalLength);
peerBf.setAllBit();
unsigned char misbitfield[8];
CPPUNIT_ASSERT(bf.getAllMissingUnusedIndexes(misbitfield,
sizeof(misbitfield),
peerBf.getBitfield(),
peerBf.getBitfieldLength()));
CPPUNIT_ASSERT_EQUAL((size_t)64, bitfield::countSetBit(misbitfield, nbits));
{
std::deque<size_t> indexes;
CPPUNIT_ASSERT(bf.getAllMissingUnusedIndexes(indexes,
peerBf.getBitfield(),
peerBf.getBitfieldLength()));
CPPUNIT_ASSERT_EQUAL((size_t)64, indexes.size());
}
for(size_t i = 0; i < 61; ++i) {
bf.setBit(i);
}
bf.setUseBit(61);
peerBf.unsetBit(62);
{
std::deque<size_t> indexes;
CPPUNIT_ASSERT(bf.getAllMissingUnusedIndexes(indexes,
peerBf.getBitfield(),
peerBf.getBitfieldLength()));
CPPUNIT_ASSERT_EQUAL((size_t)1, indexes.size());
CPPUNIT_ASSERT_EQUAL((size_t)63, indexes.front());
}
CPPUNIT_ASSERT(bf.getAllMissingUnusedIndexes(misbitfield,
sizeof(misbitfield),
peerBf.getBitfield(),
peerBf.getBitfieldLength()));
CPPUNIT_ASSERT_EQUAL((size_t)1, bitfield::countSetBit(misbitfield, nbits));
CPPUNIT_ASSERT(bitfield::test(misbitfield, nbits, 63));
}
void BitfieldManTest::testGetMissingUnusedIndex()

View File

@ -3,6 +3,7 @@
#include <cppunit/extensions/HelperMacros.h>
#include "array_fun.h"
#include "BitfieldMan.h"
namespace aria2 {
@ -25,19 +26,23 @@ CPPUNIT_TEST_SUITE_REGISTRATION(LongestSequencePieceSelectorTest);
void LongestSequencePieceSelectorTest::testSelect()
{
size_t A[] = { 1,2,3,4,7,10,11,12,13,14,15,100,112,113,114 };
std::deque<size_t> indexes(&A[0], &A[arrayLength(A)]);
BitfieldMan bf(1024, 1024*256);
for(size_t i = 0; i < arrayLength(A); ++i) {
bf.setBit(A[i]);
}
LongestSequencePieceSelector selector;
size_t index;
CPPUNIT_ASSERT(selector.select(index, indexes));
CPPUNIT_ASSERT(selector.select(index, bf.getBitfield(), bf.countBlock()));
CPPUNIT_ASSERT_EQUAL((size_t)15, index);
std::deque<size_t> zeroindexes;
CPPUNIT_ASSERT(!selector.select(index, zeroindexes));
bf.clearAllBit();
CPPUNIT_ASSERT(!selector.select(index, bf.getBitfield(), bf.countBlock()));
std::deque<size_t> oneseq(&A[0], &A[4]);
CPPUNIT_ASSERT(selector.select(index, oneseq));
// See it works in just one range
bf.setBitRange(1, 4);
CPPUNIT_ASSERT(selector.select(index, bf.getBitfield(), bf.countBlock()));
CPPUNIT_ASSERT_EQUAL((size_t)4, index);
}

View File

@ -67,7 +67,8 @@ aria2c_SOURCES = AllTest.cc\
SequentialPickerTest.cc\
RarestPieceSelectorTest.cc\
LongestSequencePieceSelectorTest.cc\
a2algoTest.cc
a2algoTest.cc\
bitfieldTest.cc
if HAVE_POSIX_FALLOCATE
aria2c_SOURCES += FallocFileAllocationIteratorTest.cc

View File

@ -194,8 +194,9 @@ am__aria2c_SOURCES_DIST = AllTest.cc TestUtil.cc TestUtil.h \
SimpleDNSCacheTest.cc DownloadHelperTest.cc BencodeTest.cc \
SequentialPickerTest.cc RarestPieceSelectorTest.cc \
LongestSequencePieceSelectorTest.cc a2algoTest.cc \
FallocFileAllocationIteratorTest.cc GZipDecoderTest.cc \
Sqlite3MozCookieParserTest.cc MessageDigestHelperTest.cc \
bitfieldTest.cc FallocFileAllocationIteratorTest.cc \
GZipDecoderTest.cc Sqlite3MozCookieParserTest.cc \
MessageDigestHelperTest.cc \
IteratableChunkChecksumValidatorTest.cc \
IteratableChecksumValidatorTest.cc BtAllowedFastMessageTest.cc \
BtBitfieldMessageTest.cc BtCancelMessageTest.cc \
@ -364,9 +365,9 @@ am_aria2c_OBJECTS = AllTest.$(OBJEXT) TestUtil.$(OBJEXT) \
SequentialPickerTest.$(OBJEXT) \
RarestPieceSelectorTest.$(OBJEXT) \
LongestSequencePieceSelectorTest.$(OBJEXT) \
a2algoTest.$(OBJEXT) $(am__objects_1) $(am__objects_2) \
$(am__objects_3) $(am__objects_4) $(am__objects_5) \
$(am__objects_6)
a2algoTest.$(OBJEXT) bitfieldTest.$(OBJEXT) $(am__objects_1) \
$(am__objects_2) $(am__objects_3) $(am__objects_4) \
$(am__objects_5) $(am__objects_6)
aria2c_OBJECTS = $(am_aria2c_OBJECTS)
am__DEPENDENCIES_1 =
aria2c_DEPENDENCIES = ../src/libaria2c.a ../src/download_helper.o \
@ -591,8 +592,9 @@ aria2c_SOURCES = AllTest.cc TestUtil.cc TestUtil.h SocketCoreTest.cc \
SimpleDNSCacheTest.cc DownloadHelperTest.cc BencodeTest.cc \
SequentialPickerTest.cc RarestPieceSelectorTest.cc \
LongestSequencePieceSelectorTest.cc a2algoTest.cc \
$(am__append_1) $(am__append_2) $(am__append_3) \
$(am__append_4) $(am__append_5) $(am__append_6)
bitfieldTest.cc $(am__append_1) $(am__append_2) \
$(am__append_3) $(am__append_4) $(am__append_5) \
$(am__append_6)
#aria2c_CXXFLAGS = ${CPPUNIT_CFLAGS} -I../src -I../lib -Wall -D_FILE_OFFSET_BITS=64
#aria2c_LDFLAGS = ${CPPUNIT_LIBS}
@ -828,6 +830,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/a2algoTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/a2functionalTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/array_funTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bitfieldTest.Po@am__quote@
.cc.o:
@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<

View File

@ -7,6 +7,7 @@
#include "Exception.h"
#include "Util.h"
#include "BitfieldMan.h"
namespace aria2 {
@ -17,6 +18,7 @@ class RarestPieceSelectorTest:public CppUnit::TestFixture {
CPPUNIT_TEST(testAddPieceStats_bitfield);
CPPUNIT_TEST(testUpdatePieceStats);
CPPUNIT_TEST(testSubtractPieceStats);
CPPUNIT_TEST(testSelect);
CPPUNIT_TEST_SUITE_END();
public:
void setUp() {}
@ -27,6 +29,7 @@ public:
void testAddPieceStats_bitfield();
void testUpdatePieceStats();
void testSubtractPieceStats();
void testSelect();
};
@ -189,5 +192,24 @@ void RarestPieceSelectorTest::testSubtractPieceStats()
}
}
void RarestPieceSelectorTest::testSelect()
{
RarestPieceSelector selector(10, false);
BitfieldMan bf(1024, 10*1024);
bf.setBitRange(0, 2);
size_t index;
selector.addPieceStats(0);
CPPUNIT_ASSERT(selector.select(index, bf.getBitfield(),
bf.countBlock()));
CPPUNIT_ASSERT_EQUAL((size_t)1, index);
selector.addPieceStats(1);
CPPUNIT_ASSERT(selector.select(index, bf.getBitfield(),
bf.countBlock()));
CPPUNIT_ASSERT_EQUAL((size_t)2, index);
}
} // namespace aria2

View File

@ -30,7 +30,6 @@ class UtilTest:public CppUnit::TestFixture {
CPPUNIT_TEST(testToUpper);
CPPUNIT_TEST(testToLower);
CPPUNIT_TEST(testUrldecode);
CPPUNIT_TEST(testCountBit);
CPPUNIT_TEST(testGetRealSize);
CPPUNIT_TEST(testAbbrevSize);
CPPUNIT_TEST(testToStream);
@ -75,7 +74,6 @@ public:
void testToUpper();
void testToLower();
void testUrldecode();
void testCountBit();
void testGetRealSize();
void testAbbrevSize();
void testToStream();
@ -338,11 +336,6 @@ void UtilTest::testUrldecode() {
CPPUNIT_ASSERT_EQUAL(std::string("/"), Util::urldecode(src6));
}
void UtilTest::testCountBit() {
CPPUNIT_ASSERT_EQUAL((unsigned int)32, Util::countBit(UINT32_MAX));
CPPUNIT_ASSERT_EQUAL((unsigned int)8, Util::countBit(255));
}
void UtilTest::testGetRealSize()
{
CPPUNIT_ASSERT_EQUAL((int64_t)4294967296LL, Util::getRealSize("4096M"));

60
test/bitfieldTest.cc Normal file
View File

@ -0,0 +1,60 @@
#include "bitfield.h"
#include <cppunit/extensions/HelperMacros.h>
namespace aria2 {
class bitfieldTest:public CppUnit::TestFixture {
CPPUNIT_TEST_SUITE(bitfieldTest);
CPPUNIT_TEST(testTest);
CPPUNIT_TEST(testCountBit32);
CPPUNIT_TEST(testCountSetBit);
CPPUNIT_TEST(testLastByteMask);
CPPUNIT_TEST_SUITE_END();
private:
public:
void testTest();
void testCountBit32();
void testCountSetBit();
void testLastByteMask();
};
CPPUNIT_TEST_SUITE_REGISTRATION( bitfieldTest );
void bitfieldTest::testTest()
{
unsigned char bitfield[] = { 0xaa };
CPPUNIT_ASSERT(bitfield::test(bitfield, 8, 0));
CPPUNIT_ASSERT(!bitfield::test(bitfield, 8, 1));
}
void bitfieldTest::testCountBit32()
{
CPPUNIT_ASSERT_EQUAL((size_t)32, bitfield::countBit32(UINT32_MAX));
CPPUNIT_ASSERT_EQUAL((size_t)8, bitfield::countBit32(255));
}
void bitfieldTest::testCountSetBit()
{
unsigned char bitfield[] = { 0xff, 0xff, 0xff, 0xf0, 0xff, 0x01 };
CPPUNIT_ASSERT_EQUAL((size_t)37, bitfield::countSetBit(bitfield, 48));
CPPUNIT_ASSERT_EQUAL((size_t)36, bitfield::countSetBit(bitfield, 47));
CPPUNIT_ASSERT_EQUAL((size_t)28, bitfield::countSetBit(bitfield, 32));
}
void bitfieldTest::testLastByteMask()
{
CPPUNIT_ASSERT_EQUAL((unsigned int)128,
(unsigned int)bitfield::lastByteMask(9));
CPPUNIT_ASSERT_EQUAL((unsigned int)240,
(unsigned int)bitfield::lastByteMask(12));
CPPUNIT_ASSERT_EQUAL((unsigned int)255,
(unsigned int)bitfield::lastByteMask(16));
}
} // namespace aria2