2009-05-06 07:49:22 +00:00
|
|
|
/* <!-- copyright */
|
|
|
|
/*
|
|
|
|
* aria2 - The high speed download utility
|
|
|
|
*
|
|
|
|
* Copyright (C) 2009 Tatsuhiro Tsujikawa
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
2010-01-05 16:01:46 +00:00
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
2009-05-06 07:49:22 +00:00
|
|
|
*
|
|
|
|
* In addition, as a special exception, the copyright holders give
|
|
|
|
* permission to link the code of portions of this program with the
|
|
|
|
* OpenSSL library under certain conditions as described in each
|
|
|
|
* individual source file, and distribute linked combinations
|
|
|
|
* including the two.
|
|
|
|
* You must obey the GNU General Public License in all respects
|
|
|
|
* for all of the code used other than OpenSSL. If you modify
|
|
|
|
* file(s) with this exception, you may extend this exception to your
|
|
|
|
* version of the file(s), but you are not obligated to do so. If you
|
|
|
|
* do not wish to do so, delete this exception statement from your
|
|
|
|
* version. If you delete this exception statement from all source
|
|
|
|
* files in the program, then also delete it here.
|
|
|
|
*/
|
|
|
|
/* copyright --> */
|
|
|
|
#include "PieceStatMan.h"
|
|
|
|
|
|
|
|
#include <algorithm>
|
|
|
|
|
|
|
|
#include "SimpleRandomizer.h"
|
2010-03-24 14:25:18 +00:00
|
|
|
#include "bitfield.h"
|
2009-05-06 07:49:22 +00:00
|
|
|
|
|
|
|
namespace aria2 {
|
|
|
|
|
2010-06-21 13:51:56 +00:00
|
|
|
PieceStat::PieceStat(size_t index):order_(0), index_(index), count_(0) {}
|
2009-05-06 07:49:22 +00:00
|
|
|
|
|
|
|
void PieceStat::addCount()
|
|
|
|
{
|
2010-06-21 13:51:56 +00:00
|
|
|
if(count_ < SIZE_MAX) {
|
|
|
|
++count_;
|
2009-05-06 07:49:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void PieceStat::subCount()
|
|
|
|
{
|
2010-06-21 13:51:56 +00:00
|
|
|
if(count_ > 0) {
|
|
|
|
--count_;
|
2009-05-06 07:49:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-08-31 13:33:05 +00:00
|
|
|
namespace {
|
2009-05-06 07:49:22 +00:00
|
|
|
class GenPieceStat {
|
|
|
|
private:
|
2010-06-21 13:51:56 +00:00
|
|
|
size_t index_;
|
2009-05-06 07:49:22 +00:00
|
|
|
public:
|
2010-06-21 13:51:56 +00:00
|
|
|
GenPieceStat():index_(0) {}
|
2009-05-06 07:49:22 +00:00
|
|
|
|
|
|
|
SharedHandle<PieceStat> operator()()
|
|
|
|
{
|
2010-06-21 13:51:56 +00:00
|
|
|
return SharedHandle<PieceStat>(new PieceStat(index_++));
|
2009-05-06 07:49:22 +00:00
|
|
|
}
|
|
|
|
};
|
2010-10-30 14:53:40 +00:00
|
|
|
} // namespace
|
2009-05-06 07:49:22 +00:00
|
|
|
|
|
|
|
PieceStatMan::PieceStatMan(size_t pieceNum, bool randomShuffle):
|
2010-06-21 13:51:56 +00:00
|
|
|
pieceStats_(pieceNum),
|
|
|
|
sortedPieceStatIndexes_(pieceNum)
|
2009-05-06 07:49:22 +00:00
|
|
|
{
|
2010-06-21 13:51:56 +00:00
|
|
|
std::generate(pieceStats_.begin(), pieceStats_.end(), GenPieceStat());
|
|
|
|
std::vector<SharedHandle<PieceStat> > sortedPieceStats(pieceStats_);
|
2009-05-06 07:49:22 +00:00
|
|
|
// we need some randomness in ordering.
|
|
|
|
if(randomShuffle) {
|
|
|
|
std::random_shuffle(sortedPieceStats.begin(), sortedPieceStats.end(),
|
2010-01-05 16:01:46 +00:00
|
|
|
*(SimpleRandomizer::getInstance().get()));
|
2009-05-06 07:49:22 +00:00
|
|
|
}
|
|
|
|
{
|
|
|
|
size_t order = 0;
|
2010-02-28 16:04:52 +00:00
|
|
|
for(std::vector<SharedHandle<PieceStat> >::const_iterator i =
|
|
|
|
sortedPieceStats.begin(), eoi = sortedPieceStats.end();
|
|
|
|
i != eoi; ++i) {
|
2010-06-21 13:51:56 +00:00
|
|
|
sortedPieceStatIndexes_[order] = (*i)->getIndex();
|
2009-05-06 07:49:22 +00:00
|
|
|
(*i)->setOrder(order++);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-11-14 07:17:55 +00:00
|
|
|
PieceStatMan::~PieceStatMan() {}
|
|
|
|
|
2010-08-31 13:33:05 +00:00
|
|
|
namespace {
|
2009-05-06 07:49:22 +00:00
|
|
|
class PieceStatRarer {
|
|
|
|
private:
|
2010-06-21 13:51:56 +00:00
|
|
|
const std::vector<SharedHandle<PieceStat> >& pieceStats_;
|
2009-05-06 07:49:22 +00:00
|
|
|
public:
|
|
|
|
PieceStatRarer(const std::vector<SharedHandle<PieceStat> >& ps):
|
2010-06-21 13:51:56 +00:00
|
|
|
pieceStats_(ps) {}
|
2009-05-06 07:49:22 +00:00
|
|
|
|
|
|
|
bool operator()(size_t lhs, size_t rhs) const
|
|
|
|
{
|
2010-11-11 07:33:43 +00:00
|
|
|
return *pieceStats_[lhs] < *pieceStats_[rhs];
|
2009-05-06 07:49:22 +00:00
|
|
|
}
|
|
|
|
};
|
2010-10-30 14:53:40 +00:00
|
|
|
} // namespace
|
2009-05-06 07:49:22 +00:00
|
|
|
|
|
|
|
void PieceStatMan::addPieceStats(const unsigned char* bitfield,
|
2010-01-05 16:01:46 +00:00
|
|
|
size_t bitfieldLength)
|
2009-05-06 07:49:22 +00:00
|
|
|
{
|
2010-06-21 13:51:56 +00:00
|
|
|
const size_t nbits = pieceStats_.size();
|
2010-03-24 14:25:18 +00:00
|
|
|
assert(nbits <= bitfieldLength*8);
|
|
|
|
for(size_t i = 0; i < nbits; ++i) {
|
|
|
|
if(bitfield::test(bitfield, nbits, i)) {
|
2010-06-21 13:51:56 +00:00
|
|
|
pieceStats_[i]->addCount();
|
2009-05-06 07:49:22 +00:00
|
|
|
}
|
|
|
|
}
|
2010-06-21 13:51:56 +00:00
|
|
|
std::sort(sortedPieceStatIndexes_.begin(), sortedPieceStatIndexes_.end(),
|
|
|
|
PieceStatRarer(pieceStats_));
|
2009-05-06 07:49:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void PieceStatMan::subtractPieceStats(const unsigned char* bitfield,
|
2010-01-05 16:01:46 +00:00
|
|
|
size_t bitfieldLength)
|
2009-05-06 07:49:22 +00:00
|
|
|
{
|
2010-06-21 13:51:56 +00:00
|
|
|
const size_t nbits = pieceStats_.size();
|
2010-03-24 14:25:18 +00:00
|
|
|
assert(nbits <= bitfieldLength*8);
|
|
|
|
for(size_t i = 0; i < nbits; ++i) {
|
|
|
|
if(bitfield::test(bitfield, nbits, i)) {
|
2010-06-21 13:51:56 +00:00
|
|
|
pieceStats_[i]->subCount();
|
2009-05-06 07:49:22 +00:00
|
|
|
}
|
|
|
|
}
|
2010-06-21 13:51:56 +00:00
|
|
|
std::sort(sortedPieceStatIndexes_.begin(), sortedPieceStatIndexes_.end(),
|
|
|
|
PieceStatRarer(pieceStats_));
|
2009-05-06 07:49:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void PieceStatMan::updatePieceStats(const unsigned char* newBitfield,
|
2010-01-05 16:01:46 +00:00
|
|
|
size_t newBitfieldLength,
|
|
|
|
const unsigned char* oldBitfield)
|
2009-05-06 07:49:22 +00:00
|
|
|
{
|
2010-06-21 13:51:56 +00:00
|
|
|
const size_t nbits = pieceStats_.size();
|
2010-03-24 14:25:18 +00:00
|
|
|
assert(nbits <= newBitfieldLength*8);
|
|
|
|
for(size_t i = 0; i < nbits; ++i) {
|
|
|
|
if(bitfield::test(newBitfield, nbits, i) &&
|
|
|
|
!bitfield::test(oldBitfield, nbits, i)) {
|
2010-06-21 13:51:56 +00:00
|
|
|
pieceStats_[i]->addCount();
|
2010-03-24 14:25:18 +00:00
|
|
|
} else if(!bitfield::test(newBitfield, nbits, i) &&
|
|
|
|
bitfield::test(oldBitfield, nbits, i)) {
|
2010-06-21 13:51:56 +00:00
|
|
|
pieceStats_[i]->subCount();
|
2009-05-06 07:49:22 +00:00
|
|
|
}
|
|
|
|
}
|
2010-06-21 13:51:56 +00:00
|
|
|
std::sort(sortedPieceStatIndexes_.begin(), sortedPieceStatIndexes_.end(),
|
|
|
|
PieceStatRarer(pieceStats_));
|
2009-05-06 07:49:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void PieceStatMan::addPieceStats(size_t index)
|
|
|
|
{
|
|
|
|
std::vector<size_t>::iterator cur =
|
2010-06-21 13:51:56 +00:00
|
|
|
std::lower_bound(sortedPieceStatIndexes_.begin(),
|
|
|
|
sortedPieceStatIndexes_.end(),
|
|
|
|
index, PieceStatRarer(pieceStats_));
|
2009-05-06 07:49:22 +00:00
|
|
|
|
2010-06-21 13:51:56 +00:00
|
|
|
pieceStats_[index]->addCount();
|
2009-05-06 07:49:22 +00:00
|
|
|
|
|
|
|
std::vector<size_t>::iterator to =
|
2010-06-21 13:51:56 +00:00
|
|
|
std::upper_bound(cur+1, sortedPieceStatIndexes_.end(),
|
|
|
|
index, PieceStatRarer(pieceStats_));
|
2009-05-06 07:49:22 +00:00
|
|
|
|
|
|
|
std::rotate(cur, cur+1, to);
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace aria2
|