merged RC_1_1 into master
This commit is contained in:
commit
8621477239
|
@ -753,6 +753,8 @@ void bind_session()
|
||||||
.def_readwrite("added_time", &add_torrent_params::added_time)
|
.def_readwrite("added_time", &add_torrent_params::added_time)
|
||||||
.def_readwrite("completed_time", &add_torrent_params::completed_time)
|
.def_readwrite("completed_time", &add_torrent_params::completed_time)
|
||||||
.def_readwrite("last_seen_complete", &add_torrent_params::last_seen_complete)
|
.def_readwrite("last_seen_complete", &add_torrent_params::last_seen_complete)
|
||||||
|
.def_readwrite("last_download", &add_torrent_params::last_download)
|
||||||
|
.def_readwrite("last_upload", &add_torrent_params::last_upload)
|
||||||
.def_readwrite("num_complete", &add_torrent_params::num_complete)
|
.def_readwrite("num_complete", &add_torrent_params::num_complete)
|
||||||
.def_readwrite("num_incomplete", &add_torrent_params::num_incomplete)
|
.def_readwrite("num_incomplete", &add_torrent_params::num_incomplete)
|
||||||
.def_readwrite("num_downloaded", &add_torrent_params::num_downloaded)
|
.def_readwrite("num_downloaded", &add_torrent_params::num_downloaded)
|
||||||
|
|
|
@ -167,9 +167,11 @@ class test_torrent_handle(unittest.TestCase):
|
||||||
sessionStart = datetime.datetime.now().replace(microsecond=0)
|
sessionStart = datetime.datetime.now().replace(microsecond=0)
|
||||||
self.setup()
|
self.setup()
|
||||||
st = self.h.status()
|
st = self.h.status()
|
||||||
|
for attr in dir(st):
|
||||||
|
print('%s: %s' % (attr, getattr(st, attr)))
|
||||||
# last upload and download times are at session start time
|
# last upload and download times are at session start time
|
||||||
self.assertLessEqual(abs(st.last_upload - sessionStart), datetime.timedelta(seconds=1))
|
self.assertEqual(st.last_upload, None)
|
||||||
self.assertLessEqual(abs(st.last_download - sessionStart), datetime.timedelta(seconds=1))
|
self.assertEqual(st.last_download, None)
|
||||||
|
|
||||||
def test_serialize_trackers(self):
|
def test_serialize_trackers(self):
|
||||||
"""Test to ensure the dict contains only python built-in types"""
|
"""Test to ensure the dict contains only python built-in types"""
|
||||||
|
|
|
@ -434,6 +434,12 @@ The file format is a bencoded dictionary containing the following fields:
|
||||||
| ``seeding_time`` | integer. The number of seconds this torrent has been active |
|
| ``seeding_time`` | integer. The number of seconds this torrent has been active |
|
||||||
| | and seeding. |
|
| | and seeding. |
|
||||||
+--------------------------+--------------------------------------------------------------+
|
+--------------------------+--------------------------------------------------------------+
|
||||||
|
| ``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. |
|
||||||
|
+--------------------------+--------------------------------------------------------------+
|
||||||
| ``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. |
|
||||||
+--------------------------+--------------------------------------------------------------+
|
+--------------------------+--------------------------------------------------------------+
|
||||||
|
|
|
@ -331,6 +331,9 @@ namespace libtorrent {
|
||||||
// applied before the torrent is added.
|
// applied before the torrent is added.
|
||||||
aux::noexcept_movable<std::map<file_index_t, std::string>> renamed_files;
|
aux::noexcept_movable<std::map<file_index_t, std::string>> renamed_files;
|
||||||
|
|
||||||
|
std::time_t last_download = 0;
|
||||||
|
std::time_t last_upload = 0;
|
||||||
|
|
||||||
#ifndef TORRENT_NO_DEPRECATE
|
#ifndef TORRENT_NO_DEPRECATE
|
||||||
// deprecated in 1.2
|
// deprecated in 1.2
|
||||||
|
|
||||||
|
|
|
@ -195,7 +195,7 @@ namespace detail {
|
||||||
break;
|
break;
|
||||||
case entry::preformatted_t:
|
case entry::preformatted_t:
|
||||||
std::copy(e.preformatted().begin(), e.preformatted().end(), out);
|
std::copy(e.preformatted().begin(), e.preformatted().end(), out);
|
||||||
ret += int(e.preformatted().size());
|
ret += static_cast<int>(e.preformatted().size());
|
||||||
break;
|
break;
|
||||||
case entry::undefined_t:
|
case entry::undefined_t:
|
||||||
|
|
||||||
|
|
|
@ -442,7 +442,8 @@ namespace aux {
|
||||||
// used to convert dirty blocks into non-dirty ones
|
// used to convert dirty blocks into non-dirty ones
|
||||||
// i.e. from being part of the write cache to being part
|
// i.e. from being part of the write cache to being part
|
||||||
// of the read cache. it's used when flushing blocks to disk
|
// of the read cache. it's used when flushing blocks to disk
|
||||||
void blocks_flushed(cached_piece_entry* pe, int const* flushed, int num_flushed);
|
// returns true if the piece entry was freed
|
||||||
|
bool blocks_flushed(cached_piece_entry* pe, int const* flushed, int num_flushed);
|
||||||
|
|
||||||
// adds a block to the cache, marks it as dirty and
|
// adds a block to the cache, marks it as dirty and
|
||||||
// associates the job with it. When the block is
|
// associates the job with it. When the block is
|
||||||
|
|
|
@ -450,7 +450,8 @@ namespace aux {
|
||||||
, span<iovec_t> iov, span<int> flushing, int block_base_index = 0);
|
, span<iovec_t> iov, span<int> flushing, int block_base_index = 0);
|
||||||
void flush_iovec(cached_piece_entry* pe, span<iovec_t const> iov, span<int const> flushing
|
void flush_iovec(cached_piece_entry* pe, span<iovec_t const> iov, span<int const> flushing
|
||||||
, int num_blocks, storage_error& error);
|
, int num_blocks, storage_error& error);
|
||||||
void iovec_flushed(cached_piece_entry* pe
|
// returns true if the piece entry was freed
|
||||||
|
bool iovec_flushed(cached_piece_entry* pe
|
||||||
, int* flushing, int num_blocks, int block_offset
|
, int* flushing, int num_blocks, int block_offset
|
||||||
, storage_error const& error
|
, storage_error const& error
|
||||||
, jobqueue_t& completed_jobs);
|
, jobqueue_t& completed_jobs);
|
||||||
|
|
|
@ -1620,9 +1620,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
|
time_point32 m_last_download{seconds32(0)};
|
||||||
time_point32 m_last_download = aux::time_now32();
|
|
||||||
|
|
||||||
// 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()
|
||||||
|
@ -1633,9 +1632,8 @@ namespace libtorrent {
|
||||||
std::uint16_t m_num_connecting_seeds = 0;
|
std::uint16_t m_num_connecting_seeds = 0;
|
||||||
|
|
||||||
// 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.
|
time_point32 m_last_upload{seconds32(0)};
|
||||||
time_point32 m_last_upload = aux::time_now32();
|
|
||||||
|
|
||||||
// ----
|
// ----
|
||||||
|
|
||||||
|
@ -1667,7 +1665,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
|
||||||
std::int16_t m_last_scrape = (std::numeric_limits<std::int16_t>::min)();
|
time_point32 m_last_scrape{seconds32(0)};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// ----
|
// ----
|
||||||
|
|
|
@ -588,9 +588,7 @@ namespace libtorrent {
|
||||||
// the info-hash for this torrent
|
// the info-hash for this torrent
|
||||||
sha1_hash info_hash;
|
sha1_hash info_hash;
|
||||||
|
|
||||||
// This value is not persistent and get set to session start time.
|
|
||||||
time_point last_upload;
|
time_point last_upload;
|
||||||
// This value is not persistent and get set to session start time.
|
|
||||||
time_point last_download;
|
time_point last_download;
|
||||||
|
|
||||||
seconds active_duration;
|
seconds active_duration;
|
||||||
|
|
|
@ -97,9 +97,9 @@ TORRENT_TEST(status_timers)
|
||||||
TEST_EQUAL(st.finished_duration.count(), since_finish.count());
|
TEST_EQUAL(st.finished_duration.count(), since_finish.count());
|
||||||
|
|
||||||
// does not upload without peers
|
// does not upload without peers
|
||||||
TEST_CHECK(st.last_upload == start_time);
|
TEST_CHECK(st.last_upload == time_point(seconds(0)));
|
||||||
// does not download in seeding mode
|
// does not download in seeding mode
|
||||||
TEST_CHECK(st.last_download == start_time);
|
TEST_CHECK(st.last_download == time_point(seconds(0)));
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
@ -110,7 +110,6 @@ TORRENT_TEST(status_timers_last_upload)
|
||||||
{
|
{
|
||||||
bool ran_to_completion = false;
|
bool ran_to_completion = false;
|
||||||
|
|
||||||
lt::time_point32 start_time;
|
|
||||||
lt::torrent_handle handle;
|
lt::torrent_handle handle;
|
||||||
|
|
||||||
setup_swarm(2, swarm_test::upload
|
setup_swarm(2, swarm_test::upload
|
||||||
|
@ -123,13 +122,12 @@ TORRENT_TEST(status_timers_last_upload)
|
||||||
if (auto ta = alert_cast<add_torrent_alert>(a))
|
if (auto ta = alert_cast<add_torrent_alert>(a))
|
||||||
{
|
{
|
||||||
TEST_CHECK(!handle.is_valid());
|
TEST_CHECK(!handle.is_valid());
|
||||||
start_time = time_now();
|
|
||||||
handle = ta->handle;
|
handle = ta->handle;
|
||||||
torrent_status st = handle.status();
|
torrent_status st = handle.status();
|
||||||
// test last upload and download state before wo go throgh
|
// test last upload and download state before wo go throgh
|
||||||
// torrent states
|
// torrent states
|
||||||
TEST_CHECK(st.last_download == start_time);
|
TEST_CHECK(st.last_upload == time_point(seconds(0)));
|
||||||
TEST_CHECK(st.last_upload == start_time);
|
TEST_CHECK(st.last_download == time_point(seconds(0)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// terminate
|
// terminate
|
||||||
|
@ -145,7 +143,7 @@ TORRENT_TEST(status_timers_last_upload)
|
||||||
// uploadtime is 0 seconds behind now
|
// uploadtime is 0 seconds behind now
|
||||||
TEST_CHECK(eq(st.last_upload, time_now()));
|
TEST_CHECK(eq(st.last_upload, time_now()));
|
||||||
// does not download in seeding mode
|
// does not download in seeding mode
|
||||||
TEST_CHECK(eq(st.last_download, start_time));
|
TEST_CHECK(st.last_download == time_point(seconds(0)));
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
TEST_CHECK(ran_to_completion);
|
TEST_CHECK(ran_to_completion);
|
||||||
|
@ -155,7 +153,6 @@ TORRENT_TEST(status_timers_time_shift_with_active_torrent)
|
||||||
{
|
{
|
||||||
bool ran_to_completion = false;
|
bool ran_to_completion = false;
|
||||||
|
|
||||||
lt::time_point32 start_time;
|
|
||||||
lt::torrent_handle handle;
|
lt::torrent_handle handle;
|
||||||
seconds expected_active_duration = seconds(1);
|
seconds expected_active_duration = seconds(1);
|
||||||
bool tick_is_in_active_range = false;
|
bool tick_is_in_active_range = false;
|
||||||
|
@ -171,13 +168,12 @@ TORRENT_TEST(status_timers_time_shift_with_active_torrent)
|
||||||
if (auto ta = alert_cast<add_torrent_alert>(a))
|
if (auto ta = alert_cast<add_torrent_alert>(a))
|
||||||
{
|
{
|
||||||
TEST_CHECK(!handle.is_valid());
|
TEST_CHECK(!handle.is_valid());
|
||||||
start_time = time_now();
|
|
||||||
handle = ta->handle;
|
handle = ta->handle;
|
||||||
torrent_status st = handle.status();
|
torrent_status st = handle.status();
|
||||||
// test last upload and download state before wo go throgh
|
// test last upload and download state before wo go throgh
|
||||||
// torrent states
|
// torrent states
|
||||||
TEST_CHECK(st.last_download == start_time);
|
TEST_CHECK(st.last_download == time_point(seconds(0)));
|
||||||
TEST_CHECK(st.last_upload == start_time);
|
TEST_CHECK(st.last_upload == time_point(seconds(0)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// terminate
|
// terminate
|
||||||
|
@ -224,9 +220,9 @@ TORRENT_TEST(status_timers_time_shift_with_active_torrent)
|
||||||
TEST_EQUAL(st.seeding_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());
|
TEST_EQUAL(st.finished_duration.count(), expected_active_duration.count());
|
||||||
// does not upload without peers
|
// does not upload without peers
|
||||||
TEST_CHECK(st.last_upload == start_time);
|
TEST_CHECK(st.last_upload == time_point(seconds(0)));
|
||||||
// does not download in seeding mode
|
// does not download in seeding mode
|
||||||
TEST_CHECK(st.last_download == start_time);
|
TEST_CHECK(st.last_download == time_point(seconds(0)));
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
@ -237,7 +233,6 @@ TORRENT_TEST(finish_time_shift_active)
|
||||||
{
|
{
|
||||||
bool ran_to_completion = false;
|
bool ran_to_completion = false;
|
||||||
|
|
||||||
lt::time_point32 start_time;
|
|
||||||
lt::torrent_handle handle;
|
lt::torrent_handle handle;
|
||||||
seconds expected_active_duration = seconds(1);
|
seconds expected_active_duration = seconds(1);
|
||||||
bool tick_is_in_active_range = false;
|
bool tick_is_in_active_range = false;
|
||||||
|
@ -252,13 +247,12 @@ TORRENT_TEST(finish_time_shift_active)
|
||||||
if (auto ta = alert_cast<add_torrent_alert>(a))
|
if (auto ta = alert_cast<add_torrent_alert>(a))
|
||||||
{
|
{
|
||||||
TEST_CHECK(!handle.is_valid());
|
TEST_CHECK(!handle.is_valid());
|
||||||
start_time = time_now();
|
|
||||||
handle = ta->handle;
|
handle = ta->handle;
|
||||||
torrent_status st = handle.status();
|
torrent_status st = handle.status();
|
||||||
// test last upload and download state before wo go throgh
|
// test last upload and download state before wo go throgh
|
||||||
// torrent states
|
// torrent states
|
||||||
TEST_CHECK(st.last_download == start_time);
|
TEST_CHECK(st.last_download == time_point(seconds(0)));
|
||||||
TEST_CHECK(st.last_upload == start_time);
|
TEST_CHECK(st.last_upload == time_point(seconds(0)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// terminate
|
// terminate
|
||||||
|
@ -298,9 +292,9 @@ TORRENT_TEST(finish_time_shift_active)
|
||||||
TEST_EQUAL(st.seeding_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());
|
TEST_EQUAL(st.finished_duration.count(), expected_active_duration.count());
|
||||||
// does not upload without peers
|
// does not upload without peers
|
||||||
TEST_CHECK(st.last_upload == start_time);
|
TEST_CHECK(st.last_upload == time_point(seconds(0)));
|
||||||
// does not download in seeding mode
|
// does not download in seeding mode
|
||||||
TEST_CHECK(st.last_download == start_time);
|
TEST_CHECK(st.last_download == time_point(seconds(0)));
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
@ -311,7 +305,6 @@ TORRENT_TEST(finish_time_shift_paused)
|
||||||
{
|
{
|
||||||
bool ran_to_completion = false;
|
bool ran_to_completion = false;
|
||||||
|
|
||||||
lt::time_point32 start_time;
|
|
||||||
lt::torrent_handle handle;
|
lt::torrent_handle handle;
|
||||||
seconds expected_active_duration = seconds(1);
|
seconds expected_active_duration = seconds(1);
|
||||||
bool tick_is_in_active_range = false;
|
bool tick_is_in_active_range = false;
|
||||||
|
@ -326,13 +319,12 @@ TORRENT_TEST(finish_time_shift_paused)
|
||||||
if (auto ta = alert_cast<add_torrent_alert>(a))
|
if (auto ta = alert_cast<add_torrent_alert>(a))
|
||||||
{
|
{
|
||||||
TEST_CHECK(!handle.is_valid());
|
TEST_CHECK(!handle.is_valid());
|
||||||
start_time = time_now();
|
|
||||||
handle = ta->handle;
|
handle = ta->handle;
|
||||||
torrent_status st = handle.status();
|
torrent_status st = handle.status();
|
||||||
// test last upload and download state before wo go throgh
|
// test last upload and download state before wo go throgh
|
||||||
// torrent states
|
// torrent states
|
||||||
TEST_CHECK(eq(st.last_download, start_time));
|
TEST_CHECK(st.last_upload == time_point(seconds(0)));
|
||||||
TEST_CHECK(eq(st.last_upload, start_time));
|
TEST_CHECK(st.last_download == time_point(seconds(0)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// terminate
|
// terminate
|
||||||
|
@ -374,9 +366,9 @@ TORRENT_TEST(finish_time_shift_paused)
|
||||||
TEST_EQUAL(st.seeding_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());
|
TEST_EQUAL(st.finished_duration.count(), expected_active_duration.count());
|
||||||
// does not upload without peers
|
// does not upload without peers
|
||||||
TEST_CHECK(st.last_upload == start_time);
|
TEST_CHECK(st.last_upload == time_point(seconds(0)));
|
||||||
// does not download in seeding mode
|
// does not download in seeding mode
|
||||||
TEST_CHECK(st.last_download == start_time);
|
TEST_CHECK(st.last_download == time_point(seconds(0)));
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
|
@ -766,7 +766,7 @@ cached_piece_entry* block_cache::add_dirty_block(disk_io_job* j)
|
||||||
// (since these blocks now are part of the read cache) the refcounts of the
|
// (since these blocks now are part of the read cache) the refcounts of the
|
||||||
// blocks are also decremented by this function. They are expected to have been
|
// blocks are also decremented by this function. They are expected to have been
|
||||||
// incremented by the caller.
|
// incremented by the caller.
|
||||||
void block_cache::blocks_flushed(cached_piece_entry* pe, int const* flushed, int num_flushed)
|
bool block_cache::blocks_flushed(cached_piece_entry* pe, int const* flushed, int num_flushed)
|
||||||
{
|
{
|
||||||
TORRENT_PIECE_ASSERT(pe->in_use, pe);
|
TORRENT_PIECE_ASSERT(pe->in_use, pe);
|
||||||
|
|
||||||
|
@ -790,7 +790,7 @@ void block_cache::blocks_flushed(cached_piece_entry* pe, int const* flushed, int
|
||||||
pe->num_dirty -= num_flushed;
|
pe->num_dirty -= num_flushed;
|
||||||
|
|
||||||
update_cache_state(pe);
|
update_cache_state(pe);
|
||||||
maybe_free_piece(pe);
|
return maybe_free_piece(pe);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<block_cache::const_iterator, block_cache::const_iterator> block_cache::all_pieces() const
|
std::pair<block_cache::const_iterator, block_cache::const_iterator> block_cache::all_pieces() const
|
||||||
|
|
|
@ -62,9 +62,10 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
#define DEBUG_DISK_THREAD 0
|
#define DEBUG_DISK_THREAD 0
|
||||||
|
|
||||||
#if DEBUG_DISK_THREAD
|
#if DEBUG_DISK_THREAD
|
||||||
#include <cstdarg>
|
#include <cstdarg> // for va_list
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <cstdio> // for vsnprintf
|
#include <cstdio> // for vsnprintf
|
||||||
|
|
||||||
#define DLOG(...) debug_log(__VA_ARGS__)
|
#define DLOG(...) debug_log(__VA_ARGS__)
|
||||||
#else
|
#else
|
||||||
#define DLOG(...) do {} while(false)
|
#define DLOG(...) do {} while(false)
|
||||||
|
@ -727,7 +728,7 @@ constexpr disk_job_flags_t disk_interface::cache_hit;
|
||||||
// It is necessary to call this function with the blocks produced by
|
// It is necessary to call this function with the blocks produced by
|
||||||
// build_iovec, to reset their state to not being flushed anymore
|
// build_iovec, to reset their state to not being flushed anymore
|
||||||
// the cache needs to be locked when calling this function
|
// the cache needs to be locked when calling this function
|
||||||
void disk_io_thread::iovec_flushed(cached_piece_entry* pe
|
bool disk_io_thread::iovec_flushed(cached_piece_entry* pe
|
||||||
, int* flushing, int const num_blocks, int const block_offset
|
, int* flushing, int const num_blocks, int const block_offset
|
||||||
, storage_error const& error
|
, storage_error const& error
|
||||||
, jobqueue_t& completed_jobs)
|
, jobqueue_t& completed_jobs)
|
||||||
|
@ -742,7 +743,8 @@ constexpr disk_job_flags_t disk_interface::cache_hit;
|
||||||
DLOG("%d ", flushing[i]);
|
DLOG("%d ", flushing[i]);
|
||||||
DLOG("]\n");
|
DLOG("]\n");
|
||||||
#endif
|
#endif
|
||||||
m_disk_cache.blocks_flushed(pe, flushing, num_blocks);
|
if (m_disk_cache.blocks_flushed(pe, flushing, num_blocks))
|
||||||
|
return true;
|
||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
|
@ -770,6 +772,8 @@ constexpr disk_job_flags_t disk_interface::cache_hit;
|
||||||
j = next;
|
j = next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// issues write operations for blocks in the given
|
// issues write operations for blocks in the given
|
||||||
|
@ -802,9 +806,8 @@ constexpr disk_job_flags_t disk_interface::cache_hit;
|
||||||
flush_iovec(pe, iov, flushing, iov_len, error);
|
flush_iovec(pe, iov, flushing, iov_len, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
iovec_flushed(pe, flushing.data(), iov_len, 0, error, completed_jobs);
|
if (!iovec_flushed(pe, flushing.data(), iov_len, 0, error, completed_jobs))
|
||||||
|
m_disk_cache.maybe_free_piece(pe);
|
||||||
m_disk_cache.maybe_free_piece(pe);
|
|
||||||
|
|
||||||
// if the cache is under high pressure, we need to evict
|
// if the cache is under high pressure, we need to evict
|
||||||
// the blocks we just flushed to make room for more write pieces
|
// the blocks we just flushed to make room for more write pieces
|
||||||
|
|
|
@ -121,6 +121,9 @@ namespace {
|
||||||
|
|
||||||
ret.last_seen_complete = std::time_t(rd.dict_find_int_value("last_seen_complete"));
|
ret.last_seen_complete = std::time_t(rd.dict_find_int_value("last_seen_complete"));
|
||||||
|
|
||||||
|
ret.last_download = rd.dict_find_int_value("last_download", 0);
|
||||||
|
ret.last_upload = rd.dict_find_int_value("last_upload", 0);
|
||||||
|
|
||||||
// scrape data cache
|
// scrape data cache
|
||||||
ret.num_complete = int(rd.dict_find_int_value("num_complete", -1));
|
ret.num_complete = int(rd.dict_find_int_value("num_complete", -1));
|
||||||
ret.num_incomplete = int(rd.dict_find_int_value("num_incomplete", -1));
|
ret.num_incomplete = int(rd.dict_find_int_value("num_incomplete", -1));
|
||||||
|
|
|
@ -308,6 +308,8 @@ namespace {
|
||||||
atp.seeding_time = resume_data.seeding_time;
|
atp.seeding_time = resume_data.seeding_time;
|
||||||
|
|
||||||
atp.last_seen_complete = resume_data.last_seen_complete;
|
atp.last_seen_complete = resume_data.last_seen_complete;
|
||||||
|
atp.last_upload = resume_data.last_upload;
|
||||||
|
atp.last_download = resume_data.last_download;
|
||||||
atp.url = resume_data.url;
|
atp.url = resume_data.url;
|
||||||
atp.uuid = resume_data.uuid;
|
atp.uuid = resume_data.uuid;
|
||||||
|
|
||||||
|
|
|
@ -97,6 +97,8 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
// for logging stat layout
|
// for logging stat layout
|
||||||
#include "libtorrent/stat.hpp"
|
#include "libtorrent/stat.hpp"
|
||||||
|
|
||||||
|
#include <cstdarg> // for va_list
|
||||||
|
|
||||||
// for logging the size of DHT structures
|
// for logging the size of DHT structures
|
||||||
#ifndef TORRENT_DISABLE_DHT
|
#ifndef TORRENT_DISABLE_DHT
|
||||||
#include <libtorrent/kademlia/find_data.hpp>
|
#include <libtorrent/kademlia/find_data.hpp>
|
||||||
|
|
|
@ -181,6 +181,8 @@ bool is_downloading_state(int const st)
|
||||||
, bool const session_paused
|
, bool const session_paused
|
||||||
, add_torrent_params const& p)
|
, add_torrent_params const& p)
|
||||||
: torrent_hot_members(ses, p, session_paused)
|
: torrent_hot_members(ses, p, session_paused)
|
||||||
|
, m_total_uploaded(p.total_uploaded)
|
||||||
|
, m_total_downloaded(p.total_downloaded)
|
||||||
, m_tracker_timer(ses.get_io_service())
|
, m_tracker_timer(ses.get_io_service())
|
||||||
, m_inactivity_timer(ses.get_io_service())
|
, m_inactivity_timer(ses.get_io_service())
|
||||||
, m_trackerid(p.trackerid)
|
, m_trackerid(p.trackerid)
|
||||||
|
@ -224,6 +226,8 @@ bool is_downloading_state(int const st)
|
||||||
, m_announce_to_dht(!(p.flags & torrent_flags::paused))
|
, m_announce_to_dht(!(p.flags & torrent_flags::paused))
|
||||||
, m_ssl_torrent(false)
|
, m_ssl_torrent(false)
|
||||||
, m_deleted(false)
|
, m_deleted(false)
|
||||||
|
, m_last_download(seconds32(p.last_download))
|
||||||
|
, m_last_upload(seconds32(p.last_upload))
|
||||||
, m_auto_managed(p.flags & torrent_flags::auto_managed)
|
, m_auto_managed(p.flags & torrent_flags::auto_managed)
|
||||||
, m_current_gauge_state(static_cast<std::uint32_t>(no_gauge_state))
|
, m_current_gauge_state(static_cast<std::uint32_t>(no_gauge_state))
|
||||||
, m_moving_storage(false)
|
, m_moving_storage(false)
|
||||||
|
@ -2968,7 +2972,7 @@ bool is_downloading_state(int const st)
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(is_single_thread());
|
TORRENT_ASSERT(is_single_thread());
|
||||||
#ifndef TORRENT_NO_DEPRECATE
|
#ifndef TORRENT_NO_DEPRECATE
|
||||||
m_last_scrape = std::int16_t(m_ses.session_time());
|
m_last_scrape = aux::time_now32();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (m_trackers.empty()) return;
|
if (m_trackers.empty()) return;
|
||||||
|
@ -3151,7 +3155,7 @@ bool is_downloading_state(int const st)
|
||||||
|
|
||||||
#ifndef TORRENT_NO_DEPRECATE
|
#ifndef TORRENT_NO_DEPRECATE
|
||||||
if (resp.complete >= 0 && resp.incomplete >= 0)
|
if (resp.complete >= 0 && resp.incomplete >= 0)
|
||||||
m_last_scrape = std::int16_t(m_ses.session_time());
|
m_last_scrape = aux::time_now32();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef TORRENT_DISABLE_LOGGING
|
#ifndef TORRENT_DISABLE_LOGGING
|
||||||
|
@ -6110,6 +6114,8 @@ bool is_downloading_state(int const st)
|
||||||
ret.finished_time = static_cast<int>(total_seconds(finished_time()));
|
ret.finished_time = static_cast<int>(total_seconds(finished_time()));
|
||||||
ret.seeding_time = static_cast<int>(total_seconds(seeding_time()));
|
ret.seeding_time = static_cast<int>(total_seconds(seeding_time()));
|
||||||
ret.last_seen_complete = m_last_seen_complete;
|
ret.last_seen_complete = m_last_seen_complete;
|
||||||
|
ret.last_upload = total_seconds(m_last_upload.time_since_epoch());
|
||||||
|
ret.last_download = total_seconds(m_last_download.time_since_epoch());
|
||||||
|
|
||||||
ret.num_complete = m_complete;
|
ret.num_complete = m_complete;
|
||||||
ret.num_incomplete = m_incomplete;
|
ret.num_incomplete = m_incomplete;
|
||||||
|
@ -8296,14 +8302,7 @@ bool is_downloading_state(int const st)
|
||||||
if (a < b) return 0;
|
if (a < b) return 0;
|
||||||
return std::uint16_t(a - b);
|
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
|
} // 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
|
||||||
|
@ -8324,10 +8323,6 @@ bool is_downloading_state(int const st)
|
||||||
pe->last_connected = clamped_subtract_u16(pe->last_connected, seconds);
|
pe->last_connected = clamped_subtract_u16(pe->last_connected, seconds);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef TORRENT_NO_DEPRECATE
|
|
||||||
m_last_scrape = clamped_subtract_s16(m_last_scrape, seconds);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// the higher seed rank, the more important to seed
|
// the higher seed rank, the more important to seed
|
||||||
|
@ -10637,8 +10632,7 @@ bool is_downloading_state(int const st)
|
||||||
st->completed_time = m_completed_time;
|
st->completed_time = m_completed_time;
|
||||||
|
|
||||||
#ifndef TORRENT_NO_DEPRECATE
|
#ifndef TORRENT_NO_DEPRECATE
|
||||||
st->last_scrape = m_last_scrape == std::numeric_limits<std::int16_t>::min() ? -1
|
st->last_scrape = static_cast<int>(total_seconds(aux::time_now32() - m_last_scrape));
|
||||||
: clamped_subtract_u16(m_ses.session_time(), m_last_scrape);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef TORRENT_NO_DEPRECATE
|
#ifndef TORRENT_NO_DEPRECATE
|
||||||
|
@ -10667,10 +10661,12 @@ bool is_downloading_state(int const st)
|
||||||
st->active_time = int(total_seconds(active_time()));
|
st->active_time = int(total_seconds(active_time()));
|
||||||
st->seeding_time = int(total_seconds(seeding_time()));
|
st->seeding_time = int(total_seconds(seeding_time()));
|
||||||
|
|
||||||
st->time_since_upload = int(total_seconds(aux::time_now()
|
time_point32 const unset{seconds32(0)};
|
||||||
- m_last_upload));
|
|
||||||
st->time_since_download = int(total_seconds(aux::time_now()
|
st->time_since_upload = m_last_upload == unset ? -1
|
||||||
- m_last_download));
|
: static_cast<int>(total_seconds(aux::time_now32() - m_last_upload));
|
||||||
|
st->time_since_download = m_last_download == unset ? -1
|
||||||
|
: static_cast<int>(total_seconds(aux::time_now32() - m_last_download));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
st->finished_duration = finished_time();
|
st->finished_duration = finished_time();
|
||||||
|
|
|
@ -63,6 +63,8 @@ namespace libtorrent {
|
||||||
ret["finished_time"] = atp.finished_time;
|
ret["finished_time"] = atp.finished_time;
|
||||||
ret["seeding_time"] = atp.seeding_time;
|
ret["seeding_time"] = atp.seeding_time;
|
||||||
ret["last_seen_complete"] = atp.last_seen_complete;
|
ret["last_seen_complete"] = atp.last_seen_complete;
|
||||||
|
ret["last_download"] = atp.last_download;
|
||||||
|
ret["last_upload"] = atp.last_upload;
|
||||||
|
|
||||||
ret["num_complete"] = atp.num_complete;
|
ret["num_complete"] = atp.num_complete;
|
||||||
ret["num_incomplete"] = atp.num_incomplete;
|
ret["num_incomplete"] = atp.num_incomplete;
|
||||||
|
|
|
@ -111,6 +111,8 @@ 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_download"] = 2;
|
||||||
|
rd["last_upload"] = 3;
|
||||||
rd["finished_time"] = 1352;
|
rd["finished_time"] = 1352;
|
||||||
if (file_priorities && file_priorities[0])
|
if (file_priorities && file_priorities[0])
|
||||||
{
|
{
|
||||||
|
@ -208,6 +210,13 @@ void default_tests(torrent_status const& s)
|
||||||
#ifndef TORRENT_NO_DEPRECATE
|
#ifndef TORRENT_NO_DEPRECATE
|
||||||
TEST_CHECK(s.active_time >= 1339);
|
TEST_CHECK(s.active_time >= 1339);
|
||||||
TEST_CHECK(s.active_time < 1339 + 10);
|
TEST_CHECK(s.active_time < 1339 + 10);
|
||||||
|
|
||||||
|
auto const now = duration_cast<seconds>(clock_type::now().time_since_epoch()).count();
|
||||||
|
TEST_CHECK(s.time_since_download >= now - 2);
|
||||||
|
TEST_CHECK(s.time_since_upload >= now - 3);
|
||||||
|
|
||||||
|
TEST_CHECK(s.time_since_download < now - 2 + 10);
|
||||||
|
TEST_CHECK(s.time_since_upload < now - 3 + 10);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
using lt::seconds;
|
using lt::seconds;
|
||||||
|
|
Loading…
Reference in New Issue