UDP tracker optimization

This commit is contained in:
Arvid Norberg 2010-02-06 08:14:18 +00:00
parent abfc92de35
commit 8c02d04d2e
8 changed files with 79 additions and 15 deletions

View File

@ -101,6 +101,7 @@
* support disk I/O priority settings
* added info_hash to torrent_deleted_alert
* improved LSD performance and made the interval configurable
* improved UDP tracker support by caching connect tokens
release 0.14.9

View File

@ -107,6 +107,7 @@ void bind_session_settings()
.def_readwrite("drop_skipped_requests", &session_settings::drop_skipped_requests)
.def_readwrite("low_prio_disk", &session_settings::low_prio_disk)
.def_readwrite("local_service_announce_interval", &session_settings::local_service_announce_interval)
.def_readwrite("udp_tracker_token_expiry", &session_settings::udp_tracker_token_expiry)
.def_readwrite("volatile_read_cache", &session_settings::volatile_read_cache)
.def_readwrite("guided_read_cache", &guided_read_cache)
;

View File

@ -3722,6 +3722,8 @@ session_settings
bool low_prio_disk;
int local_service_announce_interval;
int udp_tracker_token_expiry;
bool volatile_read_cache;
bool guided_read_cache;
bool default_min_cache_age;
@ -4219,6 +4221,13 @@ bound on the time a cache line stays in the cache is an attempt
to avoid swapping the same pieces in and out of the cache in case
there is a shortage of spare cache space.
``udp_tracker_token_expiry`` is the number of seconds libtorrent
will keep UDP tracker connection tokens around for. This is specified
to be 60 seconds, and defaults to that. The higher this value is, the
fewer packets have to be sent to the UDP tracker. In order for higher
values to work, the tracker needs to be configured to match the
expiration time for tokens.
pe_settings
===========

View File

@ -187,6 +187,7 @@ namespace libtorrent
, drop_skipped_requests(false)
, low_prio_disk(true)
, local_service_announce_interval(5 * 60)
, udp_tracker_token_expiry(60)
, volatile_read_cache(false)
, guided_read_cache(true)
, default_cache_min_age(1)
@ -694,6 +695,11 @@ namespace libtorrent
// torrents. Defaults to 5 minutes
int local_service_announce_interval;
// the number of seconds a connection ID received
// from a UDP tracker is valid for. This is specified
// as 60 seconds
int udp_tracker_token_expiry;
// if this is set to true, any block read from the
// disk cache will be dropped from the cache immediately
// following. This may be useful if the block is not

View File

@ -114,10 +114,17 @@ namespace libtorrent
std::list<udp::endpoint> m_endpoints;
int m_transaction_id;
boost::int64_t m_connection_id;
aux::session_impl const& m_ses;
int m_attempts;
struct connection_cache_entry
{
boost::int64_t connection_id;
ptime expires;
};
static std::map<address, connection_cache_entry> m_connection_cache;
action_t m_state;
};

View File

@ -285,7 +285,13 @@ namespace aux {
TORRENT_SETTING(integer, max_suggest_pieces)
TORRENT_SETTING(boolean, drop_skipped_requests)
TORRENT_SETTING(boolean, low_prio_disk)
TORRENT_SETTING(boolean, local_service_announce_interval)
TORRENT_SETTING(integer, local_service_announce_interval)
TORRENT_SETTING(integer, udp_tracker_token_expiry)
TORRENT_SETTING(boolean, volatile_read_cache)
TORRENT_SETTING(boolean, guided_read_cache)
TORRENT_SETTING(integer, default_cache_min_age)
TORRENT_SETTING(integer, num_optimistic_unchoke_slots)
TORRENT_SETTING(boolean, no_atime_storage)
};
#undef TORRENT_SETTING

View File

@ -94,6 +94,9 @@ udp_socket::~udp_socket()
void udp_socket::send(udp::endpoint const& ep, char const* p, int len, error_code& ec)
{
CHECK_MAGIC;
TORRENT_ASSERT(is_open());
// if the sockets are closed, the udp_socket is closing too
if (!is_open()) return;

View File

@ -59,6 +59,9 @@ using boost::bind;
namespace libtorrent
{
std::map<address, udp_tracker_connection::connection_cache_entry>
udp_tracker_connection::m_connection_cache;
udp_tracker_connection::udp_tracker_connection(
io_service& ios
, connection_queue& cc
@ -72,7 +75,6 @@ namespace libtorrent
, m_name_lookup(ios)
, m_socket(ios, boost::bind(&udp_tracker_connection::on_receive, self(), _1, _2, _3, _4), cc)
, m_transaction_id(0)
, m_connection_id(0)
, m_ses(ses)
, m_attempts(0)
, m_state(action_error)
@ -185,16 +187,32 @@ namespace libtorrent
if (cb) cb->m_tracker_address = tcp::endpoint(m_target.address(), m_target.port());
if (bind_interface() != address_v4::any())
error_code ec;
m_socket.bind(udp::endpoint(bind_interface(), 0), ec);
if (ec)
{
error_code ec;
m_socket.bind(udp::endpoint(bind_interface(), 0), ec);
if (ec)
fail(-1, ec.message().c_str());
return;
}
std::map<address, connection_cache_entry>::iterator cc
= m_connection_cache.find(m_target.address());
if (cc != m_connection_cache.end())
{
// we found a cached entry! Now, we can only
// use if if it hasn't expired
if (time_now() < cc->second.expires)
{
fail(-1, ec.message().c_str());
if (tracker_req().kind == tracker_request::announce_request)
send_udp_announce();
else if (tracker_req().kind == tracker_request::scrape_request)
send_udp_scrape();
return;
}
// if it expired, remove it from the cache
m_connection_cache.erase(cc);
}
send_udp_connect();
}
@ -277,8 +295,8 @@ namespace libtorrent
if (cb)
{
char msg[200];
snprintf(msg, 200, "*** UDP_TRACKER_RESPONSE [ cid: %x%x ]"
, int(m_connection_id >> 32), int(m_connection_id & 0xffffffff));
snprintf(msg, 200, "*** UDP_TRACKER_RESPONSE [ tid: %x%x ]"
, int(transaction >> 32), int(transaction & 0xffffffff));
cb->debug_log(msg);
}
#endif
@ -309,7 +327,10 @@ namespace libtorrent
// reset transaction
m_transaction_id = 0;
m_attempts = 0;
m_connection_id = detail::read_int64(buf);
boost::uint64_t connection_id = detail::read_int64(buf);
connection_cache_entry& cce = m_connection_cache[m_target.address()];
cce.connection_id = connection_id;
cce.expires = time_now() + seconds(m_ses.m_settings.udp_tracker_token_expiry);
if (tracker_req().kind == tracker_request::announce_request)
send_udp_announce();
@ -363,10 +384,16 @@ namespace libtorrent
if (!m_socket.is_open()) return; // the operation was aborted
std::map<address, connection_cache_entry>::iterator i
= m_connection_cache.find(m_target.address());
// this isn't really supposed to happen
TORRENT_ASSERT(i != m_connection_cache.end());
if (i == m_connection_cache.end()) return;
char buf[8 + 4 + 4 + 20];
char* out = buf;
detail::write_int64(m_connection_id, out); // connection_id
detail::write_int64(i->second.connection_id, out); // connection_id
detail::write_int32(action_scrape, out); // action (scrape)
detail::write_int32(m_transaction_id, out); // transaction_id
// info_hash
@ -390,8 +417,6 @@ namespace libtorrent
{
if (size < 20) return;
restart_read_timeout();
buf += 8; // skip header
restart_read_timeout();
int interval = detail::read_int32(buf);
@ -517,7 +542,13 @@ namespace libtorrent
const bool stats = req.send_stats;
session_settings const& settings = m_ses.settings();
detail::write_int64(m_connection_id, out); // connection_id
std::map<address, connection_cache_entry>::iterator i
= m_connection_cache.find(m_target.address());
// this isn't really supposed to happen
TORRENT_ASSERT(i != m_connection_cache.end());
if (i == m_connection_cache.end()) return;
detail::write_int64(i->second.connection_id, out); // connection_id
detail::write_int32(action_announce, out); // action (announce)
detail::write_int32(m_transaction_id, out); // transaction_id
std::copy(req.info_hash.begin(), req.info_hash.end(), out); // info_hash