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>
|
||||
|
||||
Made accepted socket non-block.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
/**
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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@\
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
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) {
|
||||
static const char *random_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||
std::string str;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 "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()
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 $@ $<
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"));
|
||||
|
|
|
@ -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