/* */ #include "RarestPieceSelector.h" #include #include "SimpleRandomizer.h" namespace aria2 { PieceStat::PieceStat(size_t index):_order(0), _index(index), _count(0) {} bool PieceStat::operator<(const PieceStat& pieceStat) const { if(_count == pieceStat._count) { return _order < pieceStat._order; } else { return _count < pieceStat._count; } } void PieceStat::addCount() { if(_count < SIZE_MAX) { ++_count; } } void PieceStat::subCount() { if(_count > 0) { --_count; } } size_t PieceStat::getIndex() const { return _index; } size_t PieceStat::getCount() const { return _count; } void PieceStat::setOrder(size_t order) { _order = order; } size_t PieceStat::getOrder() const { return _order; } class GenPieceStat { private: size_t _index; public: GenPieceStat():_index(0) {} SharedHandle operator()() { return SharedHandle(new PieceStat(_index++)); } }; RarestPieceSelector::RarestPieceSelector(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 FindRarestPiece { private: const std::deque& _indexes; public: FindRarestPiece(const std::deque& indexes):_indexes(indexes) {} bool operator()(const size_t& index) { return std::binary_search(_indexes.begin(), _indexes.end(), index); } }; bool RarestPieceSelector::select (size_t& index, const std::deque& candidateIndexes) const { std::vector::const_iterator i = std::find_if(_sortedPieceStatIndexes.begin(), _sortedPieceStatIndexes.end(), FindRarestPiece(candidateIndexes)); if(i == _sortedPieceStatIndexes.end()) { return false; } else { index = *i; return true; } } 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 RarestPieceSelector::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 RarestPieceSelector::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 RarestPieceSelector::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 RarestPieceSelector::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); } const std::vector& RarestPieceSelector::getSortedPieceStatIndexes() const { return _sortedPieceStatIndexes; } const std::vector >& RarestPieceSelector::getPieceStats() const { return _pieceStats; } } // namespace aria2