fix multible torrent status timer bugs related to move time (#1492)
fix last_upload and last_download overflow after 9 hours in past. change last_upload, last_download, finished_time, resume, upload_mode_time to time_point and duration
This commit is contained in:
parent
3ef4109bf3
commit
a9d6d54111
|
@ -1,3 +1,4 @@
|
|||
* fix last_upload and last_download overflow after 9 hours in past
|
||||
* python binding add more add_torrent_params fields and an invalid key check
|
||||
* introduce introduce distinct types for peer_class_t, piece_index_t and
|
||||
file_index_t.
|
||||
|
|
|
@ -5,6 +5,7 @@ import libtorrent as lt
|
|||
|
||||
import unittest
|
||||
import time
|
||||
import datetime
|
||||
import os
|
||||
import shutil
|
||||
import binascii
|
||||
|
@ -80,6 +81,18 @@ class test_torrent_handle(unittest.TestCase):
|
|||
self.setup()
|
||||
self.h.clear_piece_deadlines()
|
||||
|
||||
def test_status_last_uploaded_dowloaded(self):
|
||||
# we want to check at seconds precision but can't control session
|
||||
# time, wait for next full second to prevent second increment
|
||||
time.sleep(1 - datetime.datetime.now().microsecond / 1000000.0)
|
||||
|
||||
sessionStart = datetime.datetime.now().replace(microsecond=0)
|
||||
self.setup()
|
||||
st = self.h.status()
|
||||
# last upload and download times are at session start time
|
||||
self.assertEqual(st.last_upload, sessionStart)
|
||||
self.assertEqual(st.last_download, sessionStart)
|
||||
|
||||
def test_torrent_status(self):
|
||||
self.setup()
|
||||
st = self.h.status()
|
||||
|
@ -268,6 +281,7 @@ class test_alerts(unittest.TestCase):
|
|||
'enable_dht': False})
|
||||
ses.async_add_torrent(
|
||||
{"ti": lt.torrent_info("base.torrent"), "save_path": "."})
|
||||
|
||||
# this will cause an error (because of duplicate torrents) and the
|
||||
# torrent_info object created here will be deleted once the alert goes out
|
||||
# of scope. When that happens, it will decrement the python object, to allow
|
||||
|
|
|
@ -95,6 +95,8 @@ namespace libtorrent
|
|||
class bt_peer_connection;
|
||||
struct listen_socket_t;
|
||||
|
||||
using seconds32 = std::chrono::duration<std::int32_t>;
|
||||
|
||||
enum class waste_reason
|
||||
{
|
||||
piece_timed_out, piece_cancelled, piece_unknown, piece_seed
|
||||
|
@ -478,14 +480,15 @@ namespace libtorrent
|
|||
|
||||
void stop_when_ready(bool b);
|
||||
|
||||
int started() const { return m_started; }
|
||||
time_point started() const { return m_started; }
|
||||
void step_session_time(int seconds);
|
||||
void do_pause(bool clear_disk_cache = true);
|
||||
void do_resume();
|
||||
|
||||
int finished_time() const;
|
||||
int active_time() const;
|
||||
int seeding_time() const;
|
||||
seconds32 finished_time() const;
|
||||
seconds32 active_time() const;
|
||||
seconds32 seeding_time() const;
|
||||
seconds32 upload_mode_time() const;
|
||||
|
||||
bool is_paused() const;
|
||||
bool is_torrent_paused() const { return m_paused; }
|
||||
|
@ -496,7 +499,8 @@ namespace libtorrent
|
|||
{
|
||||
// save resume data every 15 minutes regardless, just to
|
||||
// keep stats up to date
|
||||
return m_need_save_resume_data || m_ses.session_time() - m_last_saved_resume > 15 * 60;
|
||||
return m_need_save_resume_data ||
|
||||
aux::time_now() - m_last_saved_resume > minutes(15);
|
||||
}
|
||||
|
||||
void set_need_save_resume()
|
||||
|
@ -1034,7 +1038,7 @@ namespace libtorrent
|
|||
// that are not private
|
||||
void lsd_announce();
|
||||
|
||||
void update_last_upload() { m_last_upload = int16_t(m_ses.session_time()); }
|
||||
void update_last_upload() { m_last_upload = aux::time_now(); }
|
||||
|
||||
void set_apply_ip_filter(bool b);
|
||||
bool apply_ip_filter() const { return m_apply_ip_filter; }
|
||||
|
@ -1314,9 +1318,7 @@ namespace libtorrent
|
|||
// m_num_verified = m_verified.count()
|
||||
std::uint32_t m_num_verified = 0;
|
||||
|
||||
// this timestamp is kept in session-time, to
|
||||
// make it fit in 16 bits
|
||||
std::uint16_t m_last_saved_resume;
|
||||
time_point m_last_saved_resume = aux::time_now();
|
||||
|
||||
// if this torrent is running, this was the time
|
||||
// when it was started. This is used to have a
|
||||
|
@ -1326,15 +1328,15 @@ namespace libtorrent
|
|||
// in session-time. see session_impl for details.
|
||||
// the reference point is stepped forward every 4
|
||||
// hours to keep the timestamps fit in 16 bits
|
||||
std::uint16_t m_started;
|
||||
time_point m_started = aux::time_now();
|
||||
|
||||
// if we're a seed, this is the session time
|
||||
// timestamp of when we became one
|
||||
std::uint16_t m_became_seed = 0;
|
||||
time_point m_became_seed = aux::time_now();
|
||||
|
||||
// if we're finished, this is the session time
|
||||
// timestamp of when we finished
|
||||
std::uint16_t m_became_finished = 0;
|
||||
time_point m_became_finished = aux::time_now();
|
||||
|
||||
// when checking, this is the first piece we have not
|
||||
// issued a hash job for
|
||||
|
@ -1383,7 +1385,7 @@ namespace libtorrent
|
|||
|
||||
// the session time timestamp of when we entered upload mode
|
||||
// if we're currently in upload-mode
|
||||
std::uint16_t m_upload_mode_time = 0;
|
||||
time_point m_upload_mode_time = aux::time_now();
|
||||
|
||||
// true when this torrent should announce to
|
||||
// trackers
|
||||
|
@ -1425,7 +1427,7 @@ namespace libtorrent
|
|||
// paused. specified in seconds. This only track time _before_ we started
|
||||
// the torrent this last time. When the torrent is paused, this counter is
|
||||
// incremented to include this current session.
|
||||
unsigned int m_active_time:24;
|
||||
seconds32 m_active_time;
|
||||
|
||||
// the index to the last tracker that worked
|
||||
std::int8_t m_last_working_tracker = -1;
|
||||
|
@ -1434,7 +1436,7 @@ namespace libtorrent
|
|||
|
||||
// total time we've been finished with this torrent.
|
||||
// does not count when the torrent is stopped or paused.
|
||||
unsigned int m_finished_time:24;
|
||||
seconds32 m_finished_time;
|
||||
|
||||
// in case the piece picker hasn't been constructed
|
||||
// when this settings is set, this variable will keep
|
||||
|
@ -1474,7 +1476,7 @@ namespace libtorrent
|
|||
// accounts for the time prior to the current start of the torrent. When
|
||||
// the torrent is paused, this counter is incremented to account for the
|
||||
// additional seeding time.
|
||||
unsigned int m_seeding_time:24;
|
||||
seconds32 m_seeding_time;
|
||||
|
||||
// ----
|
||||
|
||||
|
@ -1562,7 +1564,7 @@ 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
|
||||
std::int16_t m_last_download = (std::numeric_limits<std::int16_t>::min)();
|
||||
time_point m_last_download = aux::time_now();
|
||||
|
||||
// the number of peer connections to seeds. This should be the same as
|
||||
// counting the peer connections that say true for is_seed()
|
||||
|
@ -1575,7 +1577,7 @@ namespace libtorrent
|
|||
// 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.
|
||||
std::int16_t m_last_upload = (std::numeric_limits<std::int16_t>::min)();
|
||||
time_point m_last_upload = aux::time_now();
|
||||
|
||||
// ----
|
||||
|
||||
|
|
|
@ -546,7 +546,9 @@ namespace libtorrent
|
|||
// the info-hash for this torrent
|
||||
sha1_hash info_hash;
|
||||
|
||||
// This value is not persistent and get set to session start time.
|
||||
time_point last_upload;
|
||||
// This value is not persistent and get set to session start time.
|
||||
time_point last_download;
|
||||
|
||||
seconds active_duration;
|
||||
|
|
|
@ -79,24 +79,294 @@ TORRENT_TEST(status_timers)
|
|||
if ((ticks % 3600) == 0)
|
||||
{
|
||||
lt::time_point const now = lt::clock_type::now();
|
||||
auto const since_start = duration_cast<seconds>(now - start_time) - lt::seconds(1);
|
||||
// finish is 1 tick after start
|
||||
auto const since_finish = duration_cast<seconds>(now - start_time) - lt::seconds(1);
|
||||
torrent_status st = handle.status();
|
||||
TEST_CHECK(st.active_duration == since_start);
|
||||
TEST_CHECK(st.seeding_duration == since_start);
|
||||
TEST_CHECK(st.finished_duration == since_start);
|
||||
TEST_CHECK(st.last_upload < start_time);
|
||||
TEST_EQUAL(st.active_duration.count(), since_finish.count());
|
||||
TEST_EQUAL(st.seeding_duration.count(), since_finish.count());
|
||||
TEST_EQUAL(st.finished_duration.count(), since_finish.count());
|
||||
|
||||
// checking the torrent counts as downloading
|
||||
// eventually though, we've forgotten about it and go back to -1
|
||||
if (since_start > lt::seconds(65000))
|
||||
{
|
||||
TEST_CHECK(st.last_download < start_time);
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: this should really be a proximity-check
|
||||
TEST_CHECK(st.last_download == start_time + lt::seconds(1));
|
||||
}
|
||||
// does not upload without peers
|
||||
TEST_CHECK(st.last_upload == start_time);
|
||||
// does not download in seeding mode
|
||||
TEST_CHECK(st.last_download == start_time);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
TEST_CHECK(ran_to_completion);
|
||||
}
|
||||
|
||||
TORRENT_TEST(status_timers_last_upload)
|
||||
{
|
||||
bool ran_to_completion = false;
|
||||
|
||||
lt::time_point start_time;
|
||||
lt::torrent_handle handle;
|
||||
|
||||
setup_swarm(2, swarm_test::upload
|
||||
// add session
|
||||
, [](lt::settings_pack&) {}
|
||||
// add torrent
|
||||
, [](lt::add_torrent_params&) {}
|
||||
// on alert
|
||||
, [&](lt::alert const* a, lt::session&) {
|
||||
if (auto ta = alert_cast<torrent_added_alert>(a))
|
||||
{
|
||||
TEST_CHECK(!handle.is_valid());
|
||||
start_time = lt::clock_type::now();
|
||||
handle = ta->handle;
|
||||
torrent_status st = handle.status();
|
||||
// test last upload and download state before wo go throgh
|
||||
// torrent states
|
||||
TEST_CHECK(st.last_download == start_time);
|
||||
TEST_CHECK(st.last_upload == start_time);
|
||||
}
|
||||
}
|
||||
// terminate
|
||||
, [&](int ticks, lt::session&) -> bool
|
||||
{
|
||||
if (ticks > 10)
|
||||
{
|
||||
ran_to_completion = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
torrent_status st = handle.status();
|
||||
// uploadtime is 0 seconds behind now
|
||||
TEST_EQUAL(duration_cast<seconds>(st.last_upload - lt::clock_type::now()).count(), 0);
|
||||
// does not download in seeding mode
|
||||
TEST_CHECK(st.last_download == start_time);
|
||||
return false;
|
||||
});
|
||||
TEST_CHECK(ran_to_completion);
|
||||
}
|
||||
|
||||
TORRENT_TEST(status_timers_time_shift_with_active_torrent)
|
||||
{
|
||||
bool ran_to_completion = false;
|
||||
|
||||
lt::time_point start_time;
|
||||
lt::torrent_handle handle;
|
||||
seconds expected_active_duration = seconds(0);
|
||||
bool tick_is_in_active_range = false;
|
||||
int tick_check_intervall = 1;
|
||||
|
||||
setup_swarm(1, swarm_test::upload
|
||||
// add session
|
||||
, [](lt::settings_pack&) {}
|
||||
// add torrent
|
||||
, [](lt::add_torrent_params&) {}
|
||||
// on alert
|
||||
, [&](lt::alert const* a, lt::session&) {
|
||||
if (auto ta = alert_cast<torrent_added_alert>(a))
|
||||
{
|
||||
TEST_CHECK(!handle.is_valid());
|
||||
start_time = lt::clock_type::now();
|
||||
handle = ta->handle;
|
||||
torrent_status st = handle.status();
|
||||
// test last upload and download state before wo go throgh
|
||||
// torrent states
|
||||
TEST_CHECK(st.last_download == start_time);
|
||||
TEST_CHECK(st.last_upload == start_time);
|
||||
}
|
||||
}
|
||||
// terminate
|
||||
, [&](int ticks, lt::session&) -> bool
|
||||
{
|
||||
if(tick_is_in_active_range){
|
||||
// 1 second per tick
|
||||
expected_active_duration++;
|
||||
}
|
||||
|
||||
switch(ticks)
|
||||
{
|
||||
case 0:
|
||||
// torrent get ready for seeding on first tick, means time +1s
|
||||
tick_is_in_active_range = true;
|
||||
break;
|
||||
case 1:
|
||||
// pause after we did have the first upload tick
|
||||
handle.pause();
|
||||
tick_is_in_active_range = false;
|
||||
break;
|
||||
case 64000:
|
||||
// resume just before we hit the time shift handling
|
||||
// this is needed to test what happend if we want to
|
||||
// shift more time then we have active time because
|
||||
// we shift 4 hours and have less then 1 hours active time
|
||||
handle.resume();
|
||||
tick_is_in_active_range = true;
|
||||
// don't check every tick
|
||||
tick_check_intervall = 600;
|
||||
break;
|
||||
case 68000:
|
||||
// simulate at least 68000 seconds because timestamps are
|
||||
// 16 bits counting seconds
|
||||
ran_to_completion = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
// verify that the timers seem correct
|
||||
if (tick_is_in_active_range && (ticks % tick_check_intervall) == 0)
|
||||
{
|
||||
torrent_status st = handle.status();
|
||||
TEST_EQUAL(st.active_duration.count(), expected_active_duration.count());
|
||||
TEST_EQUAL(st.seeding_duration.count(), expected_active_duration.count());
|
||||
TEST_EQUAL(st.finished_duration.count(), expected_active_duration.count());
|
||||
// does not upload without peers
|
||||
TEST_CHECK(st.last_upload == start_time);
|
||||
// does not download in seeding mode
|
||||
TEST_CHECK(st.last_download == start_time);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
TEST_CHECK(ran_to_completion);
|
||||
}
|
||||
|
||||
TORRENT_TEST(finish_time_shift_active)
|
||||
{
|
||||
bool ran_to_completion = false;
|
||||
|
||||
lt::time_point start_time;
|
||||
lt::torrent_handle handle;
|
||||
seconds expected_active_duration = seconds(0);
|
||||
bool tick_is_in_active_range = false;
|
||||
|
||||
setup_swarm(1, swarm_test::upload
|
||||
// add session
|
||||
, [](lt::settings_pack&) {}
|
||||
// add torrent
|
||||
, [](lt::add_torrent_params&) {}
|
||||
// on alert
|
||||
, [&](lt::alert const* a, lt::session&) {
|
||||
if (auto ta = alert_cast<torrent_added_alert>(a))
|
||||
{
|
||||
TEST_CHECK(!handle.is_valid());
|
||||
start_time = lt::clock_type::now();
|
||||
handle = ta->handle;
|
||||
torrent_status st = handle.status();
|
||||
// test last upload and download state before wo go throgh
|
||||
// torrent states
|
||||
TEST_CHECK(st.last_download == start_time);
|
||||
TEST_CHECK(st.last_upload == start_time);
|
||||
}
|
||||
}
|
||||
// terminate
|
||||
, [&](int ticks, lt::session&) -> bool
|
||||
{
|
||||
if(tick_is_in_active_range){
|
||||
// 1 second per tick
|
||||
expected_active_duration++;
|
||||
}
|
||||
|
||||
switch(ticks)
|
||||
{
|
||||
case 0:
|
||||
// torrent get ready for seeding on first tick, means time +1s
|
||||
tick_is_in_active_range = true;
|
||||
break;
|
||||
case 7000:
|
||||
// pause before 4 hours to get a become finish timestamp which
|
||||
// will be clamped
|
||||
handle.pause();
|
||||
// resume to get an become finish update
|
||||
handle.resume();
|
||||
tick_is_in_active_range = true;
|
||||
break;
|
||||
case 70000:
|
||||
// simulate at least 70000 seconds because timestamps are
|
||||
// 16 bits counting seconds
|
||||
ran_to_completion = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
// verify that the timers seem correct
|
||||
if ((ticks % 3600) == 0)
|
||||
{
|
||||
torrent_status st = handle.status();
|
||||
TEST_EQUAL(st.active_duration.count(), expected_active_duration.count());
|
||||
TEST_EQUAL(st.seeding_duration.count(), expected_active_duration.count());
|
||||
TEST_EQUAL(st.finished_duration.count(), expected_active_duration.count());
|
||||
// does not upload without peers
|
||||
TEST_CHECK(st.last_upload == start_time);
|
||||
// does not download in seeding mode
|
||||
TEST_CHECK(st.last_download == start_time);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
TEST_CHECK(ran_to_completion);
|
||||
}
|
||||
|
||||
TORRENT_TEST(finish_time_shift_paused)
|
||||
{
|
||||
bool ran_to_completion = false;
|
||||
|
||||
lt::time_point start_time;
|
||||
lt::torrent_handle handle;
|
||||
seconds expected_active_duration = seconds(0);
|
||||
bool tick_is_in_active_range = false;
|
||||
|
||||
setup_swarm(1, swarm_test::upload
|
||||
// add session
|
||||
, [](lt::settings_pack&) {}
|
||||
// add torrent
|
||||
, [](lt::add_torrent_params&) {}
|
||||
// on alert
|
||||
, [&](lt::alert const* a, lt::session&) {
|
||||
if (auto ta = alert_cast<torrent_added_alert>(a))
|
||||
{
|
||||
TEST_CHECK(!handle.is_valid());
|
||||
start_time = lt::clock_type::now();
|
||||
handle = ta->handle;
|
||||
torrent_status st = handle.status();
|
||||
// test last upload and download state before wo go throgh
|
||||
// torrent states
|
||||
TEST_CHECK(st.last_download == start_time);
|
||||
TEST_CHECK(st.last_upload == start_time);
|
||||
}
|
||||
}
|
||||
// terminate
|
||||
, [&](int ticks, lt::session&) -> bool
|
||||
{
|
||||
if(tick_is_in_active_range){
|
||||
// 1 second per tick
|
||||
expected_active_duration++;
|
||||
}
|
||||
|
||||
switch(ticks)
|
||||
{
|
||||
case 0:
|
||||
// torrent get ready for seeding on first tick, means time +1s
|
||||
tick_is_in_active_range = true;
|
||||
break;
|
||||
case 7000:
|
||||
// pause before 4 hours to get a become finish timestamp which
|
||||
// will be clamped
|
||||
handle.pause();
|
||||
// resume to get an become finish update
|
||||
handle.resume();
|
||||
// pause to test timeshift in paused state
|
||||
handle.pause();
|
||||
tick_is_in_active_range = false;
|
||||
break;
|
||||
case 70000:
|
||||
// simulate at least 70000 seconds because timestamps are
|
||||
// 16 bits counting seconds
|
||||
ran_to_completion = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
// verify that the timers seem correct
|
||||
if (tick_is_in_active_range && (ticks % 3600) == 0)
|
||||
{
|
||||
torrent_status st = handle.status();
|
||||
TEST_EQUAL(st.active_duration.count(), expected_active_duration.count());
|
||||
TEST_EQUAL(st.seeding_duration.count(), expected_active_duration.count());
|
||||
TEST_EQUAL(st.finished_duration.count(), expected_active_duration.count());
|
||||
// does not upload without peers
|
||||
TEST_CHECK(st.last_upload == start_time);
|
||||
// does not download in seeding mode
|
||||
TEST_CHECK(st.last_download == start_time);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
|
164
src/torrent.cpp
164
src/torrent.cpp
|
@ -102,6 +102,9 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#endif
|
||||
|
||||
using namespace std::placeholders;
|
||||
using std::chrono::duration_cast;
|
||||
using std::chrono::seconds;
|
||||
using libtorrent::seconds32;
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
|
@ -121,7 +124,6 @@ namespace libtorrent
|
|||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
constexpr int default_piece_priority = 4;
|
||||
|
||||
} // anonymous namespace
|
||||
|
@ -180,8 +182,8 @@ namespace libtorrent
|
|||
, m_storage_constructor(p.storage)
|
||||
, m_added_time(time(nullptr))
|
||||
, m_info_hash(info_hash)
|
||||
, m_last_saved_resume(ses.session_time())
|
||||
, m_started(ses.session_time())
|
||||
, m_last_saved_resume(aux::time_now())
|
||||
, m_started(aux::time_now())
|
||||
, m_error_file(torrent_status::error_file_none)
|
||||
, m_sequence_number(seq)
|
||||
, m_announce_to_trackers((p.flags & add_torrent_params::flag_paused) == 0)
|
||||
|
@ -373,9 +375,9 @@ namespace libtorrent
|
|||
|
||||
// the number of seconds this torrent has spent in started, finished and
|
||||
// seeding state so far, respectively.
|
||||
m_active_time = p.active_time;
|
||||
m_finished_time = p.finished_time;
|
||||
m_seeding_time = p.seeding_time;
|
||||
m_active_time = seconds(p.active_time);
|
||||
m_finished_time = seconds(p.finished_time);
|
||||
m_seeding_time = seconds(p.seeding_time);
|
||||
|
||||
m_added_time = p.added_time ? p.added_time : time(nullptr);
|
||||
m_completed_time = p.completed_time;
|
||||
|
@ -961,7 +963,7 @@ namespace libtorrent
|
|||
p->cancel_all_requests();
|
||||
}
|
||||
// this is used to try leaving upload only mode periodically
|
||||
m_upload_mode_time = m_ses.session_time();
|
||||
m_upload_mode_time = aux::time_now();
|
||||
}
|
||||
else if (m_peer_list)
|
||||
{
|
||||
|
@ -3849,7 +3851,7 @@ namespace libtorrent
|
|||
// is deallocated by the torrent once it starts seeding
|
||||
}
|
||||
|
||||
m_last_download = m_ses.session_time();
|
||||
m_last_download = aux::time_now();
|
||||
|
||||
if (m_share_mode)
|
||||
recalc_share_mode();
|
||||
|
@ -5950,9 +5952,10 @@ namespace libtorrent
|
|||
ret["total_uploaded"] = m_total_uploaded;
|
||||
ret["total_downloaded"] = m_total_downloaded;
|
||||
|
||||
ret["active_time"] = active_time();
|
||||
ret["finished_time"] = finished_time();
|
||||
ret["seeding_time"] = seeding_time();
|
||||
// cast to seconds in case that internal values doesn't have ratio<1>
|
||||
ret["active_time"] = duration_cast<seconds>(active_time()).count();
|
||||
ret["finished_time"] = duration_cast<seconds>(finished_time()).count();
|
||||
ret["seeding_time"] = duration_cast<seconds>(seeding_time()).count();
|
||||
ret["last_seen_complete"] = m_last_seen_complete;
|
||||
|
||||
ret["num_complete"] = m_complete;
|
||||
|
@ -7241,7 +7244,7 @@ namespace libtorrent
|
|||
set_state(torrent_status::finished);
|
||||
set_queue_position(-1);
|
||||
|
||||
m_became_finished = m_ses.session_time();
|
||||
m_became_finished = aux::time_now();
|
||||
|
||||
// we have to call completed() before we start
|
||||
// disconnecting peers, since there's an assert
|
||||
|
@ -7358,7 +7361,7 @@ namespace libtorrent
|
|||
maybe_done_flushing();
|
||||
|
||||
set_state(torrent_status::seeding);
|
||||
m_became_seed = m_ses.session_time();
|
||||
m_became_seed = aux::time_now();
|
||||
|
||||
if (!m_announcing) return;
|
||||
|
||||
|
@ -8220,14 +8223,14 @@ namespace libtorrent
|
|||
if (a < b) return 0;
|
||||
return std::uint16_t(a - b);
|
||||
}
|
||||
|
||||
#ifndef TORRENT_NO_DEPRECATE
|
||||
std::int16_t clamped_subtract_s16(int a, int b)
|
||||
{
|
||||
if (a + (std::numeric_limits<std::int16_t>::min)() < b)
|
||||
return (std::numeric_limits<std::int16_t>::min)();
|
||||
return std::int16_t(a - b);
|
||||
}
|
||||
|
||||
#endif
|
||||
} // anonymous namespace
|
||||
|
||||
// this is called every time the session timer takes a step back. Since the
|
||||
|
@ -8249,44 +8252,9 @@ namespace libtorrent
|
|||
}
|
||||
}
|
||||
|
||||
// m_active_time, m_seeding_time and m_finished_time are absolute counters
|
||||
// of the historical time we've spent in each state. The current time
|
||||
// we've spent in those states (this session) is calculated by
|
||||
// session_time() - m_started
|
||||
// session_time() - m_became_seed
|
||||
// session_time() - m_became_finished respectively. If any of the
|
||||
// comparison points were pulled back to the oldest representable value (0)
|
||||
// the left-over time must be transferred into the m_*_time counters.
|
||||
|
||||
if (m_started < seconds && !is_paused())
|
||||
{
|
||||
int const lost_seconds = seconds - m_started;
|
||||
m_active_time += lost_seconds;
|
||||
}
|
||||
m_started = clamped_subtract_u16(m_started, seconds);
|
||||
|
||||
if (m_became_seed < seconds && is_seed())
|
||||
{
|
||||
int const lost_seconds = seconds - m_became_seed;
|
||||
m_seeding_time += lost_seconds;
|
||||
}
|
||||
m_became_seed = clamped_subtract_u16(m_became_seed, seconds);
|
||||
|
||||
if (m_became_finished < seconds && is_finished())
|
||||
{
|
||||
int const lost_seconds = seconds - m_became_finished;
|
||||
m_finished_time += lost_seconds;
|
||||
}
|
||||
m_became_finished = clamped_subtract_u16(m_became_finished, seconds);
|
||||
|
||||
m_last_upload = clamped_subtract_s16(m_last_upload, seconds);
|
||||
m_last_download = clamped_subtract_s16(m_last_download, seconds);
|
||||
#ifndef TORRENT_NO_DEPRECATE
|
||||
m_last_scrape = clamped_subtract_s16(m_last_scrape, seconds);
|
||||
#endif
|
||||
|
||||
m_last_saved_resume = clamped_subtract_u16(m_last_saved_resume, seconds);
|
||||
m_upload_mode_time = clamped_subtract_u16(m_upload_mode_time, seconds);
|
||||
}
|
||||
|
||||
// the higher seed rank, the more important to seed
|
||||
|
@ -8308,15 +8276,16 @@ namespace libtorrent
|
|||
|
||||
int ret = 0;
|
||||
|
||||
std::int64_t const fin_time = finished_time();
|
||||
std::int64_t const download_time = int(active_time()) - fin_time;
|
||||
seconds32 const act_time = active_time();
|
||||
seconds32 const fin_time = finished_time();
|
||||
seconds32 const download_time = act_time - fin_time;
|
||||
|
||||
// if we haven't yet met the seed limits, set the seed_ratio_not_met
|
||||
// flag. That will make this seed prioritized
|
||||
// downloaded may be 0 if the torrent is 0-sized
|
||||
std::int64_t const downloaded = (std::max)(m_total_downloaded, m_torrent_file->total_size());
|
||||
if (fin_time < s.get_int(settings_pack::seed_time_limit)
|
||||
&& (download_time > 1
|
||||
if (fin_time < seconds(s.get_int(settings_pack::seed_time_limit))
|
||||
&& (download_time.count() > 1
|
||||
&& fin_time * 100 / download_time < s.get_int(settings_pack::seed_time_ratio_limit))
|
||||
&& downloaded > 0
|
||||
&& m_total_uploaded * 100 / downloaded < s.get_int(settings_pack::share_ratio_limit))
|
||||
|
@ -8324,7 +8293,7 @@ namespace libtorrent
|
|||
|
||||
// if this torrent is running, and it was started less
|
||||
// than 30 minutes ago, give it priority, to avoid oscillation
|
||||
if (!is_paused() && (m_ses.session_time() - m_started) < 30 * 60)
|
||||
if (!is_paused() && act_time < minutes(30))
|
||||
ret |= recently_started;
|
||||
|
||||
// if we have any scrape data, use it to calculate
|
||||
|
@ -8375,7 +8344,7 @@ namespace libtorrent
|
|||
}
|
||||
|
||||
m_need_save_resume_data = false;
|
||||
m_last_saved_resume = m_ses.session_time();
|
||||
m_last_saved_resume = aux::time_now();
|
||||
m_save_resume_flags = std::uint8_t(flags);
|
||||
state_updated();
|
||||
|
||||
|
@ -8472,13 +8441,16 @@ namespace libtorrent
|
|||
update_state_list();
|
||||
update_want_tick();
|
||||
|
||||
m_active_time += m_ses.session_time() - m_started;
|
||||
const time_point now = aux::time_now();
|
||||
|
||||
if (is_seed())
|
||||
m_seeding_time += m_ses.session_time() - m_became_seed;
|
||||
m_active_time +=
|
||||
duration_cast<seconds32>(now - m_started);
|
||||
|
||||
if (is_finished())
|
||||
m_finished_time += m_ses.session_time() - m_became_finished;
|
||||
if (is_seed()) m_seeding_time +=
|
||||
duration_cast<seconds32>(now - m_became_seed);
|
||||
|
||||
if (is_finished()) m_finished_time +=
|
||||
duration_cast<seconds32>(now - m_became_finished);
|
||||
|
||||
m_announce_to_dht = false;
|
||||
m_announce_to_trackers = false;
|
||||
|
@ -8704,7 +8676,7 @@ namespace libtorrent
|
|||
if (alerts().should_post<torrent_resumed_alert>())
|
||||
alerts().emplace_alert<torrent_resumed_alert>(get_handle());
|
||||
|
||||
m_started = m_ses.session_time();
|
||||
m_started = aux::time_now();
|
||||
if (is_seed()) m_became_seed = m_started;
|
||||
if (is_finished()) m_became_finished = m_started;
|
||||
|
||||
|
@ -8893,31 +8865,45 @@ namespace libtorrent
|
|||
announce_with_tracker(tracker_request::stopped);
|
||||
}
|
||||
|
||||
int torrent::finished_time() const
|
||||
seconds32 torrent::finished_time() const
|
||||
{
|
||||
// m_finished_time does not account for the current "session", just the
|
||||
// time before we last started this torrent. To get the current time, we
|
||||
// need to add the time since we started it
|
||||
return m_finished_time + ((!is_finished() || is_paused()) ? 0
|
||||
: (m_ses.session_time() - m_became_finished));
|
||||
if(!is_finished() || is_paused())
|
||||
return m_finished_time;
|
||||
|
||||
return m_finished_time + duration_cast<seconds32>(
|
||||
aux::time_now() - m_became_finished);
|
||||
}
|
||||
|
||||
int torrent::active_time() const
|
||||
seconds32 torrent::active_time() const
|
||||
{
|
||||
if(is_paused())
|
||||
return m_active_time;
|
||||
|
||||
// m_active_time does not account for the current "session", just the
|
||||
// time before we last started this torrent. To get the current time, we
|
||||
// need to add the time since we started it
|
||||
return m_active_time + (is_paused() ? 0
|
||||
: m_ses.session_time() - m_started);
|
||||
return m_active_time + duration_cast<seconds32>(
|
||||
aux::time_now() - m_started);
|
||||
}
|
||||
|
||||
int torrent::seeding_time() const
|
||||
seconds32 torrent::seeding_time() const
|
||||
{
|
||||
if(!is_seed() || is_paused())
|
||||
return m_seeding_time;
|
||||
// m_seeding_time does not account for the current "session", just the
|
||||
// time before we last started this torrent. To get the current time, we
|
||||
// need to add the time since we started it
|
||||
return m_seeding_time + ((!is_seed() || is_paused()) ? 0
|
||||
: m_ses.session_time() - m_became_seed);
|
||||
return m_seeding_time + duration_cast<seconds32>(
|
||||
aux::time_now() - m_became_seed);
|
||||
}
|
||||
|
||||
seconds32 torrent::upload_mode_time() const
|
||||
{
|
||||
if(!m_upload_mode)
|
||||
return seconds32(0);
|
||||
|
||||
return duration_cast<seconds32>(
|
||||
aux::time_now() - m_upload_mode_time);
|
||||
}
|
||||
|
||||
void torrent::second_tick(int tick_interval_ms)
|
||||
|
@ -8940,9 +8926,8 @@ namespace libtorrent
|
|||
// if we're in upload only mode and we're auto-managed
|
||||
// leave upload mode every 10 minutes hoping that the error
|
||||
// condition has been fixed
|
||||
if (m_upload_mode && m_auto_managed
|
||||
&& int(m_ses.session_time() - m_upload_mode_time)
|
||||
>= settings().get_int(settings_pack::optimistic_disk_retry))
|
||||
if (m_upload_mode && m_auto_managed && upload_mode_time() >=
|
||||
seconds(settings().get_int(settings_pack::optimistic_disk_retry)))
|
||||
{
|
||||
set_upload_mode(false);
|
||||
}
|
||||
|
@ -10580,22 +10565,23 @@ namespace libtorrent
|
|||
|
||||
// activity time
|
||||
#ifndef TORRENT_NO_DEPRECATE
|
||||
st->finished_time = finished_time();
|
||||
st->active_time = active_time();
|
||||
st->seeding_time = seeding_time();
|
||||
// cast to seconds in case that internal values doesn't have ratio<1>
|
||||
st->finished_time = int(duration_cast<seconds>(finished_time()).count());
|
||||
st->active_time = int(duration_cast<seconds>(active_time()).count());
|
||||
st->seeding_time = int(duration_cast<seconds>(seeding_time()).count());
|
||||
|
||||
st->time_since_upload = m_last_upload == (std::numeric_limits<std::int16_t>::min)() ? -1
|
||||
: clamped_subtract_u16(m_ses.session_time(), m_last_upload);
|
||||
st->time_since_download = m_last_download == (std::numeric_limits<std::int16_t>::min)() ? -1
|
||||
: clamped_subtract_u16(m_ses.session_time(), m_last_download);
|
||||
st->time_since_upload = int(total_seconds(aux::time_now()
|
||||
- m_last_upload));
|
||||
st->time_since_download = int(total_seconds(aux::time_now()
|
||||
- m_last_download));
|
||||
#endif
|
||||
|
||||
st->finished_duration = seconds{finished_time()};
|
||||
st->active_duration = seconds{active_time()};
|
||||
st->seeding_duration = seconds{seeding_time()};
|
||||
st->finished_duration = finished_time();
|
||||
st->active_duration = active_time();
|
||||
st->seeding_duration = seeding_time();
|
||||
|
||||
st->last_upload = m_ses.session_start_time() + seconds(m_last_upload);
|
||||
st->last_download = m_ses.session_start_time() + seconds(m_last_download);
|
||||
st->last_upload = m_last_upload;
|
||||
st->last_download = m_last_download;
|
||||
|
||||
st->storage_mode = static_cast<storage_mode_t>(m_storage_mode);
|
||||
|
||||
|
|
Loading…
Reference in New Issue