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:
@@ -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)
|
||||
|
Reference in New Issue
Block a user