introduced a stricter timeout on piece requests and snubbing. exposed some more data about this through the peer_info. Fixes #40
This commit is contained in:
parent
ae9f1e0465
commit
2ac5c13e6f
|
@ -2457,6 +2457,7 @@ It contains the following fields::
|
|||
on_parole = 0x200,
|
||||
seed = 0x400,
|
||||
optimistic_unchoke = 0x800,
|
||||
snubbed = 0x1000,
|
||||
rc4_encrypted = 0x100000,
|
||||
plaintext_encrypted = 0x200000
|
||||
};
|
||||
|
@ -2492,6 +2493,7 @@ It contains the following fields::
|
|||
|
||||
time_duration last_request;
|
||||
time_duration last_active;
|
||||
int request_timeout;
|
||||
|
||||
int send_buffer_size;
|
||||
int used_send_buffer;
|
||||
|
@ -2587,17 +2589,10 @@ any combination of the enums above. The following table describes each flag:
|
|||
| | doesn't within some period of time, it will be choked |
|
||||
| | and another peer will be optimistically unchoked. |
|
||||
+-------------------------+-------------------------------------------------------+
|
||||
| ``writing`` | The peer is currently waiting for a write operation |
|
||||
| | on the socket to complete. |
|
||||
+-------------------------+-------------------------------------------------------+
|
||||
| ``reading`` | The peer is currently waiting for a read operation |
|
||||
| | on the socket to complete. |
|
||||
+-------------------------+-------------------------------------------------------+
|
||||
| ``waiting_write_quota`` | The peer is currently waiting for the bandwidth- |
|
||||
| | manager to hand out more write quota to this peer. |
|
||||
+-------------------------+-------------------------------------------------------+
|
||||
| ``waiting_read_quota`` | The peer is currently waiting for the bandwidth- |
|
||||
| | manager to hand out more read quota to this peer. |
|
||||
| ``snubbed`` | This peer has recently failed to send a block within |
|
||||
| | the request timeout from when the request was sent. |
|
||||
| | We're currently picking one block at a time from this |
|
||||
| | peer. |
|
||||
+-------------------------+-------------------------------------------------------+
|
||||
|
||||
__ extension_protocol.html
|
||||
|
@ -2678,6 +2673,10 @@ receive. -1 means it's unlimited.
|
|||
``last_request`` and ``last_active`` is the time since we last sent a request
|
||||
to this peer and since any transfer occurred with this peer, respectively.
|
||||
|
||||
``request_timeout`` is the number of seconds until the current front piece request
|
||||
will time out. This timeout can be adjusted through ``session_settings::request_timeout``.
|
||||
-1 means that there is not outstanding request.
|
||||
|
||||
``send_buffer_size`` and ``used_send_buffer`` is the number of bytes allocated
|
||||
and used for the peer's send buffer, respectively.
|
||||
|
||||
|
|
|
@ -317,10 +317,10 @@ void print_peer_info(std::ostream& out, std::vector<libtorrent::peer_info> const
|
|||
#ifndef TORRENT_DISABLE_GEO_IP
|
||||
if (print_as) out << "AS ";
|
||||
#endif
|
||||
out << "down (total | peak ) up (total | peak ) sent-req recv flags source ";
|
||||
out << "down (total | peak ) up (total | peak ) sent-req recv flags source ";
|
||||
if (print_fails) out << "fail hshf ";
|
||||
if (print_send_bufs) out << "sndb quota rcvb ";
|
||||
if (print_timers) out << "inactive wait ";
|
||||
if (print_timers) out << "inactive wait timeout ";
|
||||
out << "disk rtt ";
|
||||
if (print_block) out << "block-progress ";
|
||||
#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES
|
||||
|
@ -378,6 +378,7 @@ void print_peer_info(std::ostream& out, std::vector<libtorrent::peer_info> const
|
|||
<< ((i->write_state == peer_info::bw_torrent)?'t':
|
||||
(i->write_state == peer_info::bw_global)?'w':
|
||||
(i->write_state == peer_info::bw_network)?'W':'.')
|
||||
<< ((i->flags & peer_info::snubbed)?'S':'.')
|
||||
#ifndef TORRENT_DISABLE_ENCRYPTION
|
||||
<< ((i->flags & peer_info::rc4_encrypted)?'E':
|
||||
(i->flags & peer_info::plaintext_encrypted)?'e':'.')
|
||||
|
@ -404,7 +405,8 @@ void print_peer_info(std::ostream& out, std::vector<libtorrent::peer_info> const
|
|||
if (print_timers)
|
||||
{
|
||||
out << to_string(total_seconds(i->last_active), 8) << " "
|
||||
<< to_string(total_seconds(i->last_request), 4) << " ";
|
||||
<< to_string(total_seconds(i->last_request), 4) << " "
|
||||
<< to_string(i->request_timeout, 7) << " ";
|
||||
}
|
||||
out << add_suffix(i->pending_disk_bytes) << " "
|
||||
<< to_string(i->rtt, 4) << " ";
|
||||
|
|
|
@ -567,6 +567,12 @@ namespace libtorrent
|
|||
ptime m_last_receive;
|
||||
ptime m_last_sent;
|
||||
|
||||
// the time when the first entry in the
|
||||
// request queue was requested, increased
|
||||
// for each entry that is popped from the
|
||||
// download queue. Used for request timeout
|
||||
ptime m_requested;
|
||||
|
||||
// a timestamp when the remote download rate
|
||||
// was last updated
|
||||
ptime m_remote_dl_update;
|
||||
|
@ -823,6 +829,11 @@ namespace libtorrent
|
|||
// set to true when this peer is only uploading
|
||||
bool m_upload_only:1;
|
||||
|
||||
// set to true when a piece request times out. The
|
||||
// result is that the desired pending queue size
|
||||
// is set to 1
|
||||
bool m_snubbed:1;
|
||||
|
||||
#ifndef NDEBUG
|
||||
public:
|
||||
bool m_in_constructor:1;
|
||||
|
|
|
@ -56,7 +56,8 @@ namespace libtorrent
|
|||
queued = 0x100,
|
||||
on_parole = 0x200,
|
||||
seed = 0x400,
|
||||
optimistic_unchoke = 0x800
|
||||
optimistic_unchoke = 0x800,
|
||||
snubbed = 0x1000
|
||||
#ifndef TORRENT_DISABLE_ENCRYPTION
|
||||
, rc4_encrypted = 0x100000,
|
||||
plaintext_encrypted = 0x200000
|
||||
|
@ -105,6 +106,10 @@ namespace libtorrent
|
|||
// time since last download or upload
|
||||
time_duration last_active;
|
||||
|
||||
// the number of seconds until the current
|
||||
// pending request times out
|
||||
int request_timeout;
|
||||
|
||||
// the size of the send buffer for this peer, in bytes
|
||||
int send_buffer_size;
|
||||
// the number bytes that's actually used of the send buffer
|
||||
|
|
|
@ -88,6 +88,7 @@ namespace libtorrent
|
|||
, stop_tracker_timeout(5)
|
||||
, tracker_maximum_response_length(1024*1024)
|
||||
, piece_timeout(10)
|
||||
, request_timeout(40)
|
||||
, request_queue_time(3.f)
|
||||
, max_allowed_in_request_queue(250)
|
||||
, max_out_request_queue(200)
|
||||
|
@ -168,6 +169,11 @@ namespace libtorrent
|
|||
// it times out if no piece response is returned.
|
||||
int piece_timeout;
|
||||
|
||||
// the number of seconds one block (16kB) is expected
|
||||
// to be received within. If it's not, the block is
|
||||
// requested from a different peer
|
||||
int request_timeout;
|
||||
|
||||
// the length of the request queue given in the number
|
||||
// of seconds it should take for the other end to send
|
||||
// all the pieces. i.e. the actual number of requests
|
||||
|
|
|
@ -81,6 +81,7 @@ namespace libtorrent
|
|||
, m_last_unchoke(min_time())
|
||||
, m_last_receive(time_now())
|
||||
, m_last_sent(time_now())
|
||||
, m_requested(min_time())
|
||||
, m_remote_dl_update(time_now())
|
||||
, m_became_uninterested(time_now())
|
||||
, m_became_uninteresting(time_now())
|
||||
|
@ -126,6 +127,7 @@ namespace libtorrent
|
|||
, m_queued(true)
|
||||
, m_request_large_blocks(false)
|
||||
, m_upload_only(false)
|
||||
, m_snubbed(false)
|
||||
#ifndef NDEBUG
|
||||
, m_in_constructor(true)
|
||||
#endif
|
||||
|
@ -166,7 +168,7 @@ namespace libtorrent
|
|||
// incoming connection
|
||||
peer_connection::peer_connection(
|
||||
session_impl& ses
|
||||
, boost::shared_ptr<socket_type> s
|
||||
, shared_ptr<socket_type> s
|
||||
, tcp::endpoint const& endp
|
||||
, policy::peer* peerinfo)
|
||||
:
|
||||
|
@ -182,6 +184,7 @@ namespace libtorrent
|
|||
, m_last_unchoke(min_time())
|
||||
, m_last_receive(time_now())
|
||||
, m_last_sent(time_now())
|
||||
, m_requested(min_time())
|
||||
, m_remote_dl_update(time_now())
|
||||
, m_became_uninterested(time_now())
|
||||
, m_became_uninteresting(time_now())
|
||||
|
@ -226,6 +229,7 @@ namespace libtorrent
|
|||
, m_queued(false)
|
||||
, m_request_large_blocks(false)
|
||||
, m_upload_only(false)
|
||||
, m_snubbed(false)
|
||||
#ifndef NDEBUG
|
||||
, m_in_constructor(true)
|
||||
#endif
|
||||
|
@ -1433,7 +1437,7 @@ namespace libtorrent
|
|||
{
|
||||
disconnect("out of memory");
|
||||
return;
|
||||
}
|
||||
}
|
||||
disk_buffer_holder holder(m_ses, buffer);
|
||||
std::memcpy(buffer, data, p.length);
|
||||
incoming_piece(p, holder);
|
||||
|
@ -1562,12 +1566,19 @@ namespace libtorrent
|
|||
TORRENT_ASSERT(*b == block_finished);
|
||||
}
|
||||
|
||||
if (total_seconds(time_now() - m_requested) < m_ses.settings().request_timeout)
|
||||
m_snubbed = false;
|
||||
|
||||
// if the block we got is already finished, then ignore it
|
||||
if (picker.is_downloaded(block_finished))
|
||||
{
|
||||
t->received_redundant_data(p.length);
|
||||
|
||||
m_download_queue.erase(b);
|
||||
|
||||
if (!m_download_queue.empty())
|
||||
m_requested = time_now();
|
||||
|
||||
request_a_block(*t, *this);
|
||||
send_block_requests();
|
||||
return;
|
||||
|
@ -1579,6 +1590,9 @@ namespace libtorrent
|
|||
TORRENT_ASSERT(m_channel_state[download_channel] == peer_info::bw_idle);
|
||||
m_download_queue.erase(b);
|
||||
|
||||
if (!m_download_queue.empty())
|
||||
m_requested = time_now();
|
||||
|
||||
// did we request this block from any other peers?
|
||||
bool multi = picker.num_peers(block_finished) > 1;
|
||||
picker.mark_as_writing(block_finished, peer_info_struct());
|
||||
|
@ -2073,6 +2087,8 @@ namespace libtorrent
|
|||
|
||||
if ((int)m_download_queue.size() >= m_desired_queue_size) return;
|
||||
|
||||
bool empty_download_queue = m_download_queue.empty();
|
||||
|
||||
while (!m_request_queue.empty()
|
||||
&& (int)m_download_queue.size() < m_desired_queue_size)
|
||||
{
|
||||
|
@ -2166,6 +2182,13 @@ namespace libtorrent
|
|||
#endif
|
||||
}
|
||||
m_last_piece = time_now();
|
||||
|
||||
if (!m_download_queue.empty()
|
||||
&& empty_download_queue)
|
||||
{
|
||||
// This means we just added a request to this connection
|
||||
m_requested = time_now();
|
||||
}
|
||||
}
|
||||
|
||||
void peer_connection::timed_out()
|
||||
|
@ -2321,6 +2344,8 @@ namespace libtorrent
|
|||
{
|
||||
TORRENT_ASSERT(!associated_torrent().expired());
|
||||
|
||||
ptime now = time_now();
|
||||
|
||||
p.download_rate_peak = m_download_rate_peak;
|
||||
p.upload_rate_peak = m_upload_rate_peak;
|
||||
p.rtt = m_rtt;
|
||||
|
@ -2333,6 +2358,8 @@ namespace libtorrent
|
|||
p.pending_disk_bytes = m_outstanding_writing_bytes;
|
||||
p.send_quota = m_bandwidth_limit[upload_channel].quota_left();
|
||||
p.receive_quota = m_bandwidth_limit[download_channel].quota_left();
|
||||
if (m_download_queue.empty()) p.request_timeout = -1;
|
||||
else p.request_timeout = total_seconds(m_requested - now) + m_ses.settings().request_timeout;
|
||||
#ifndef TORRENT_DISABLE_GEO_IP
|
||||
p.inet_as_name = m_inet_as_name;
|
||||
#endif
|
||||
|
@ -2377,7 +2404,6 @@ namespace libtorrent
|
|||
}
|
||||
|
||||
p.pieces = get_bitfield();
|
||||
ptime now = time_now();
|
||||
p.last_request = now - m_last_request;
|
||||
p.last_active = now - (std::max)(m_last_sent, m_last_receive);
|
||||
|
||||
|
@ -2386,6 +2412,7 @@ namespace libtorrent
|
|||
get_specific_peer_info(p);
|
||||
|
||||
p.flags |= is_seed() ? peer_info::seed : 0;
|
||||
p.flags |= m_snubbed ? peer_info::snubbed : 0;
|
||||
if (peer_info_struct())
|
||||
{
|
||||
policy::peer* pi = peer_info_struct();
|
||||
|
@ -2583,6 +2610,21 @@ namespace libtorrent
|
|||
return;
|
||||
}
|
||||
|
||||
if (!m_download_queue.empty()
|
||||
&& now > m_requested + seconds(m_ses.settings().request_timeout))
|
||||
{
|
||||
m_snubbed = true;
|
||||
m_desired_queue_size = 1;
|
||||
piece_picker& picker = t->picker();
|
||||
// the front request timed out!
|
||||
picker.abort_download(m_download_queue[0]);
|
||||
m_download_queue.pop_front();
|
||||
if (!m_download_queue.empty())
|
||||
m_requested = time_now();
|
||||
request_a_block(*t, *this);
|
||||
send_block_requests();
|
||||
}
|
||||
|
||||
// if we haven't sent something in too long, send a keep-alive
|
||||
keep_alive();
|
||||
|
||||
|
@ -2623,12 +2665,19 @@ namespace libtorrent
|
|||
? t->torrent_file().piece_length() : t->block_size();
|
||||
TORRENT_ASSERT(block_size > 0);
|
||||
|
||||
m_desired_queue_size = static_cast<int>(queue_time
|
||||
* statistics().download_rate() / block_size);
|
||||
if (m_desired_queue_size > m_max_out_request_queue)
|
||||
m_desired_queue_size = m_max_out_request_queue;
|
||||
if (m_desired_queue_size < min_request_queue)
|
||||
m_desired_queue_size = min_request_queue;
|
||||
if (m_snubbed)
|
||||
{
|
||||
m_desired_queue_size = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_desired_queue_size = static_cast<int>(queue_time
|
||||
* statistics().download_rate() / block_size);
|
||||
if (m_desired_queue_size > m_max_out_request_queue)
|
||||
m_desired_queue_size = m_max_out_request_queue;
|
||||
if (m_desired_queue_size < min_request_queue)
|
||||
m_desired_queue_size = min_request_queue;
|
||||
}
|
||||
|
||||
if (!m_download_queue.empty()
|
||||
&& now - m_last_piece > seconds(m_ses.settings().piece_timeout))
|
||||
|
@ -2643,6 +2692,9 @@ namespace libtorrent
|
|||
<< " " << total_seconds(now - m_last_piece) << "] ***\n";
|
||||
#endif
|
||||
|
||||
m_snubbed = true;
|
||||
m_desired_queue_size = 1;
|
||||
|
||||
if (t->is_seed())
|
||||
{
|
||||
m_download_queue.clear();
|
||||
|
|
Loading…
Reference in New Issue