added support for piece picker to pick multiple pieces (previously it could only pick one piece tops). Made the web_peer_connection always try to make 1 MB requests at a time. added tests to the piece_picker unit test
This commit is contained in:
parent
5fc49a6cf4
commit
6d40519e66
|
@ -152,11 +152,15 @@ namespace libtorrent
|
|||
int upload_limit() const { return m_upload_limit; }
|
||||
int download_limit() const { return m_download_limit; }
|
||||
|
||||
bool prefer_whole_pieces() const
|
||||
{ return m_prefer_whole_pieces; }
|
||||
int prefer_whole_pieces() const
|
||||
{
|
||||
if (m_prefer_whole_pieces == 0)
|
||||
return peer_info_struct() && peer_info_struct()->on_parole ? 1 : 0;
|
||||
return m_prefer_whole_pieces;
|
||||
}
|
||||
|
||||
void prefer_whole_pieces(bool b)
|
||||
{ m_prefer_whole_pieces = b; }
|
||||
void prefer_whole_pieces(int num)
|
||||
{ m_prefer_whole_pieces = num; }
|
||||
|
||||
bool request_large_blocks() const
|
||||
{ return m_request_large_blocks; }
|
||||
|
@ -665,12 +669,13 @@ namespace libtorrent
|
|||
bool m_writing;
|
||||
bool m_reading;
|
||||
|
||||
// if set to true, this peer will always prefer
|
||||
// to request entire pieces, rather than blocks.
|
||||
// if it is false, the download rate limit setting
|
||||
// if set to non-zero, this peer will always prefer
|
||||
// to request entire n pieces, rather than blocks.
|
||||
// where n is the value of this variable.
|
||||
// if it is 0, the download rate limit setting
|
||||
// will be used to determine if whole pieces
|
||||
// are preferred.
|
||||
bool m_prefer_whole_pieces;
|
||||
int m_prefer_whole_pieces;
|
||||
|
||||
// if this is true, the blocks picked by the piece
|
||||
// picker will be merged before passed to the
|
||||
|
|
|
@ -191,9 +191,9 @@ namespace libtorrent
|
|||
// THIS IS DONE BY THE peer_connection::send_request() MEMBER FUNCTION!
|
||||
// The last argument is the policy::peer pointer for the peer that
|
||||
// we'll download from.
|
||||
void pick_pieces(const std::vector<bool>& pieces
|
||||
void pick_pieces(std::vector<bool> const& pieces
|
||||
, std::vector<piece_block>& interesting_blocks
|
||||
, int num_pieces, bool prefer_whole_pieces
|
||||
, int num_pieces, int prefer_whole_pieces
|
||||
, void* peer, piece_state_t speed
|
||||
, bool rarest_first) const;
|
||||
|
||||
|
@ -202,11 +202,11 @@ namespace libtorrent
|
|||
// are added to interesting_blocks, and busy blocks are
|
||||
// added to backup_blocks. num blocks is the number of
|
||||
// blocks to be picked.
|
||||
int add_interesting_blocks(const std::vector<int>& piece_list
|
||||
int add_interesting_blocks(std::vector<int> const& piece_list
|
||||
, const std::vector<bool>& pieces
|
||||
, std::vector<piece_block>& interesting_blocks
|
||||
, std::vector<piece_block>& backup_blocks
|
||||
, int num_blocks, bool prefer_whole_pieces
|
||||
, int num_blocks, int prefer_whole_pieces
|
||||
, void* peer, piece_state_t speed
|
||||
, bool ignore_downloading_pieces) const;
|
||||
|
||||
|
@ -284,6 +284,9 @@ namespace libtorrent
|
|||
|
||||
private:
|
||||
|
||||
std::pair<int, int> expand_piece(int piece, int whole_pieces
|
||||
, std::vector<bool> const& have) const;
|
||||
|
||||
struct piece_pos
|
||||
{
|
||||
piece_pos() {}
|
||||
|
|
|
@ -521,6 +521,7 @@ namespace libtorrent
|
|||
assert(t);
|
||||
|
||||
assert(t->valid_metadata());
|
||||
torrent_info const& ti = t->torrent_file();
|
||||
|
||||
return p.piece >= 0
|
||||
&& p.piece < t->torrent_file().num_pieces()
|
||||
|
@ -528,11 +529,13 @@ namespace libtorrent
|
|||
&& p.start >= 0
|
||||
&& (p.length == t->block_size()
|
||||
|| (p.length < t->block_size()
|
||||
&& p.piece == t->torrent_file().num_pieces()-1
|
||||
&& p.start + p.length == t->torrent_file().piece_size(p.piece))
|
||||
&& p.piece == ti.num_pieces()-1
|
||||
&& p.start + p.length == ti.piece_size(p.piece))
|
||||
|| (m_request_large_blocks
|
||||
&& p.length <= t->torrent_file().piece_size(p.piece)))
|
||||
&& p.start + p.length <= t->torrent_file().piece_size(p.piece)
|
||||
&& p.length <= ti.piece_length() * m_prefer_whole_pieces == 0 ?
|
||||
1 : m_prefer_whole_pieces))
|
||||
&& p.piece * int64_t(ti.piece_length()) + p.start + p.length
|
||||
<= ti.total_size()
|
||||
&& (p.start % t->block_size() == 0);
|
||||
}
|
||||
|
||||
|
@ -1623,6 +1626,7 @@ namespace libtorrent
|
|||
assert(block.block_index >= 0);
|
||||
assert(block.block_index < t->torrent_file().piece_size(block.piece_index));
|
||||
assert(!t->picker().is_requested(block) || (t->picker().num_peers(block) > 0));
|
||||
assert(!t->have_piece(block.piece_index));
|
||||
|
||||
piece_picker::piece_state_t state;
|
||||
peer_speed_t speed = peer_speed();
|
||||
|
@ -1815,21 +1819,27 @@ namespace libtorrent
|
|||
// blocks that are in the same piece into larger requests
|
||||
if (m_request_large_blocks)
|
||||
{
|
||||
while (!m_request_queue.empty()
|
||||
&& m_request_queue.front().piece_index == r.piece
|
||||
&& m_request_queue.front().block_index == block.block_index + 1)
|
||||
int blocks_per_piece = t->torrent_file().piece_length() / t->block_size();
|
||||
|
||||
while (!m_request_queue.empty())
|
||||
{
|
||||
// check to see if this block is connected to the previous one
|
||||
// if it is, merge them, otherwise, break this merge loop
|
||||
piece_block const& front = m_request_queue.front();
|
||||
if (front.piece_index * blocks_per_piece + front.block_index
|
||||
!= block.piece_index * blocks_per_piece + block.block_index + 1)
|
||||
break;
|
||||
block = m_request_queue.front();
|
||||
m_request_queue.pop_front();
|
||||
m_download_queue.push_back(block);
|
||||
/*
|
||||
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
(*m_logger) << time_now_string()
|
||||
<< " *** REQUEST-QUEUE** [ "
|
||||
<< " *** MERGING REQUEST ** [ "
|
||||
"piece: " << block.piece_index << " | "
|
||||
"block: " << block.block_index << " ]\n";
|
||||
#endif
|
||||
*/
|
||||
|
||||
block_offset = block.block_index * t->block_size();
|
||||
block_size = (std::min)((int)t->torrent_file().piece_size(
|
||||
block.piece_index) - block_offset, t->block_size());
|
||||
|
|
|
@ -1079,7 +1079,7 @@ namespace libtorrent
|
|||
// or slow once they're started.
|
||||
void piece_picker::pick_pieces(const std::vector<bool>& pieces
|
||||
, std::vector<piece_block>& interesting_blocks
|
||||
, int num_blocks, bool prefer_whole_pieces
|
||||
, int num_blocks, int prefer_whole_pieces
|
||||
, void* peer, piece_state_t speed, bool rarest_first) const
|
||||
{
|
||||
TORRENT_PIECE_PICKER_INVARIANT_CHECK;
|
||||
|
@ -1102,7 +1102,7 @@ namespace libtorrent
|
|||
// ignored as long as possible. All blocks found in downloading
|
||||
// pieces are regarded as backup blocks
|
||||
bool ignore_downloading_pieces = false;
|
||||
if (prefer_whole_pieces || !rarest_first)
|
||||
if (prefer_whole_pieces > 0 || !rarest_first)
|
||||
{
|
||||
std::vector<int> downloading_pieces;
|
||||
downloading_pieces.reserve(m_downloads.size());
|
||||
|
@ -1111,7 +1111,7 @@ namespace libtorrent
|
|||
{
|
||||
downloading_pieces.push_back(i->index);
|
||||
}
|
||||
if (prefer_whole_pieces)
|
||||
if (prefer_whole_pieces > 0)
|
||||
{
|
||||
add_interesting_blocks(downloading_pieces, pieces
|
||||
, backup_blocks, backup_blocks, num_blocks
|
||||
|
@ -1159,8 +1159,9 @@ namespace libtorrent
|
|||
while (num_blocks > 0)
|
||||
{
|
||||
while (!pieces[piece]
|
||||
|| m_piece_map[piece].index == piece_pos::we_have_index
|
||||
|| m_piece_map[piece].downloading)
|
||||
|| m_piece_map[piece].have()
|
||||
|| m_piece_map[piece].downloading
|
||||
|| m_piece_map[piece].filtered())
|
||||
{
|
||||
++piece;
|
||||
if (piece == int(m_piece_map.size())) piece = 0;
|
||||
|
@ -1170,14 +1171,20 @@ namespace libtorrent
|
|||
|
||||
assert(m_piece_map[piece].downloading == false);
|
||||
|
||||
int num_blocks_in_piece = blocks_in_piece(piece);
|
||||
|
||||
if (!prefer_whole_pieces && num_blocks_in_piece > num_blocks)
|
||||
num_blocks_in_piece = num_blocks;
|
||||
for (int j = 0; j < num_blocks_in_piece; ++j)
|
||||
interesting_blocks.push_back(piece_block(piece, j));
|
||||
num_blocks -= (std::min)(num_blocks_in_piece, num_blocks);
|
||||
++piece;
|
||||
int start, end;
|
||||
boost::tie(start, end) = expand_piece(piece, prefer_whole_pieces, pieces);
|
||||
for (int k = start; k < end; ++k)
|
||||
{
|
||||
int num_blocks_in_piece = blocks_in_piece(k);
|
||||
if (prefer_whole_pieces == 0 && num_blocks_in_piece > num_blocks)
|
||||
num_blocks_in_piece = num_blocks;
|
||||
for (int j = 0; j < num_blocks_in_piece; ++j)
|
||||
{
|
||||
interesting_blocks.push_back(piece_block(k, j));
|
||||
--num_blocks;
|
||||
}
|
||||
}
|
||||
piece = end;
|
||||
if (piece == int(m_piece_map.size())) piece = 0;
|
||||
// could not find any more pieces
|
||||
if (piece == start_piece) return;
|
||||
|
@ -1233,7 +1240,7 @@ namespace libtorrent
|
|||
, std::vector<bool> const& pieces
|
||||
, std::vector<piece_block>& interesting_blocks
|
||||
, std::vector<piece_block>& backup_blocks
|
||||
, int num_blocks, bool prefer_whole_pieces
|
||||
, int num_blocks, int prefer_whole_pieces
|
||||
, void* peer, piece_state_t speed
|
||||
, bool ignore_downloading_pieces) const
|
||||
{
|
||||
|
@ -1277,7 +1284,7 @@ namespace libtorrent
|
|||
// blocks to the backup list. If the prioritized
|
||||
// blocks aren't enough, blocks from this list
|
||||
// will be picked.
|
||||
if (prefer_whole_pieces && !exclusive)
|
||||
if (prefer_whole_pieces > 0 && !exclusive)
|
||||
{
|
||||
for (int j = 0; j < num_blocks_in_piece; ++j)
|
||||
{
|
||||
|
@ -1332,7 +1339,7 @@ namespace libtorrent
|
|||
num_blocks--;
|
||||
// if we prefer whole pieces, continue picking from this
|
||||
// piece even though we have num_blocks
|
||||
if (prefer_whole_pieces) continue;
|
||||
if (prefer_whole_pieces > 0) continue;
|
||||
assert(num_blocks >= 0);
|
||||
if (num_blocks == 0) return num_blocks;
|
||||
}
|
||||
|
@ -1341,23 +1348,68 @@ namespace libtorrent
|
|||
backup_blocks.push_back(piece_block(*i, j));
|
||||
}
|
||||
}
|
||||
assert(num_blocks >= 0 || prefer_whole_pieces);
|
||||
assert(num_blocks >= 0 || prefer_whole_pieces > 0);
|
||||
if (num_blocks < 0) num_blocks = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!prefer_whole_pieces && num_blocks_in_piece > num_blocks)
|
||||
num_blocks_in_piece = num_blocks;
|
||||
for (int j = 0; j < num_blocks_in_piece; ++j)
|
||||
interesting_blocks.push_back(piece_block(*i, j));
|
||||
num_blocks -= (std::min)(num_blocks_in_piece, num_blocks);
|
||||
// pick a new piece
|
||||
if (prefer_whole_pieces == 0)
|
||||
{
|
||||
if (num_blocks_in_piece > num_blocks)
|
||||
num_blocks_in_piece = num_blocks;
|
||||
for (int j = 0; j < num_blocks_in_piece; ++j)
|
||||
interesting_blocks.push_back(piece_block(*i, j));
|
||||
num_blocks -= num_blocks_in_piece;
|
||||
}
|
||||
else
|
||||
{
|
||||
int start, end;
|
||||
boost::tie(start, end) = expand_piece(*i, prefer_whole_pieces, pieces);
|
||||
for (int k = start; k < end; ++k)
|
||||
{
|
||||
num_blocks_in_piece = blocks_in_piece(k);
|
||||
for (int j = 0; j < num_blocks_in_piece; ++j)
|
||||
{
|
||||
interesting_blocks.push_back(piece_block(k, j));
|
||||
--num_blocks;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
assert(num_blocks >= 0);
|
||||
if (num_blocks == 0) return num_blocks;
|
||||
if (num_blocks <= 0) return num_blocks < 0 ? 0 : num_blocks;
|
||||
}
|
||||
return num_blocks;
|
||||
}
|
||||
|
||||
std::pair<int, int> piece_picker::expand_piece(int piece, int whole_pieces
|
||||
, std::vector<bool> const& have) const
|
||||
{
|
||||
if (whole_pieces == 0) return std::make_pair(piece, piece + 1);
|
||||
|
||||
int start = piece - 1;
|
||||
int lower_limit = piece - whole_pieces;
|
||||
if (lower_limit < -1) lower_limit = -1;
|
||||
while (start > lower_limit
|
||||
&& have[start]
|
||||
&& !m_piece_map[start].downloading
|
||||
&& !m_piece_map[start].filtered()
|
||||
&& !m_piece_map[start].have())
|
||||
--start;
|
||||
++start;
|
||||
assert(start >= 0);
|
||||
int end = piece + 1;
|
||||
int upper_limit = start + whole_pieces;
|
||||
if (upper_limit > int(m_piece_map.size())) upper_limit = int(m_piece_map.size());
|
||||
while (end < upper_limit
|
||||
&& have[end]
|
||||
&& !m_piece_map[end].downloading
|
||||
&& !m_piece_map[end].filtered()
|
||||
&& !m_piece_map[end].have())
|
||||
++end;
|
||||
return std::make_pair(start, end);
|
||||
}
|
||||
|
||||
bool piece_picker::is_piece_finished(int index) const
|
||||
{
|
||||
assert(index < (int)m_piece_map.size());
|
||||
|
@ -1443,6 +1495,7 @@ namespace libtorrent
|
|||
assert(block.block_index >= 0);
|
||||
assert(block.piece_index < (int)m_piece_map.size());
|
||||
assert(block.block_index < blocks_in_piece(block.piece_index));
|
||||
assert(!m_piece_map[block.piece_index].have());
|
||||
|
||||
piece_pos& p = m_piece_map[block.piece_index];
|
||||
if (p.downloading == 0)
|
||||
|
|
|
@ -209,16 +209,15 @@ namespace libtorrent
|
|||
std::vector<piece_block> interesting_pieces;
|
||||
interesting_pieces.reserve(100);
|
||||
|
||||
bool prefer_whole_pieces = c.prefer_whole_pieces()
|
||||
|| (c.peer_info_struct() && c.peer_info_struct()->on_parole);
|
||||
int prefer_whole_pieces = c.prefer_whole_pieces();
|
||||
|
||||
bool rarest_first = t.num_pieces() >= t.settings().initial_picker_threshold;
|
||||
|
||||
if (!prefer_whole_pieces)
|
||||
if (prefer_whole_pieces == 0)
|
||||
{
|
||||
prefer_whole_pieces = c.statistics().download_payload_rate()
|
||||
* t.settings().whole_pieces_threshold
|
||||
> t.torrent_file().piece_length();
|
||||
> t.torrent_file().piece_length() ? 1 : 0;
|
||||
}
|
||||
|
||||
// if we prefer whole pieces, the piece picker will pick at least
|
||||
|
@ -265,12 +264,9 @@ namespace libtorrent
|
|||
std::vector<int> const& suggested = c.suggested_pieces();
|
||||
|
||||
p.add_interesting_blocks(suggested, c.get_bitfield()
|
||||
, interesting_pieces, busy_pieces, num_requests
|
||||
, prefer_whole_pieces, c.peer_info_struct(), state
|
||||
, false);
|
||||
interesting_pieces.insert(interesting_pieces.end()
|
||||
, busy_pieces.begin(), busy_pieces.end());
|
||||
busy_pieces.clear();
|
||||
, interesting_pieces, busy_pieces, num_requests
|
||||
, prefer_whole_pieces, c.peer_info_struct(), state
|
||||
, false);
|
||||
}
|
||||
|
||||
// picks the interesting pieces from this peer
|
||||
|
@ -285,13 +281,14 @@ namespace libtorrent
|
|||
p.pick_pieces(c.get_bitfield(), interesting_pieces
|
||||
, num_requests, prefer_whole_pieces, c.peer_info_struct()
|
||||
, state, rarest_first);
|
||||
|
||||
busy_pieces.reserve(10);
|
||||
}
|
||||
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
(*c.m_logger) << time_now_string() << " PIECE_PICKER [ picked: " << interesting_pieces.size() << " ]\n";
|
||||
(*c.m_logger) << time_now_string() << " PIECE_PICKER [ php: " << prefer_whole_pieces
|
||||
<< " picked: " << interesting_pieces.size() << " ]\n";
|
||||
#endif
|
||||
std::deque<piece_block> const& dq = c.download_queue();
|
||||
std::deque<piece_block> const& rq = c.request_queue();
|
||||
for (std::vector<piece_block>::iterator i = interesting_pieces.begin();
|
||||
i != interesting_pieces.end(); ++i)
|
||||
{
|
||||
|
@ -299,8 +296,6 @@ namespace libtorrent
|
|||
{
|
||||
if (num_requests <= 0) break;
|
||||
// don't request pieces we already have in our request queue
|
||||
const std::deque<piece_block>& dq = c.download_queue();
|
||||
const std::deque<piece_block>& rq = c.request_queue();
|
||||
if (std::find(dq.begin(), dq.end(), *i) != dq.end()
|
||||
|| std::find(rq.begin(), rq.end(), *i) != rq.end())
|
||||
continue;
|
||||
|
|
|
@ -69,9 +69,6 @@ namespace libtorrent
|
|||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
// we always prefer downloading entire
|
||||
// pieces from web seeds
|
||||
prefer_whole_pieces(true);
|
||||
// we want large blocks as well, so
|
||||
// we can request more bytes at once
|
||||
request_large_blocks(true);
|
||||
|
@ -80,6 +77,10 @@ namespace libtorrent
|
|||
shared_ptr<torrent> tor = t.lock();
|
||||
assert(tor);
|
||||
int blocks_per_piece = tor->torrent_file().piece_length() / tor->block_size();
|
||||
|
||||
// we always prefer downloading 1 MB chunks
|
||||
// from web seeds
|
||||
prefer_whole_pieces((1024 * 1024) / tor->torrent_file().piece_length());
|
||||
|
||||
// multiply with the blocks per piece since that many requests are
|
||||
// merged into one http request
|
||||
|
@ -178,13 +179,16 @@ namespace libtorrent
|
|||
|
||||
int size = r.length;
|
||||
const int block_size = t->block_size();
|
||||
const int piece_size = t->torrent_file().piece_length();
|
||||
peer_request pr;
|
||||
while (size > 0)
|
||||
{
|
||||
int request_size = (std::min)(block_size, size);
|
||||
peer_request pr = {r.piece, r.start + r.length - size
|
||||
, request_size};
|
||||
int request_offset = r.start + r.length - size;
|
||||
pr.start = request_offset % piece_size;
|
||||
pr.length = (std::min)(block_size, size);
|
||||
pr.piece = r.piece + request_offset / piece_size;
|
||||
m_requests.push_back(pr);
|
||||
size -= request_size;
|
||||
size -= pr.length;
|
||||
}
|
||||
|
||||
proxy_settings const& ps = m_ses.web_seed_proxy();
|
||||
|
@ -477,8 +481,11 @@ namespace libtorrent
|
|||
|
||||
peer_request front_request = m_requests.front();
|
||||
|
||||
if (in_range.piece != front_request.piece
|
||||
|| in_range.start > front_request.start + int(m_piece.size()))
|
||||
size_type rs = size_type(in_range.piece) * info.piece_length() + in_range.start;
|
||||
size_type re = rs + in_range.length;
|
||||
size_type fs = size_type(front_request.piece) * info.piece_length() + front_request.start;
|
||||
size_type fe = fs + front_request.length;
|
||||
if (fs < rs || fe > re)
|
||||
{
|
||||
throw std::runtime_error("invalid range in HTTP response");
|
||||
}
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
|
||||
using namespace libtorrent;
|
||||
|
||||
const int blocks_per_piece = 4;
|
||||
|
||||
std::vector<bool> string2vec(char const* have_str)
|
||||
{
|
||||
const int num_pieces = strlen(have_str);
|
||||
|
@ -30,7 +32,6 @@ boost::shared_ptr<piece_picker> setup_picker(
|
|||
, char const* priority
|
||||
, char const* partial)
|
||||
{
|
||||
const int blocks_per_piece = 4;
|
||||
const int num_pieces = strlen(availability);
|
||||
assert(int(strlen(have_str)) == num_pieces);
|
||||
|
||||
|
@ -183,10 +184,10 @@ int test_main()
|
|||
// whole pieces are preferred. The only whole piece is 1.
|
||||
p = setup_picker("1111111", " ", "1111111", "1023460");
|
||||
picked.clear();
|
||||
p->pick_pieces(string2vec("****** "), picked, 1, true, 0, piece_picker::fast, true);
|
||||
p->pick_pieces(string2vec("****** "), picked, 1, 1, 0, piece_picker::fast, true);
|
||||
TEST_CHECK(verify_pick(p, picked));
|
||||
TEST_CHECK(picked.size() >= 4);
|
||||
for (int i = 0; i < 4 && i < int(picked.size()); ++i)
|
||||
TEST_CHECK(int(picked.size()) >= blocks_per_piece);
|
||||
for (int i = 0; i < blocks_per_piece && i < int(picked.size()); ++i)
|
||||
TEST_CHECK(picked[i].piece_index == 1);
|
||||
|
||||
// ========================================================
|
||||
|
@ -233,48 +234,48 @@ int test_main()
|
|||
p = setup_picker("7654321", " ", "", "");
|
||||
picked.clear();
|
||||
p->set_sequenced_download_threshold(3);
|
||||
p->pick_pieces(string2vec("***** "), picked, 5 * 4, false, 0, piece_picker::fast, true);
|
||||
p->pick_pieces(string2vec("***** "), picked, 5 * blocks_per_piece, false, 0, piece_picker::fast, true);
|
||||
print_pick(picked);
|
||||
TEST_CHECK(verify_pick(p, picked));
|
||||
TEST_CHECK(picked.size() == 5 * 4);
|
||||
for (int i = 0; i < 5 * 4 && i < int(picked.size()); ++i)
|
||||
TEST_CHECK(picked[i].piece_index == i / 4);
|
||||
TEST_CHECK(picked.size() == 5 * blocks_per_piece);
|
||||
for (int i = 0; i < 5 * blocks_per_piece && i < int(picked.size()); ++i)
|
||||
TEST_CHECK(picked[i].piece_index == i / blocks_per_piece);
|
||||
|
||||
picked.clear();
|
||||
p->set_sequenced_download_threshold(4);
|
||||
p->pick_pieces(string2vec("**** "), picked, 5 * 4, false, 0, piece_picker::fast, true);
|
||||
p->pick_pieces(string2vec("**** "), picked, 5 * blocks_per_piece, false, 0, piece_picker::fast, true);
|
||||
print_pick(picked);
|
||||
TEST_CHECK(verify_pick(p, picked));
|
||||
TEST_CHECK(picked.size() == 4 * 4);
|
||||
for (int i = 0; i < 4 * 4 && i < int(picked.size()); ++i)
|
||||
TEST_CHECK(picked[i].piece_index == i / 4);
|
||||
TEST_CHECK(picked.size() == 4 * blocks_per_piece);
|
||||
for (int i = 0; i < 4 * blocks_per_piece && i < int(picked.size()); ++i)
|
||||
TEST_CHECK(picked[i].piece_index == i / blocks_per_piece);
|
||||
|
||||
picked.clear();
|
||||
p->set_sequenced_download_threshold(2);
|
||||
p->pick_pieces(string2vec("****** "), picked, 6 * 4, false, 0, piece_picker::fast, true);
|
||||
p->pick_pieces(string2vec("****** "), picked, 6 * blocks_per_piece, false, 0, piece_picker::fast, true);
|
||||
print_pick(picked);
|
||||
TEST_CHECK(verify_pick(p, picked));
|
||||
TEST_CHECK(picked.size() == 6 * 4);
|
||||
for (int i = 0; i < 6 * 4 && i < int(picked.size()); ++i)
|
||||
TEST_CHECK(picked[i].piece_index == i / 4);
|
||||
TEST_CHECK(picked.size() == 6 * blocks_per_piece);
|
||||
for (int i = 0; i < 6 * blocks_per_piece && i < int(picked.size()); ++i)
|
||||
TEST_CHECK(picked[i].piece_index == i / blocks_per_piece);
|
||||
|
||||
picked.clear();
|
||||
p->set_piece_priority(0, 0);
|
||||
p->pick_pieces(string2vec("****** "), picked, 6 * 4, false, 0, piece_picker::fast, true);
|
||||
p->pick_pieces(string2vec("****** "), picked, 6 * blocks_per_piece, false, 0, piece_picker::fast, true);
|
||||
print_pick(picked);
|
||||
TEST_CHECK(verify_pick(p, picked));
|
||||
TEST_CHECK(picked.size() == 5 * 4);
|
||||
for (int i = 0; i < 5 * 4 && i < int(picked.size()); ++i)
|
||||
TEST_CHECK(picked[i].piece_index == i / 4 + 1);
|
||||
TEST_CHECK(picked.size() == 5 * blocks_per_piece);
|
||||
for (int i = 0; i < 5 * blocks_per_piece && i < int(picked.size()); ++i)
|
||||
TEST_CHECK(picked[i].piece_index == i / blocks_per_piece + 1);
|
||||
|
||||
picked.clear();
|
||||
p->set_piece_priority(0, 1);
|
||||
p->pick_pieces(string2vec("****** "), picked, 6 * 4, false, 0, piece_picker::fast, true);
|
||||
p->pick_pieces(string2vec("****** "), picked, 6 * blocks_per_piece, false, 0, piece_picker::fast, true);
|
||||
print_pick(picked);
|
||||
TEST_CHECK(verify_pick(p, picked));
|
||||
TEST_CHECK(picked.size() == 6 * 4);
|
||||
for (int i = 0; i < 6 * 4 && i < int(picked.size()); ++i)
|
||||
TEST_CHECK(picked[i].piece_index == i / 4);
|
||||
TEST_CHECK(picked.size() == 6 * blocks_per_piece);
|
||||
for (int i = 0; i < 6 * blocks_per_piece && i < int(picked.size()); ++i)
|
||||
TEST_CHECK(picked[i].piece_index == i / blocks_per_piece);
|
||||
|
||||
// ========================================================
|
||||
|
||||
|
@ -291,17 +292,17 @@ int test_main()
|
|||
TEST_CHECK(p->num_have_filtered() == 1);
|
||||
|
||||
picked.clear();
|
||||
p->pick_pieces(string2vec("*******"), picked, 6 * 4, false, 0, piece_picker::fast, true);
|
||||
p->pick_pieces(string2vec("*******"), picked, 6 * blocks_per_piece, false, 0, piece_picker::fast, true);
|
||||
print_pick(picked);
|
||||
TEST_CHECK(verify_pick(p, picked));
|
||||
TEST_CHECK(picked.size() == 6 * 4);
|
||||
TEST_CHECK(picked[0].piece_index == 5);
|
||||
TEST_CHECK(picked.size() == 6 * blocks_per_piece);
|
||||
TEST_CHECK(picked[0 * blocks_per_piece].piece_index == 5);
|
||||
// priority 5 and 6 is currently the same
|
||||
TEST_CHECK(picked[4].piece_index == 6 || picked[4].piece_index == 4);
|
||||
TEST_CHECK(picked[8].piece_index == 6 || picked[8].piece_index == 4);
|
||||
TEST_CHECK(picked[12].piece_index == 3);
|
||||
TEST_CHECK(picked[16].piece_index == 1);
|
||||
TEST_CHECK(picked[20].piece_index == 2);
|
||||
TEST_CHECK(picked[1 * blocks_per_piece].piece_index == 6 || picked[1 * blocks_per_piece].piece_index == 4);
|
||||
TEST_CHECK(picked[2 * blocks_per_piece].piece_index == 6 || picked[2 * blocks_per_piece].piece_index == 4);
|
||||
TEST_CHECK(picked[3 * blocks_per_piece].piece_index == 3);
|
||||
TEST_CHECK(picked[4 * blocks_per_piece].piece_index == 1);
|
||||
TEST_CHECK(picked[5 * blocks_per_piece].piece_index == 2);
|
||||
|
||||
std::vector<int> prios;
|
||||
p->piece_priorities(prios);
|
||||
|
@ -365,12 +366,12 @@ int test_main()
|
|||
// test non-rarest-first mode
|
||||
p = setup_picker("1234567", "* * * ", "1111122", "");
|
||||
picked.clear();
|
||||
p->pick_pieces(string2vec("****** "), picked, 5 * 4, false, 0, piece_picker::fast, false);
|
||||
p->pick_pieces(string2vec("****** "), picked, 5 * blocks_per_piece, false, 0, piece_picker::fast, false);
|
||||
print_pick(picked);
|
||||
TEST_CHECK(verify_pick(p, picked));
|
||||
TEST_CHECK(picked.size() == 3 * 4);
|
||||
TEST_CHECK(picked.size() == 3 * blocks_per_piece);
|
||||
|
||||
for (int i = 0; i < 4 * 4 && i < int(picked.size()); ++i)
|
||||
for (int i = 0; i < 4 * blocks_per_piece && i < int(picked.size()); ++i)
|
||||
{
|
||||
TEST_CHECK(picked[i].piece_index != 0);
|
||||
TEST_CHECK(picked[i].piece_index != 2);
|
||||
|
@ -393,8 +394,6 @@ int test_main()
|
|||
std::cout << "distributed copies: " << dc << std::endl;
|
||||
TEST_CHECK(fabs(dc - (1.f + 5.f / 7.f)) < 0.01f);
|
||||
|
||||
|
||||
|
||||
// ========================================================
|
||||
|
||||
// test have_all and have_none, with a sequenced download threshold
|
||||
|
@ -419,11 +418,11 @@ int test_main()
|
|||
p->pick_pieces(string2vec(" * ****"), picked, 100, false, 0, piece_picker::fast, true);
|
||||
print_pick(picked);
|
||||
TEST_CHECK(verify_pick(p, picked));
|
||||
TEST_CHECK(picked.size() >= 4 * 4);
|
||||
TEST_CHECK(picked[0].piece_index == 3);
|
||||
TEST_CHECK(picked[4].piece_index == 4);
|
||||
TEST_CHECK(picked[8].piece_index == 5);
|
||||
TEST_CHECK(picked[12].piece_index == 6);
|
||||
TEST_CHECK(picked.size() >= 4 * blocks_per_piece);
|
||||
TEST_CHECK(picked[0 * blocks_per_piece].piece_index == 3);
|
||||
TEST_CHECK(picked[1 * blocks_per_piece].piece_index == 4);
|
||||
TEST_CHECK(picked[2 * blocks_per_piece].piece_index == 5);
|
||||
TEST_CHECK(picked[3 * blocks_per_piece].piece_index == 6);
|
||||
|
||||
// ========================================================
|
||||
|
||||
|
@ -464,6 +463,36 @@ int test_main()
|
|||
TEST_CHECK(p->get_downloader(piece_block(4, 3)) == 0);
|
||||
TEST_CHECK(p->unverified_blocks() == 2);
|
||||
|
||||
// ========================================================
|
||||
|
||||
// test prefer_whole_pieces
|
||||
p = setup_picker("1111111", " ", "", "");
|
||||
picked.clear();
|
||||
p->pick_pieces(string2vec("*******"), picked, 1, 3, 0, piece_picker::fast, true);
|
||||
print_pick(picked);
|
||||
TEST_CHECK(verify_pick(p, picked));
|
||||
TEST_CHECK(picked.size() >= 3 * blocks_per_piece);
|
||||
piece_block b = picked.front();
|
||||
for (int i = 1; i < int(picked.size()); ++i)
|
||||
{
|
||||
TEST_CHECK(picked[i].piece_index * blocks_per_piece + picked[i].block_index
|
||||
== b.piece_index * blocks_per_piece + b.block_index + 1);
|
||||
b = picked[i];
|
||||
}
|
||||
|
||||
picked.clear();
|
||||
p->pick_pieces(string2vec("*******"), picked, 1, 3, 0, piece_picker::fast, false);
|
||||
print_pick(picked);
|
||||
TEST_CHECK(verify_pick(p, picked));
|
||||
TEST_CHECK(picked.size() >= 3 * blocks_per_piece);
|
||||
b = picked.front();
|
||||
for (int i = 1; i < int(picked.size()); ++i)
|
||||
{
|
||||
TEST_CHECK(picked[i].piece_index * blocks_per_piece + picked[i].block_index
|
||||
== b.piece_index * blocks_per_piece + b.block_index + 1);
|
||||
b = picked[i];
|
||||
}
|
||||
|
||||
// MISSING TESTS:
|
||||
// 2. inc_ref() from 0 to 1 while sequenced download threshold is 1
|
||||
// 4. filtered_pieces
|
||||
|
|
Loading…
Reference in New Issue