From 127d3e6ad52c05c7edc98d9efba494d602387ec3 Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Thu, 17 Jan 2008 17:40:46 +0000 Subject: [PATCH] bandwidth limiter fixes. proper priority that cannot starve connections --- examples/client_test.cpp | 11 +- include/libtorrent/bandwidth_manager.hpp | 73 +++---- include/libtorrent/bandwidth_queue_entry.hpp | 9 +- include/libtorrent/peer_connection.hpp | 14 +- include/libtorrent/session_status.hpp | 3 + include/libtorrent/torrent.hpp | 4 +- include/libtorrent/torrent_handle.hpp | 5 + src/peer_connection.cpp | 12 +- src/session_impl.cpp | 9 +- src/torrent.cpp | 31 ++- src/web_peer_connection.cpp | 2 +- test/test_bandwidth_limiter.cpp | 212 +++++++++++-------- 12 files changed, 219 insertions(+), 166 deletions(-) diff --git a/examples/client_test.cpp b/examples/client_test.cpp index d64641bb1..69386e264 100644 --- a/examples/client_test.cpp +++ b/examples/client_test.cpp @@ -1105,8 +1105,9 @@ int main(int ac, char* av[]) out << "download: " << "(" << esc("32") << add_suffix(s.total_download) << esc("0") << ") "; } out << "upload: " << esc("31") << (s.upload_rate > 0 ? add_suffix(s.upload_rate) + "/s ": " ") << esc("0") - << "(" << esc("31") << add_suffix(s.total_upload) << esc("0") << ") " - << "ratio: " << ratio(s.total_payload_download, s.total_payload_upload) << "\n"; + << "(" << esc("31") << add_suffix(s.total_upload) << esc("0") << ") " + << "ratio: " << ratio(s.total_payload_download, s.total_payload_upload) + << " bw queue: (" << s.up_bandwidth_queue << " | " << s.down_bandwidth_queue << ")\n"; if (s.state != torrent_status::seeding) { boost::posix_time::time_duration t = s.next_announce; @@ -1188,12 +1189,14 @@ int main(int ac, char* av[]) } - out << "==== conns: " << sess_stat.num_peers << " down: " << esc("32") << add_suffix(sess_stat.download_rate) << "/s" << esc("0") + out << "==== conns: " << sess_stat.num_peers + << " down: " << esc("32") << add_suffix(sess_stat.download_rate) << "/s" << esc("0") << " (" << esc("32") << add_suffix(sess_stat.total_download) << esc("0") << ") " " up: " << esc("31") << add_suffix(sess_stat.upload_rate) << "/s " << esc("0") << " (" << esc("31") << add_suffix(sess_stat.total_upload) << esc("0") << ")" " unchoked: " << sess_stat.num_unchoked << " / " << sess_stat.allowed_upload_slots - << " ====" << std::endl; + << " bw queues: (" << sess_stat.up_bandwidth_queue + << " | " << sess_stat.down_bandwidth_queue << ") ====" << std::endl; if (print_log) { diff --git a/include/libtorrent/bandwidth_manager.hpp b/include/libtorrent/bandwidth_manager.hpp index 4a6122b15..706fc1d90 100644 --- a/include/libtorrent/bandwidth_manager.hpp +++ b/include/libtorrent/bandwidth_manager.hpp @@ -91,6 +91,15 @@ T clamp(T val, T ceiling, T floor) return val; } +template +struct assign_at_exit +{ + assign_at_exit(T& var, T val): var_(var), val_(val) {} + ~assign_at_exit() { var_ = val_; } + T& var_; + T val_; +}; + template struct bandwidth_manager { @@ -169,47 +178,35 @@ struct bandwidth_manager } #endif + int queue_size() const + { + mutex_t::scoped_lock l(m_mutex); + return m_queue.size(); + } // 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 - , int blk - , bool non_prioritized) + , int blk, int priority) { mutex_t::scoped_lock l(m_mutex); INVARIANT_CHECK; TORRENT_ASSERT(blk > 0); TORRENT_ASSERT(!is_queued(peer.get(), l)); - TORRENT_ASSERT(!peer->ignore_bandwidth_limits()); // make sure this peer isn't already in line // waiting for bandwidth TORRENT_ASSERT(peer->max_assignable_bandwidth(m_channel) > 0); - boost::shared_ptr t = peer->associated_torrent().lock(); - m_queue.push_back(bw_queue_entry(peer, blk, non_prioritized)); - if (!non_prioritized) + typename queue_t::reverse_iterator i(m_queue.rbegin()); + while (i != m_queue.rend() && priority > i->priority) { - typename queue_t::reverse_iterator i = m_queue.rbegin(); - typename queue_t::reverse_iterator j(i); - for (++j; j != m_queue.rend(); ++j) - { - // if the peer's torrent is not the same one - // continue looking for a peer from the same torrent - if (j->peer->associated_torrent().lock() != t) - continue; - // if we found a peer from the same torrent that - // is prioritized, there is no point looking - // any further. - if (!j->non_prioritized) break; - - using std::swap; - swap(*i, *j); - i = j; - } + ++i->priority; + ++i; } + m_queue.insert(i.base(), bw_queue_entry(peer, blk, priority)); if (!m_queue.empty()) hand_out_bandwidth(l); } @@ -222,8 +219,13 @@ struct bandwidth_manager { current_quota += i->amount; } - TORRENT_ASSERT(current_quota == m_current_quota); + + typename queue_t::const_iterator j = m_queue.begin(); + ++j; + for (typename queue_t::const_iterator i = m_queue.begin() + , end(m_queue.end()); i != end && j != end; ++i, ++j) + TORRENT_ASSERT(i->priority >= j->priority); } #endif @@ -308,6 +310,8 @@ private: // to the loop further down on the callstack if (m_in_hand_out_bandwidth) return; m_in_hand_out_bandwidth = true; + // set it to false when exiting function + assign_at_exit sg(m_in_hand_out_bandwidth, false); INVARIANT_CHECK; @@ -318,22 +322,16 @@ private: // available bandwidth to hand out int amount = limit - m_current_quota; - if (amount <= 0) - { - m_in_hand_out_bandwidth = false; - return; - } + if (amount <= 0) return; - queue_t q; queue_t tmp; - m_queue.swap(q); - while (!q.empty() && amount > 0) + while (!m_queue.empty() && amount > 0) { - bw_queue_entry qe = q.front(); + bw_queue_entry qe = m_queue.front(); TORRENT_ASSERT(qe.max_block_size > 0); - q.pop_front(); + m_queue.pop_front(); - shared_ptr t = qe.peer->associated_torrent().lock(); + shared_ptr t = qe.torrent.lock(); if (!t) continue; if (qe.peer->is_disconnecting()) { @@ -390,9 +388,10 @@ private: } if (block_size > qe.max_block_size) block_size = qe.max_block_size; - if (amount < block_size / 2) + if (amount < block_size / 4) { tmp.push_back(qe); +// m_queue.push_front(qe); break; } @@ -411,9 +410,7 @@ private: add_history_entry(history_entry( qe.peer, t, hand_out_amount, now + bw_window_size)); } - if (!q.empty()) m_queue.insert(m_queue.begin(), q.begin(), q.end()); if (!tmp.empty()) m_queue.insert(m_queue.begin(), tmp.begin(), tmp.end()); - m_in_hand_out_bandwidth = false; } diff --git a/include/libtorrent/bandwidth_queue_entry.hpp b/include/libtorrent/bandwidth_queue_entry.hpp index 76c119d96..f8b44846c 100644 --- a/include/libtorrent/bandwidth_queue_entry.hpp +++ b/include/libtorrent/bandwidth_queue_entry.hpp @@ -40,12 +40,15 @@ namespace libtorrent { template struct bw_queue_entry { + typedef typename PeerConnection::torrent_type torrent_type; bw_queue_entry(boost::intrusive_ptr const& pe - , int blk, bool no_prio) - : peer(pe), max_block_size(blk), non_prioritized(no_prio) {} + , int blk, int prio) + : peer(pe), torrent(peer->associated_torrent()) + , max_block_size(blk), priority(prio) {} boost::intrusive_ptr peer; + boost::weak_ptr torrent; int max_block_size; - bool non_prioritized; + int priority; // 0 is low prio }; } diff --git a/include/libtorrent/peer_connection.hpp b/include/libtorrent/peer_connection.hpp index 566d8a845..35572f50e 100755 --- a/include/libtorrent/peer_connection.hpp +++ b/include/libtorrent/peer_connection.hpp @@ -98,6 +98,8 @@ namespace libtorrent friend class invariant_access; public: + typedef torrent torrent_type; + enum channels { upload_channel, @@ -173,8 +175,8 @@ namespace libtorrent void request_large_blocks(bool b) { m_request_large_blocks = b; } - void set_non_prioritized(bool b) - { m_non_prioritized = b; } + void set_priority(int p) + { m_priority = p; } void fast_reconnect(bool r); bool fast_reconnect() const { return m_fast_reconnect; } @@ -684,11 +686,9 @@ namespace libtorrent // at a time. bool m_request_large_blocks; - // if this is true, other (prioritized) peers will - // skip ahead of it in the queue for bandwidth. The - // effect is that non prioritized peers will only use - // the left-over bandwidth (suitable for web seeds). - bool m_non_prioritized; + // this is the priority with which this peer gets + // download bandwidth quota assigned to it. + int m_priority; int m_upload_limit; int m_download_limit; diff --git a/include/libtorrent/session_status.hpp b/include/libtorrent/session_status.hpp index 2c451a3c8..4e42dba5f 100644 --- a/include/libtorrent/session_status.hpp +++ b/include/libtorrent/session_status.hpp @@ -57,6 +57,9 @@ namespace libtorrent int num_unchoked; int allowed_upload_slots; + int up_bandwidth_queue; + int down_bandwidth_queue; + #ifndef TORRENT_DISABLE_DHT int dht_nodes; int dht_node_cache; diff --git a/include/libtorrent/torrent.hpp b/include/libtorrent/torrent.hpp index 10aab86a1..5d0439313 100755 --- a/include/libtorrent/torrent.hpp +++ b/include/libtorrent/torrent.hpp @@ -234,11 +234,11 @@ namespace libtorrent void request_bandwidth(int channel , boost::intrusive_ptr const& p - , bool non_prioritized, int max_block_size); + , int max_block_size, int priority); void perform_bandwidth_request(int channel , boost::intrusive_ptr const& p - , int block_size, bool non_prioritized); + , int block_size, int priority); void expire_bandwidth(int channel, int amount); void assign_bandwidth(int channel, int amount, int blk); diff --git a/include/libtorrent/torrent_handle.hpp b/include/libtorrent/torrent_handle.hpp index 48a17e2ec..14217d9a4 100755 --- a/include/libtorrent/torrent_handle.hpp +++ b/include/libtorrent/torrent_handle.hpp @@ -112,6 +112,8 @@ namespace libtorrent , uploads_limit(0) , connections_limit(0) , storage_mode(storage_mode_sparse) + , up_bandwidth_queue(0) + , down_bandwidth_queue(0) {} enum state_t @@ -231,6 +233,9 @@ namespace libtorrent // true if the torrent is saved in compact mode // false if it is saved in full allocation mode storage_mode_t storage_mode; + + int up_bandwidth_queue; + int down_bandwidth_queue; }; struct TORRENT_EXPORT block_info diff --git a/src/peer_connection.cpp b/src/peer_connection.cpp index 670d5134b..a95c9dacf 100755 --- a/src/peer_connection.cpp +++ b/src/peer_connection.cpp @@ -107,7 +107,7 @@ namespace libtorrent , m_queued(true) , m_prefer_whole_pieces(false) , m_request_large_blocks(false) - , m_non_prioritized(false) + , m_priority(1) , m_upload_limit(bandwidth_limit::inf) , m_download_limit(bandwidth_limit::inf) , m_peer_info(peerinfo) @@ -189,7 +189,7 @@ namespace libtorrent , m_queued(false) , m_prefer_whole_pieces(false) , m_request_large_blocks(false) - , m_non_prioritized(false) + , m_priority(1) , m_upload_limit(bandwidth_limit::inf) , m_download_limit(bandwidth_limit::inf) , m_peer_info(peerinfo) @@ -2551,8 +2551,8 @@ namespace libtorrent // peers that we are not interested in are non-prioritized m_channel_state[upload_channel] = peer_info::bw_torrent; t->request_bandwidth(upload_channel, self() - , !(is_interesting() && !has_peer_choked()) - , m_send_buffer.size()); + , m_send_buffer.size() + , is_interesting() * 2); } return; } @@ -2601,8 +2601,8 @@ namespace libtorrent #endif 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); + t->request_bandwidth(download_channel, self() + , m_download_queue.size() * 16 * 1024 + 30, m_priority); } return; } diff --git a/src/session_impl.cpp b/src/session_impl.cpp index dbd0aaf03..6f8b31aff 100755 --- a/src/session_impl.cpp +++ b/src/session_impl.cpp @@ -1434,9 +1434,9 @@ namespace detail if (m_settings.auto_upload_slots && upload_limit != bandwidth_limit::inf) { // if our current upload rate is less than 90% of our - // limit AND most torrents are not "congested", i.e. - // they are not holding back because of a per-torrent - // limit + // limit AND most torrents are not "congested", i.e. + // they are not holding back because of a per-torrent + // limit if (m_stat.upload_rate() < upload_limit * 0.9f && m_allowed_upload_slots <= m_num_unchoked + 1 && congested_torrents < uncongested_torrents) @@ -2042,6 +2042,9 @@ namespace detail s.num_unchoked = m_num_unchoked; s.allowed_upload_slots = m_allowed_upload_slots; + s.up_bandwidth_queue = m_upload_channel.queue_size(); + s.down_bandwidth_queue = m_download_channel.queue_size(); + s.has_incoming_connections = m_incoming_connection; s.download_rate = m_stat.download_rate(); diff --git a/src/torrent.cpp b/src/torrent.cpp index 11bcb52d9..57b8fa896 100755 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -2278,7 +2278,7 @@ namespace libtorrent void torrent::request_bandwidth(int channel , boost::intrusive_ptr const& p - , bool non_prioritized, int max_block_size) + , int max_block_size, int priority) { TORRENT_ASSERT(max_block_size > 0); TORRENT_ASSERT(m_bandwidth_limit[channel].throttle() > 0); @@ -2290,17 +2290,20 @@ namespace libtorrent if (m_bandwidth_limit[channel].max_assignable() > 0) { - perform_bandwidth_request(channel, p, block_size, non_prioritized); + perform_bandwidth_request(channel, p, block_size, priority); } else { // skip forward in the queue until we find a prioritized peer // or hit the front of it. queue_t::reverse_iterator i = m_bandwidth_queue[channel].rbegin(); - if (!non_prioritized) - while (i != m_bandwidth_queue[channel].rend() && i->non_prioritized) ++i; + while (i != m_bandwidth_queue[channel].rend() && priority > i->priority) + { + ++i->priority; + ++i; + } m_bandwidth_queue[channel].insert(i.base(), bw_queue_entry( - p, block_size, non_prioritized)); + p, block_size, priority)); } } @@ -2326,7 +2329,7 @@ namespace libtorrent continue; } perform_bandwidth_request(channel, qe.peer - , qe.max_block_size, qe.non_prioritized); + , qe.max_block_size, qe.priority); } m_bandwidth_queue[channel].insert(m_bandwidth_queue[channel].begin(), tmp.begin(), tmp.end()); } @@ -2334,12 +2337,12 @@ namespace libtorrent void torrent::perform_bandwidth_request(int channel , boost::intrusive_ptr const& p , int block_size - , bool non_prioritized) + , int priority) { 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); + , block_size, priority); m_bandwidth_limit[channel].assign(block_size); } @@ -2672,6 +2675,15 @@ namespace libtorrent TORRENT_ASSERT(m_bandwidth_queue[0].size() <= m_connections.size()); TORRENT_ASSERT(m_bandwidth_queue[1].size() <= m_connections.size()); + for (int c = 0; c < 2; ++c) + { + queue_t::const_iterator j = m_bandwidth_queue[c].begin(); + ++j; + for (queue_t::const_iterator i = m_bandwidth_queue[c].begin() + , end(m_bandwidth_queue[c].end()); i != end && j != end; ++i, ++j) + TORRENT_ASSERT(i->priority >= j->priority); + } + int num_uploads = 0; std::map num_requests; for (const_peer_iterator i = begin(); i != end(); ++i) @@ -3118,6 +3130,9 @@ namespace libtorrent torrent_status st; + st.up_bandwidth_queue = (int)m_bandwidth_queue[peer_connection::upload_channel].size(); + st.down_bandwidth_queue = (int)m_bandwidth_queue[peer_connection::download_channel].size(); + st.num_peers = (int)std::count_if(m_connections.begin(), m_connections.end() , !boost::bind(&peer_connection::is_connecting, _1)); diff --git a/src/web_peer_connection.cpp b/src/web_peer_connection.cpp index 0851499f8..e859435c0 100755 --- a/src/web_peer_connection.cpp +++ b/src/web_peer_connection.cpp @@ -73,7 +73,7 @@ namespace libtorrent // we can request more bytes at once request_large_blocks(true); // we only want left-over bandwidth - set_non_prioritized(true); + set_priority(0); shared_ptr tor = t.lock(); TORRENT_ASSERT(tor); int blocks_per_piece = tor->torrent_file().piece_length() / tor->block_size(); diff --git a/test/test_bandwidth_limiter.cpp b/test/test_bandwidth_limiter.cpp index ba9b01bb0..4fc7053b6 100644 --- a/test/test_bandwidth_limiter.cpp +++ b/test/test_bandwidth_limiter.cpp @@ -1,6 +1,8 @@ #include "test.hpp" #include "libtorrent/bandwidth_manager.hpp" +#include "libtorrent/bandwidth_queue_entry.hpp" +#include "libtorrent/bandwidth_limit.hpp" #include "libtorrent/socket.hpp" #include "libtorrent/stat.hpp" #include "libtorrent/time.hpp" @@ -17,6 +19,43 @@ const float sample_time = 6.f; // seconds //#define VERBOSE_LOGGING + +struct peer_connection: intrusive_ptr_base +{ + typedef torrent torrent_type; + + peer_connection(io_service& ios, boost::shared_ptr const& t + , int prio, bool ignore_limits, std::string name); + + bool ignore_bandwidth_limits() { return m_ignore_limits; } + int max_assignable_bandwidth(int channel) const + { return m_bandwidth_limit[channel].max_assignable(); } + boost::weak_ptr associated_torrent() const + { return m_torrent; } + bool is_disconnecting() const { return m_abort; } + void assign_bandwidth(int channel, int amount); + void on_transfer(int channel, int amount); + void start(); + void stop() { m_abort = true; } + void expire_bandwidth(int channel, int amount); + void tick(); + + int bandwidth_throttle(int channel) const + { return m_bandwidth_limit[channel].throttle(); } + + void throttle(int limit) { m_bandwidth_limit[0].throttle(limit); } + + bandwidth_limit m_bandwidth_limit[1]; + boost::weak_ptr m_torrent; + int m_priority; + bool m_ignore_limits; + bool m_abort; + libtorrent::stat m_stats; + io_service& m_ios; + std::string m_name; + bool m_writing; +}; + struct torrent { torrent(bandwidth_manager& m) @@ -43,10 +82,13 @@ struct torrent void request_bandwidth(int channel , boost::intrusive_ptr const& p - , bool non_prioritized) + , int max_block_size + , int priority) { - TEST_CHECK(m_bandwidth_limit[channel].throttle() > 0); - int block_size = m_bandwidth_limit[channel].throttle() / 10; + TORRENT_ASSERT(max_block_size > 0); + TORRENT_ASSERT(m_bandwidth_limit[channel].throttle() > 0); + int block_size = (std::min)(m_bandwidth_limit[channel].throttle() / 10 + , max_block_size); if (block_size <= 0) block_size = 1; if (m_bandwidth_limit[channel].max_assignable() > 0) @@ -55,7 +97,7 @@ struct torrent std::cerr << time_now_string() << ": request bandwidth " << block_size << std::endl; #endif - perform_bandwidth_request(channel, p, block_size, non_prioritized); + perform_bandwidth_request(channel, p, block_size, priority); } else { @@ -63,13 +105,16 @@ struct torrent std::cerr << time_now_string() << ": queue bandwidth request" << block_size << std::endl; #endif - // skip forward in the queue until we find a prioritized peer // or hit the front of it. queue_t::reverse_iterator i = m_bandwidth_queue[channel].rbegin(); - while (i != m_bandwidth_queue[channel].rend() && i->non_prioritized) ++i; + while (i != m_bandwidth_queue[channel].rend() && priority > i->priority) + { + ++i->priority; + ++i; + } m_bandwidth_queue[channel].insert(i.base(), bw_queue_entry( - p, block_size, non_prioritized)); + p, block_size, priority)); } } @@ -78,10 +123,10 @@ struct torrent void perform_bandwidth_request(int channel , boost::intrusive_ptr const& p , int block_size - , bool non_prioritized) + , int priority) { m_bandwidth_manager.request_bandwidth(p - , block_size, non_prioritized); + , block_size, priority); m_bandwidth_limit[channel].assign(block_size); } bandwidth_limit m_bandwidth_limit[1]; @@ -90,99 +135,79 @@ struct torrent bandwidth_manager& m_bandwidth_manager; }; -struct peer_connection: intrusive_ptr_base -{ - peer_connection(io_service& ios, boost::shared_ptr const& t - , bool prio, bool ignore_limits, std::string name) - : m_torrent(t) - , m_prioritized(prio) - , m_ignore_limits(ignore_limits) - , m_abort(false) - , m_ios(ios) - , m_name(name) - , m_writing(false) - {} +peer_connection::peer_connection(io_service& ios, boost::shared_ptr const& t + , int prio, bool ignore_limits, std::string name) + : m_torrent(t) + , m_priority(prio) + , m_ignore_limits(ignore_limits) + , m_abort(false) + , m_ios(ios) + , m_name(name) + , m_writing(false) +{} - bool ignore_bandwidth_limits() { return m_ignore_limits; } - int max_assignable_bandwidth(int channel) const - { return m_bandwidth_limit[channel].max_assignable(); } - boost::weak_ptr associated_torrent() const - { return m_torrent; } - bool is_disconnecting() const { return m_abort; } - void assign_bandwidth(int channel, int amount) - { - TEST_CHECK(m_writing); +void peer_connection::assign_bandwidth(int channel, int amount) +{ + TEST_CHECK(m_writing); #ifdef VERBOSE_LOGGING - std::cerr << time_now_string() << ": [" << m_name - << "] assign bandwidth, " << amount << std::endl; + std::cerr << time_now_string() << ": [" << m_name + << "] assign bandwidth, " << amount << std::endl; #endif - TEST_CHECK(amount > 0); - m_bandwidth_limit[channel].assign(amount); - m_ios.post(boost::bind(&peer_connection::on_transfer, self(), channel, amount)); - } - void on_transfer(int channel, int amount) + TEST_CHECK(amount > 0); + m_bandwidth_limit[channel].assign(amount); + m_ios.post(boost::bind(&peer_connection::on_transfer, self(), channel, amount)); +} + +void peer_connection::on_transfer(int channel, int amount) +{ + TEST_CHECK(m_writing); + m_writing = false; + m_stats.sent_bytes(amount, 0); + + boost::shared_ptr t = m_torrent.lock(); + if (!t) return; + if (m_bandwidth_limit[channel].max_assignable() > 0) { - TEST_CHECK(m_writing); - m_writing = false; - m_stats.sent_bytes(amount, 0); - - boost::shared_ptr t = m_torrent.lock(); - if (!t) return; - if (m_bandwidth_limit[channel].max_assignable() > 0) - { - m_writing = true; - t->request_bandwidth(0, this, !m_prioritized); - } + m_writing = true; + t->request_bandwidth(0, this, 32 * 1024, m_priority); } - void start() +} + +void peer_connection::start() +{ + boost::shared_ptr t = m_torrent.lock(); + if (!t) return; + m_writing = true; + t->request_bandwidth(0, this, 32 * 1024, m_priority); +} + +void peer_connection::expire_bandwidth(int channel, int amount) +{ + TEST_CHECK(amount > 0); +#ifdef VERBOSE_LOGGING + std::cerr << time_now_string() << ": [" << m_name + << "] expire bandwidth, " << amount << std::endl; +#endif + m_bandwidth_limit[channel].expire(amount); + + if (!m_writing && m_bandwidth_limit[channel].max_assignable() > 0) { boost::shared_ptr t = m_torrent.lock(); if (!t) return; m_writing = true; - t->request_bandwidth(0, this, !m_prioritized); + t->request_bandwidth(0, this, 32 * 1024, m_priority); } - void stop() { m_abort = true; } - void expire_bandwidth(int channel, int amount) - { - TEST_CHECK(amount > 0); +} + +void peer_connection::tick() +{ #ifdef VERBOSE_LOGGING - std::cerr << time_now_string() << ": [" << m_name - << "] expire bandwidth, " << amount << std::endl; + std::cerr << time_now_string() << ": [" << m_name + << "] tick, rate: " << m_stats.upload_rate() << std::endl; #endif - m_bandwidth_limit[channel].expire(amount); + m_stats.second_tick(1.f); +} - if (!m_writing && m_bandwidth_limit[channel].max_assignable() > 0) - { - boost::shared_ptr t = m_torrent.lock(); - if (!t) return; - m_writing = true; - t->request_bandwidth(0, this, !m_prioritized); - } - } - void tick() - { -#ifdef VERBOSE_LOGGING - std::cerr << time_now_string() << ": [" << m_name - << "] tick, rate: " << m_stats.upload_rate() << std::endl; -#endif - m_stats.second_tick(1.f); - } - - int bandwidth_throttle(int channel) const - { return m_bandwidth_limit[channel].throttle(); } - - void throttle(int limit) { m_bandwidth_limit[0].throttle(limit); } - - bandwidth_limit m_bandwidth_limit[1]; - boost::weak_ptr m_torrent; - bool m_prioritized; - bool m_ignore_limits; - bool m_abort; - libtorrent::stat m_stats; - io_service& m_ios; - std::string m_name; - bool m_writing; -}; void torrent::expire_bandwidth(int channel, int amount) { @@ -201,12 +226,11 @@ void torrent::expire_bandwidth(int channel, int amount) m_bandwidth_queue[channel].pop_front(); if (qe.peer->max_assignable_bandwidth(channel) <= 0) { - TORRENT_ASSERT(m_bandwidth_manager.is_in_history(qe.peer.get())); if (!qe.peer->is_disconnecting()) tmp.push_back(qe); continue; } perform_bandwidth_request(channel, qe.peer - , qe.max_block_size, qe.non_prioritized); + , qe.max_block_size, qe.priority); } m_bandwidth_queue[channel].insert(m_bandwidth_queue[channel].begin(), tmp.begin(), tmp.end()); } @@ -311,7 +335,7 @@ void spawn_connections(connections_t& v, io_service& ios { for (int i = 0; i < num; ++i) { - v.push_back(new peer_connection(ios, t, true, false + v.push_back(new peer_connection(ios, t, 200, false , prefix + boost::lexical_cast(i))); } } @@ -545,7 +569,7 @@ void test_peer_priority(int limit, bool torrent_limit) connections_t v; std::copy(v1.begin(), v1.end(), std::back_inserter(v)); boost::intrusive_ptr p( - new peer_connection(ios, t1, false, false, "no-priority")); + new peer_connection(ios, t1, 0, false, "no-priority")); v.push_back(p); run_test(ios, v); @@ -581,7 +605,7 @@ void test_no_starvation(int limit) connections_t v; std::copy(v1.begin(), v1.end(), std::back_inserter(v)); boost::intrusive_ptr p( - new peer_connection(ios, t2, false, false, "no-priority")); + new peer_connection(ios, t2, 0, false, "no-priority")); v.push_back(p); run_test(ios, v);