more piece_picker unit tests and some fixes

This commit is contained in:
Arvid Norberg 2015-02-13 02:58:21 +00:00
parent 01ee9cd9af
commit 51f1a61d2d
6 changed files with 104 additions and 49 deletions

10
Jamfile
View File

@ -28,14 +28,10 @@ VERSION = 1.1.0 ;
rule coverage ( properties * )
{
local result ;
if ! <test-coverage>on
{
return $(result) ;
}
if <toolset>gcc in $(properties)
if <test-coverage>on in $(properties)
&& ( <toolset>gcc in $(properties)
|| <toolset>darwin in $(properties)
|| <toolset>clang in $(properties)
|| <toolset>clang in $(properties) )
{
result += <cxxflags>-fprofile-arcs <cxxflags>-ftest-coverage ;

View File

@ -173,6 +173,8 @@ namespace libtorrent
// info about each block
// this is a pointer into the m_block_info
// vector owned by the piece_picker
// TODO: 2 if we could make this an index into m_block_info instead
// we would save at least 4 or 5 bytes
block_info* info;
// the index of the piece
@ -366,8 +368,8 @@ namespace libtorrent
void piece_passed(int index);
void mark_as_checking(int index);
void mark_as_done_checking(int index);
// void mark_as_checking(int index);
// void mark_as_done_checking(int index);
// returns information about the given piece
void piece_info(int index, piece_picker::downloading_piece& st) const;
@ -405,10 +407,6 @@ namespace libtorrent
// the hash-check yet
int unverified_blocks() const;
// return the peer pointers for all blocks that are currently
// in requested state (i.e. requested but not received)
void get_requestors(std::vector<void*>& d, int index) const;
// return the peer pointers to all peers that participated in
// this piece
void get_downloaders(std::vector<void*>& d, int index) const;

View File

@ -2790,7 +2790,7 @@ namespace libtorrent
if (st.requested > 0 && st.writing + st.finished + st.requested == num_blocks)
{
std::vector<void*> d;
t->picker().get_requestors(d, piece);
t->picker().get_downloaders(d, piece);
if (d.size() == 1)
{
// only make predictions if all remaining

View File

@ -3425,7 +3425,9 @@ get_out:
void piece_picker::mark_as_canceled(piece_block block, void* peer)
{
#ifdef TORRENT_PICKER_LOG
std::cerr << "[" << this << "] " << "mark_as_cancelled( {" << block.piece_index << ", " << block.block_index << "} )" << std::endl;
std::cerr << "[" << this << "] " << "mark_as_cancelled( {"
<< block.piece_index << ", " << block.block_index
<< "} )" << std::endl;
#endif
#if TORRENT_USE_INVARIANT_CHECKS
@ -3458,6 +3460,21 @@ get_out:
{
--i->writing;
info.state = block_info::state_none;
// i may be invalid after this call
i = update_piece_state(i);
if (i->finished + i->writing + i->requested == 0)
{
piece_pos& p = m_piece_map[block.piece_index];
int prev_priority = p.priority(this);
erase_download_piece(i);
int new_priority = p.priority(this);
if (m_dirty) return;
if (new_priority == prev_priority) return;
if (prev_priority == -1) add(block.piece_index);
else update(prev_priority, p.index);
}
}
else
{
@ -3569,48 +3586,26 @@ get_out:
}
// TODO: 3 this doesn't appear to be used for anything. Can it be removed
// or should it be used to plug some race when requesting and checking pieces?
/*
void piece_picker::mark_as_checking(int index)
{
/*
int state = m_piece_map[index].download_queue();
if (state == piece_pos::piece_open) return;
std::vector<downloading_piece>::iterator i = find_dl_piece(state, index);
if (i == m_downloads[state].end()) return;
TORRENT_ASSERT(i->outstanding_hash_check == false);
i->outstanding_hash_check = true;
*/
}
void piece_picker::mark_as_done_checking(int index)
{
/*
int state = m_piece_map[index].download_queue();
if (state == piece_pos::piece_open) return;
std::vector<downloading_piece>::iterator i = find_dl_piece(state, index);
if (i == m_downloads[state].end()) return;
i->outstanding_hash_check = false;
}
*/
}
void piece_picker::get_requestors(std::vector<void*>& d, int index) const
{
TORRENT_ASSERT(index >= 0 && index <= (int)m_piece_map.size());
int state = m_piece_map[index].download_queue();
TORRENT_ASSERT(state != piece_pos::piece_open);
std::vector<downloading_piece>::const_iterator i = find_dl_piece(state, index);
TORRENT_ASSERT(i != m_downloads[state].end());
d.clear();
for (int j = 0, end(blocks_in_piece(index)); j != end; ++j)
{
if (i->info[j].state != block_info::state_requested) continue;
if (i->info[j].peer == 0) continue;
d.push_back(i->info[j].peer);
}
}
void piece_picker::get_downloaders(std::vector<void*>& d, int index) const
{
@ -3618,18 +3613,21 @@ get_out:
d.clear();
int state = m_piece_map[index].download_queue();
int num_blocks = blocks_in_piece(index);
d.reserve(num_blocks);
if (state == piece_pos::piece_open)
{
int num_blocks = blocks_in_piece(index);
for (int i = 0; i < num_blocks; ++i) d.push_back(0);
return;
}
std::vector<downloading_piece>::const_iterator i = find_dl_piece(state, index);
std::vector<downloading_piece>::const_iterator i
= find_dl_piece(state, index);
TORRENT_ASSERT(i != m_downloads[state].end());
TORRENT_ASSERT(i->info >= &m_block_info[0]
&& i->info < &m_block_info[0] + m_block_info.size());
for (int j = 0, end(blocks_in_piece(index)); j != end; ++j)
for (int j = 0; j != num_blocks; ++j)
{
TORRENT_ASSERT(i->info[j].peer == 0 || static_cast<torrent_peer*>(i->info[j].peer)->in_use);
d.push_back(i->info[j].peer);

View File

@ -3897,7 +3897,7 @@ namespace libtorrent
TORRENT_ASSERT(!m_picker->have_piece(j->piece));
picker().mark_as_done_checking(j->piece);
// picker().mark_as_done_checking(j->piece);
state_updated();
@ -10824,7 +10824,7 @@ namespace libtorrent
// adds a piece
void torrent::verify_piece(int piece)
{
picker().mark_as_checking(piece);
// picker().mark_as_checking(piece);
inc_refcount("verify_piece");
m_ses.disk_thread().async_hash(m_storage.get(), piece, 0

View File

@ -1550,18 +1550,81 @@ int test_main()
TEST_EQUAL(p->has_piece_passed(1), false);
TEST_EQUAL(p->have_piece(1), false);
// ========================================================
// make sure write_failed() and lock_piece() actually
// locks the piece, and that it won't be picked.
// also make sure restore_piece() unlocks it and makes
// it available for picking again.
// test mark_as_canceled()
picked = pick_pieces(p, " * ", 1, blocks_per_piece, 0);
TEST_EQUAL(picked.size(), 0);
// test get_download_queue()
p->restore_piece(1);
// test get_requestors() (similar to get_downloaders())
picked = pick_pieces(p, " * ", 1, blocks_per_piece, 0);
TEST_EQUAL(picked.size(), blocks_per_piece);
// locking pieces only works on partial pieces
p->mark_as_writing(piece_block(1, 0), &tmp1);
p->lock_piece(1);
picked = pick_pieces(p, " * ", 1, blocks_per_piece, 0);
TEST_EQUAL(picked.size(), 0);
// ========================================================
print_title("test write_failed (clear piece)");
p = setup_picker("1111111", "* * ", "1101111", "");
stat = p->piece_stats(1);
TEST_EQUAL(stat.downloading, 0);
p->mark_as_writing(piece_block(1, 0), &tmp1);
stat = p->piece_stats(1);
TEST_EQUAL(stat.downloading, 1);
p->write_failed(piece_block(1, 0));
stat = p->piece_stats(1);
TEST_EQUAL(stat.downloading, 0);
// ========================================================
print_title("test mark_as_canceled");
p = setup_picker("1111111", "* * ", "1101111", "");
stat = p->piece_stats(1);
TEST_EQUAL(stat.downloading, 0);
p->mark_as_writing(piece_block(1, 0), &tmp1);
stat = p->piece_stats(1);
TEST_EQUAL(stat.downloading, 1);
p->mark_as_canceled(piece_block(1, 0), &tmp1);
stat = p->piece_stats(1);
TEST_EQUAL(stat.downloading, 0);
// ========================================================
print_title("test get_download_queue");
p = setup_picker("1111111", " ", "1101111", "0327000");
std::vector<piece_picker::downloading_piece> downloads
= p->get_download_queue();
// the download queue should have piece 1, 2 and 3 in it
TEST_EQUAL(downloads.size(), 3);
TEST_CHECK(std::find_if(downloads.begin(), downloads.end()
, boost::bind(&piece_picker::downloading_piece::index, _1) == 1) != downloads.end());
TEST_CHECK(std::find_if(downloads.begin(), downloads.end()
, boost::bind(&piece_picker::downloading_piece::index, _1) == 2) != downloads.end());
TEST_CHECK(std::find_if(downloads.begin(), downloads.end()
, boost::bind(&piece_picker::downloading_piece::index, _1) == 3) != downloads.end());
/*