diff --git a/docs/manual.html b/docs/manual.html
index 35aa1b6c3..523cde0c1 100644
--- a/docs/manual.html
+++ b/docs/manual.html
@@ -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).
+
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.
up_speed and down_speed contains the current upload and download speed
diff --git a/docs/manual.rst b/docs/manual.rst
index 3acbb91b2..d1980e79a 100644
--- a/docs/manual.rst
+++ b/docs/manual.rst
@@ -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.
diff --git a/examples/client_test.cpp b/examples/client_test.cpp
index 5c146b9d4..d64641bb1 100644
--- a/examples/client_test.cpp
+++ b/examples/client_test.cpp
@@ -340,8 +340,12 @@ void print_peer_info(std::ostream& out, std::vector 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':'.')
diff --git a/include/libtorrent/peer_connection.hpp b/include/libtorrent/peer_connection.hpp
index 2a88ed334..566d8a845 100755
--- a/include/libtorrent/peer_connection.hpp
+++ b/include/libtorrent/peer_connection.hpp
@@ -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.
diff --git a/include/libtorrent/peer_info.hpp b/include/libtorrent/peer_info.hpp
index e12a2404b..d06ed9a6a 100755
--- a/include/libtorrent/peer_info.hpp
+++ b/include/libtorrent/peer_info.hpp
@@ -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;
diff --git a/src/peer_connection.cpp b/src/peer_connection.cpp
index 715a0b172..422aefc92 100755
--- a/src/peer_connection.cpp
+++ b/src/peer_connection.cpp
@@ -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 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 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 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 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";
diff --git a/src/torrent.cpp b/src/torrent.cpp
index 5cd7232d1..5c49d8358 100755
--- a/src/torrent.cpp
+++ b/src/torrent.cpp
@@ -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);