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

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