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;