fixed synchronization issue between download queue and piece picker
This commit is contained in:
parent
1a0d33a592
commit
23ba8c8a72
|
@ -28,6 +28,7 @@
|
||||||
incoming connection
|
incoming connection
|
||||||
* added more detailed instrumentation of the disk I/O thread
|
* added more detailed instrumentation of the disk I/O thread
|
||||||
|
|
||||||
|
* fixed synchronization issue between download queue and piece picker
|
||||||
* fixed bug in udp tracker scrape response parsing
|
* fixed bug in udp tracker scrape response parsing
|
||||||
* fixed bug in the disk thread that could get triggered under heavy load
|
* fixed bug in the disk thread that could get triggered under heavy load
|
||||||
* fixed bug in add_piece() that would trigger asserts
|
* fixed bug in add_piece() that would trigger asserts
|
||||||
|
|
|
@ -98,12 +98,14 @@ namespace libtorrent
|
||||||
struct pending_block
|
struct pending_block
|
||||||
{
|
{
|
||||||
pending_block(piece_block const& b)
|
pending_block(piece_block const& b)
|
||||||
: skipped(0), not_wanted(false), timed_out(false)
|
: block(b), skipped(0), not_wanted(false)
|
||||||
, busy(false), block(b) {}
|
, timed_out(false), busy(false) {}
|
||||||
|
|
||||||
|
piece_block block;
|
||||||
|
|
||||||
// the number of times the request
|
// the number of times the request
|
||||||
// has been skipped by out of order blocks
|
// has been skipped by out of order blocks
|
||||||
boost::uint16_t skipped;
|
boost::uint16_t skipped:13;
|
||||||
|
|
||||||
// if any of these are set to true, this block
|
// if any of these are set to true, this block
|
||||||
// is not allocated
|
// is not allocated
|
||||||
|
@ -120,8 +122,6 @@ namespace libtorrent
|
||||||
// busy request at a time in each peer's queue
|
// busy request at a time in each peer's queue
|
||||||
bool busy:1;
|
bool busy:1;
|
||||||
|
|
||||||
piece_block block;
|
|
||||||
|
|
||||||
bool operator==(pending_block const& b)
|
bool operator==(pending_block const& b)
|
||||||
{
|
{
|
||||||
return b.skipped == skipped && b.block == block
|
return b.skipped == skipped && b.block == block
|
||||||
|
|
|
@ -63,13 +63,18 @@ namespace libtorrent
|
||||||
|
|
||||||
struct TORRENT_EXPORT piece_block
|
struct TORRENT_EXPORT piece_block
|
||||||
{
|
{
|
||||||
|
const static piece_block invalid;
|
||||||
|
|
||||||
piece_block() {}
|
piece_block() {}
|
||||||
piece_block(int p_index, int b_index)
|
piece_block(boost::uint32_t p_index, boost::uint16_t b_index)
|
||||||
: piece_index(p_index)
|
: piece_index(p_index)
|
||||||
, block_index(b_index)
|
, block_index(b_index)
|
||||||
{}
|
{
|
||||||
int piece_index;
|
TORRENT_ASSERT(p_index < (1 << 18));
|
||||||
int block_index;
|
TORRENT_ASSERT(b_index < (1 << 14));
|
||||||
|
}
|
||||||
|
boost::uint32_t piece_index:18;
|
||||||
|
boost::uint32_t block_index:14;
|
||||||
|
|
||||||
bool operator<(piece_block const& b) const
|
bool operator<(piece_block const& b) const
|
||||||
{
|
{
|
||||||
|
|
|
@ -99,7 +99,7 @@ namespace libtorrent
|
||||||
, m_socket(s)
|
, m_socket(s)
|
||||||
, m_remote(endp)
|
, m_remote(endp)
|
||||||
, m_torrent(tor)
|
, m_torrent(tor)
|
||||||
, m_receiving_block(-1, -1)
|
, m_receiving_block(piece_block::invalid)
|
||||||
, m_last_seen_complete(0)
|
, m_last_seen_complete(0)
|
||||||
, m_timeout_extend(0)
|
, m_timeout_extend(0)
|
||||||
, m_outstanding_bytes(0)
|
, m_outstanding_bytes(0)
|
||||||
|
@ -234,7 +234,7 @@ namespace libtorrent
|
||||||
, m_disk_recv_buffer(ses, 0)
|
, m_disk_recv_buffer(ses, 0)
|
||||||
, m_socket(s)
|
, m_socket(s)
|
||||||
, m_remote(endp)
|
, m_remote(endp)
|
||||||
, m_receiving_block(-1, -1)
|
, m_receiving_block(piece_block::invalid)
|
||||||
, m_last_seen_complete(0)
|
, m_last_seen_complete(0)
|
||||||
, m_timeout_extend(0)
|
, m_timeout_extend(0)
|
||||||
, m_outstanding_bytes(0)
|
, m_outstanding_bytes(0)
|
||||||
|
@ -2056,6 +2056,7 @@ namespace libtorrent
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_download_queue.insert(m_download_queue.begin(), b);
|
||||||
if (!in_req_queue)
|
if (!in_req_queue)
|
||||||
{
|
{
|
||||||
if (t->alerts().should_post<unwanted_block_alert>())
|
if (t->alerts().should_post<unwanted_block_alert>())
|
||||||
|
@ -2067,9 +2068,9 @@ namespace libtorrent
|
||||||
(*m_logger) << " *** The block we just got was not in the "
|
(*m_logger) << " *** The block we just got was not in the "
|
||||||
"request queue ***\n";
|
"request queue ***\n";
|
||||||
#endif
|
#endif
|
||||||
|
TORRENT_ASSERT(m_download_queue.front().block == b);
|
||||||
|
m_download_queue.front().not_wanted = true;
|
||||||
}
|
}
|
||||||
m_download_queue.insert(m_download_queue.begin(), b);
|
|
||||||
if (!in_req_queue) m_download_queue.front().not_wanted = true;
|
|
||||||
m_outstanding_bytes += r.length;
|
m_outstanding_bytes += r.length;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3038,6 +3039,23 @@ namespace libtorrent
|
||||||
{
|
{
|
||||||
pending_block block = m_request_queue.front();
|
pending_block block = m_request_queue.front();
|
||||||
|
|
||||||
|
m_request_queue.erase(m_request_queue.begin());
|
||||||
|
if (m_queued_time_critical) --m_queued_time_critical;
|
||||||
|
|
||||||
|
// if we're a seed, we don't have a piece picker
|
||||||
|
// so we don't have to worry about invariants getting
|
||||||
|
// out of sync with it
|
||||||
|
if (t->is_seed()) continue;
|
||||||
|
|
||||||
|
// this can happen if a block times out, is re-requested and
|
||||||
|
// then arrives "unexpectedly"
|
||||||
|
if (t->picker().is_finished(block.block)
|
||||||
|
|| t->picker().is_downloaded(block.block))
|
||||||
|
{
|
||||||
|
t->picker().abort_download(block.block);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
int block_offset = block.block.block_index * t->block_size();
|
int block_offset = block.block.block_index * t->block_size();
|
||||||
int block_size = (std::min)(t->torrent_file().piece_size(
|
int block_size = (std::min)(t->torrent_file().piece_size(
|
||||||
block.block.piece_index) - block_offset, t->block_size());
|
block.block.piece_index) - block_offset, t->block_size());
|
||||||
|
@ -3049,21 +3067,13 @@ namespace libtorrent
|
||||||
r.start = block_offset;
|
r.start = block_offset;
|
||||||
r.length = block_size;
|
r.length = block_size;
|
||||||
|
|
||||||
m_request_queue.erase(m_request_queue.begin());
|
|
||||||
if (m_queued_time_critical) --m_queued_time_critical;
|
|
||||||
if (t->is_seed()) continue;
|
|
||||||
// this can happen if a block times out, is re-requested and
|
|
||||||
// then arrives "unexpectedly"
|
|
||||||
if (t->picker().is_finished(block.block)
|
|
||||||
|| t->picker().is_downloaded(block.block))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
TORRENT_ASSERT(verify_piece(t->to_req(block.block)));
|
TORRENT_ASSERT(verify_piece(t->to_req(block.block)));
|
||||||
m_download_queue.push_back(block);
|
m_download_queue.push_back(block);
|
||||||
m_outstanding_bytes += block_size;
|
m_outstanding_bytes += block_size;
|
||||||
#if !defined TORRENT_DISABLE_INVARIANT_CHECKS && defined TORRENT_DEBUG
|
#if !defined TORRENT_DISABLE_INVARIANT_CHECKS && defined TORRENT_DEBUG
|
||||||
check_invariant();
|
check_invariant();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
#ifdef TORRENT_VERBOSE_LOGGING
|
#ifdef TORRENT_VERBOSE_LOGGING
|
||||||
(*m_logger) << time_now_string()
|
(*m_logger) << time_now_string()
|
||||||
|
@ -3913,7 +3923,7 @@ namespace libtorrent
|
||||||
request_a_block(*t, *this);
|
request_a_block(*t, *this);
|
||||||
m_desired_queue_size = 1;
|
m_desired_queue_size = 1;
|
||||||
|
|
||||||
piece_block r(-1, -1);
|
piece_block r(piece_block::invalid);
|
||||||
// time out the last request in the queue
|
// time out the last request in the queue
|
||||||
if (prev_request_queue > 0)
|
if (prev_request_queue > 0)
|
||||||
{
|
{
|
||||||
|
@ -4955,7 +4965,7 @@ namespace libtorrent
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TORRENT_DEBUG
|
#ifdef TORRENT_DEBUG
|
||||||
struct peer_count_t { int num_peers; int num_peers_with_timeouts; };
|
struct peer_count_t { int num_peers; int num_peers_with_timeouts; int num_peers_with_nowant; };
|
||||||
|
|
||||||
void peer_connection::check_invariant() const
|
void peer_connection::check_invariant() const
|
||||||
{
|
{
|
||||||
|
@ -5086,12 +5096,14 @@ namespace libtorrent
|
||||||
{
|
{
|
||||||
++num_requests[i->block].num_peers;
|
++num_requests[i->block].num_peers;
|
||||||
++num_requests[i->block].num_peers_with_timeouts;
|
++num_requests[i->block].num_peers_with_timeouts;
|
||||||
|
++num_requests[i->block].num_peers_with_nowant;
|
||||||
}
|
}
|
||||||
for (std::vector<pending_block>::const_iterator i = p.download_queue().begin()
|
for (std::vector<pending_block>::const_iterator i = p.download_queue().begin()
|
||||||
, end(p.download_queue().end()); i != end; ++i)
|
, end(p.download_queue().end()); i != end; ++i)
|
||||||
{
|
{
|
||||||
if (!i->not_wanted && !i->timed_out) ++num_requests[i->block].num_peers;
|
if (!i->not_wanted && !i->timed_out) ++num_requests[i->block].num_peers;
|
||||||
++num_requests[i->block].num_peers_with_timeouts;
|
if (i->timed_out) ++num_requests[i->block].num_peers_with_timeouts;
|
||||||
|
if (i->not_wanted) ++num_requests[i->block].num_peers_with_nowant;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (std::map<piece_block, peer_count_t>::iterator i = num_requests.begin()
|
for (std::map<piece_block, peer_count_t>::iterator i = num_requests.begin()
|
||||||
|
@ -5100,6 +5112,7 @@ namespace libtorrent
|
||||||
piece_block b = i->first;
|
piece_block b = i->first;
|
||||||
int count = i->second.num_peers;
|
int count = i->second.num_peers;
|
||||||
int count_with_timeouts = i->second.num_peers_with_timeouts;
|
int count_with_timeouts = i->second.num_peers_with_timeouts;
|
||||||
|
int count_with_nowant = i->second.num_peers_with_nowant;
|
||||||
int picker_count = t->picker().num_peers(b);
|
int picker_count = t->picker().num_peers(b);
|
||||||
if (!t->picker().is_downloaded(b))
|
if (!t->picker().is_downloaded(b))
|
||||||
TORRENT_ASSERT(picker_count == count);
|
TORRENT_ASSERT(picker_count == count);
|
||||||
|
|
|
@ -55,6 +55,8 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
namespace libtorrent
|
namespace libtorrent
|
||||||
{
|
{
|
||||||
|
|
||||||
|
const piece_block piece_block::invalid(0x3FFFF, 0x3FFF);
|
||||||
|
|
||||||
piece_picker::piece_picker()
|
piece_picker::piece_picker()
|
||||||
: m_seeds(0)
|
: m_seeds(0)
|
||||||
, m_priority_boundries(1, int(m_pieces.size()))
|
, m_priority_boundries(1, int(m_pieces.size()))
|
||||||
|
|
Loading…
Reference in New Issue