diff --git a/docs/manual.rst b/docs/manual.rst index 2efb6b680..858bb14c8 100644 --- a/docs/manual.rst +++ b/docs/manual.rst @@ -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 | | | 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 | | | limit, this is that limit. In bytes per second. | +--------------------------+--------------------------------------------------------------+ diff --git a/include/libtorrent/torrent.hpp b/include/libtorrent/torrent.hpp index f165b10be..44946ff72 100644 --- a/include/libtorrent/torrent.hpp +++ b/include/libtorrent/torrent.hpp @@ -735,11 +735,7 @@ namespace libtorrent void scrape_tracker(int idx, bool user_triggered); void announce_with_tracker(boost::uint8_t e = tracker_request::none); - int seconds_since_last_scrape() const - { - return m_last_scrape == (std::numeric_limits::min)() - ? -1 : int(m_ses.session_time() - m_last_scrape); - } + int seconds_since_last_scrape() const; #ifndef TORRENT_DISABLE_DHT void dht_announce(); @@ -1089,7 +1085,8 @@ namespace libtorrent // that are not private 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); 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 - // session_time. This is signed because it must be able to represent time - // before the session started - boost::int16_t m_last_download; + // seconds since epoch. + boost::uint32_t m_last_download; // the number of peer connections to seeds. This should be the same as // counting the peer connections that say true for is_seed() @@ -1667,9 +1663,8 @@ namespace libtorrent boost::uint16_t m_num_connecting_seeds; // 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 - // before the session started. - boost::int16_t m_last_upload; + // seconds since epoch. + boost::uint32_t m_last_upload; // this is a second count-down to when we should tick the // 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 // this torrent specified in session_time. This is signed because it must // be able to represent time before the session started - boost::int16_t m_last_scrape; + boost::uint32_t m_last_scrape; // ---- diff --git a/src/torrent.cpp b/src/torrent.cpp index 0e5f90633..075bbeb52 100644 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -115,6 +115,8 @@ namespace libtorrent { namespace { + boost::uint32_t const unset = std::numeric_limits::max(); + bool is_downloading_state(int st) { switch (st) @@ -302,17 +304,17 @@ namespace libtorrent , m_deleted(false) , m_pinned((p.flags & add_torrent_params::flag_pinned) != 0) , m_should_be_loaded(true) - , m_last_download((std::numeric_limits::min)()) + , m_last_download(unset) , m_num_seeds(0) , m_num_connecting_seeds(0) - , m_last_upload((std::numeric_limits::min)()) + , m_last_upload(unset) , m_storage_tick(0) , m_auto_managed(p.flags & add_torrent_params::flag_auto_managed) , m_current_gauge_state(no_gauge_state) , m_moving_storage(false) , m_inactive(false) , m_downloaded(0xffffff) - , m_last_scrape((std::numeric_limits::min)()) + , m_last_scrape(unset) , m_progress_ppm(0) , m_pending_active_change(false) , 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); } + 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) { 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; @@ -3555,7 +3563,7 @@ namespace { update_tracker_timer(now); 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 std::string resolved_to; @@ -4403,7 +4411,7 @@ namespace { // 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) recalc_share_mode(); @@ -7027,13 +7035,12 @@ namespace { #endif } - int now = m_ses.session_time(); - int tmp = rd.dict_find_int_value("last_scrape", -1); - m_last_scrape = tmp == -1 ? (std::numeric_limits::min)() : now - tmp; + boost::int64_t tmp = rd.dict_find_int_value("last_scrape", -1); + m_last_scrape = tmp == -1 ? unset : tmp; tmp = rd.dict_find_int_value("last_download", -1); - m_last_download = tmp == -1 ? (std::numeric_limits::min)() : now - tmp; + m_last_download = tmp == -1 ? unset : tmp; tmp = rd.dict_find_int_value("last_upload", -1); - m_last_upload = tmp == -1 ? (std::numeric_limits::min)() : now - tmp; + m_last_upload = tmp == -1 ? unset : tmp; if (m_use_resume_save_path) { @@ -7275,6 +7282,9 @@ namespace { ret["num_complete"] = m_complete; ret["num_incomplete"] = m_incomplete; 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; @@ -9613,13 +9623,6 @@ namespace { return a - b; } - int clamped_subtract_s16(int a, int b) - { - if (a + (std::numeric_limits::min)() < b) - return (std::numeric_limits::min)(); - return a - b; - } - } // anonymous namespace // 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_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_upload_mode_time = clamped_subtract(m_upload_mode_time, seconds); } @@ -12145,8 +12144,8 @@ namespace { st->added_time = m_added_time; st->completed_time = m_completed_time; - st->last_scrape = m_last_scrape == (std::numeric_limits::min)() ? -1 - : clamped_subtract(m_ses.session_time(), m_last_scrape); + st->last_scrape = m_last_scrape == unset ? -1 + : total_seconds(clock_type::now() - time_point(seconds(m_last_scrape))); st->share_mode = m_share_mode; st->upload_mode = m_upload_mode; @@ -12168,10 +12167,10 @@ namespace { st->finished_time = finished_time(); st->active_time = active_time(); st->seeding_time = seeding_time(); - st->time_since_upload = m_last_upload == (std::numeric_limits::min)() ? -1 - : clamped_subtract(m_ses.session_time(), m_last_upload); - st->time_since_download = m_last_download == (std::numeric_limits::min)() ? -1 - : clamped_subtract(m_ses.session_time(), m_last_download); + st->time_since_upload = m_last_upload == unset ? -1 + : total_seconds(clock_type::now() - time_point(seconds(m_last_upload))); + st->time_since_download = m_last_download == unset ? -1 + : total_seconds(clock_type::now() - time_point(seconds(m_last_download))); st->storage_mode = static_cast(m_storage_mode); diff --git a/test/test_resume.cpp b/test/test_resume.cpp index 62841ed70..639a9ed8b 100644 --- a/test/test_resume.cpp +++ b/test/test_resume.cpp @@ -99,9 +99,9 @@ std::vector generate_resume_data(torrent_info* ti rd["super_seeding"] = 0; rd["added_time"] = 1347; rd["completed_time"] = 1348; - rd["last_scrape"] = 1349; - rd["last_download"] = 1350; - rd["last_upload"] = 1351; + rd["last_scrape"] = 1; + rd["last_download"] = 2; + rd["last_upload"] = 3; rd["finished_time"] = 1352; 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 // relative times. If the computer is busy while running the unit test // or running under valgrind it may take several seconds - TEST_CHECK(s.last_scrape >= 1349); - TEST_CHECK(s.time_since_download >= 1350); - TEST_CHECK(s.time_since_upload >= 1351); + int const now = duration_cast(clock_type::now().time_since_epoch()).count(); + TEST_CHECK(s.last_scrape >= now - 1); + 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.last_scrape < 1349 + 10); - TEST_CHECK(s.time_since_download < 1350 + 10); - TEST_CHECK(s.time_since_upload < 1351 + 10); + TEST_CHECK(s.last_scrape < now - 1 + 10); + TEST_CHECK(s.time_since_download < now - 2 + 10); + TEST_CHECK(s.time_since_upload < now - 3 + 10); TEST_CHECK(s.active_time < 1339 + 10); TEST_CHECK(s.finished_time >= 1352);