From 7607f20e2a7ab7013265837e01101d28c4f396bd Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Mon, 4 Feb 2013 07:17:31 +0000 Subject: [PATCH] add per-tracker scrape information to announce_entry --- ChangeLog | 1 + docs/manual.rst | 16 ++++++- include/libtorrent/torrent.hpp | 8 ++-- include/libtorrent/torrent_info.hpp | 11 +++++ include/libtorrent/tracker_manager.hpp | 1 + src/http_tracker_connection.cpp | 3 +- src/torrent.cpp | 63 +++++++++++++++++++------- src/torrent_info.cpp | 3 ++ src/udp_tracker_connection.cpp | 2 +- 9 files changed, 84 insertions(+), 24 deletions(-) diff --git a/ChangeLog b/ChangeLog index 69b273c53..c8343c18d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,4 @@ + * add per-tracker scrape information to announce_entry * report errors in read_piece_alert * DHT memory optimization * improve DHT lookup speed diff --git a/docs/manual.rst b/docs/manual.rst index f1c1902da..ba11cd937 100644 --- a/docs/manual.rst +++ b/docs/manual.rst @@ -2126,6 +2126,10 @@ ones with lower tier will always be tried before the one with higher tier number int next_announce_in() const; int min_announce_in() const; + int scrape_incomplete; + int scrape_complete; + int scrape_downloaded; + error_code last_error; std::string message; @@ -2156,6 +2160,13 @@ allowed to force another tracker update with this tracker. If the last time this tracker was contacted failed, ``last_error`` is the error code describing what error occurred. +``scrape_incomplete``, ``scrape_complete`` and ``scrape_downloaded`` are either +-1 or the scrape information this tracker last responded with. *incomplete* is +the current number of downloaders in the swarm, *complete* is the current number +of seeds in the swarm and *downloaded* is the cumulative number of completed +downloads of this torrent, since the beginning of time (from this tracker's point +of view). + If the last time this tracker was contacted, the tracker returned a warning or error message, ``message`` contains that message. @@ -6703,8 +6714,9 @@ the DHT. int num_peers; }; -The ``num_peers`` tells how many peers were returned from the tracker. This is -not necessarily all new peers, some of them may already be connected. +The ``num_peers`` tells how many peers the tracker returned in this response. This is +not expected to be more thant the ``num_want`` settings. These are not necessarily +all new peers, some of them may already be connected. tracker_warning_alert --------------------- diff --git a/include/libtorrent/torrent.hpp b/include/libtorrent/torrent.hpp index af6f7bd42..27a6b9a8f 100644 --- a/include/libtorrent/torrent.hpp +++ b/include/libtorrent/torrent.hpp @@ -448,8 +448,8 @@ namespace libtorrent , address const& tracker_ip , std::list
const& ip_list , std::vector& e, int interval, int min_interval - , int complete, int incomplete, address const& external_ip - , std::string const& trackerid); + , int complete, int incomplete, int downloaded + , address const& external_ip, std::string const& trackerid); virtual void tracker_request_error(tracker_request const& r , int response_code, error_code const& ec, const std::string& msg , int retry_interval); @@ -458,6 +458,8 @@ namespace libtorrent virtual void tracker_scrape_response(tracker_request const& req , int complete, int incomplete, int downloaded, int downloaders); + void update_scrape_state(); + // if no password and username is set // this will return an empty string, otherwise // it will concatenate the login and password @@ -1338,7 +1340,7 @@ namespace libtorrent // the scrape data from the tracker response, this // is optional and may be 0xffffff - unsigned int m_downloaders:24; + unsigned int m_downloaded:24; // round-robin index into m_interfaces mutable boost::uint8_t m_interface_index; diff --git a/include/libtorrent/torrent_info.hpp b/include/libtorrent/torrent_info.hpp index f268457d1..25d7cf04a 100644 --- a/include/libtorrent/torrent_info.hpp +++ b/include/libtorrent/torrent_info.hpp @@ -105,6 +105,17 @@ namespace libtorrent // no announces before this time ptime min_announce; + // TODO: include the number of peers received from this tracker, at last announce + + // if this tracker has returned scrape data, these fields are filled + // in with valid numbers. Otherwise they are set to -1. + // the number of current downloaders + int scrape_incomplete; + // the number of current seeds + int scrape_complete; + // the cumulative number of completed downloads, ever + int scrape_downloaded; + // the tier this tracker belongs to boost::uint8_t tier; diff --git a/include/libtorrent/tracker_manager.hpp b/include/libtorrent/tracker_manager.hpp index c7cac6bb4..4bd67a096 100644 --- a/include/libtorrent/tracker_manager.hpp +++ b/include/libtorrent/tracker_manager.hpp @@ -156,6 +156,7 @@ namespace libtorrent , int min_interval , int complete , int incomplete + , int downloaded , address const& external_ip , std::string const& trackerid) = 0; virtual void tracker_request_error( diff --git a/src/http_tracker_connection.cpp b/src/http_tracker_connection.cpp index 1fead9d00..03beec528 100644 --- a/src/http_tracker_connection.cpp +++ b/src/http_tracker_connection.cpp @@ -527,6 +527,7 @@ namespace libtorrent int complete = int(e.dict_find_int_value("complete", -1)); int incomplete = int(e.dict_find_int_value("incomplete", -1)); + int downloaded = int(e.dict_find_int_value("downloaded", -1)); std::list
ip_list; if (m_tracker_connection) @@ -542,7 +543,7 @@ namespace libtorrent } cb->tracker_response(tracker_req(), m_tracker_ip, ip_list, peer_list - , interval, min_interval, complete, incomplete, external_ip, trackerid); + , interval, min_interval, complete, incomplete, downloaded, external_ip, trackerid); } } diff --git a/src/torrent.cpp b/src/torrent.cpp index a1e5318a7..3df6b54ac 100644 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -415,7 +415,7 @@ namespace libtorrent , m_last_download(0) , m_last_upload(0) , m_last_scrape(0) - , m_downloaders(0xffffff) + , m_downloaded(0xffffff) , m_interface_index(0) , m_graceful_pause_mode(false) , m_need_connect_boost(true) @@ -2470,21 +2470,47 @@ namespace libtorrent INVARIANT_CHECK; TORRENT_ASSERT(req.kind == tracker_request::scrape_request); - if ((complete >= 0 && m_complete != complete) - || (incomplete >= 0 && m_incomplete != incomplete) - || (downloaders >= 0 && m_downloaders != downloaders)) - state_updated(); + announce_entry* ae = find_tracker(req); + if (ae) + { + if (incomplete >= 0) ae->scrape_incomplete = incomplete; + if (complete >= 0) ae->scrape_complete = complete; + if (downloaded >= 0) ae->scrape_downloaded = downloaded; - if (complete >= 0) m_complete = complete; - if (incomplete >= 0) m_incomplete = incomplete; - if (downloaders >= 0) m_downloaders = downloaders; + update_scrape_state(); + } if (m_ses.m_alerts.should_post()) { m_ses.m_alerts.post_alert(scrape_reply_alert( - get_handle(), m_incomplete, m_complete, req.url)); + get_handle(), incomplete, complete, req.url)); } } + + void torrent::update_scrape_state() + { + // loop over all trackers and find the largest numbers for each scrape field + // then update the torrent-wide understanding of number of downloaders and seeds + int complete = -1; + int incomplete = -1; + int downloaded = -1; + for (std::vector::iterator i = m_trackers.begin() + , end(m_trackers.end()); i != end; ++i) + { + complete = (std::max)(i->scrape_complete, complete); + incomplete = (std::max)(i->scrape_incomplete, incomplete); + downloaded = (std::max)(i->scrape_downloaded, downloaded); + } + + if ((complete >= 0 && m_complete != complete) + || (incomplete >= 0 && m_incomplete != incomplete) + || (downloaded >= 0 && m_downloaded != downloaded)) + state_updated(); + + m_complete = complete; + m_incomplete = incomplete; + m_downloaded = downloaded; + } void torrent::tracker_response( tracker_request const& r @@ -2495,6 +2521,7 @@ namespace libtorrent , int min_interval , int complete , int incomplete + , int downloaded , address const& external_ip , const std::string& trackerid) { @@ -2516,6 +2543,9 @@ namespace libtorrent announce_entry* ae = find_tracker(r); if (ae) { + if (incomplete >= 0) ae->scrape_incomplete = incomplete; + if (complete >= 0) ae->scrape_complete = complete; + if (downloaded >= 0) ae->scrape_downloaded = downloaded; if (!ae->start_sent && r.event == tracker_request::started) ae->start_sent = true; if (!ae->complete_sent && r.event == tracker_request::completed) @@ -2534,11 +2564,11 @@ namespace libtorrent if (m_ses.m_alerts.should_post()) m_ses.m_alerts.post_alert(trackerid_alert(get_handle(), r.url, trackerid)); } + + update_scrape_state(); } update_tracker_timer(now); - if (complete >= 0) m_complete = complete; - if (incomplete >= 0) m_incomplete = incomplete; if (complete >= 0 && incomplete >= 0) m_last_scrape = 0; @@ -5033,9 +5063,9 @@ namespace libtorrent m_finished_time = rd.dict_find_int_value("finished_time"); m_seeding_time = rd.dict_find_int_value("seeding_time"); m_last_seen_complete = rd.dict_find_int_value("last_seen_complete"); - m_complete = rd.dict_find_int_value("num_seeds", 0xffffff); + m_complete = rd.dict_find_int_value("num_complete", 0xffffff); m_incomplete = rd.dict_find_int_value("num_incomplete", 0xffffff); - m_downloaders = rd.dict_find_int_value("num_downloaders", 0xffffff); + m_downloaded = rd.dict_find_int_value("num_downloaded", 0xffffff); set_upload_limit(rd.dict_find_int_value("upload_rate_limit", -1)); set_download_limit(rd.dict_find_int_value("download_rate_limit", -1)); set_max_connections(rd.dict_find_int_value("max_connections", -1)); @@ -5231,9 +5261,9 @@ namespace libtorrent ret["seeding_time"] = m_seeding_time; ret["last_seen_complete"] = m_last_seen_complete; - ret["num_seeds"] = m_complete; + ret["num_complete"] = m_complete; ret["num_incomplete"] = m_incomplete; - ret["num_downloaders"] = m_downloaders; + ret["num_downloaded"] = m_downloaded; ret["sequential_download"] = m_sequential_download; @@ -7063,8 +7093,7 @@ namespace libtorrent if (m_complete != 0xffffff) seeds = m_complete; else seeds = m_policy.num_seeds(); - if (m_downloaders != 0xffffff) downloaders = m_downloaders; - else if (m_incomplete != 0xffffff) downloaders = m_incomplete; + if (m_incomplete != 0xffffff) downloaders = m_incomplete; else downloaders = m_policy.num_peers() - m_policy.num_seeds(); if (seeds == 0) diff --git a/src/torrent_info.cpp b/src/torrent_info.cpp index 55dae34e6..0aa640fc8 100644 --- a/src/torrent_info.cpp +++ b/src/torrent_info.cpp @@ -454,6 +454,9 @@ namespace libtorrent : url(u) , next_announce(min_time()) , min_announce(min_time()) + , scrape_incomplete(-1) + , scrape_complete(-1) + , scrape_downloaded(-1) , tier(0) , fail_limit(0) , fails(0) diff --git a/src/udp_tracker_connection.cpp b/src/udp_tracker_connection.cpp index ba41d4a42..36364963c 100644 --- a/src/udp_tracker_connection.cpp +++ b/src/udp_tracker_connection.cpp @@ -569,7 +569,7 @@ namespace libtorrent } cb->tracker_response(tracker_req(), m_target.address(), ip_list - , peer_list, interval, min_interval, complete, incomplete, address(), "" /*trackerid*/); + , peer_list, interval, min_interval, complete, incomplete, 0, address(), "" /*trackerid*/); close(); return true;