fix last_upload, last_download and last_scrape to be reported accurately and saved/restored in resume data

This commit is contained in:
arvidn 2018-04-20 13:03:36 +02:00 committed by Arvid Norberg
parent 44479bcca3
commit 3ede0b9c20
4 changed files with 54 additions and 50 deletions

View File

@ -459,6 +459,15 @@ The file format is a bencoded dictionary containing the following fields:
| | torrent when the resume data was last saved. This is used as | | | torrent when the resume data was last saved. This is used as |
| | an initial estimate until we acquire up-to-date scrape info. | | | an initial estimate until we acquire up-to-date scrape info. |
+--------------------------+--------------------------------------------------------------+ +--------------------------+--------------------------------------------------------------+
| ``last_upload`` | integer. The number of seconds since epoch when we last |
| | uploaded payload to a peer on this torrent. |
+--------------------------+--------------------------------------------------------------+
| ``last_download`` | integer. The number of seconds since epoch when we last |
| | downloaded payload from a peer on this torrent. |
+--------------------------+--------------------------------------------------------------+
| ``last_scrape`` | integer. The number of seconds since epoch when we last sent |
| | a scrape request to a tracker on this torrent. |
+--------------------------+--------------------------------------------------------------+
| ``upload_rate_limit`` | integer. In case this torrent has a per-torrent upload rate | | ``upload_rate_limit`` | integer. In case this torrent has a per-torrent upload rate |
| | limit, this is that limit. In bytes per second. | | | limit, this is that limit. In bytes per second. |
+--------------------------+--------------------------------------------------------------+ +--------------------------+--------------------------------------------------------------+

View File

@ -735,11 +735,7 @@ namespace libtorrent
void scrape_tracker(int idx, bool user_triggered); void scrape_tracker(int idx, bool user_triggered);
void announce_with_tracker(boost::uint8_t e void announce_with_tracker(boost::uint8_t e
= tracker_request::none); = tracker_request::none);
int seconds_since_last_scrape() const int seconds_since_last_scrape() const;
{
return m_last_scrape == (std::numeric_limits<boost::int16_t>::min)()
? -1 : int(m_ses.session_time() - m_last_scrape);
}
#ifndef TORRENT_DISABLE_DHT #ifndef TORRENT_DISABLE_DHT
void dht_announce(); void dht_announce();
@ -1089,7 +1085,8 @@ namespace libtorrent
// that are not private // that are not private
void lsd_announce(); void lsd_announce();
void update_last_upload() { m_last_upload = m_ses.session_time(); } void update_last_upload()
{ m_last_upload = total_seconds(clock_type::now().time_since_epoch()); }
void set_apply_ip_filter(bool b); void set_apply_ip_filter(bool b);
bool apply_ip_filter() const { return m_apply_ip_filter; } bool apply_ip_filter() const { return m_apply_ip_filter; }
@ -1654,9 +1651,8 @@ namespace libtorrent
// ---- // ----
// the timestamp of the last piece passed for this torrent specified in // the timestamp of the last piece passed for this torrent specified in
// session_time. This is signed because it must be able to represent time // seconds since epoch.
// before the session started boost::uint32_t m_last_download;
boost::int16_t m_last_download;
// the number of peer connections to seeds. This should be the same as // the number of peer connections to seeds. This should be the same as
// counting the peer connections that say true for is_seed() // counting the peer connections that say true for is_seed()
@ -1667,9 +1663,8 @@ namespace libtorrent
boost::uint16_t m_num_connecting_seeds; boost::uint16_t m_num_connecting_seeds;
// the timestamp of the last byte uploaded from this torrent specified in // the timestamp of the last byte uploaded from this torrent specified in
// session_time. This is signed because it must be able to represent time // seconds since epoch.
// before the session started. boost::uint32_t m_last_upload;
boost::int16_t m_last_upload;
// this is a second count-down to when we should tick the // this is a second count-down to when we should tick the
// storage for this torrent. Ticking the storage is used // storage for this torrent. Ticking the storage is used
@ -1709,7 +1704,7 @@ namespace libtorrent
// the timestamp of the last scrape request to one of the trackers in // the timestamp of the last scrape request to one of the trackers in
// this torrent specified in session_time. This is signed because it must // this torrent specified in session_time. This is signed because it must
// be able to represent time before the session started // be able to represent time before the session started
boost::int16_t m_last_scrape; boost::uint32_t m_last_scrape;
// ---- // ----

View File

@ -115,6 +115,8 @@ namespace libtorrent
{ {
namespace { namespace {
boost::uint32_t const unset = std::numeric_limits<boost::uint32_t>::max();
bool is_downloading_state(int st) bool is_downloading_state(int st)
{ {
switch (st) switch (st)
@ -302,17 +304,17 @@ namespace libtorrent
, m_deleted(false) , m_deleted(false)
, m_pinned((p.flags & add_torrent_params::flag_pinned) != 0) , m_pinned((p.flags & add_torrent_params::flag_pinned) != 0)
, m_should_be_loaded(true) , m_should_be_loaded(true)
, m_last_download((std::numeric_limits<boost::int16_t>::min)()) , m_last_download(unset)
, m_num_seeds(0) , m_num_seeds(0)
, m_num_connecting_seeds(0) , m_num_connecting_seeds(0)
, m_last_upload((std::numeric_limits<boost::int16_t>::min)()) , m_last_upload(unset)
, m_storage_tick(0) , m_storage_tick(0)
, m_auto_managed(p.flags & add_torrent_params::flag_auto_managed) , m_auto_managed(p.flags & add_torrent_params::flag_auto_managed)
, m_current_gauge_state(no_gauge_state) , m_current_gauge_state(no_gauge_state)
, m_moving_storage(false) , m_moving_storage(false)
, m_inactive(false) , m_inactive(false)
, m_downloaded(0xffffff) , m_downloaded(0xffffff)
, m_last_scrape((std::numeric_limits<boost::int16_t>::min)()) , m_last_scrape(unset)
, m_progress_ppm(0) , m_progress_ppm(0)
, m_pending_active_change(false) , m_pending_active_change(false)
, m_use_resume_save_path((p.flags & add_torrent_params::flag_use_resume_save_path) != 0) , m_use_resume_save_path((p.flags & add_torrent_params::flag_use_resume_save_path) != 0)
@ -3393,10 +3395,16 @@ namespace {
update_tracker_timer(now); update_tracker_timer(now);
} }
int torrent::seconds_since_last_scrape() const
{
return m_last_scrape == unset ? -1
: total_seconds(clock_type::now() - time_point(seconds(m_last_scrape)));
}
void torrent::scrape_tracker(int idx, bool user_triggered) void torrent::scrape_tracker(int idx, bool user_triggered)
{ {
TORRENT_ASSERT(is_single_thread()); TORRENT_ASSERT(is_single_thread());
m_last_scrape = m_ses.session_time(); m_last_scrape = total_seconds(clock_type::now().time_since_epoch());
if (m_trackers.empty()) return; if (m_trackers.empty()) return;
@ -3555,7 +3563,7 @@ namespace {
update_tracker_timer(now); update_tracker_timer(now);
if (resp.complete >= 0 && resp.incomplete >= 0) if (resp.complete >= 0 && resp.incomplete >= 0)
m_last_scrape = m_ses.session_time(); m_last_scrape = total_seconds(clock_type::now().time_since_epoch());
#ifndef TORRENT_DISABLE_LOGGING #ifndef TORRENT_DISABLE_LOGGING
std::string resolved_to; std::string resolved_to;
@ -4403,7 +4411,7 @@ namespace {
// is deallocated by the torrent once it starts seeding // is deallocated by the torrent once it starts seeding
} }
m_last_download = m_ses.session_time(); m_last_download = total_seconds(clock_type::now().time_since_epoch());
if (m_share_mode) if (m_share_mode)
recalc_share_mode(); recalc_share_mode();
@ -7027,13 +7035,12 @@ namespace {
#endif #endif
} }
int now = m_ses.session_time(); boost::int64_t tmp = rd.dict_find_int_value("last_scrape", -1);
int tmp = rd.dict_find_int_value("last_scrape", -1); m_last_scrape = tmp == -1 ? unset : tmp;
m_last_scrape = tmp == -1 ? (std::numeric_limits<boost::int16_t>::min)() : now - tmp;
tmp = rd.dict_find_int_value("last_download", -1); tmp = rd.dict_find_int_value("last_download", -1);
m_last_download = tmp == -1 ? (std::numeric_limits<boost::int16_t>::min)() : now - tmp; m_last_download = tmp == -1 ? unset : tmp;
tmp = rd.dict_find_int_value("last_upload", -1); tmp = rd.dict_find_int_value("last_upload", -1);
m_last_upload = tmp == -1 ? (std::numeric_limits<boost::int16_t>::min)() : now - tmp; m_last_upload = tmp == -1 ? unset : tmp;
if (m_use_resume_save_path) if (m_use_resume_save_path)
{ {
@ -7275,6 +7282,9 @@ namespace {
ret["num_complete"] = m_complete; ret["num_complete"] = m_complete;
ret["num_incomplete"] = m_incomplete; ret["num_incomplete"] = m_incomplete;
ret["num_downloaded"] = m_downloaded; ret["num_downloaded"] = m_downloaded;
ret["last_upload"] = m_last_upload == unset ? -1 : boost::int64_t(m_last_upload);
ret["last_download"] = m_last_download == unset ? -1 : boost::int64_t(m_last_download);
ret["last_scrape"] = m_last_scrape == unset ? -1 : boost::int64_t(m_last_scrape);
ret["sequential_download"] = m_sequential_download; ret["sequential_download"] = m_sequential_download;
@ -9613,13 +9623,6 @@ namespace {
return a - b; return a - b;
} }
int clamped_subtract_s16(int a, int b)
{
if (a + (std::numeric_limits<boost::int16_t>::min)() < b)
return (std::numeric_limits<boost::int16_t>::min)();
return a - b;
}
} // anonymous namespace } // anonymous namespace
// this is called every time the session timer takes a step back. Since the // this is called every time the session timer takes a step back. Since the
@ -9674,10 +9677,6 @@ namespace {
} }
m_became_finished = clamped_subtract(m_became_finished, seconds); m_became_finished = clamped_subtract(m_became_finished, seconds);
m_last_upload = clamped_subtract_s16(m_last_upload, seconds);
m_last_download = clamped_subtract_s16(m_last_download, seconds);
m_last_scrape = clamped_subtract_s16(m_last_scrape, seconds);
m_last_saved_resume = clamped_subtract(m_last_saved_resume, seconds); m_last_saved_resume = clamped_subtract(m_last_saved_resume, seconds);
m_upload_mode_time = clamped_subtract(m_upload_mode_time, seconds); m_upload_mode_time = clamped_subtract(m_upload_mode_time, seconds);
} }
@ -12145,8 +12144,8 @@ namespace {
st->added_time = m_added_time; st->added_time = m_added_time;
st->completed_time = m_completed_time; st->completed_time = m_completed_time;
st->last_scrape = m_last_scrape == (std::numeric_limits<boost::int16_t>::min)() ? -1 st->last_scrape = m_last_scrape == unset ? -1
: clamped_subtract(m_ses.session_time(), m_last_scrape); : total_seconds(clock_type::now() - time_point(seconds(m_last_scrape)));
st->share_mode = m_share_mode; st->share_mode = m_share_mode;
st->upload_mode = m_upload_mode; st->upload_mode = m_upload_mode;
@ -12168,10 +12167,10 @@ namespace {
st->finished_time = finished_time(); st->finished_time = finished_time();
st->active_time = active_time(); st->active_time = active_time();
st->seeding_time = seeding_time(); st->seeding_time = seeding_time();
st->time_since_upload = m_last_upload == (std::numeric_limits<boost::int16_t>::min)() ? -1 st->time_since_upload = m_last_upload == unset ? -1
: clamped_subtract(m_ses.session_time(), m_last_upload); : total_seconds(clock_type::now() - time_point(seconds(m_last_upload)));
st->time_since_download = m_last_download == (std::numeric_limits<boost::int16_t>::min)() ? -1 st->time_since_download = m_last_download == unset ? -1
: clamped_subtract(m_ses.session_time(), m_last_download); : total_seconds(clock_type::now() - time_point(seconds(m_last_download)));
st->storage_mode = static_cast<storage_mode_t>(m_storage_mode); st->storage_mode = static_cast<storage_mode_t>(m_storage_mode);

View File

@ -99,9 +99,9 @@ std::vector<char> generate_resume_data(torrent_info* ti
rd["super_seeding"] = 0; rd["super_seeding"] = 0;
rd["added_time"] = 1347; rd["added_time"] = 1347;
rd["completed_time"] = 1348; rd["completed_time"] = 1348;
rd["last_scrape"] = 1349; rd["last_scrape"] = 1;
rd["last_download"] = 1350; rd["last_download"] = 2;
rd["last_upload"] = 1351; rd["last_upload"] = 3;
rd["finished_time"] = 1352; rd["finished_time"] = 1352;
if (file_priorities && file_priorities[0]) if (file_priorities && file_priorities[0])
{ {
@ -177,14 +177,15 @@ void default_tests(torrent_status const& s)
// allow some slack in the time stamps since they are reported as // allow some slack in the time stamps since they are reported as
// relative times. If the computer is busy while running the unit test // relative times. If the computer is busy while running the unit test
// or running under valgrind it may take several seconds // or running under valgrind it may take several seconds
TEST_CHECK(s.last_scrape >= 1349); int const now = duration_cast<seconds>(clock_type::now().time_since_epoch()).count();
TEST_CHECK(s.time_since_download >= 1350); TEST_CHECK(s.last_scrape >= now - 1);
TEST_CHECK(s.time_since_upload >= 1351); TEST_CHECK(s.time_since_download >= now - 2);
TEST_CHECK(s.time_since_upload >= now - 3);
TEST_CHECK(s.active_time >= 1339); TEST_CHECK(s.active_time >= 1339);
TEST_CHECK(s.last_scrape < 1349 + 10); TEST_CHECK(s.last_scrape < now - 1 + 10);
TEST_CHECK(s.time_since_download < 1350 + 10); TEST_CHECK(s.time_since_download < now - 2 + 10);
TEST_CHECK(s.time_since_upload < 1351 + 10); TEST_CHECK(s.time_since_upload < now - 3 + 10);
TEST_CHECK(s.active_time < 1339 + 10); TEST_CHECK(s.active_time < 1339 + 10);
TEST_CHECK(s.finished_time >= 1352); TEST_CHECK(s.finished_time >= 1352);