piece picker update

This commit is contained in:
Arvid Norberg
2008-02-18 03:07:14 +00:00
parent 5c14ec2eb1
commit 333839c9b4
5 changed files with 99 additions and 43 deletions

View File

@@ -242,6 +242,7 @@ namespace libtorrent
, piece_state_t s); , piece_state_t s);
void mark_as_writing(piece_block block, void* peer); void mark_as_writing(piece_block block, void* peer);
void mark_as_finished(piece_block block, void* peer); void mark_as_finished(piece_block block, void* peer);
void write_failed(piece_block block);
int num_peers(piece_block block) const; int num_peers(piece_block block) const;
// returns information about the given piece // returns information about the given piece

View File

@@ -1476,7 +1476,7 @@ namespace libtorrent
if (ret == -1 || !t) if (ret == -1 || !t)
{ {
if (t->has_picker()) t->picker().abort_download(block_finished); if (t->has_picker()) t->picker().write_failed(block_finished);
if (!t) if (!t)
{ {

View File

@@ -49,6 +49,7 @@ POSSIBILITY OF SUCH DAMAGE.
#endif #endif
//#define TORRENT_PIECE_PICKER_INVARIANT_CHECK INVARIANT_CHECK //#define TORRENT_PIECE_PICKER_INVARIANT_CHECK INVARIANT_CHECK
//#define TORRENT_NO_EXPENSIVE_INVARIANT_CHECK
#define TORRENT_PIECE_PICKER_INVARIANT_CHECK #define TORRENT_PIECE_PICKER_INVARIANT_CHECK
//#define TORRENT_PICKER_LOG //#define TORRENT_PICKER_LOG
@@ -276,7 +277,7 @@ namespace libtorrent
TORRENT_ASSERT(p == prio); TORRENT_ASSERT(p == prio);
} }
} }
#ifndef NDEBUG
void piece_picker::print_pieces() const void piece_picker::print_pieces() const
{ {
for (std::vector<int>::const_iterator i = m_priority_boundries.begin() for (std::vector<int>::const_iterator i = m_priority_boundries.begin()
@@ -300,32 +301,9 @@ namespace libtorrent
} }
std::cout << std::endl; std::cout << std::endl;
} }
#endif
void piece_picker::check_invariant(const torrent* t) const void piece_picker::check_invariant(const torrent* t) const
{ {
if (m_sequential_download == -1 && !m_dirty)
{
TORRENT_ASSERT(!m_priority_boundries.empty());
int prio = 0;
int start = 0;
for (std::vector<int>::const_iterator i = m_priority_boundries.begin()
, end(m_priority_boundries.end()); i != end; ++i)
{
verify_priority(start, *i, prio);
++prio;
start = *i;
}
TORRENT_ASSERT(m_priority_boundries.back() == int(m_pieces.size()));
}
else if (m_sequential_download >= 0)
{
int index = 0;
for (std::vector<piece_pos>::const_iterator i = m_piece_map.begin()
, end(m_piece_map.end()); i != end && (i->have() || i->filtered());
++i, ++index);
TORRENT_ASSERT(m_sequential_download == index);
}
TORRENT_ASSERT(sizeof(piece_pos) == 4); TORRENT_ASSERT(sizeof(piece_pos) == 4);
TORRENT_ASSERT(m_num_have >= 0); TORRENT_ASSERT(m_num_have >= 0);
TORRENT_ASSERT(m_num_have_filtered >= 0); TORRENT_ASSERT(m_num_have_filtered >= 0);
@@ -358,17 +336,18 @@ namespace libtorrent
if (i->info[k].state == block_info::state_finished) if (i->info[k].state == block_info::state_finished)
{ {
++num_finished; ++num_finished;
continue; TORRENT_ASSERT(i->info[k].num_peers == 0);
} }
if (i->info[k].state == block_info::state_requested) else if (i->info[k].state == block_info::state_requested)
{ {
++num_requested; ++num_requested;
blocks_requested = true; blocks_requested = true;
TORRENT_ASSERT(i->info[k].num_peers > 0); TORRENT_ASSERT(i->info[k].num_peers > 0);
} }
if (i->info[k].state == block_info::state_writing) else if (i->info[k].state == block_info::state_writing)
{ {
++num_writing; ++num_writing;
TORRENT_ASSERT(i->info[k].num_peers == 0);
} }
} }
TORRENT_ASSERT(blocks_requested == (i->state != none)); TORRENT_ASSERT(blocks_requested == (i->state != none));
@@ -376,7 +355,32 @@ namespace libtorrent
TORRENT_ASSERT(num_writing == i->writing); TORRENT_ASSERT(num_writing == i->writing);
TORRENT_ASSERT(num_finished == i->finished); TORRENT_ASSERT(num_finished == i->finished);
} }
#ifdef TORRENT_NO_EXPENSIVE_INVARIANT_CHECK
return;
#endif
if (m_sequential_download == -1 && !m_dirty)
{
TORRENT_ASSERT(!m_priority_boundries.empty());
int prio = 0;
int start = 0;
for (std::vector<int>::const_iterator i = m_priority_boundries.begin()
, end(m_priority_boundries.end()); i != end; ++i)
{
verify_priority(start, *i, prio);
++prio;
start = *i;
}
TORRENT_ASSERT(m_priority_boundries.back() == int(m_pieces.size()));
}
else if (m_sequential_download >= 0)
{
int index = 0;
for (std::vector<piece_pos>::const_iterator i = m_piece_map.begin()
, end(m_piece_map.end()); i != end && (i->have() || i->filtered());
++i, ++index);
TORRENT_ASSERT(m_sequential_download == index);
}
int num_filtered = 0; int num_filtered = 0;
int num_have_filtered = 0; int num_have_filtered = 0;
@@ -807,9 +811,9 @@ namespace libtorrent
TORRENT_ASSERT(m_piece_map[index].downloading == 1); TORRENT_ASSERT(m_piece_map[index].downloading == 1);
std::vector<downloading_piece>::iterator i std::vector<downloading_piece>::iterator i
= std::find_if(m_downloads.begin(), = std::find_if(m_downloads.begin(), m_downloads.end()
m_downloads.end(), , has_index(index));
has_index(index));
TORRENT_ASSERT(i != m_downloads.end()); TORRENT_ASSERT(i != m_downloads.end());
erase_download_piece(i); erase_download_piece(i);
@@ -1814,7 +1818,8 @@ namespace libtorrent
TORRENT_ASSERT(info.state != block_info::state_writing); TORRENT_ASSERT(info.state != block_info::state_writing);
++i->writing; ++i->writing;
info.state = block_info::state_writing; info.state = block_info::state_writing;
if (info.num_peers > 0) --info.num_peers; TORRENT_ASSERT(info.num_peers > 0);
info.num_peers = 0;
if (i->requested == 0) if (i->requested == 0)
{ {
@@ -1824,6 +1829,31 @@ namespace libtorrent
} }
sort_piece(i); sort_piece(i);
} }
void piece_picker::write_failed(piece_block block)
{
TORRENT_PIECE_PICKER_INVARIANT_CHECK;
std::vector<downloading_piece>::iterator i
= std::find_if(m_downloads.begin(), m_downloads.end(), has_index(block.piece_index));
TORRENT_ASSERT(i != m_downloads.end());
block_info& info = i->info[block.block_index];
TORRENT_ASSERT(info.state == block_info::state_writing);
--i->writing;
if (info.num_peers > 0)
{
// there are other peers on this block
// turn it back into requested
++i->requested;
info.state = block_info::state_requested;
}
else
{
info.state = block_info::state_none;
}
info.peer = 0;
}
void piece_picker::mark_as_finished(piece_block block, void* peer) void piece_picker::mark_as_finished(piece_block block, void* peer)
{ {
@@ -1851,6 +1881,7 @@ namespace libtorrent
block_info& info = dp.info[block.block_index]; block_info& info = dp.info[block.block_index];
info.peer = peer; info.peer = peer;
TORRENT_ASSERT(info.state == block_info::state_none); TORRENT_ASSERT(info.state == block_info::state_none);
TORRENT_ASSERT(info.num_peers == 0);
if (info.state != block_info::state_finished) if (info.state != block_info::state_finished)
{ {
++dp.finished; ++dp.finished;
@@ -1866,6 +1897,7 @@ namespace libtorrent
= std::find_if(m_downloads.begin(), m_downloads.end(), has_index(block.piece_index)); = std::find_if(m_downloads.begin(), m_downloads.end(), has_index(block.piece_index));
TORRENT_ASSERT(i != m_downloads.end()); TORRENT_ASSERT(i != m_downloads.end());
block_info& info = i->info[block.block_index]; block_info& info = i->info[block.block_index];
TORRENT_ASSERT(info.num_peers == 0);
info.peer = peer; info.peer = peer;
TORRENT_ASSERT(info.state == block_info::state_writing TORRENT_ASSERT(info.state == block_info::state_writing
|| peer == 0); || peer == 0);
@@ -1936,25 +1968,35 @@ namespace libtorrent
TORRENT_ASSERT(i != m_downloads.end()); TORRENT_ASSERT(i != m_downloads.end());
block_info& info = i->info[block.block_index]; block_info& info = i->info[block.block_index];
--info.num_peers;
if (info.num_peers > 0) return;
if (i->info[block.block_index].state == block_info::state_finished TORRENT_ASSERT(info.state == block_info::state_requested);
|| i->info[block.block_index].state == block_info::state_writing) TORRENT_ASSERT(info.num_peers > 0);
--info.num_peers;
TORRENT_ASSERT(block.block_index < blocks_in_piece(block.piece_index));
// if there are other peers
if (info.num_peers > 0)
{ {
if (i->info[block.block_index].state == block_info::state_writing)
{
++i->requested;
--i->writing;
i->info[block.block_index].state = block_info::state_requested;
// since we just cleared the writing state, we know that
// the peer for this block was the one we canceled
info.peer = 0;
}
return; return;
} }
TORRENT_ASSERT(block.block_index < blocks_in_piece(block.piece_index)); // clear the downloader of this block
TORRENT_ASSERT(i->info[block.block_index].state == block_info::state_requested); info.peer = 0;
// clear this block as being downloaded // clear this block as being downloaded
info.state = block_info::state_none; info.state = block_info::state_none;
--i->requested; --i->requested;
// clear the downloader of this block
info.peer = 0;
// if there are no other blocks in this piece // if there are no other blocks in this piece
// that's being downloaded, remove it from the list // that's being downloaded, remove it from the list
if (i->requested + i->finished + i->writing == 0) if (i->requested + i->finished + i->writing == 0)

View File

@@ -1359,8 +1359,11 @@ namespace libtorrent
std::map<int, partial_hash>::iterator i = m_piece_hasher.find(piece_index); std::map<int, partial_hash>::iterator i = m_piece_hasher.find(piece_index);
if (i != m_piece_hasher.end()) if (i != m_piece_hasher.end())
{ {
#ifndef NDEBUG
TORRENT_ASSERT(i->second.offset > 0); TORRENT_ASSERT(i->second.offset > 0);
TORRENT_ASSERT(offset >= i->second.offset); int hash_offset = i->second.offset;
TORRENT_ASSERT(offset >= hash_offset);
#endif
if (offset == i->second.offset) if (offset == i->second.offset)
{ {
i->second.offset += size; i->second.offset += size;

View File

@@ -3069,6 +3069,16 @@ namespace libtorrent
TORRENT_ASSERT(piece_index >= 0); TORRENT_ASSERT(piece_index >= 0);
TORRENT_ASSERT(piece_index < m_torrent_file->num_pieces()); TORRENT_ASSERT(piece_index < m_torrent_file->num_pieces());
TORRENT_ASSERT(piece_index < (int)m_have_pieces.size()); TORRENT_ASSERT(piece_index < (int)m_have_pieces.size());
#ifndef NDEBUG
if (m_picker)
{
int blocks_in_piece = m_picker->blocks_in_piece(piece_index);
for (int i = 0; i < blocks_in_piece; ++i)
{
TORRENT_ASSERT(m_picker->num_peers(piece_block(piece_index, i)) == 0);
}
}
#endif
m_storage->async_hash(piece_index, bind(&torrent::on_piece_verified m_storage->async_hash(piece_index, bind(&torrent::on_piece_verified
, shared_from_this(), _1, _2, f)); , shared_from_this(), _1, _2, f));