/* */ #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_; } } namespace { class GenPieceStat { private: size_t index_; public: GenPieceStat():index_(0) {} SharedHandle operator()() { return SharedHandle(new PieceStat(index_++)); } }; } // namespace 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++); } } } PieceStatMan::~PieceStatMan() {} namespace { 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]; } }; } // namespace 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