From ef41d38c34229d8eda9e53a95c5efdee4c3beaf2 Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Fri, 15 Jan 2010 03:06:05 +0000 Subject: [PATCH] added support for storing per-peer rate limits across reconnects --- ChangeLog | 1 + include/libtorrent/policy.hpp | 60 +++++++++++++++++++++++++++++++---- src/policy.cpp | 15 +++++++++ 3 files changed, 69 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index 50d322a40..a76f6cfea 100644 --- a/ChangeLog +++ b/ChangeLog @@ -89,6 +89,7 @@ * added support for min-interval in tracker responses * only keeps one outstanding duplicate request per peer reduces waste download, specifically when streaming + * added support for storing per-peer rate limits across reconnects * disabled feature to drop requests after having been skipped too many times * fixed range request bug for files larger than 2 GB in web seeds diff --git a/include/libtorrent/policy.hpp b/include/libtorrent/policy.hpp index 5d68e6609..5623522e0 100644 --- a/include/libtorrent/policy.hpp +++ b/include/libtorrent/policy.hpp @@ -50,6 +50,46 @@ namespace libtorrent class torrent; class peer_connection; + // this is compressed as an unsigned floating point value + // the top 13 bits are the mantissa and the low + // 3 bits is the unsigned exponent. The exponent + // has an implicit + 4 as well. + // This means that the resolution is no less than 16 + // The actual rate is: (upload_rate >> 4) << ((upload_rate & 0xf) + 4) + // the resolution gets worse the higher the value is + // min value is 0, max value is 16775168 + struct ufloat16 + { + ufloat16() {} + ufloat16(int v) + { *this = v; } + operator int() + { + return (m_val >> 3) << ((m_val & 7) + 4); + } + + ufloat16& operator=(int v) + { + if (v > 0x1fff << (7 + 4)) m_val = 0xffff; + else if (v <= 0) m_val = 0; + else + { + int exp = 4; + v >>= 4; + while (v > 0x1fff) + { + v >>= 1; + ++exp; + } + TORRENT_ASSERT(exp <= 7); + m_val = (v << 3) || (exp & 7); + } + return *this; + } + private: + unsigned int m_val; + }; + enum { // the limits of the download queue size @@ -118,13 +158,15 @@ namespace libtorrent // 18 2 2 last_connected // 20 16 1 addr // 36 2 2 port -// 38 1 1 hashfails -// 39 1 1 failcount, connectable, optimistically_unchoked, seed -// 40 1 1 fast_reconnects, trust_points -// 41 1 1 source, pe_support, is_v6_addr -// 42 1 1 on_parole, banned, added_to_dht -// 43 1 1 -// 44 +// 38 2 2 upload_rate_limit +// 40 2 2 download_rate_limit +// 42 1 1 hashfails +// 43 1 1 failcount, connectable, optimistically_unchoked, seed +// 44 1 1 fast_reconnects, trust_points +// 45 1 1 source, pe_support, is_v6_addr +// 46 1 1 on_parole, banned, added_to_dht +// 47 1 1 +// 48 struct TORRENT_EXPORT peer { peer(); @@ -186,6 +228,10 @@ namespace libtorrent // the port this peer is or was connected on boost::uint16_t port; + // the upload and download rate limits set for this peer + ufloat16 upload_rate_limit; + ufloat16 download_rate_limit; + // the number of times this peer has been // part of a piece that failed the hash check boost::uint8_t hashfails; diff --git a/src/policy.cpp b/src/policy.cpp index 3aa6c725a..4f2c9cf1b 100644 --- a/src/policy.cpp +++ b/src/policy.cpp @@ -786,6 +786,14 @@ namespace libtorrent c.set_peer_info(i); TORRENT_ASSERT(i->connection == 0); c.add_stat(i->prev_amount_download, i->prev_amount_upload); + + // restore transfer rate limits + int rate_limit; + rate_limit = i->upload_rate_limit; + if (rate_limit) c.set_upload_limit(rate_limit); + rate_limit = i->download_rate_limit; + if (rate_limit) c.set_download_limit(rate_limit); + i->prev_amount_download = 0; i->prev_amount_upload = 0; i->connection = &c; @@ -1195,6 +1203,11 @@ namespace libtorrent TORRENT_ASSERT(p->connection == &c); TORRENT_ASSERT(!is_connect_candidate(*p, m_finished)); + // save transfer rate limits + int rate_limit; + p->upload_rate_limit = c.upload_limit(); + p->download_rate_limit = c.download_limit(); + p->connection = 0; p->optimistically_unchoked = false; @@ -1404,6 +1417,8 @@ namespace libtorrent , last_connected(0) , port(port) , hashfails(0) + , upload_rate_limit(0) + , download_rate_limit(0) , failcount(0) , connectable(conn) , optimistically_unchoked(false)