generalized peer read/write state

This commit is contained in:
Arvid Norberg 2008-01-13 23:46:43 +00:00
parent 3f4474caba
commit b19bf337bf
7 changed files with 115 additions and 68 deletions

View File

@ -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

View File

@ -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.

View File

@ -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':'.')

View File

@ -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.

View File

@ -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;

View File

@ -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";

View File

@ -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);