mirror of https://github.com/aria2/aria2
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.ccpull/1/head
parent
3531d57d37
commit
a6b02840fa
32
ChangeLog
32
ChangeLog
|
@ -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>
|
2009-03-28 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
|
||||||
|
|
||||||
Made accepted socket non-block.
|
Made accepted socket non-block.
|
||||||
|
|
|
@ -34,11 +34,13 @@
|
||||||
/* copyright --> */
|
/* copyright --> */
|
||||||
#include "BitfieldMan.h"
|
#include "BitfieldMan.h"
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
#include "Randomizer.h"
|
#include "Randomizer.h"
|
||||||
#include "Util.h"
|
#include "Util.h"
|
||||||
#include "array_fun.h"
|
#include "array_fun.h"
|
||||||
|
#include "bitfield.h"
|
||||||
|
|
||||||
namespace aria2 {
|
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
|
size_t
|
||||||
BitfieldMan::getNthBitIndex(const unsigned char bitfield, size_t nth) const
|
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 bitfieldLength) const
|
||||||
{
|
{
|
||||||
size_t byte = randomizer->getRandomNumber(bitfieldLength);
|
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) {
|
for(size_t i = 0; i < bitfieldLength; ++i) {
|
||||||
unsigned char mask;
|
unsigned char mask;
|
||||||
if(byte == bitfieldLength-1) {
|
if(byte == bitfieldLength-1) {
|
||||||
mask = lastMask;
|
mask = bitfield::lastByteMask(blocks);
|
||||||
} else {
|
} else {
|
||||||
mask = 0xff;
|
mask = 0xff;
|
||||||
}
|
}
|
||||||
|
@ -218,7 +197,7 @@ bool BitfieldMan::getMissingIndexRandomly(size_t& index,
|
||||||
index = byte*8+getNthBitIndex(bits, 1);
|
index = byte*8+getNthBitIndex(bits, 1);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
byte++;
|
++byte;
|
||||||
if(byte == bitfieldLength) {
|
if(byte == bitfieldLength) {
|
||||||
byte = 0;
|
byte = 0;
|
||||||
}
|
}
|
||||||
|
@ -322,27 +301,6 @@ bool BitfieldMan::getMissingUnusedIndex(size_t& index) const
|
||||||
return getMissingIndexRandomly(index, bf, bitfieldLength);
|
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 {
|
size_t BitfieldMan::getStartIndex(size_t index) const {
|
||||||
while(index < blocks && (isUseBitSet(index) || isBitSet(index))) {
|
while(index < blocks && (isUseBitSet(index) || isBitSet(index))) {
|
||||||
index++;
|
index++;
|
||||||
|
@ -393,36 +351,35 @@ bool BitfieldMan::getSparseMissingUnusedIndex(size_t& index) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Array>
|
template<typename Array>
|
||||||
bool BitfieldMan::getAllMissingIndexes(std::deque<size_t>& indexes,
|
static bool copyBitfield(unsigned char* dst, const Array& src, size_t blocks)
|
||||||
const Array& bitfield,
|
|
||||||
size_t bitfieldLength) const
|
|
||||||
{
|
{
|
||||||
for(size_t i = 0; i < bitfieldLength; ++i) {
|
unsigned char bits = 0;
|
||||||
unsigned char bits = bitfield[i];
|
size_t len = (blocks+7)/8;
|
||||||
unsigned char mask = 128;
|
for(size_t i = 0; i < len-1; ++i) {
|
||||||
size_t index = i*8;
|
dst[i] = src[i];
|
||||||
for(size_t bi = 0; bi < 8 && index < blocks; ++bi, mask >>= 1, ++index) {
|
bits |= dst[i];
|
||||||
if(bits & mask) {
|
|
||||||
indexes.push_back(index);
|
|
||||||
}
|
}
|
||||||
}
|
dst[len-1] = src[len-1]&bitfield::lastByteMask(blocks);
|
||||||
}
|
bits |= dst[len-1];
|
||||||
return !indexes.empty();
|
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);
|
array_fun<unsigned char> bf = array_negate(bitfield);
|
||||||
if(filterEnabled) {
|
if(filterEnabled) {
|
||||||
bf = array_and(bf, filterBitfield);
|
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,
|
const unsigned char* peerBitfield,
|
||||||
size_t peerBitfieldLength) const
|
size_t peerBitfieldLength) const
|
||||||
{
|
{
|
||||||
|
assert(len == bitfieldLength);
|
||||||
if(bitfieldLength != peerBitfieldLength) {
|
if(bitfieldLength != peerBitfieldLength) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -431,13 +388,15 @@ bool BitfieldMan::getAllMissingIndexes(std::deque<size_t>& indexes,
|
||||||
if(filterEnabled) {
|
if(filterEnabled) {
|
||||||
bf = array_and(bf, filterBitfield);
|
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,
|
const unsigned char* peerBitfield,
|
||||||
size_t peerBitfieldLength) const
|
size_t peerBitfieldLength) const
|
||||||
{
|
{
|
||||||
|
assert(len == bitfieldLength);
|
||||||
if(bitfieldLength != peerBitfieldLength) {
|
if(bitfieldLength != peerBitfieldLength) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -447,7 +406,7 @@ bool BitfieldMan::getAllMissingUnusedIndexes(std::deque<size_t>& indexes,
|
||||||
if(filterEnabled) {
|
if(filterEnabled) {
|
||||||
bf = array_and(bf, filterBitfield);
|
bf = array_and(bf, filterBitfield);
|
||||||
}
|
}
|
||||||
return getAllMissingIndexes(indexes, bf, bitfieldLength);
|
return copyBitfield(misbitfield, bf, blocks);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t BitfieldMan::countMissingBlock() const {
|
size_t BitfieldMan::countMissingBlock() const {
|
||||||
|
@ -456,16 +415,15 @@ size_t BitfieldMan::countMissingBlock() const {
|
||||||
|
|
||||||
size_t BitfieldMan::countMissingBlockNow() const {
|
size_t BitfieldMan::countMissingBlockNow() const {
|
||||||
if(filterEnabled) {
|
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) {
|
for(size_t i = 0; i < bitfieldLength; ++i) {
|
||||||
temp[i] = bitfield[i]&filterBitfield[i];
|
temp[i] = bitfield[i]&filterBitfield[i];
|
||||||
}
|
}
|
||||||
size_t count = countSetBit(filterBitfield, bitfieldLength)-
|
size_t count = bitfield::countSetBit(filterBitfield, blocks)-
|
||||||
countSetBit(temp, bitfieldLength);
|
bitfield::countSetBit(temp, blocks);
|
||||||
delete [] temp;
|
|
||||||
return count;
|
return count;
|
||||||
} else {
|
} 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 {
|
size_t BitfieldMan::countFilteredBlockNow() const {
|
||||||
if(filterEnabled) {
|
if(filterEnabled) {
|
||||||
return countSetBit(filterBitfield, bitfieldLength);
|
return bitfield::countSetBit(filterBitfield, blocks);
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -550,18 +508,14 @@ bool BitfieldMan::isAllBitSet() const {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BitfieldMan::isBitSetInternal(const unsigned char* bitfield, size_t index) const {
|
bool BitfieldMan::isBitSet(size_t index) const
|
||||||
if(index < 0 || blocks <= index) { return false; }
|
{
|
||||||
unsigned char mask = 128 >> index%8;
|
return bitfield::test(bitfield, blocks, index);
|
||||||
return (bitfield[index/8] & mask) != 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BitfieldMan::isBitSet(size_t index) const {
|
bool BitfieldMan::isUseBitSet(size_t index) const
|
||||||
return isBitSetInternal(bitfield, index);
|
{
|
||||||
}
|
return bitfield::test(useBitfield, blocks, index);
|
||||||
|
|
||||||
bool BitfieldMan::isUseBitSet(size_t index) const {
|
|
||||||
return isBitSetInternal(useBitfield, index);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BitfieldMan::setBitfield(const unsigned char* bitfield, size_t bitfieldLength) {
|
void BitfieldMan::setBitfield(const unsigned char* bitfield, size_t bitfieldLength) {
|
||||||
|
@ -656,11 +610,11 @@ uint64_t BitfieldMan::getFilteredTotalLengthNow() const {
|
||||||
if(!filterBitfield) {
|
if(!filterBitfield) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
size_t filteredBlocks = countSetBit(filterBitfield, bitfieldLength);
|
size_t filteredBlocks = bitfield::countSetBit(filterBitfield, blocks);
|
||||||
if(filteredBlocks == 0) {
|
if(filteredBlocks == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if(isBitSetInternal(filterBitfield, blocks-1)) {
|
if(bitfield::test(filterBitfield, blocks, blocks-1)) {
|
||||||
return ((uint64_t)filteredBlocks-1)*blockLength+getLastBlockLength();
|
return ((uint64_t)filteredBlocks-1)*blockLength+getLastBlockLength();
|
||||||
} else {
|
} else {
|
||||||
return ((uint64_t)filteredBlocks)*blockLength;
|
return ((uint64_t)filteredBlocks)*blockLength;
|
||||||
|
@ -679,12 +633,12 @@ uint64_t BitfieldMan::getCompletedLength(bool useFilter) const {
|
||||||
} else {
|
} else {
|
||||||
memcpy(temp, bitfield, bitfieldLength);
|
memcpy(temp, bitfield, bitfieldLength);
|
||||||
}
|
}
|
||||||
size_t completedBlocks = countSetBit(temp, bitfieldLength);
|
size_t completedBlocks = bitfield::countSetBit(temp, blocks);
|
||||||
uint64_t completedLength = 0;
|
uint64_t completedLength = 0;
|
||||||
if(completedBlocks == 0) {
|
if(completedBlocks == 0) {
|
||||||
completedLength = 0;
|
completedLength = 0;
|
||||||
} else {
|
} else {
|
||||||
if(isBitSetInternal(temp, blocks-1)) {
|
if(bitfield::test(temp, blocks, blocks-1)) {
|
||||||
completedLength = ((uint64_t)completedBlocks-1)*blockLength+getLastBlockLength();
|
completedLength = ((uint64_t)completedBlocks-1)*blockLength+getLastBlockLength();
|
||||||
} else {
|
} else {
|
||||||
completedLength = ((uint64_t)completedBlocks)*blockLength;
|
completedLength = ((uint64_t)completedBlocks)*blockLength;
|
||||||
|
|
|
@ -62,7 +62,6 @@ private:
|
||||||
uint64_t cachedFilteredComletedLength;
|
uint64_t cachedFilteredComletedLength;
|
||||||
uint64_t cachedFilteredTotalLength;
|
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;
|
size_t getNthBitIndex(const unsigned char bit, size_t nth) const;
|
||||||
bool getMissingIndexRandomly(size_t& index, const unsigned char* bitfield, size_t len) const;
|
bool getMissingIndexRandomly(size_t& index, const unsigned char* bitfield, size_t len) const;
|
||||||
|
|
||||||
|
@ -77,7 +76,6 @@ private:
|
||||||
const Array& bitfield,
|
const Array& bitfield,
|
||||||
size_t bitfieldLength) const;
|
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 setBitInternal(unsigned char* bitfield, size_t index, bool on);
|
||||||
bool setFilterBit(size_t index);
|
bool setFilterBit(size_t index);
|
||||||
|
|
||||||
|
@ -85,6 +83,27 @@ private:
|
||||||
size_t getEndIndex(size_t index) const;
|
size_t getEndIndex(size_t index) const;
|
||||||
|
|
||||||
uint64_t getCompletedLength(bool useFilter) 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:
|
public:
|
||||||
BitfieldMan(size_t blockLength, uint64_t totalLength);
|
BitfieldMan(size_t blockLength, uint64_t totalLength);
|
||||||
BitfieldMan(const BitfieldMan& bitfieldMan);
|
BitfieldMan(const BitfieldMan& bitfieldMan);
|
||||||
|
@ -139,16 +158,16 @@ public:
|
||||||
/**
|
/**
|
||||||
* affected by filter
|
* affected by filter
|
||||||
*/
|
*/
|
||||||
bool getAllMissingIndexes(std::deque<size_t>&indexes) const;
|
bool getAllMissingIndexes(unsigned char* misbitfield, size_t mislen) const;
|
||||||
/**
|
/**
|
||||||
* affected by filter
|
* 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;
|
const unsigned char* bitfield, size_t len) const;
|
||||||
/**
|
/**
|
||||||
* affected by filter
|
* affected by filter
|
||||||
*/
|
*/
|
||||||
bool getAllMissingUnusedIndexes(std::deque<size_t>& indexes,
|
bool getAllMissingUnusedIndexes(unsigned char* misbitfield, size_t mislen,
|
||||||
const unsigned char* bitfield,
|
const unsigned char* bitfield,
|
||||||
size_t len) const;
|
size_t len) const;
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -47,6 +47,7 @@
|
||||||
#include "BtMessage.h"
|
#include "BtMessage.h"
|
||||||
#include "a2functional.h"
|
#include "a2functional.h"
|
||||||
#include "SimpleRandomizer.h"
|
#include "SimpleRandomizer.h"
|
||||||
|
#include "array_fun.h"
|
||||||
|
|
||||||
namespace aria2 {
|
namespace aria2 {
|
||||||
|
|
||||||
|
@ -170,13 +171,27 @@ void DefaultBtRequestFactory::createRequestMessagesOnEndGame
|
||||||
for(Pieces::iterator itr = pieces.begin();
|
for(Pieces::iterator itr = pieces.begin();
|
||||||
itr != pieces.end() && requests.size() < max; ++itr) {
|
itr != pieces.end() && requests.size() < max; ++itr) {
|
||||||
PieceHandle& piece = *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;
|
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(),
|
std::random_shuffle(missingBlockIndexes.begin(), missingBlockIndexes.end(),
|
||||||
*(SimpleRandomizer::getInstance().get()));
|
*(SimpleRandomizer::getInstance().get()));
|
||||||
for(std::deque<size_t>::const_iterator bitr = missingBlockIndexes.begin();
|
for(std::deque<size_t>::const_iterator bitr = missingBlockIndexes.begin();
|
||||||
bitr != missingBlockIndexes.end() && requests.size() < max; bitr++) {
|
bitr != missingBlockIndexes.end() && requests.size() < max; bitr++) {
|
||||||
size_t blockIndex = *bitr;
|
const size_t& blockIndex = *bitr;
|
||||||
if(!dispatcher->isOutstandingRequest(piece->getIndex(),
|
if(!dispatcher->isOutstandingRequest(piece->getIndex(),
|
||||||
blockIndex)) {
|
blockIndex)) {
|
||||||
_logger->debug("Creating RequestMessage index=%u, begin=%u, blockIndex=%u",
|
_logger->debug("Creating RequestMessage index=%u, begin=%u, blockIndex=%u",
|
||||||
|
|
|
@ -57,6 +57,7 @@
|
||||||
#include "Option.h"
|
#include "Option.h"
|
||||||
#include "StringFormat.h"
|
#include "StringFormat.h"
|
||||||
#include "RarestPieceSelector.h"
|
#include "RarestPieceSelector.h"
|
||||||
|
#include "array_fun.h"
|
||||||
|
|
||||||
namespace aria2 {
|
namespace aria2 {
|
||||||
|
|
||||||
|
@ -97,18 +98,21 @@ bool DefaultPieceStorage::isEndGame()
|
||||||
|
|
||||||
bool DefaultPieceStorage::getMissingPieceIndex(size_t& index,
|
bool DefaultPieceStorage::getMissingPieceIndex(size_t& index,
|
||||||
const unsigned char* bitfield,
|
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;
|
bool r;
|
||||||
if(isEndGame()) {
|
if(isEndGame()) {
|
||||||
r = bitfieldMan->getAllMissingIndexes(indexes, bitfield, length);
|
r = bitfieldMan->getAllMissingIndexes(misbitfield, mislen,
|
||||||
|
bitfield, length);
|
||||||
} else {
|
} else {
|
||||||
r = bitfieldMan->getAllMissingUnusedIndexes(indexes, bitfield, length);
|
r = bitfieldMan->getAllMissingUnusedIndexes(misbitfield, mislen,
|
||||||
|
bitfield, length);
|
||||||
}
|
}
|
||||||
if(r) {
|
if(r) {
|
||||||
// We assume indexes is sorted using comparator less.
|
// We assume indexes is sorted using comparator less.
|
||||||
return _pieceSelector->select(index, indexes);
|
return _pieceSelector->select(index, misbitfield,bitfieldMan->countBlock());
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,7 +84,7 @@ private:
|
||||||
SharedHandle<PieceSelector> _pieceSelector;
|
SharedHandle<PieceSelector> _pieceSelector;
|
||||||
|
|
||||||
bool getMissingPieceIndex(size_t& index,
|
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,
|
SharedHandle<Piece> getMissingPiece(const unsigned char* bitfield,
|
||||||
size_t length);
|
size_t length);
|
||||||
|
|
|
@ -33,21 +33,55 @@
|
||||||
*/
|
*/
|
||||||
/* copyright --> */
|
/* copyright --> */
|
||||||
#include "LongestSequencePieceSelector.h"
|
#include "LongestSequencePieceSelector.h"
|
||||||
#include "a2algo.h"
|
#include "bitfield.h"
|
||||||
|
|
||||||
namespace aria2 {
|
namespace aria2 {
|
||||||
|
|
||||||
bool LongestSequencePieceSelector::select
|
static size_t getStartIndex
|
||||||
(size_t& index,
|
(size_t from, const unsigned char* bitfield, size_t nbits)
|
||||||
const std::deque<size_t>& candidateIndexes) const
|
|
||||||
{
|
{
|
||||||
std::pair<std::deque<size_t>::const_iterator, size_t> p =
|
while(from < nbits && !bitfield::test(bitfield, nbits, from)) {
|
||||||
max_sequence(candidateIndexes.begin(), candidateIndexes.end());
|
++from;
|
||||||
if(p.second == 0) {
|
}
|
||||||
return false;
|
if(nbits <= from) {
|
||||||
|
return nbits;
|
||||||
} else {
|
} 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;
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,11 +42,11 @@ namespace aria2 {
|
||||||
class LongestSequencePieceSelector:public PieceSelector {
|
class LongestSequencePieceSelector:public PieceSelector {
|
||||||
public:
|
public:
|
||||||
// Returns the last index of longest continuous sequence in candidateIndexes.
|
// 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
|
// { 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.
|
// returns 15 because { 10, 11, 12, 13, 14, 15 } is the longest sequence.
|
||||||
virtual bool select
|
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);
|
virtual void addPieceStats(size_t index);
|
||||||
|
|
||||||
|
|
|
@ -205,7 +205,8 @@ SRCS = Socket.h\
|
||||||
HttpServerResponseCommand.cc HttpServerResponseCommand.h\
|
HttpServerResponseCommand.cc HttpServerResponseCommand.h\
|
||||||
HttpServer.cc HttpServer.h\
|
HttpServer.cc HttpServer.h\
|
||||||
PieceSelector.h\
|
PieceSelector.h\
|
||||||
LongestSequencePieceSelector.cc LongestSequencePieceSelector.h
|
LongestSequencePieceSelector.cc LongestSequencePieceSelector.h\
|
||||||
|
bitfield.h
|
||||||
|
|
||||||
if HAVE_POSIX_FALLOCATE
|
if HAVE_POSIX_FALLOCATE
|
||||||
SRCS += FallocFileAllocationIterator.cc FallocFileAllocationIterator.h
|
SRCS += FallocFileAllocationIterator.cc FallocFileAllocationIterator.h
|
||||||
|
|
|
@ -417,11 +417,12 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \
|
||||||
HttpServerCommand.h HttpServerResponseCommand.cc \
|
HttpServerCommand.h HttpServerResponseCommand.cc \
|
||||||
HttpServerResponseCommand.h HttpServer.cc HttpServer.h \
|
HttpServerResponseCommand.h HttpServer.cc HttpServer.h \
|
||||||
PieceSelector.h LongestSequencePieceSelector.cc \
|
PieceSelector.h LongestSequencePieceSelector.cc \
|
||||||
LongestSequencePieceSelector.h FallocFileAllocationIterator.cc \
|
LongestSequencePieceSelector.h bitfield.h \
|
||||||
FallocFileAllocationIterator.h EpollEventPoll.cc \
|
FallocFileAllocationIterator.cc FallocFileAllocationIterator.h \
|
||||||
EpollEventPoll.h TLSContext.h LibgnutlsTLSContext.cc \
|
EpollEventPoll.cc EpollEventPoll.h TLSContext.h \
|
||||||
LibgnutlsTLSContext.h LibsslTLSContext.cc LibsslTLSContext.h \
|
LibgnutlsTLSContext.cc LibgnutlsTLSContext.h \
|
||||||
GZipDecoder.cc GZipDecoder.h Sqlite3MozCookieParser.cc \
|
LibsslTLSContext.cc LibsslTLSContext.h GZipDecoder.cc \
|
||||||
|
GZipDecoder.h Sqlite3MozCookieParser.cc \
|
||||||
Sqlite3MozCookieParser.h AsyncNameResolver.cc \
|
Sqlite3MozCookieParser.h AsyncNameResolver.cc \
|
||||||
AsyncNameResolver.h IteratableChunkChecksumValidator.cc \
|
AsyncNameResolver.h IteratableChunkChecksumValidator.cc \
|
||||||
IteratableChunkChecksumValidator.h \
|
IteratableChunkChecksumValidator.h \
|
||||||
|
@ -1157,14 +1158,14 @@ SRCS = Socket.h SocketCore.cc SocketCore.h BinaryStream.h Command.cc \
|
||||||
HttpServerCommand.h HttpServerResponseCommand.cc \
|
HttpServerCommand.h HttpServerResponseCommand.cc \
|
||||||
HttpServerResponseCommand.h HttpServer.cc HttpServer.h \
|
HttpServerResponseCommand.h HttpServer.cc HttpServer.h \
|
||||||
PieceSelector.h LongestSequencePieceSelector.cc \
|
PieceSelector.h LongestSequencePieceSelector.cc \
|
||||||
LongestSequencePieceSelector.h $(am__append_1) $(am__append_2) \
|
LongestSequencePieceSelector.h bitfield.h $(am__append_1) \
|
||||||
$(am__append_3) $(am__append_4) $(am__append_5) \
|
$(am__append_2) $(am__append_3) $(am__append_4) \
|
||||||
$(am__append_6) $(am__append_7) $(am__append_8) \
|
$(am__append_5) $(am__append_6) $(am__append_7) \
|
||||||
$(am__append_9) $(am__append_10) $(am__append_11) \
|
$(am__append_8) $(am__append_9) $(am__append_10) \
|
||||||
$(am__append_12) $(am__append_13) $(am__append_14) \
|
$(am__append_11) $(am__append_12) $(am__append_13) \
|
||||||
$(am__append_15) $(am__append_16) $(am__append_17) \
|
$(am__append_14) $(am__append_15) $(am__append_16) \
|
||||||
$(am__append_18) $(am__append_19) $(am__append_20) \
|
$(am__append_17) $(am__append_18) $(am__append_19) \
|
||||||
$(am__append_21) $(am__append_22)
|
$(am__append_20) $(am__append_21) $(am__append_22)
|
||||||
noinst_LIBRARIES = libaria2c.a
|
noinst_LIBRARIES = libaria2c.a
|
||||||
libaria2c_a_SOURCES = $(SRCS)
|
libaria2c_a_SOURCES = $(SRCS)
|
||||||
aria2c_LDADD = libaria2c.a @LIBINTL@ @ALLOCA@ @LIBGNUTLS_LIBS@\
|
aria2c_LDADD = libaria2c.a @LIBINTL@ @ALLOCA@ @LIBGNUTLS_LIBS@\
|
||||||
|
|
|
@ -197,8 +197,10 @@ bool Piece::getFirstMissingBlockIndexWithoutLock(size_t& index) const
|
||||||
return bitfield->getFirstMissingIndex(index);
|
return bitfield->getFirstMissingIndex(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Piece::getAllMissingBlockIndexes(std::deque<size_t>& indexes) const {
|
bool Piece::getAllMissingBlockIndexes
|
||||||
return bitfield->getAllMissingIndexes(indexes);
|
(unsigned char* misbitfield, size_t mislen) const
|
||||||
|
{
|
||||||
|
return bitfield->getAllMissingIndexes(misbitfield, mislen);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Piece::toString() const {
|
std::string Piece::toString() const {
|
||||||
|
|
|
@ -89,7 +89,8 @@ public:
|
||||||
bool getMissingUnusedBlockIndex(size_t& index) const;
|
bool getMissingUnusedBlockIndex(size_t& index) const;
|
||||||
bool getMissingBlockIndex(size_t& index) const;
|
bool getMissingBlockIndex(size_t& index) const;
|
||||||
bool getFirstMissingBlockIndexWithoutLock(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 completeBlock(size_t blockIndex);
|
||||||
void cancelBlock(size_t blockIndex);
|
void cancelBlock(size_t blockIndex);
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,7 @@ public:
|
||||||
virtual ~PieceSelector() {}
|
virtual ~PieceSelector() {}
|
||||||
|
|
||||||
virtual bool select
|
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;
|
virtual void addPieceStats(size_t index) = 0;
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
/* copyright --> */
|
/* copyright --> */
|
||||||
#include "RarestPieceSelector.h"
|
#include "RarestPieceSelector.h"
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
#include "SimpleRandomizer.h"
|
#include "SimpleRandomizer.h"
|
||||||
|
@ -121,23 +122,26 @@ RarestPieceSelector::RarestPieceSelector(size_t pieceNum, bool randomShuffle):
|
||||||
class FindRarestPiece
|
class FindRarestPiece
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
const std::deque<size_t>& _indexes;
|
const unsigned char* _misbitfield;
|
||||||
|
size_t _numbits;
|
||||||
public:
|
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)
|
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
|
bool RarestPieceSelector::select
|
||||||
(size_t& index,
|
(size_t& index, const unsigned char* bitfield, size_t nbits) const
|
||||||
const std::deque<size_t>& candidateIndexes) const
|
|
||||||
{
|
{
|
||||||
std::vector<size_t>::const_iterator i =
|
std::vector<size_t>::const_iterator i =
|
||||||
std::find_if(_sortedPieceStatIndexes.begin(), _sortedPieceStatIndexes.end(),
|
std::find_if(_sortedPieceStatIndexes.begin(), _sortedPieceStatIndexes.end(),
|
||||||
FindRarestPiece(candidateIndexes));
|
FindRarestPiece(bitfield, nbits));
|
||||||
if(i == _sortedPieceStatIndexes.end()) {
|
if(i == _sortedPieceStatIndexes.end()) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -69,7 +69,7 @@ public:
|
||||||
RarestPieceSelector(size_t pieceNum, bool randomShuffle);
|
RarestPieceSelector(size_t pieceNum, bool randomShuffle);
|
||||||
|
|
||||||
virtual bool select
|
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);
|
virtual void addPieceStats(size_t index);
|
||||||
|
|
||||||
|
|
27
src/Util.cc
27
src/Util.cc
|
@ -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) {
|
std::string Util::randomAlpha(size_t length, const RandomizerHandle& randomizer) {
|
||||||
static const char *random_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
static const char *random_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||||
std::string str;
|
std::string str;
|
||||||
|
|
|
@ -212,8 +212,6 @@ public:
|
||||||
// this function temporarily put here
|
// this function temporarily put here
|
||||||
static std::string getContentDispositionFilename(const std::string& header);
|
static std::string getContentDispositionFilename(const std::string& header);
|
||||||
|
|
||||||
static unsigned int countBit(uint32_t n);
|
|
||||||
|
|
||||||
static std::string randomAlpha(size_t length,
|
static std::string randomAlpha(size_t length,
|
||||||
const SharedHandle<Randomizer>& randomizer);
|
const SharedHandle<Randomizer>& randomizer);
|
||||||
|
|
||||||
|
|
|
@ -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_
|
|
@ -5,6 +5,7 @@
|
||||||
#include <cppunit/extensions/HelperMacros.h>
|
#include <cppunit/extensions/HelperMacros.h>
|
||||||
|
|
||||||
#include "FixedNumberRandomizer.h"
|
#include "FixedNumberRandomizer.h"
|
||||||
|
#include "bitfield.h"
|
||||||
|
|
||||||
namespace aria2 {
|
namespace aria2 {
|
||||||
|
|
||||||
|
@ -25,6 +26,7 @@ class BitfieldManTest:public CppUnit::TestFixture {
|
||||||
CPPUNIT_TEST(testSetBitRange);
|
CPPUNIT_TEST(testSetBitRange);
|
||||||
CPPUNIT_TEST(testGetAllMissingIndexes);
|
CPPUNIT_TEST(testGetAllMissingIndexes);
|
||||||
CPPUNIT_TEST(testGetAllMissingIndexes_noarg);
|
CPPUNIT_TEST(testGetAllMissingIndexes_noarg);
|
||||||
|
CPPUNIT_TEST(testGetAllMissingIndexes_checkLastByte);
|
||||||
CPPUNIT_TEST(testGetAllMissingUnusedIndexes);
|
CPPUNIT_TEST(testGetAllMissingUnusedIndexes);
|
||||||
CPPUNIT_TEST(testGetMissingUnusedIndex);
|
CPPUNIT_TEST(testGetMissingUnusedIndex);
|
||||||
CPPUNIT_TEST(testGetMissingIndex_noarg);
|
CPPUNIT_TEST(testGetMissingIndex_noarg);
|
||||||
|
@ -54,6 +56,7 @@ public:
|
||||||
void testGetMissingUnusedIndex_noarg();
|
void testGetMissingUnusedIndex_noarg();
|
||||||
void testGetAllMissingIndexes();
|
void testGetAllMissingIndexes();
|
||||||
void testGetAllMissingIndexes_noarg();
|
void testGetAllMissingIndexes_noarg();
|
||||||
|
void testGetAllMissingIndexes_checkLastByte();
|
||||||
void testGetAllMissingUnusedIndexes();
|
void testGetAllMissingUnusedIndexes();
|
||||||
|
|
||||||
void testIsAllBitSet();
|
void testIsAllBitSet();
|
||||||
|
@ -607,83 +610,87 @@ void BitfieldManTest::testGetAllMissingIndexes_noarg()
|
||||||
{
|
{
|
||||||
size_t blockLength = 16*1024;
|
size_t blockLength = 16*1024;
|
||||||
uint64_t totalLength = 1024*1024;
|
uint64_t totalLength = 1024*1024;
|
||||||
|
size_t nbits = (totalLength+blockLength-1)/blockLength;
|
||||||
BitfieldMan bf(blockLength, totalLength);
|
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) {
|
for(size_t i = 0; i < 63; ++i) {
|
||||||
bf.setBit(i);
|
bf.setBit(i);
|
||||||
}
|
}
|
||||||
{
|
CPPUNIT_ASSERT(bf.getAllMissingIndexes(misbitfield, sizeof(misbitfield)));
|
||||||
std::deque<size_t> indexes;
|
CPPUNIT_ASSERT_EQUAL((size_t)1, bitfield::countSetBit(misbitfield, nbits));
|
||||||
CPPUNIT_ASSERT(bf.getAllMissingIndexes(indexes));
|
CPPUNIT_ASSERT(bitfield::test(misbitfield, nbits, 63));
|
||||||
CPPUNIT_ASSERT_EQUAL((size_t)1, indexes.size());
|
}
|
||||||
CPPUNIT_ASSERT_EQUAL((size_t)63, indexes.front());
|
|
||||||
}
|
// 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()
|
void BitfieldManTest::testGetAllMissingIndexes()
|
||||||
{
|
{
|
||||||
size_t blockLength = 16*1024;
|
size_t blockLength = 16*1024;
|
||||||
uint64_t totalLength = 1024*1024;
|
uint64_t totalLength = 1024*1024;
|
||||||
|
size_t nbits = (totalLength+blockLength-1)/blockLength;
|
||||||
BitfieldMan bf(blockLength, totalLength);
|
BitfieldMan bf(blockLength, totalLength);
|
||||||
BitfieldMan peerBf(blockLength, totalLength);
|
BitfieldMan peerBf(blockLength, totalLength);
|
||||||
peerBf.setAllBit();
|
peerBf.setAllBit();
|
||||||
|
unsigned char misbitfield[8];
|
||||||
|
|
||||||
{
|
CPPUNIT_ASSERT(bf.getAllMissingIndexes(misbitfield, sizeof(misbitfield),
|
||||||
std::deque<size_t> indexes;
|
|
||||||
CPPUNIT_ASSERT(bf.getAllMissingIndexes(indexes,
|
|
||||||
peerBf.getBitfield(),
|
peerBf.getBitfield(),
|
||||||
peerBf.getBitfieldLength()));
|
peerBf.getBitfieldLength()));
|
||||||
CPPUNIT_ASSERT_EQUAL((size_t)64, indexes.size());
|
CPPUNIT_ASSERT_EQUAL((size_t)64, bitfield::countSetBit(misbitfield, nbits));
|
||||||
}
|
|
||||||
for(size_t i = 0; i < 62; ++i) {
|
for(size_t i = 0; i < 62; ++i) {
|
||||||
bf.setBit(i);
|
bf.setBit(i);
|
||||||
}
|
}
|
||||||
peerBf.unsetBit(62);
|
peerBf.unsetBit(62);
|
||||||
{
|
|
||||||
std::deque<size_t> indexes;
|
CPPUNIT_ASSERT(bf.getAllMissingIndexes(misbitfield, sizeof(misbitfield),
|
||||||
CPPUNIT_ASSERT(bf.getAllMissingIndexes(indexes,
|
|
||||||
peerBf.getBitfield(),
|
peerBf.getBitfield(),
|
||||||
peerBf.getBitfieldLength()));
|
peerBf.getBitfieldLength()));
|
||||||
|
CPPUNIT_ASSERT_EQUAL((size_t)1, bitfield::countSetBit(misbitfield, nbits));
|
||||||
CPPUNIT_ASSERT_EQUAL((size_t)1, indexes.size());
|
CPPUNIT_ASSERT(bitfield::test(misbitfield, nbits, 63));
|
||||||
CPPUNIT_ASSERT_EQUAL((size_t)63, indexes.front());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BitfieldManTest::testGetAllMissingUnusedIndexes()
|
void BitfieldManTest::testGetAllMissingUnusedIndexes()
|
||||||
{
|
{
|
||||||
size_t blockLength = 16*1024;
|
size_t blockLength = 16*1024;
|
||||||
uint64_t totalLength = 1024*1024;
|
uint64_t totalLength = 1024*1024;
|
||||||
|
size_t nbits = (totalLength+blockLength-1)/blockLength;
|
||||||
BitfieldMan bf(blockLength, totalLength);
|
BitfieldMan bf(blockLength, totalLength);
|
||||||
BitfieldMan peerBf(blockLength, totalLength);
|
BitfieldMan peerBf(blockLength, totalLength);
|
||||||
peerBf.setAllBit();
|
peerBf.setAllBit();
|
||||||
|
unsigned char misbitfield[8];
|
||||||
|
|
||||||
{
|
CPPUNIT_ASSERT(bf.getAllMissingUnusedIndexes(misbitfield,
|
||||||
std::deque<size_t> indexes;
|
sizeof(misbitfield),
|
||||||
CPPUNIT_ASSERT(bf.getAllMissingUnusedIndexes(indexes,
|
|
||||||
peerBf.getBitfield(),
|
peerBf.getBitfield(),
|
||||||
peerBf.getBitfieldLength()));
|
peerBf.getBitfieldLength()));
|
||||||
CPPUNIT_ASSERT_EQUAL((size_t)64, indexes.size());
|
CPPUNIT_ASSERT_EQUAL((size_t)64, bitfield::countSetBit(misbitfield, nbits));
|
||||||
}
|
|
||||||
for(size_t i = 0; i < 61; ++i) {
|
for(size_t i = 0; i < 61; ++i) {
|
||||||
bf.setBit(i);
|
bf.setBit(i);
|
||||||
}
|
}
|
||||||
bf.setUseBit(61);
|
bf.setUseBit(61);
|
||||||
peerBf.unsetBit(62);
|
peerBf.unsetBit(62);
|
||||||
{
|
CPPUNIT_ASSERT(bf.getAllMissingUnusedIndexes(misbitfield,
|
||||||
std::deque<size_t> indexes;
|
sizeof(misbitfield),
|
||||||
CPPUNIT_ASSERT(bf.getAllMissingUnusedIndexes(indexes,
|
|
||||||
peerBf.getBitfield(),
|
peerBf.getBitfield(),
|
||||||
peerBf.getBitfieldLength()));
|
peerBf.getBitfieldLength()));
|
||||||
|
CPPUNIT_ASSERT_EQUAL((size_t)1, bitfield::countSetBit(misbitfield, nbits));
|
||||||
CPPUNIT_ASSERT_EQUAL((size_t)1, indexes.size());
|
CPPUNIT_ASSERT(bitfield::test(misbitfield, nbits, 63));
|
||||||
CPPUNIT_ASSERT_EQUAL((size_t)63, indexes.front());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BitfieldManTest::testGetMissingUnusedIndex()
|
void BitfieldManTest::testGetMissingUnusedIndex()
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include <cppunit/extensions/HelperMacros.h>
|
#include <cppunit/extensions/HelperMacros.h>
|
||||||
|
|
||||||
#include "array_fun.h"
|
#include "array_fun.h"
|
||||||
|
#include "BitfieldMan.h"
|
||||||
|
|
||||||
namespace aria2 {
|
namespace aria2 {
|
||||||
|
|
||||||
|
@ -25,19 +26,23 @@ CPPUNIT_TEST_SUITE_REGISTRATION(LongestSequencePieceSelectorTest);
|
||||||
void LongestSequencePieceSelectorTest::testSelect()
|
void LongestSequencePieceSelectorTest::testSelect()
|
||||||
{
|
{
|
||||||
size_t A[] = { 1,2,3,4,7,10,11,12,13,14,15,100,112,113,114 };
|
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;
|
LongestSequencePieceSelector selector;
|
||||||
size_t index;
|
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);
|
CPPUNIT_ASSERT_EQUAL((size_t)15, index);
|
||||||
|
|
||||||
std::deque<size_t> zeroindexes;
|
bf.clearAllBit();
|
||||||
CPPUNIT_ASSERT(!selector.select(index, zeroindexes));
|
CPPUNIT_ASSERT(!selector.select(index, bf.getBitfield(), bf.countBlock()));
|
||||||
|
|
||||||
std::deque<size_t> oneseq(&A[0], &A[4]);
|
// See it works in just one range
|
||||||
CPPUNIT_ASSERT(selector.select(index, oneseq));
|
bf.setBitRange(1, 4);
|
||||||
|
CPPUNIT_ASSERT(selector.select(index, bf.getBitfield(), bf.countBlock()));
|
||||||
CPPUNIT_ASSERT_EQUAL((size_t)4, index);
|
CPPUNIT_ASSERT_EQUAL((size_t)4, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -67,7 +67,8 @@ aria2c_SOURCES = AllTest.cc\
|
||||||
SequentialPickerTest.cc\
|
SequentialPickerTest.cc\
|
||||||
RarestPieceSelectorTest.cc\
|
RarestPieceSelectorTest.cc\
|
||||||
LongestSequencePieceSelectorTest.cc\
|
LongestSequencePieceSelectorTest.cc\
|
||||||
a2algoTest.cc
|
a2algoTest.cc\
|
||||||
|
bitfieldTest.cc
|
||||||
|
|
||||||
if HAVE_POSIX_FALLOCATE
|
if HAVE_POSIX_FALLOCATE
|
||||||
aria2c_SOURCES += FallocFileAllocationIteratorTest.cc
|
aria2c_SOURCES += FallocFileAllocationIteratorTest.cc
|
||||||
|
|
|
@ -194,8 +194,9 @@ am__aria2c_SOURCES_DIST = AllTest.cc TestUtil.cc TestUtil.h \
|
||||||
SimpleDNSCacheTest.cc DownloadHelperTest.cc BencodeTest.cc \
|
SimpleDNSCacheTest.cc DownloadHelperTest.cc BencodeTest.cc \
|
||||||
SequentialPickerTest.cc RarestPieceSelectorTest.cc \
|
SequentialPickerTest.cc RarestPieceSelectorTest.cc \
|
||||||
LongestSequencePieceSelectorTest.cc a2algoTest.cc \
|
LongestSequencePieceSelectorTest.cc a2algoTest.cc \
|
||||||
FallocFileAllocationIteratorTest.cc GZipDecoderTest.cc \
|
bitfieldTest.cc FallocFileAllocationIteratorTest.cc \
|
||||||
Sqlite3MozCookieParserTest.cc MessageDigestHelperTest.cc \
|
GZipDecoderTest.cc Sqlite3MozCookieParserTest.cc \
|
||||||
|
MessageDigestHelperTest.cc \
|
||||||
IteratableChunkChecksumValidatorTest.cc \
|
IteratableChunkChecksumValidatorTest.cc \
|
||||||
IteratableChecksumValidatorTest.cc BtAllowedFastMessageTest.cc \
|
IteratableChecksumValidatorTest.cc BtAllowedFastMessageTest.cc \
|
||||||
BtBitfieldMessageTest.cc BtCancelMessageTest.cc \
|
BtBitfieldMessageTest.cc BtCancelMessageTest.cc \
|
||||||
|
@ -364,9 +365,9 @@ am_aria2c_OBJECTS = AllTest.$(OBJEXT) TestUtil.$(OBJEXT) \
|
||||||
SequentialPickerTest.$(OBJEXT) \
|
SequentialPickerTest.$(OBJEXT) \
|
||||||
RarestPieceSelectorTest.$(OBJEXT) \
|
RarestPieceSelectorTest.$(OBJEXT) \
|
||||||
LongestSequencePieceSelectorTest.$(OBJEXT) \
|
LongestSequencePieceSelectorTest.$(OBJEXT) \
|
||||||
a2algoTest.$(OBJEXT) $(am__objects_1) $(am__objects_2) \
|
a2algoTest.$(OBJEXT) bitfieldTest.$(OBJEXT) $(am__objects_1) \
|
||||||
$(am__objects_3) $(am__objects_4) $(am__objects_5) \
|
$(am__objects_2) $(am__objects_3) $(am__objects_4) \
|
||||||
$(am__objects_6)
|
$(am__objects_5) $(am__objects_6)
|
||||||
aria2c_OBJECTS = $(am_aria2c_OBJECTS)
|
aria2c_OBJECTS = $(am_aria2c_OBJECTS)
|
||||||
am__DEPENDENCIES_1 =
|
am__DEPENDENCIES_1 =
|
||||||
aria2c_DEPENDENCIES = ../src/libaria2c.a ../src/download_helper.o \
|
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 \
|
SimpleDNSCacheTest.cc DownloadHelperTest.cc BencodeTest.cc \
|
||||||
SequentialPickerTest.cc RarestPieceSelectorTest.cc \
|
SequentialPickerTest.cc RarestPieceSelectorTest.cc \
|
||||||
LongestSequencePieceSelectorTest.cc a2algoTest.cc \
|
LongestSequencePieceSelectorTest.cc a2algoTest.cc \
|
||||||
$(am__append_1) $(am__append_2) $(am__append_3) \
|
bitfieldTest.cc $(am__append_1) $(am__append_2) \
|
||||||
$(am__append_4) $(am__append_5) $(am__append_6)
|
$(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_CXXFLAGS = ${CPPUNIT_CFLAGS} -I../src -I../lib -Wall -D_FILE_OFFSET_BITS=64
|
||||||
#aria2c_LDFLAGS = ${CPPUNIT_LIBS}
|
#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)/a2algoTest.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/a2functionalTest.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)/array_funTest.Po@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bitfieldTest.Po@am__quote@
|
||||||
|
|
||||||
.cc.o:
|
.cc.o:
|
||||||
@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
|
@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
#include "Exception.h"
|
#include "Exception.h"
|
||||||
#include "Util.h"
|
#include "Util.h"
|
||||||
|
#include "BitfieldMan.h"
|
||||||
|
|
||||||
namespace aria2 {
|
namespace aria2 {
|
||||||
|
|
||||||
|
@ -17,6 +18,7 @@ class RarestPieceSelectorTest:public CppUnit::TestFixture {
|
||||||
CPPUNIT_TEST(testAddPieceStats_bitfield);
|
CPPUNIT_TEST(testAddPieceStats_bitfield);
|
||||||
CPPUNIT_TEST(testUpdatePieceStats);
|
CPPUNIT_TEST(testUpdatePieceStats);
|
||||||
CPPUNIT_TEST(testSubtractPieceStats);
|
CPPUNIT_TEST(testSubtractPieceStats);
|
||||||
|
CPPUNIT_TEST(testSelect);
|
||||||
CPPUNIT_TEST_SUITE_END();
|
CPPUNIT_TEST_SUITE_END();
|
||||||
public:
|
public:
|
||||||
void setUp() {}
|
void setUp() {}
|
||||||
|
@ -27,6 +29,7 @@ public:
|
||||||
void testAddPieceStats_bitfield();
|
void testAddPieceStats_bitfield();
|
||||||
void testUpdatePieceStats();
|
void testUpdatePieceStats();
|
||||||
void testSubtractPieceStats();
|
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
|
} // namespace aria2
|
||||||
|
|
|
@ -30,7 +30,6 @@ class UtilTest:public CppUnit::TestFixture {
|
||||||
CPPUNIT_TEST(testToUpper);
|
CPPUNIT_TEST(testToUpper);
|
||||||
CPPUNIT_TEST(testToLower);
|
CPPUNIT_TEST(testToLower);
|
||||||
CPPUNIT_TEST(testUrldecode);
|
CPPUNIT_TEST(testUrldecode);
|
||||||
CPPUNIT_TEST(testCountBit);
|
|
||||||
CPPUNIT_TEST(testGetRealSize);
|
CPPUNIT_TEST(testGetRealSize);
|
||||||
CPPUNIT_TEST(testAbbrevSize);
|
CPPUNIT_TEST(testAbbrevSize);
|
||||||
CPPUNIT_TEST(testToStream);
|
CPPUNIT_TEST(testToStream);
|
||||||
|
@ -75,7 +74,6 @@ public:
|
||||||
void testToUpper();
|
void testToUpper();
|
||||||
void testToLower();
|
void testToLower();
|
||||||
void testUrldecode();
|
void testUrldecode();
|
||||||
void testCountBit();
|
|
||||||
void testGetRealSize();
|
void testGetRealSize();
|
||||||
void testAbbrevSize();
|
void testAbbrevSize();
|
||||||
void testToStream();
|
void testToStream();
|
||||||
|
@ -338,11 +336,6 @@ void UtilTest::testUrldecode() {
|
||||||
CPPUNIT_ASSERT_EQUAL(std::string("/"), Util::urldecode(src6));
|
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()
|
void UtilTest::testGetRealSize()
|
||||||
{
|
{
|
||||||
CPPUNIT_ASSERT_EQUAL((int64_t)4294967296LL, Util::getRealSize("4096M"));
|
CPPUNIT_ASSERT_EQUAL((int64_t)4294967296LL, Util::getRealSize("4096M"));
|
||||||
|
|
|
@ -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
|
Loading…
Reference in New Issue