forked from premiere/premiere-libtorrent
fix overflow in calc_bytes(), add more tests, fix bug in piece picker accounting of filtered pad blocks.
This commit is contained in:
parent
fc7b61a6f3
commit
16249b8135
|
@ -3526,6 +3526,12 @@ get_out:
|
|||
|
||||
++m_pads_in_piece[block.piece_index];
|
||||
|
||||
piece_pos& p = m_piece_map[block.piece_index];
|
||||
if (p.filtered())
|
||||
{
|
||||
++m_filtered_pad_blocks;
|
||||
}
|
||||
|
||||
// if we mark and entire piece as a pad file, we need to also
|
||||
// consder that piece as "had" and increment some counters
|
||||
int const blocks = blocks_in_piece(block.piece_index);
|
||||
|
@ -3664,33 +3670,49 @@ get_out:
|
|||
piece_count piece_picker::want() const
|
||||
{
|
||||
bool const want_last = piece_priority(piece_index_t(num_pieces() - 1)) != dont_download;
|
||||
return { num_pieces() - m_num_filtered - m_num_have_filtered
|
||||
piece_count ret{ num_pieces() - m_num_filtered - m_num_have_filtered
|
||||
, num_pad_blocks() - m_filtered_pad_blocks - m_have_filtered_pad_blocks
|
||||
, want_last };
|
||||
TORRENT_ASSERT(!(ret.num_pieces == 0 && ret.last_piece == true));
|
||||
TORRENT_ASSERT(!(ret.num_pieces == 0 && ret.pad_blocks > 0));
|
||||
TORRENT_ASSERT(!(ret.num_pieces == num_pieces() && ret.last_piece == false));
|
||||
return ret;
|
||||
}
|
||||
|
||||
piece_count piece_picker::have_want() const
|
||||
{
|
||||
bool const have_last = have_piece(piece_index_t(num_pieces() - 1));
|
||||
bool const want_last = piece_priority(piece_index_t(num_pieces() - 1)) != dont_download;
|
||||
return { m_num_have - m_num_have_filtered
|
||||
piece_count ret{ m_num_have - m_num_have_filtered
|
||||
, m_have_pad_blocks - m_have_filtered_pad_blocks
|
||||
, have_last && want_last };
|
||||
TORRENT_ASSERT(!(ret.num_pieces == 0 && ret.last_piece == true));
|
||||
TORRENT_ASSERT(!(ret.num_pieces == 0 && ret.pad_blocks > 0));
|
||||
TORRENT_ASSERT(!(ret.num_pieces == num_pieces() && ret.last_piece == false));
|
||||
return ret;
|
||||
}
|
||||
|
||||
piece_count piece_picker::have() const
|
||||
{
|
||||
bool const have_last = have_piece(piece_index_t(num_pieces() - 1));
|
||||
return { m_num_have
|
||||
piece_count ret{ m_num_have
|
||||
, m_have_pad_blocks
|
||||
, have_last };
|
||||
TORRENT_ASSERT(!(ret.num_pieces == 0 && ret.last_piece == true));
|
||||
TORRENT_ASSERT(!(ret.num_pieces == 0 && ret.pad_blocks > 0));
|
||||
TORRENT_ASSERT(!(ret.num_pieces == num_pieces() && ret.last_piece == false));
|
||||
return ret;
|
||||
}
|
||||
|
||||
piece_count piece_picker::all_pieces() const
|
||||
{
|
||||
return { num_pieces()
|
||||
piece_count ret{ num_pieces()
|
||||
, num_pad_blocks()
|
||||
, true};
|
||||
TORRENT_ASSERT(!(ret.num_pieces == 0 && ret.last_piece == true));
|
||||
TORRENT_ASSERT(!(ret.num_pieces == 0 && ret.pad_blocks > 0));
|
||||
TORRENT_ASSERT(!(ret.num_pieces == num_pieces() && ret.last_piece == false));
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -3478,10 +3478,10 @@ bool is_downloading_state(int const st)
|
|||
int const block_size = std::min(default_block_size, fs.piece_length());
|
||||
|
||||
// every block should not be a pad block
|
||||
TORRENT_ASSERT(pc.pad_blocks <= pc.num_pieces * fs.piece_length() / block_size);
|
||||
TORRENT_ASSERT(pc.pad_blocks <= std::int64_t(pc.num_pieces) * fs.piece_length() / block_size);
|
||||
|
||||
return std::int64_t(pc.num_pieces) * fs.piece_length()
|
||||
- (pc.last_piece ? 1 : 0) * (fs.piece_length() - fs.piece_size(fs.last_piece()))
|
||||
- (pc.last_piece ? fs.piece_length() - fs.piece_size(fs.last_piece()) : 0)
|
||||
- std::int64_t(pc.pad_blocks) * block_size;
|
||||
}
|
||||
|
||||
|
|
|
@ -2061,5 +2061,90 @@ TORRENT_TEST(pad_blocks_in_last_piece)
|
|||
TEST_EQUAL(p->pad_blocks_in_piece(piece_index_t{0}), 0);
|
||||
}
|
||||
|
||||
namespace {
|
||||
void validate_piece_count(piece_count const& c)
|
||||
{
|
||||
// it's an impossible combination to have 0 pieces, but still have one of them be the last piece
|
||||
TEST_CHECK(!(c.num_pieces == 0 && c.last_piece == true));
|
||||
|
||||
// if we have 0 pieces, we can't have any pad blocks either
|
||||
TEST_CHECK(!(c.num_pieces == 0 && c.pad_blocks > 0));
|
||||
|
||||
// if we have all pieces, we must also have the last one
|
||||
TEST_CHECK(!(c.num_pieces == 4 && c.last_piece == false));
|
||||
}
|
||||
|
||||
void validate_all_pieces(piece_count const& c)
|
||||
{
|
||||
TEST_EQUAL(c.last_piece, true);
|
||||
TEST_EQUAL(c.num_pieces, 4);
|
||||
TEST_EQUAL(c.pad_blocks, 3);
|
||||
}
|
||||
|
||||
void validate_no_pieces(piece_count const& c)
|
||||
{
|
||||
TEST_EQUAL(c.last_piece, false);
|
||||
TEST_EQUAL(c.num_pieces, 0);
|
||||
TEST_EQUAL(c.pad_blocks, 0);
|
||||
}
|
||||
}
|
||||
|
||||
TORRENT_TEST(pad_blocks_all_filtered)
|
||||
{
|
||||
auto p = setup_picker("1111", " ", "0000", "");
|
||||
p->mark_as_pad({piece_index_t{1}, 0});
|
||||
p->mark_as_pad({piece_index_t{1}, 1});
|
||||
p->mark_as_pad({piece_index_t{2}, 0});
|
||||
|
||||
validate_piece_count(p->all_pieces());
|
||||
validate_piece_count(p->have());
|
||||
validate_piece_count(p->have_want());
|
||||
validate_piece_count(p->want());
|
||||
|
||||
validate_all_pieces(p->all_pieces());
|
||||
validate_no_pieces(p->have());
|
||||
validate_no_pieces(p->have_want());
|
||||
validate_no_pieces(p->want());
|
||||
}
|
||||
|
||||
TORRENT_TEST(pad_blocks_all_wanted)
|
||||
{
|
||||
auto p = setup_picker("1111", " ", "4444", "");
|
||||
p->mark_as_pad({piece_index_t{1}, 0});
|
||||
p->mark_as_pad({piece_index_t{1}, 1});
|
||||
p->mark_as_pad({piece_index_t{2}, 0});
|
||||
|
||||
validate_piece_count(p->all_pieces());
|
||||
validate_piece_count(p->have());
|
||||
validate_piece_count(p->have_want());
|
||||
validate_piece_count(p->want());
|
||||
|
||||
validate_all_pieces(p->all_pieces());
|
||||
validate_all_pieces(p->want());
|
||||
validate_no_pieces(p->have());
|
||||
validate_no_pieces(p->have_want());
|
||||
}
|
||||
|
||||
TORRENT_TEST(pad_blocks_some_wanted)
|
||||
{
|
||||
auto p = setup_picker("1111", " ", "0404", "");
|
||||
p->mark_as_pad({piece_index_t{1}, 0});
|
||||
p->mark_as_pad({piece_index_t{1}, 1});
|
||||
p->mark_as_pad({piece_index_t{2}, 0});
|
||||
|
||||
validate_piece_count(p->all_pieces());
|
||||
validate_piece_count(p->have());
|
||||
validate_piece_count(p->have_want());
|
||||
validate_piece_count(p->want());
|
||||
|
||||
validate_all_pieces(p->all_pieces());
|
||||
validate_no_pieces(p->have());
|
||||
validate_no_pieces(p->have_want());
|
||||
|
||||
TEST_EQUAL(p->want().num_pieces, 2);
|
||||
TEST_EQUAL(p->want().last_piece, true);
|
||||
TEST_EQUAL(p->want().pad_blocks, 2);
|
||||
}
|
||||
|
||||
//TODO: 2 test picking with partial pieces and other peers present so that both
|
||||
// backup_pieces and backup_pieces2 are used
|
||||
|
|
|
@ -694,13 +694,13 @@ TORRENT_TEST(test_read_piece_out_of_range)
|
|||
}
|
||||
|
||||
namespace {
|
||||
int const piece_size = 0x4000 * 2;
|
||||
int const piece_size = 0x4000 * 128;
|
||||
|
||||
file_storage test_fs()
|
||||
{
|
||||
file_storage fs;
|
||||
fs.set_piece_length(piece_size);
|
||||
fs.add_file("temp", 999999);
|
||||
fs.add_file("temp", 99999999999);
|
||||
fs.set_num_pieces(int((fs.total_size() + piece_size - 1) / piece_size));
|
||||
return fs;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue