/* */ #include "PieceStatMan.h" #include #include "SimpleRandomizer.h" #include "bitfield.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 >::const_iterator i = sortedPieceStats.begin(), eoi = sortedPieceStats.end(); i != eoi; ++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) { const size_t nbits = _pieceStats.size(); assert(nbits <= bitfieldLength*8); for(size_t i = 0; i < nbits; ++i) { if(bitfield::test(bitfield, nbits, i)) { _pieceStats[i]->addCount(); } } std::sort(_sortedPieceStatIndexes.begin(), _sortedPieceStatIndexes.end(), PieceStatRarer(_pieceStats)); } void PieceStatMan::subtractPieceStats(const unsigned char* bitfield, size_t bitfieldLength) { const size_t nbits = _pieceStats.size(); assert(nbits <= bitfieldLength*8); for(size_t i = 0; i < nbits; ++i) { if(bitfield::test(bitfield, nbits, i)) { _pieceStats[i]->subCount(); } } std::sort(_sortedPieceStatIndexes.begin(), _sortedPieceStatIndexes.end(), PieceStatRarer(_pieceStats)); } void PieceStatMan::updatePieceStats(const unsigned char* newBitfield, size_t newBitfieldLength, const unsigned char* oldBitfield) { const size_t nbits = _pieceStats.size(); assert(nbits <= newBitfieldLength*8); for(size_t i = 0; i < nbits; ++i) { if(bitfield::test(newBitfield, nbits, i) && !bitfield::test(oldBitfield, nbits, i)) { _pieceStats[i]->addCount(); } else if(!bitfield::test(newBitfield, nbits, i) && bitfield::test(oldBitfield, nbits, i)) { _pieceStats[i]->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