/* */ #include "RarestPieceSelector.h" #include 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) { std::generate(_pieceStats.begin(), _pieceStats.end(), GenPieceStat()); _sortedPieceStats = _pieceStats; // we need some randomness in ordering. if(randomShuffle) { std::random_shuffle(_sortedPieceStats.begin(), _sortedPieceStats.end()); } { size_t order = 0; for(std::deque >::iterator i = _sortedPieceStats.begin(); i != _sortedPieceStats.end(); ++i) { (*i)->setOrder(order++); } } } class FindRarestPiece { private: const std::deque& _indexes; public: FindRarestPiece(const std::deque& indexes):_indexes(indexes) {} bool operator()(const SharedHandle& pieceStat) { return std::binary_search(_indexes.begin(), _indexes.end(), pieceStat->getIndex()); } }; bool RarestPieceSelector::select (size_t& index, const std::deque& candidateIndexes) const { std::deque >::const_iterator i = std::find_if(_sortedPieceStats.begin(), _sortedPieceStats.end(), FindRarestPiece(candidateIndexes)); if(i == _sortedPieceStats.end()) { return false; } else { index = (*i)->getIndex(); return true; } } 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(_sortedPieceStats.begin(), _sortedPieceStats.end()); } 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(_sortedPieceStats.begin(), _sortedPieceStats.end()); } 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(_sortedPieceStats.begin(), _sortedPieceStats.end()); } void RarestPieceSelector::addPieceStats(size_t index) { SharedHandle pieceStat(_pieceStats[index]); { std::deque >::iterator cur = std::lower_bound(_sortedPieceStats.begin(), _sortedPieceStats.end(), pieceStat); _sortedPieceStats.erase(cur); } pieceStat->addCount(); std::deque >::iterator to = std::lower_bound(_sortedPieceStats.begin(), _sortedPieceStats.end(), pieceStat); _sortedPieceStats.insert(to, pieceStat); } const std::deque >& RarestPieceSelector::getSortedPieceStats() const { return _sortedPieceStats; } } // namespace aria2