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_idleThe peer is not waiting for any external events to +send or receive data.
bw_torrentThe peer is waiting for the torrent to receive +bandwidth quota in order to forward the bandwidth +request to the global manager.
bw_globalThe peer is waiting for the global bandwidth manager +to receive more quota in order to handle the request.
bw_networkThe 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);