From 573a291495362b1e7fb5a9d5475a49c7f7d5a0c5 Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Thu, 21 Apr 2011 03:13:53 +0000 Subject: [PATCH] first step to remove recursion in bandwidth channel --- include/libtorrent/bandwidth_manager.hpp | 4 ++- include/libtorrent/peer_connection.hpp | 4 +-- src/bandwidth_manager.cpp | 8 +++--- src/peer_connection.cpp | 36 ++++++++++++++++-------- 4 files changed, 33 insertions(+), 19 deletions(-) diff --git a/include/libtorrent/bandwidth_manager.hpp b/include/libtorrent/bandwidth_manager.hpp index ba7223999..1720b757f 100644 --- a/include/libtorrent/bandwidth_manager.hpp +++ b/include/libtorrent/bandwidth_manager.hpp @@ -74,7 +74,9 @@ struct TORRENT_EXPORT bandwidth_manager // non prioritized means that, if there's a line for bandwidth, // others will cut in front of the non-prioritized peers. // this is used by web seeds - void request_bandwidth(intrusive_ptr const& peer + // returns the number of bytes to assign to the peer, or 0 + // if the peer's 'assign_bandwidth' callback will be called later + int request_bandwidth(intrusive_ptr const& peer , int blk, int priority , bandwidth_channel* chan1 = 0 , bandwidth_channel* chan2 = 0 diff --git a/include/libtorrent/peer_connection.hpp b/include/libtorrent/peer_connection.hpp index cb8fe3aa0..421e38a5e 100644 --- a/include/libtorrent/peer_connection.hpp +++ b/include/libtorrent/peer_connection.hpp @@ -732,12 +732,12 @@ namespace libtorrent void on_disk_read_complete(int ret, disk_io_job const& j, peer_request r); void on_disk_write_complete(int ret, disk_io_job const& j , peer_request r, boost::shared_ptr t); - void request_upload_bandwidth( + int request_upload_bandwidth( bandwidth_channel* bwc1 , bandwidth_channel* bwc2 = 0 , bandwidth_channel* bwc3 = 0 , bandwidth_channel* bwc4 = 0); - void request_download_bandwidth( + int request_download_bandwidth( bandwidth_channel* bwc1 , bandwidth_channel* bwc2 = 0 , bandwidth_channel* bwc3 = 0 diff --git a/src/bandwidth_manager.cpp b/src/bandwidth_manager.cpp index 5881e1010..8488e5c1a 100644 --- a/src/bandwidth_manager.cpp +++ b/src/bandwidth_manager.cpp @@ -84,7 +84,7 @@ namespace libtorrent // non prioritized means that, if there's a line for bandwidth, // others will cut in front of the non-prioritized peers. // this is used by web seeds - void bandwidth_manager::request_bandwidth(boost::intrusive_ptr const& peer + int bandwidth_manager::request_bandwidth(boost::intrusive_ptr const& peer , int blk, int priority , bandwidth_channel* chan1 , bandwidth_channel* chan2 @@ -94,7 +94,7 @@ namespace libtorrent ) { INVARIANT_CHECK; - if (m_abort) return; + if (m_abort) return 0; TORRENT_ASSERT(blk > 0); TORRENT_ASSERT(priority > 0); @@ -113,11 +113,11 @@ namespace libtorrent // bandwidth channels, or it doesn't belong to any // channels. There's no point in adding it to // the queue, just satisfy the request immediately - bwr.peer->assign_bandwidth(m_channel, blk); - return; + return blk; } m_queued_bytes += blk; m_queue.push_back(bwr); + return 0; } #ifdef TORRENT_DEBUG diff --git a/src/peer_connection.cpp b/src/peer_connection.cpp index c35ec33f2..f9131adb3 100644 --- a/src/peer_connection.cpp +++ b/src/peer_connection.cpp @@ -2472,7 +2472,7 @@ namespace libtorrent #endif // in case the outstanding bytes just dropped down // to allow to receive more data - setup_receive(); + setup_receive(read_async); piece_block block_finished(p.piece, p.start / t->block_size()); @@ -4377,7 +4377,7 @@ namespace libtorrent } } - void peer_connection::request_upload_bandwidth( + int peer_connection::request_upload_bandwidth( bandwidth_channel* bwc1 , bandwidth_channel* bwc2 , bandwidth_channel* bwc3 @@ -4424,14 +4424,14 @@ namespace libtorrent , (bwc4?bwc4->throttle():0) , m_ignore_bandwidth_limits); #endif - m_ses.m_upload_rate.request_bandwidth(self() + return m_ses.m_upload_rate.request_bandwidth(self() , (std::max)(m_send_buffer.size(), m_statistics.upload_rate() * 2 / (1000 / m_ses.m_settings.tick_interval)) , priority , bwc1, bwc2, bwc3, bwc4); } - void peer_connection::request_download_bandwidth( + int peer_connection::request_download_bandwidth( bandwidth_channel* bwc1 , bandwidth_channel* bwc2 , bandwidth_channel* bwc3 @@ -4459,7 +4459,7 @@ namespace libtorrent TORRENT_ASSERT(m_outstanding_bytes >= 0); TORRENT_ASSERT(m_channel_state[download_channel] != peer_info::bw_disk); m_channel_state[download_channel] = peer_info::bw_limit; - m_ses.m_download_rate.request_bandwidth(self() + return m_ses.m_download_rate.request_bandwidth(self() , (std::max)((std::max)(m_outstanding_bytes, m_packet_size - m_recv_pos) + 30 , m_statistics.download_rate() * 2 / (1000 / m_ses.m_settings.tick_interval)) @@ -4478,6 +4478,7 @@ namespace libtorrent && !m_connecting && t) { + int ret = 0; if (!m_ignore_bandwidth_limits) { bool utp = m_socket->get() != 0; @@ -4485,7 +4486,7 @@ namespace libtorrent // in this case, we have data to send, but no // bandwidth. So, we simply request bandwidth // from the bandwidth manager - request_upload_bandwidth( + ret = request_upload_bandwidth( (m_ses.m_settings.rate_limit_utp || !utp) ? &m_ses.m_upload_channel : 0 , &t->m_bandwidth_channel[upload_channel] , &m_bandwidth_channel[upload_channel] @@ -4498,10 +4499,15 @@ namespace libtorrent // instead we rate limit ourself against the special // global bandwidth channel for local peers, which defaults // to unthrottled - request_upload_bandwidth(&m_ses.m_local_upload_channel + ret = request_upload_bandwidth(&m_ses.m_local_upload_channel , &m_bandwidth_channel[upload_channel]); } - return; + if (ret == 0) return; + + // we were just assigned 'ret' quota + TORRENT_ASSERT(ret > 0); + m_quota[upload_channel] += ret; + m_channel_state[upload_channel] = peer_info::bw_idle; } int quota_left = m_quota[upload_channel]; @@ -4589,7 +4595,7 @@ namespace libtorrent m_ses.dec_disk_queue(download_channel); m_channel_state[download_channel] = peer_info::bw_idle; - setup_receive(); + setup_receive(read_async); } void peer_connection::setup_receive(sync_t sync) @@ -4604,6 +4610,7 @@ namespace libtorrent && !m_connecting && t) { + int ret = 0; if (!m_ignore_bandwidth_limits) { bool utp = m_socket->get() != 0; @@ -4611,7 +4618,7 @@ namespace libtorrent // in this case, we have outstanding data to // receive, but no bandwidth quota. So, we simply // request bandwidth from the bandwidth manager - request_download_bandwidth( + ret = request_download_bandwidth( (m_ses.m_settings.rate_limit_utp || !utp) ? &m_ses.m_download_channel : 0 , &t->m_bandwidth_channel[download_channel] , &m_bandwidth_channel[download_channel] @@ -4624,10 +4631,15 @@ namespace libtorrent // instead we rate limit ourself against the special // global bandwidth channel for local peers, which defaults // to unthrottled - request_download_bandwidth(&m_ses.m_local_download_channel + ret = request_download_bandwidth(&m_ses.m_local_download_channel , &m_bandwidth_channel[download_channel]); } - return; + if (ret == 0) return; + + // we were just assigned 'ret' quota + TORRENT_ASSERT(ret > 0); + m_quota[download_channel] += ret; + m_channel_state[download_channel] = peer_info::bw_idle; } if (!can_read(&m_channel_state[download_channel]))