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:
Arvid Norberg 2007-09-03 21:16:24 +00:00
parent 5fc49a6cf4
commit 6d40519e66
7 changed files with 214 additions and 112 deletions

View File

@ -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

View File

@ -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() {}

View File

@ -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());

View File

@ -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)

View File

@ -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;

View File

@ -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");
}

View File

@ -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