forked from premiere/premiere-libtorrent
generalized peer read/write state
This commit is contained in:
parent
3f4474caba
commit
b19bf337bf
|
@ -2218,10 +2218,6 @@ struct peer_info
|
|||
on_parole = 0x200,
|
||||
seed = 0x400,
|
||||
optimistic_unchoke = 0x800,
|
||||
writing = 0x1000,
|
||||
reading = 0x2000,
|
||||
waiting_write_quota = 0x4000,
|
||||
waiting_read_quota = 0x8000,
|
||||
rc4_encrypted = 0x100000,
|
||||
plaintext_encrypted = 0x200000
|
||||
};
|
||||
|
@ -2238,6 +2234,11 @@ struct peer_info
|
|||
|
||||
int source;
|
||||
|
||||
enum bw_state { bw_idle, bw_torrent, bw_global, bw_network };
|
||||
|
||||
char read_state;
|
||||
char write_state;
|
||||
|
||||
asio::ip::tcp::endpoint ip;
|
||||
float up_speed;
|
||||
float down_speed;
|
||||
|
@ -2396,6 +2397,36 @@ discovery (The peer is on the local network).</td>
|
|||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p><tt class="docutils literal"><span class="pre">read_state</span></tt> and <tt class="docutils literal"><span class="pre">write_state</span></tt> indicates what state this peer is in with regards
|
||||
to sending and receiving data. The states are declared in the <tt class="docutils literal"><span class="pre">bw_state</span></tt> enum and
|
||||
defines as follows:</p>
|
||||
<table border="1" class="docutils">
|
||||
<colgroup>
|
||||
<col width="30%" />
|
||||
<col width="70%" />
|
||||
</colgroup>
|
||||
<tbody valign="top">
|
||||
<tr><td><tt class="docutils literal"><span class="pre">bw_idle</span></tt></td>
|
||||
<td>The peer is not waiting for any external events to
|
||||
send or receive data.</td>
|
||||
</tr>
|
||||
<tr><td><tt class="docutils literal"><span class="pre">bw_torrent</span></tt></td>
|
||||
<td>The peer is waiting for the torrent to receive
|
||||
bandwidth quota in order to forward the bandwidth
|
||||
request to the global manager.</td>
|
||||
</tr>
|
||||
<tr><td><tt class="docutils literal"><span class="pre">bw_global</span></tt></td>
|
||||
<td>The peer is waiting for the global bandwidth manager
|
||||
to receive more quota in order to handle the request.</td>
|
||||
</tr>
|
||||
<tr><td><tt class="docutils literal"><span class="pre">bw_network</span></tt></td>
|
||||
<td>The peer has quota and is currently waiting for a
|
||||
network read or write operation to complete. This is
|
||||
the state all peers are in if there are no bandwidth
|
||||
limits.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>The <tt class="docutils literal"><span class="pre">ip</span></tt> field is the IP-address to this peer. The type is an asio endpoint. For
|
||||
more info, see the <a class="reference" href="http://asio.sf.net">asio</a> documentation.</p>
|
||||
<p><tt class="docutils literal"><span class="pre">up_speed</span></tt> and <tt class="docutils literal"><span class="pre">down_speed</span></tt> contains the current upload and download speed
|
||||
|
|
|
@ -2208,10 +2208,6 @@ It contains the following fields::
|
|||
on_parole = 0x200,
|
||||
seed = 0x400,
|
||||
optimistic_unchoke = 0x800,
|
||||
writing = 0x1000,
|
||||
reading = 0x2000,
|
||||
waiting_write_quota = 0x4000,
|
||||
waiting_read_quota = 0x8000,
|
||||
rc4_encrypted = 0x100000,
|
||||
plaintext_encrypted = 0x200000
|
||||
};
|
||||
|
@ -2228,6 +2224,11 @@ It contains the following fields::
|
|||
|
||||
int source;
|
||||
|
||||
enum bw_state { bw_idle, bw_torrent, bw_global, bw_network };
|
||||
|
||||
char read_state;
|
||||
char write_state;
|
||||
|
||||
asio::ip::tcp::endpoint ip;
|
||||
float up_speed;
|
||||
float down_speed;
|
||||
|
@ -2357,6 +2358,31 @@ was received. The flags are:
|
|||
| ``resume_data`` | The peer was added from the fast resume data. |
|
||||
+------------------------+--------------------------------------------------------+
|
||||
|
||||
``read_state`` and ``write_state`` indicates what state this peer is in with regards
|
||||
to sending and receiving data. The states are declared in the ``bw_state`` enum and
|
||||
defines as follows:
|
||||
|
||||
+------------------------+--------------------------------------------------------+
|
||||
| ``bw_idle`` | The peer is not waiting for any external events to |
|
||||
| | send or receive data. |
|
||||
| | |
|
||||
+------------------------+--------------------------------------------------------+
|
||||
| ``bw_torrent`` | The peer is waiting for the torrent to receive |
|
||||
| | bandwidth quota in order to forward the bandwidth |
|
||||
| | request to the global manager. |
|
||||
| | |
|
||||
+------------------------+--------------------------------------------------------+
|
||||
| ``bw_global`` | The peer is waiting for the global bandwidth manager |
|
||||
| | to receive more quota in order to handle the request. |
|
||||
| | |
|
||||
+------------------------+--------------------------------------------------------+
|
||||
| ``bw_network`` | The peer has quota and is currently waiting for a |
|
||||
| | network read or write operation to complete. This is |
|
||||
| | the state all peers are in if there are no bandwidth |
|
||||
| | limits. |
|
||||
| | |
|
||||
+------------------------+--------------------------------------------------------+
|
||||
|
||||
The ``ip`` field is the IP-address to this peer. The type is an asio endpoint. For
|
||||
more info, see the asio_ documentation.
|
||||
|
||||
|
|
|
@ -340,8 +340,12 @@ void print_peer_info(std::ostream& out, std::vector<libtorrent::peer_info> const
|
|||
<< ((i->flags & peer_info::seed)?'s':'.')
|
||||
<< ((i->flags & peer_info::on_parole)?'p':'.')
|
||||
<< ((i->flags & peer_info::optimistic_unchoke)?'O':'.')
|
||||
<< ((i->flags & peer_info::reading)?'R':(i->flags & peer_info::waiting_read_quota)?'r':'.')
|
||||
<< ((i->flags & peer_info::writing)?'W':(i->flags & peer_info::waiting_write_quota)?'w':'.')
|
||||
<< ((i->read_state == peer_info::bw_torrent)?'t':
|
||||
(i->read_state == peer_info::bw_global)?'r':
|
||||
(i->read_state == peer_info::bw_network)?'R':'.')
|
||||
<< ((i->write_state == peer_info::bw_torrent)?'t':
|
||||
(i->write_state == peer_info::bw_global)?'w':
|
||||
(i->write_state == peer_info::bw_network)?'W':'.')
|
||||
#ifndef TORRENT_DISABLE_ENCRYPTION
|
||||
<< ((i->flags & peer_info::rc4_encrypted)?'E':
|
||||
(i->flags & peer_info::plaintext_encrypted)?'e':'.')
|
||||
|
|
|
@ -408,6 +408,10 @@ namespace libtorrent
|
|||
bool piece_failed;
|
||||
#endif
|
||||
|
||||
// upload and download channel state
|
||||
// enum from peer_info::bw_state
|
||||
char m_channel_state[2];
|
||||
|
||||
protected:
|
||||
|
||||
virtual void get_specific_peer_info(peer_info& p) const = 0;
|
||||
|
@ -664,14 +668,6 @@ namespace libtorrent
|
|||
// connections.
|
||||
bool m_queued;
|
||||
|
||||
// these are true when there's a asynchronous write
|
||||
// or read operation in progress. Or an asyncronous bandwidth
|
||||
// request is in progress.
|
||||
bool m_writing;
|
||||
bool m_reading;
|
||||
bool m_requested_write_quota;
|
||||
bool m_requested_read_quota;
|
||||
|
||||
// if set to non-zero, this peer will always prefer
|
||||
// to request entire n pieces, rather than blocks.
|
||||
// where n is the value of this variable.
|
||||
|
|
|
@ -57,11 +57,7 @@ namespace libtorrent
|
|||
queued = 0x100,
|
||||
on_parole = 0x200,
|
||||
seed = 0x400,
|
||||
optimistic_unchoke = 0x800,
|
||||
writing = 0x1000,
|
||||
reading = 0x2000,
|
||||
waiting_write_quota = 0x4000,
|
||||
waiting_read_quota = 0x8000
|
||||
optimistic_unchoke = 0x800
|
||||
#ifndef TORRENT_DISABLE_ENCRYPTION
|
||||
, rc4_encrypted = 0x100000,
|
||||
plaintext_encrypted = 0x200000
|
||||
|
@ -82,6 +78,16 @@ namespace libtorrent
|
|||
|
||||
int source;
|
||||
|
||||
// bw_idle: the channel is not used
|
||||
// bw_torrent: the channel is waiting for torrent quota
|
||||
// bw_global: the channel is waiting for global quota
|
||||
// bw_network: the channel is waiting for an async write
|
||||
// for read operation to complete
|
||||
enum bw_state { bw_idle, bw_torrent, bw_global, bw_network };
|
||||
|
||||
char read_state;
|
||||
char write_state;
|
||||
|
||||
tcp::endpoint ip;
|
||||
float up_speed;
|
||||
float down_speed;
|
||||
|
|
|
@ -105,10 +105,6 @@ namespace libtorrent
|
|||
, m_became_uninteresting(time_now())
|
||||
, m_connecting(true)
|
||||
, m_queued(true)
|
||||
, m_writing(false)
|
||||
, m_reading(false)
|
||||
, m_requested_write_quota(false)
|
||||
, m_requested_read_quota(false)
|
||||
, m_prefer_whole_pieces(false)
|
||||
, m_request_large_blocks(false)
|
||||
, m_non_prioritized(false)
|
||||
|
@ -126,6 +122,9 @@ namespace libtorrent
|
|||
, m_in_constructor(true)
|
||||
#endif
|
||||
{
|
||||
m_channel_state[upload_channel] = peer_info::bw_idle;
|
||||
m_channel_state[download_channel] = peer_info::bw_idle;
|
||||
|
||||
TORRENT_ASSERT(peerinfo == 0 || peerinfo->banned == false);
|
||||
#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES
|
||||
std::fill(m_country, m_country + 2, 0);
|
||||
|
@ -188,10 +187,6 @@ namespace libtorrent
|
|||
, m_became_uninteresting(time_now())
|
||||
, m_connecting(false)
|
||||
, m_queued(false)
|
||||
, m_writing(false)
|
||||
, m_reading(false)
|
||||
, m_requested_write_quota(false)
|
||||
, m_requested_read_quota(false)
|
||||
, m_prefer_whole_pieces(false)
|
||||
, m_request_large_blocks(false)
|
||||
, m_non_prioritized(false)
|
||||
|
@ -209,6 +204,8 @@ namespace libtorrent
|
|||
, m_in_constructor(true)
|
||||
#endif
|
||||
{
|
||||
m_channel_state[upload_channel] = peer_info::bw_idle;
|
||||
m_channel_state[download_channel] = peer_info::bw_idle;
|
||||
tcp::socket::non_blocking_io ioc(true);
|
||||
asio::error_code ec;
|
||||
m_socket->io_control(ioc, ec);
|
||||
|
@ -1449,7 +1446,7 @@ namespace libtorrent
|
|||
fs.async_write(p, data, bind(&peer_connection::on_disk_write_complete
|
||||
, self(), _1, _2, p, t));
|
||||
m_outstanding_writing_bytes += p.length;
|
||||
TORRENT_ASSERT(!m_reading);
|
||||
TORRENT_ASSERT(!m_channel_state[download_channel] != peer_info::bw_network);
|
||||
picker.mark_as_writing(block_finished, peer_info_struct());
|
||||
#ifndef NDEBUG
|
||||
t->check_invariant();
|
||||
|
@ -2226,10 +2223,8 @@ namespace libtorrent
|
|||
|
||||
p.send_buffer_size = m_send_buffer.capacity();
|
||||
p.used_send_buffer = m_send_buffer.size();
|
||||
p.flags |= m_reading ? peer_info::reading : 0;
|
||||
p.flags |= m_writing ? peer_info::writing : 0;
|
||||
p.flags |= m_requested_write_quota ? peer_info::waiting_write_quota : 0;
|
||||
p.flags |= m_requested_read_quota ? peer_info::waiting_read_quota : 0;
|
||||
p.write_state = m_channel_state[upload_channel];
|
||||
p.read_state = m_channel_state[download_channel];
|
||||
}
|
||||
|
||||
void peer_connection::cut_receive_buffer(int size, int packet_size)
|
||||
|
@ -2499,16 +2494,14 @@ namespace libtorrent
|
|||
#endif
|
||||
|
||||
m_bandwidth_limit[channel].assign(amount);
|
||||
TORRENT_ASSERT(m_channel_state[channel] == peer_info::bw_global);
|
||||
m_channel_state[channel] = peer_info::bw_idle;
|
||||
if (channel == upload_channel)
|
||||
{
|
||||
TORRENT_ASSERT(m_requested_write_quota);
|
||||
m_requested_write_quota = false;
|
||||
setup_send();
|
||||
}
|
||||
else if (channel == download_channel)
|
||||
{
|
||||
TORRENT_ASSERT(m_requested_read_quota);
|
||||
m_requested_read_quota = false;
|
||||
setup_receive();
|
||||
}
|
||||
}
|
||||
|
@ -2534,7 +2527,7 @@ namespace libtorrent
|
|||
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_writing || m_requested_write_quota) return;
|
||||
if (m_channel_state[upload_channel] != peer_info::bw_idle) return;
|
||||
|
||||
shared_ptr<torrent> t = m_torrent.lock();
|
||||
|
||||
|
@ -2554,10 +2547,8 @@ namespace libtorrent
|
|||
(*m_logger) << "req bandwidth [ " << upload_channel << " ]\n";
|
||||
#endif
|
||||
|
||||
TORRENT_ASSERT(!m_writing);
|
||||
// peers that we are not interested in are non-prioritized
|
||||
TORRENT_ASSERT(!m_requested_write_quota);
|
||||
m_requested_write_quota = true;
|
||||
m_channel_state[upload_channel] = peer_info::bw_torrent;
|
||||
t->request_bandwidth(upload_channel, self()
|
||||
, !(is_interesting() && !has_peer_choked())
|
||||
, m_send_buffer.size());
|
||||
|
@ -2567,8 +2558,6 @@ namespace libtorrent
|
|||
|
||||
if (!can_write()) return;
|
||||
|
||||
TORRENT_ASSERT(!m_writing);
|
||||
|
||||
// send the actual buffer
|
||||
if (!m_send_buffer.empty())
|
||||
{
|
||||
|
@ -2585,7 +2574,7 @@ namespace libtorrent
|
|||
std::list<asio::const_buffer> const& vec = m_send_buffer.build_iovec(amount_to_send);
|
||||
m_socket->async_write_some(vec, bind(&peer_connection::on_send_data, self(), _1, _2));
|
||||
|
||||
m_writing = true;
|
||||
m_channel_state[upload_channel] = peer_info::bw_network;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2595,10 +2584,7 @@ namespace libtorrent
|
|||
|
||||
INVARIANT_CHECK;
|
||||
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
(*m_logger) << "setup_receive: reading = " << m_reading << "\n";
|
||||
#endif
|
||||
if (m_reading || m_requested_read_quota) return;
|
||||
if (m_channel_state[download_channel] != peer_info::bw_idle) return;
|
||||
|
||||
shared_ptr<torrent> t = m_torrent.lock();
|
||||
|
||||
|
@ -2612,8 +2598,8 @@ namespace libtorrent
|
|||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
(*m_logger) << "req bandwidth [ " << download_channel << " ]\n";
|
||||
#endif
|
||||
TORRENT_ASSERT(!m_requested_read_quota);
|
||||
m_requested_read_quota = true;
|
||||
TORRENT_ASSERT(m_channel_state[download_channel] == peer_info::bw_idle);
|
||||
m_channel_state[download_channel] = peer_info::bw_torrent;
|
||||
t->request_bandwidth(download_channel, self(), m_non_prioritized
|
||||
, m_download_queue.size() * 16 * 1024 + 30);
|
||||
}
|
||||
|
@ -2632,14 +2618,13 @@ namespace libtorrent
|
|||
|
||||
TORRENT_ASSERT(m_recv_pos >= 0);
|
||||
TORRENT_ASSERT(m_packet_size > 0);
|
||||
|
||||
TORRENT_ASSERT(can_read());
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
(*m_logger) << "async_read " << max_receive << " bytes\n";
|
||||
#endif
|
||||
m_socket->async_read_some(asio::buffer(&m_recv_buffer[m_recv_pos]
|
||||
, max_receive), bind(&peer_connection::on_receive_data, self(), _1, _2));
|
||||
m_reading = true;
|
||||
m_channel_state[download_channel] = peer_info::bw_network;
|
||||
}
|
||||
|
||||
void peer_connection::reset_recv_buffer(int packet_size)
|
||||
|
@ -2738,8 +2723,8 @@ namespace libtorrent
|
|||
|
||||
INVARIANT_CHECK;
|
||||
|
||||
TORRENT_ASSERT(m_reading);
|
||||
m_reading = false;
|
||||
TORRENT_ASSERT(m_channel_state[download_channel] == peer_info::bw_network);
|
||||
m_channel_state[download_channel] = peer_info::bw_idle;
|
||||
|
||||
if (error)
|
||||
{
|
||||
|
@ -2857,10 +2842,6 @@ namespace libtorrent
|
|||
&& m_outstanding_writing_bytes <
|
||||
m_ses.settings().max_outstanding_disk_bytes_per_connection;
|
||||
|
||||
#if defined(TORRENT_VERBOSE_LOGGING)
|
||||
(*m_logger) << "*** can_read() " << ret << " reading: " << m_reading << "\n";
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -2972,11 +2953,11 @@ namespace libtorrent
|
|||
|
||||
INVARIANT_CHECK;
|
||||
|
||||
TORRENT_ASSERT(m_writing);
|
||||
TORRENT_ASSERT(m_channel_state[upload_channel] == peer_info::bw_network);
|
||||
|
||||
m_send_buffer.pop_front(bytes_transferred);
|
||||
|
||||
m_writing = false;
|
||||
m_channel_state[upload_channel] = peer_info::bw_idle;
|
||||
|
||||
if (!m_ignore_bandwidth_limits)
|
||||
m_bandwidth_limit[upload_channel].use_quota(bytes_transferred);
|
||||
|
@ -3030,11 +3011,11 @@ namespace libtorrent
|
|||
|| m_bandwidth_limit[i].throttle() == bandwidth_limit::inf);
|
||||
}
|
||||
|
||||
TORRENT_ASSERT(int(m_reading) + int(m_requested_read_quota) <= 1);
|
||||
TORRENT_ASSERT(int(m_writing) + int(m_requested_write_quota) <= 1);
|
||||
if (m_requested_read_quota)
|
||||
if (m_channel_state[download_channel] == peer_info::bw_torrent
|
||||
|| m_channel_state[download_channel] == peer_info::bw_global)
|
||||
TORRENT_ASSERT(m_bandwidth_limit[download_channel].quota_left() == 0);
|
||||
if (m_requested_write_quota)
|
||||
if (m_channel_state[upload_channel] == peer_info::bw_torrent
|
||||
|| m_channel_state[upload_channel] == peer_info::bw_global)
|
||||
TORRENT_ASSERT(m_bandwidth_limit[upload_channel].quota_left() == 0);
|
||||
|
||||
std::set<piece_block> unique;
|
||||
|
@ -3259,7 +3240,7 @@ namespace libtorrent
|
|||
|
||||
// if the last send has not completed yet, do not send a keep
|
||||
// alive
|
||||
if (m_writing) return;
|
||||
if (m_channel_state[upload_channel] != peer_info::bw_idle) return;
|
||||
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
(*m_logger) << time_now_string() << " ==> KEEPALIVE\n";
|
||||
|
|
|
@ -2278,6 +2278,7 @@ namespace libtorrent
|
|||
TORRENT_ASSERT(max_block_size > 0);
|
||||
TORRENT_ASSERT(m_bandwidth_limit[channel].throttle() > 0);
|
||||
TORRENT_ASSERT(p->max_assignable_bandwidth(channel) > 0);
|
||||
TORRENT_ASSERT(p->m_channel_state[channel] == peer_info::bw_torrent);
|
||||
int block_size = (std::min)(m_bandwidth_limit[channel].throttle() / 10
|
||||
, max_block_size);
|
||||
if (block_size <= 0) block_size = 1;
|
||||
|
@ -2330,6 +2331,8 @@ namespace libtorrent
|
|||
, int block_size
|
||||
, bool non_prioritized)
|
||||
{
|
||||
TORRENT_ASSERT(p->m_channel_state[channel] == peer_info::bw_torrent);
|
||||
p->m_channel_state[channel] = peer_info::bw_global;
|
||||
m_ses.m_bandwidth_manager[channel]->request_bandwidth(p
|
||||
, block_size, non_prioritized);
|
||||
m_bandwidth_limit[channel].assign(block_size);
|
||||
|
|
Loading…
Reference in New Issue