/* */ #include "PieceStatMan.h" #include #include "SimpleRandomizer.h" namespace aria2 { PieceStat::PieceStat(size_t index):_order(0), _index(index), _count(0) {} void PieceStat::addCount() { if(_count < SIZE_MAX) { ++_count; } } void PieceStat::subCount() { if(_count > 0) { --_count; } } class GenPieceStat { private: size_t _index; public: GenPieceStat():_index(0) {} SharedHandle operator()() { return SharedHandle(new PieceStat(_index++)); } }; PieceStatMan::PieceStatMan(size_t pieceNum, bool randomShuffle): _pieceStats(pieceNum), _sortedPieceStatIndexes(pieceNum) { std::generate(_pieceStats.begin(), _pieceStats.end(), GenPieceStat()); std::vector > sortedPieceStats(_pieceStats); // we need some randomness in ordering. if(randomShuffle) { std::random_shuffle(sortedPieceStats.begin(), sortedPieceStats.end(), *(SimpleRandomizer::getInstance().get())); } { size_t order = 0; for(std::vector >::iterator i = sortedPieceStats.begin(); i != sortedPieceStats.end(); ++i) { _sortedPieceStatIndexes[order] = (*i)->getIndex(); (*i)->setOrder(order++); } } } class PieceStatRarer { private: const std::vector >& _pieceStats; public: PieceStatRarer(const std::vector >& ps): _pieceStats(ps) {} bool operator()(size_t lhs, size_t rhs) const { return _pieceStats[lhs] < _pieceStats[rhs]; } }; void PieceStatMan::addPieceStats(const unsigned char* bitfield, size_t bitfieldLength) { size_t index = 0; for(size_t bi = 0; bi < bitfieldLength; ++bi) { for(size_t i = 0; i < 8; ++i, ++index) { unsigned char mask = 128 >> i; if(bitfield[bi]&mask) { _pieceStats[index]->addCount(); } } } std::sort(_sortedPieceStatIndexes.begin(), _sortedPieceStatIndexes.end(), PieceStatRarer(_pieceStats)); } void PieceStatMan::subtractPieceStats(const unsigned char* bitfield, size_t bitfieldLength) { size_t index = 0; for(size_t bi = 0; bi < bitfieldLength; ++bi) { for(size_t i = 0; i < 8; ++i, ++index) { unsigned char mask = 128 >> i; if(bitfield[bi]&mask) { _pieceStats[index]->subCount(); } } } std::sort(_sortedPieceStatIndexes.begin(), _sortedPieceStatIndexes.end(), PieceStatRarer(_pieceStats)); } void PieceStatMan::updatePieceStats(const unsigned char* newBitfield, size_t newBitfieldLength, const unsigned char* oldBitfield) { size_t index = 0; for(size_t bi = 0; bi < newBitfieldLength; ++bi) { for(size_t i = 0; i < 8; ++i, ++index) { unsigned char mask = 128 >> i; if((newBitfield[bi]&mask) && !(oldBitfield[bi]&mask)) { _pieceStats[index]->addCount(); } else if(!(newBitfield[bi]&mask) && (oldBitfield[bi]&mask)) { _pieceStats[index]->subCount(); } } } std::sort(_sortedPieceStatIndexes.begin(), _sortedPieceStatIndexes.end(), PieceStatRarer(_pieceStats)); } void PieceStatMan::addPieceStats(size_t index) { std::vector::iterator cur = std::lower_bound(_sortedPieceStatIndexes.begin(), _sortedPieceStatIndexes.end(), index, PieceStatRarer(_pieceStats)); _pieceStats[index]->addCount(); std::vector::iterator to = std::upper_bound(cur+1, _sortedPieceStatIndexes.end(), index, PieceStatRarer(_pieceStats)); std::rotate(cur, cur+1, to); } } // namespace aria2