From 5d196ed5550f6028127be25777db969e2e47bd01 Mon Sep 17 00:00:00 2001
From: Arvid Norberg
Date: Sun, 13 Jan 2008 11:18:18 +0000
Subject: [PATCH] auto upload slots. opens up more slots if upload rate is not
met. On by default
---
ChangeLog | 5 ++++
docs/manual.html | 11 +++++++++
docs/manual.rst | 13 +++++++++++
examples/client_test.cpp | 6 +++--
include/libtorrent/aux_/session_impl.hpp | 7 ++++++
include/libtorrent/session_settings.hpp | 10 ++++++++
include/libtorrent/session_status.hpp | 2 ++
src/session_impl.cpp | 29 ++++++++++++++++++++++--
8 files changed, 79 insertions(+), 4 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 68a0ddee7..9a36cb84e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+ * Auto Upload slots. Automtically opens up more slots if
+ upload limit is not met.
+ * Improved NAT-PMP support by querying the default gateway (no
+ linux support yet)
+ * Improved UPnP support by ignoring routers not on the clients subnet.
release 0.13
diff --git a/docs/manual.html b/docs/manual.html
index e986501d3..35aa1b6c3 100644
--- a/docs/manual.html
+++ b/docs/manual.html
@@ -607,6 +607,8 @@ struct session_status
size_type total_payload_upload;
int num_peers;
+ int num_unchoked;
+ int allowed_upload_slots;
int dht_nodes;
int dht_cache_nodes;
@@ -628,6 +630,8 @@ incoming connections that still hasn't sent their handshake or outgoing connecti
that still hasn't completed the TCP connection. This number may be slightly higher
than the sum of all peers of all torrents because the incoming connections may not
be assigned a torrent yet.
+num_unchoked is the current number of unchoked peers.
+allowed_upload_slots is the current allowed number of unchoked peers.
dht_nodes, dht_cache_nodes and dht_torrents are only available when
built with DHT support. They are all set to 0 if the DHT isn't running. When
the DHT is running, dht_nodes is set to the number of nodes in the routing
@@ -2499,6 +2503,7 @@ struct session_settings
bool free_torrent_hashes;
bool upnp_ignore_nonrouters;
int send_buffer_watermark;
+ bool auto_upload_slots;
};
user_agent this is the client identification to the tracker.
@@ -2615,6 +2620,12 @@ if the send buffer has fewer bytes than this, we'll read another 16kB block
onto it. If set too small, upload rate capacity will suffer. If set too high,
memory will be wasted. The actual watermark may be lower than this in case
the upload rate is low, this is the upper limit.
+auto_upload_slots defaults to true. When true, if there is a global upload
+limit set and the current upload rate is less than 90% of that, another upload
+slot is opened. If the upload rate has been saturated for an extended period
+of time, on upload slot is closed. The number of upload slots will never be
+less than what has been set by session::set_max_uploads(). To query the
+current number of upload slots, see session_status::allowed_upload_slots.
diff --git a/docs/manual.rst b/docs/manual.rst
index 2612e608c..3acbb91b2 100644
--- a/docs/manual.rst
+++ b/docs/manual.rst
@@ -447,6 +447,8 @@ struct has the following members::
size_type total_payload_upload;
int num_peers;
+ int num_unchoked;
+ int allowed_upload_slots;
int dht_nodes;
int dht_cache_nodes;
@@ -472,6 +474,9 @@ that still hasn't completed the TCP connection. This number may be slightly high
than the sum of all peers of all torrents because the incoming connections may not
be assigned a torrent yet.
+``num_unchoked`` is the current number of unchoked peers.
+``allowed_upload_slots`` is the current allowed number of unchoked peers.
+
``dht_nodes``, ``dht_cache_nodes`` and ``dht_torrents`` are only available when
built with DHT support. They are all set to 0 if the DHT isn't running. When
the DHT is running, ``dht_nodes`` is set to the number of nodes in the routing
@@ -2487,6 +2492,7 @@ that will be sent to the tracker. The user-agent is a good way to identify your
bool free_torrent_hashes;
bool upnp_ignore_nonrouters;
int send_buffer_watermark;
+ bool auto_upload_slots;
};
``user_agent`` this is the client identification to the tracker.
@@ -2630,6 +2636,13 @@ onto it. If set too small, upload rate capacity will suffer. If set too high,
memory will be wasted. The actual watermark may be lower than this in case
the upload rate is low, this is the upper limit.
+``auto_upload_slots`` defaults to true. When true, if there is a global upload
+limit set and the current upload rate is less than 90% of that, another upload
+slot is opened. If the upload rate has been saturated for an extended period
+of time, on upload slot is closed. The number of upload slots will never be
+less than what has been set by ``session::set_max_uploads()``. To query the
+current number of upload slots, see ``session_status::allowed_upload_slots``.
+
pe_settings
===========
diff --git a/examples/client_test.cpp b/examples/client_test.cpp
index 7ed6eac91..5c146b9d4 100644
--- a/examples/client_test.cpp
+++ b/examples/client_test.cpp
@@ -1184,10 +1184,12 @@ 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") << ")" << std::endl;
+ << " (" << esc("31") << add_suffix(sess_stat.total_upload) << esc("0") << ")"
+ " unchoked: " << sess_stat.num_unchoked << " / " << sess_stat.allowed_upload_slots
+ << " ====" << std::endl;
if (print_log)
{
diff --git a/include/libtorrent/aux_/session_impl.hpp b/include/libtorrent/aux_/session_impl.hpp
index 9d232b644..916d842a2 100644
--- a/include/libtorrent/aux_/session_impl.hpp
+++ b/include/libtorrent/aux_/session_impl.hpp
@@ -503,7 +503,14 @@ namespace libtorrent
// should exit
volatile bool m_abort;
+ // the max number of unchoked peers as set by the user
int m_max_uploads;
+
+ // the number of unchoked peers as set by the auto-unchoker
+ // this should always be >= m_max_uploads
+ int m_allowed_upload_slots;
+
+ // the max number of connections, as set by the user
int m_max_connections;
// the number of unchoked peers
diff --git a/include/libtorrent/session_settings.hpp b/include/libtorrent/session_settings.hpp
index 1b70f6c98..f2abe6b3c 100644
--- a/include/libtorrent/session_settings.hpp
+++ b/include/libtorrent/session_settings.hpp
@@ -119,6 +119,7 @@ namespace libtorrent
, free_torrent_hashes(true)
, upnp_ignore_nonrouters(true)
, send_buffer_watermark(80 * 1024)
+ , auto_upload_slots(true)
{}
// this is the user agent that will be sent to the tracker
@@ -307,6 +308,15 @@ namespace libtorrent
// The actual watermark may be lower than this in case
// the upload rate is low, this is the upper limit.
int send_buffer_watermark;
+
+ // if auto_upload_slots is true, and a global upload
+ // limit is set and the upload rate is less than 90%
+ // of the upload limit, on new slot is opened up. If
+ // the upload rate is >= upload limit for an extended
+ // period of time, one upload slot is closed. The
+ // upload slots are never automatically decreased below
+ // the manual settings, through max_uploads.
+ bool auto_upload_slots;
};
#ifndef TORRENT_DISABLE_DHT
diff --git a/include/libtorrent/session_status.hpp b/include/libtorrent/session_status.hpp
index adbb1b57d..2c451a3c8 100644
--- a/include/libtorrent/session_status.hpp
+++ b/include/libtorrent/session_status.hpp
@@ -54,6 +54,8 @@ namespace libtorrent
size_type total_payload_upload;
int num_peers;
+ int num_unchoked;
+ int allowed_upload_slots;
#ifndef TORRENT_DISABLE_DHT
int dht_nodes;
diff --git a/src/session_impl.cpp b/src/session_impl.cpp
index 475897505..42bad0b43 100755
--- a/src/session_impl.cpp
+++ b/src/session_impl.cpp
@@ -564,6 +564,7 @@ namespace detail
, m_listen_interface(address::from_string(listen_interface), listen_port_range.first)
, m_abort(false)
, m_max_uploads(8)
+ , m_allowed_upload_slots(8)
, m_max_connections(200)
, m_num_unchoked(0)
, m_unchoke_time_scaler(0)
@@ -808,6 +809,7 @@ namespace detail
TORRENT_ASSERT(s.unchoke_interval >= 5);
m_settings = s;
m_files.resize(m_settings.file_pool_size);
+ if (!s.auto_upload_slots) m_allowed_upload_slots = m_max_uploads;
// replace all occurances of '\n' with ' '.
std::string::iterator i = m_settings.user_agent.begin();
while ((i = std::find(i, m_settings.user_agent.end(), '\n'))
@@ -1420,8 +1422,25 @@ namespace detail
, bind(&stat::download_payload_rate, bind(&peer_connection::statistics, _1))
> bind(&stat::download_payload_rate, bind(&peer_connection::statistics, _2)));
+ // auto unchoke
+ int upload_limit = m_bandwidth_manager[peer_connection::upload_channel]->throttle();
+ if (m_settings.auto_upload_slots && upload_limit != bandwidth_limit::inf)
+ {
+ // if our current upload rate is less than 90% of our
+ if (m_stat.upload_rate() < upload_limit * 0.9f
+ && m_allowed_upload_slots < m_num_unchoked + 2)
+ {
+ ++m_allowed_upload_slots;
+ }
+ else if (m_stat.upload_rate() >= upload_limit
+ && m_allowed_upload_slots > m_max_uploads)
+ {
+ --m_allowed_upload_slots;
+ }
+ }
+
// reserve one upload slot for optimistic unchokes
- int unchoke_set_size = m_max_uploads - 1;
+ int unchoke_set_size = m_allowed_upload_slots - 1;
m_num_unchoked = 0;
// go through all the peers and unchoke the first ones and choke
@@ -2007,8 +2026,12 @@ namespace detail
// INVARIANT_CHECK;
session_status s;
- s.has_incoming_connections = m_incoming_connection;
+
s.num_peers = (int)m_connections.size();
+ s.num_unchoked = m_num_unchoked;
+ s.allowed_upload_slots = m_allowed_upload_slots;
+
+ s.has_incoming_connections = m_incoming_connection;
s.download_rate = m_stat.download_rate();
s.upload_rate = m_stat.upload_rate();
@@ -2213,6 +2236,7 @@ namespace detail
if (limit <= 0) limit = (std::numeric_limits
::max)();
m_max_uploads = limit;
+ if (m_allowed_upload_slots < limit) m_allowed_upload_slots = limit;
}
void session_impl::set_max_connections(int limit)
@@ -2422,6 +2446,7 @@ namespace detail
{
TORRENT_ASSERT(m_max_connections > 0);
TORRENT_ASSERT(m_max_uploads > 0);
+ TORRENT_ASSERT(m_allowed_upload_slots >= m_max_uploads);
int unchokes = 0;
int num_optimistic = 0;
for (connection_map::const_iterator i = m_connections.begin();