merged RC_1_1 into master

This commit is contained in:
arvidn 2018-09-04 14:31:05 +02:00
commit 78a344bd8b
19 changed files with 228 additions and 85 deletions

View File

@ -88,6 +88,9 @@
* resume data no longer has timestamps of files
* require C++11 to build libtorrent
* add option to ignore min-interval from trackers on force-reannounce
* raise default setting for active_limit
* fall back to copy+remove if rename_file fails
* improve handling of filesystems not supporting fallocate()
* force-proxy no longer disables DHT
* improve connect-boost feature, to make new torrents quickly connect peers

View File

@ -411,6 +411,7 @@ void bind_converters()
to_python_converter<lt::file_flags_t, from_bitfield_flag<lt::file_flags_t>>();
to_python_converter<lt::create_flags_t, from_bitfield_flag<lt::create_flags_t>>();
to_python_converter<lt::pex_flags_t, from_bitfield_flag<lt::pex_flags_t>>();
to_python_converter<lt::reannounce_flags_t, from_bitfield_flag<lt::reannounce_flags_t>>();
to_python_converter<lt::string_view, from_string_view>();
// work-around types
@ -494,4 +495,5 @@ void bind_converters()
to_bitfield_flag<lt::file_flags_t>();
to_bitfield_flag<lt::create_flags_t>();
to_bitfield_flag<lt::pex_flags_t>();
to_bitfield_flag<lt::reannounce_flags_t>();
}

View File

@ -431,12 +431,13 @@ class dummy4 {};
class dummy6 {};
class dummy7 {};
class dummy8 {};
class dummy15 {};
using by_value = return_value_policy<return_by_value>;
void bind_torrent_handle()
{
// arguments are: number of seconds and tracker index
void (torrent_handle::*force_reannounce0)(int, int) const = &torrent_handle::force_reannounce;
void (torrent_handle::*force_reannounce0)(int, int, reannounce_flags_t) const = &torrent_handle::force_reannounce;
#if TORRENT_ABI_VERSION == 1
bool (torrent_handle::*super_seeding0)() const = &torrent_handle::super_seeding;
@ -474,7 +475,8 @@ void bind_torrent_handle()
;
#endif
class_<torrent_handle>("torrent_handle")
{
scope s = class_<torrent_handle>("torrent_handle")
.def(self == self)
.def(self != self)
.def(self < self)
@ -524,7 +526,7 @@ void bind_torrent_handle()
.def("save_resume_data", _(&torrent_handle::save_resume_data), arg("flags") = 0)
.def("need_save_resume_data", _(&torrent_handle::need_save_resume_data))
.def("force_reannounce", _(force_reannounce0)
, (arg("seconds") = 0, arg("tracker_idx") = -1))
, (arg("seconds") = 0, arg("tracker_idx") = -1, arg("flags") = reannounce_flags_t{}))
#ifndef TORRENT_DISABLE_DHT
.def("force_dht_announce", _(&torrent_handle::force_dht_announce))
#endif
@ -580,6 +582,21 @@ void bind_torrent_handle()
#endif
;
s.attr("ignore_min_interval") = torrent_handle::ignore_min_interval;
s.attr("overwrite_existing") = torrent_handle::overwrite_existing;
s.attr("piece_granularity") = int(torrent_handle::piece_granularity);
s.attr("graceful_pause") = torrent_handle::graceful_pause;
s.attr("flush_disk_cache") = torrent_handle::flush_disk_cache;
s.attr("save_info_dict") = torrent_handle::save_info_dict;
s.attr("only_if_modified") = torrent_handle::only_if_modified;
s.attr("alert_when_available") = torrent_handle::alert_when_available;
s.attr("query_distributed_copies") = torrent_handle::query_distributed_copies;
s.attr("query_accurate_download_counters") = torrent_handle::query_accurate_download_counters;
s.attr("query_last_seen_complete") = torrent_handle::query_last_seen_complete;
s.attr("query_pieces") = torrent_handle::query_pieces;
s.attr("query_verified_pieces") = torrent_handle::query_verified_pieces;
}
class_<open_file_state>("open_file_state")
.add_property("file_index", make_getter((&open_file_state::file_index), by_value()))
.def_readonly("last_use", &open_file_state::last_use)
@ -621,6 +638,11 @@ void bind_torrent_handle()
s.attr("only_if_modified") = torrent_handle::only_if_modified;
}
{
scope s = class_<dummy15>("reannounce_flags_t");
s.attr("ignore_min_interval") = torrent_handle::ignore_min_interval;
}
{
scope s = class_<dummy8>("deadline_flags_t");
s.attr("alert_when_available") = torrent_handle::alert_when_available;

View File

@ -301,7 +301,7 @@ namespace aux {
// returns a pretty-printed string representation
// of the bencoded structure, with JSON-style syntax
std::string to_string() const;
std::string to_string(bool single_line = false) const;
protected:
@ -311,7 +311,7 @@ namespace aux {
private:
void to_string_impl(std::string& out, int indent) const;
void to_string_impl(std::string& out, int indent, bool single_line) const;
aux::aligned_union<1
#if TORRENT_COMPLETE_TYPES_REQUIRED

View File

@ -747,7 +747,7 @@ namespace libtorrent {
void do_connect_boost();
// forcefully sets next_announce to the current time
void force_tracker_request(time_point, int tracker_idx);
void force_tracker_request(time_point, int tracker_idx, reannounce_flags_t flags);
void scrape_tracker(int idx, bool user_triggered);
void announce_with_tracker(std::uint8_t e
= tracker_request::none);

View File

@ -80,6 +80,7 @@ namespace aux {
using pause_flags_t = flags::bitfield_flag<std::uint8_t, struct pause_flags_tag>;
using deadline_flags_t = flags::bitfield_flag<std::uint8_t, struct deadline_flags_tag>;
using resume_data_flags_t = flags::bitfield_flag<std::uint8_t, struct resume_data_flags_tag>;
using reannounce_flags_t = flags::bitfield_flag<std::uint8_t, struct reannounce_flags_tag>;
using queue_position_t = aux::strong_typedef<int, struct queue_position_tag>;
// holds the state of a block in a piece. Who we requested
@ -1020,6 +1021,11 @@ namespace aux {
std::vector<int> file_priorities() const;
#endif
// by default, force-reannounce will still honor the min-interval
// published by the tracker. If this flag is set, it will be ignored
// and the tracker is announced immediately.
static constexpr reannounce_flags_t ignore_min_interval = 0_bit;
// ``force_reannounce()`` will force this torrent to do another tracker
// request, to receive new peers. The ``seconds`` argument specifies how
// many seconds from now to issue the tracker announces.
@ -1032,9 +1038,12 @@ namespace aux {
// The ``tracker_index`` argument specifies which tracker to re-announce.
// If set to -1 (which is the default), all trackers are re-announce.
//
// The ``flags`` argument can be used to affect the re-announce. See
// ignore_min_interval.
//
// ``force_dht_announce`` will announce the torrent to the DHT
// immediately.
void force_reannounce(int seconds = 0, int tracker_index = -1) const;
void force_reannounce(int seconds = 0, int tracker_index = -1, reannounce_flags_t = {}) const;
void force_dht_announce() const;
#if TORRENT_ABI_VERSION == 1

View File

@ -169,7 +169,7 @@ namespace libtorrent {
{
tracker_response()
: interval(1800)
, min_interval(120)
, min_interval(1)
, complete(-1)
, incomplete(-1)
, downloaders(-1)

View File

@ -1679,7 +1679,7 @@ namespace {
if (should_log(peer_log_alert::incoming_message))
{
peer_log(peer_log_alert::incoming_message, "EXTENDED_HANDSHAKE"
, "%s", print_entry(root).c_str());
, "%s", print_entry(root, true).c_str());
}
#endif
@ -2166,7 +2166,7 @@ namespace {
if (should_log(peer_log_alert::outgoing_message))
{
peer_log(peer_log_alert::outgoing_message, "EXTENDED_HANDSHAKE"
, "%s", handshake.to_string().c_str());
, "%s", handshake.to_string(true).c_str());
}
#endif
}

View File

@ -1138,6 +1138,15 @@ constexpr disk_job_flags_t disk_interface::cache_hit;
std::shared_ptr<storage_interface> storage = j->storage;
#ifdef TORRENT_EXPENSIVE_INVARIANT_CHECKS
if (j->storage)
{
std::unique_lock<std::mutex> l(m_cache_mutex);
auto const& pieces = j->storage->cached_pieces();
for (auto const& p : pieces)
TORRENT_ASSERT(p.storage == j->storage);
}
#endif
// TODO: 4 instead of doing this. pass in the settings to each storage_interface
// call. Each disk thread could hold its most recent understanding of the settings
// in a shared_ptr, and update it every time it wakes up from a job. That way
@ -1835,6 +1844,14 @@ constexpr disk_job_flags_t disk_interface::cache_hit;
j->storage = m_torrents[storage]->shared_from_this();
j->callback = std::move(handler);
#ifdef TORRENT_EXPENSIVE_INVARIANT_CHECKS
{
std::unique_lock<std::mutex> l(m_cache_mutex);
auto const& pieces = j->storage->cached_pieces();
for (auto const& p : pieces)
TORRENT_ASSERT(p.storage == j->storage);
}
#endif
add_fence_job(j);
}

View File

@ -662,86 +662,81 @@ namespace {
}
}
std::string entry::to_string() const
std::string entry::to_string(bool const single_line) const
{
std::string ret;
if (type() == dictionary_t) ret.reserve(280);
to_string_impl(ret, 0);
to_string_impl(ret, 0, single_line);
return ret;
}
void entry::to_string_impl(std::string& out, int const indent) const
namespace {
bool is_binary(std::string const& str)
{
for (char const c : str)
{
if (!is_print(c)) return true;
}
return false;
}
void add_indent(std::string& out, int const indent)
{
out.resize(out.size() + size_t(indent), ' ');
}
}
void entry::to_string_impl(std::string& out, int const indent
, bool const single_line) const
{
TORRENT_ASSERT(indent >= 0);
for (int i = 0; i < indent; ++i) out += ' ';
switch (type())
switch (m_type)
{
case int_t:
out += libtorrent::to_string(integer()).data();
out += '\n';
break;
case string_t:
{
bool binary_string = false;
for (auto const i : string())
{
if (!is_print(i))
{
binary_string = true;
break;
}
}
if (binary_string)
{
out += aux::to_hex(string());
out += '\n';
}
else
{
out += string();
out += '\n';
}
out += "'";
if (is_binary(string())) out += aux::to_hex(string());
else out += string();
out += "'";
} break;
case list_t:
{
out += "list\n";
for (auto const& i : list())
out += single_line ? "[ " : "[\n";
bool first = true;
for (list_type::const_iterator i = list().begin(); i != list().end(); ++i)
{
i.to_string_impl(out, indent + 1);
if (!first) out += single_line ? ", " : ",\n";
first = false;
if (!single_line) add_indent(out, indent+1);
i->to_string_impl(out, indent+1, single_line);
}
out += " ]";
} break;
case dictionary_t:
{
out += "dictionary\n";
for (auto const& i : dict())
out += single_line ? "{ " : "{\n";
bool first = true;
for (dictionary_type::const_iterator i = dict().begin(); i != dict().end(); ++i)
{
bool binary_string = false;
for (auto const k : i.first)
{
if (!is_print(k))
{
binary_string = true;
break;
}
}
for (int j = 0; j < indent + 1; ++j) out += ' ';
out += '[';
if (binary_string) out += aux::to_hex(i.first);
else out += i.first;
out += ']';
if (!first) out += single_line ? ", " : ",\n";
first = false;
if (!single_line) add_indent(out, indent+1);
out += "'";
if (is_binary(i->first)) out += aux::to_hex(i->first);
else out += i->first;
out += "': ";
if (i.second.type() != entry::string_t
&& i.second.type() != entry::int_t)
out += '\n';
else out += ' ';
i.second.to_string_impl(out, indent + 2);
i->second.to_string_impl(out, indent+2, single_line);
}
out += " }";
} break;
case preformatted_t:
out += "<preformatted>\n";
out += "<preformatted>";
break;
case undefined_t:
out += "<uninitialized>\n";
out += "<uninitialized>";
}
}
}

View File

@ -1748,14 +1748,13 @@ namespace libtorrent {
t->unchoke_peer(*this);
}
#ifndef TORRENT_DISABLE_LOGGING
else
else if (should_log(peer_log_alert::info))
{
if (should_log(peer_log_alert::info))
{
peer_log(peer_log_alert::info, "UNCHOKE", "did not unchoke, the number of uploads (%d) "
"is more than or equal to the limit (%d)"
, m_ses.num_uploads(), m_settings.get_int(settings_pack::unchoke_slots_limit));
}
peer_log(peer_log_alert::info, "UNCHOKE", "did not unchoke, the number of uploads (%d) "
"is more than or equal to the available slots (%d), limit (%d)"
, int(m_counters[counters::num_peers_up_unchoked])
, int(m_counters[counters::num_unchoke_slots])
, m_settings.get_int(settings_pack::unchoke_slots_limit));
}
#endif
}

View File

@ -248,7 +248,7 @@ namespace {
set.set_int(settings_pack::peer_timeout, 20);
set.set_int(settings_pack::inactivity_timeout, 20);
set.set_int(settings_pack::active_limit, 2000);
set.set_int(settings_pack::active_limit, 20000);
set.set_int(settings_pack::active_tracker_limit, 2000);
set.set_int(settings_pack::active_dht_limit, 600);
set.set_int(settings_pack::active_seeds, 2000);

View File

@ -258,7 +258,7 @@ constexpr int CLOSE_FILE_INTERVAL = 0;
SET(active_dht_limit, 88, nullptr),
SET(active_tracker_limit, 1600, nullptr),
SET(active_lsd_limit, 60, nullptr),
SET(active_limit, 15, &session_impl::trigger_auto_manage),
SET(active_limit, 500, &session_impl::trigger_auto_manage),
DEPRECATED_SET(active_loaded_limit, 0, &session_impl::trigger_auto_manage),
SET(auto_manage_interval, 30, nullptr),
SET(seed_time_limit, 24 * 60 * 60, nullptr),

View File

@ -398,9 +398,18 @@ namespace libtorrent {
if (ec)
{
ec.file(index);
ec.operation = operation_t::file_rename;
return;
ec.ec.clear();
copy_file(old_name, new_path, ec.ec);
if (ec)
{
ec.file(index);
ec.operation = operation_t::file_rename;
return;
}
error_code ignore;
remove(old_name, ignore);
}
}
else if (ec.ec)

View File

@ -3147,10 +3147,12 @@ bool is_downloading_state(int const st)
}
debug_log("TRACKER RESPONSE\n"
"interval: %d\n"
"min-interval: %d\n"
"external ip: %s\n"
"resolved to: %s\n"
"we connected to: %s\n"
, interval.count()
, resp.min_interval.count()
, print_address(resp.external_ip).c_str()
, resolved_to.c_str()
, print_address(tracker_ip).c_str());
@ -3325,7 +3327,8 @@ bool is_downloading_state(int const st)
// this is the entry point for the client to force a re-announce. It's
// considered a client-initiated announce (as opposed to the regular ones,
// issued by libtorrent)
void torrent::force_tracker_request(time_point const t, int const tracker_idx)
void torrent::force_tracker_request(time_point const t, int const tracker_idx
, reannounce_flags_t const flags)
{
TORRENT_ASSERT_PRECOND((tracker_idx >= 0
&& tracker_idx < int(m_trackers.size()))
@ -3338,8 +3341,10 @@ bool is_downloading_state(int const st)
{
for (auto& aep : e.endpoints)
{
aep.next_announce = std::max(time_point_cast<seconds32>(t)
, aep.min_announce) + seconds(1);
aep.next_announce = (flags & torrent_handle::ignore_min_interval)
? time_point_cast<seconds32>(t) + seconds32(1)
: std::max(time_point_cast<seconds32>(t), aep.min_announce) + seconds32(1);
aep.min_announce = aep.next_announce;
aep.triggered_manually = true;
}
}
@ -3351,8 +3356,10 @@ bool is_downloading_state(int const st)
announce_entry& e = m_trackers[tracker_idx];
for (auto& aep : e.endpoints)
{
aep.next_announce = std::max(time_point_cast<seconds32>(t)
, aep.min_announce) + seconds32(1);
aep.next_announce = (flags & torrent_handle::ignore_min_interval)
? time_point_cast<seconds32>(t) + seconds32(1)
: std::max(time_point_cast<seconds32>(t), aep.min_announce) + seconds32(1);
aep.min_announce = aep.next_announce;
aep.triggered_manually = true;
}
}

View File

@ -66,6 +66,7 @@ namespace libtorrent {
constexpr pause_flags_t torrent_handle::graceful_pause;
constexpr pause_flags_t torrent_handle::clear_disk_cache;
constexpr deadline_flags_t torrent_handle::alert_when_available;
constexpr reannounce_flags_t torrent_handle::ignore_min_interval;
constexpr status_flags_t torrent_handle::query_distributed_copies;
constexpr status_flags_t torrent_handle::query_accurate_download_counters;
@ -732,7 +733,7 @@ namespace libtorrent {
boost::posix_time::time_duration duration) const
{
async_call(&torrent::force_tracker_request, aux::time_now()
+ seconds(duration.total_seconds()), -1);
+ seconds(duration.total_seconds()), -1, reannounce_flags_t{});
}
void torrent_handle::file_status(std::vector<open_file_state>& status) const
@ -753,9 +754,9 @@ namespace libtorrent {
#endif
}
void torrent_handle::force_reannounce(int s, int idx) const
void torrent_handle::force_reannounce(int s, int idx, reannounce_flags_t const flags) const
{
async_call(&torrent::force_tracker_request, aux::time_now() + seconds(s), idx);
async_call(&torrent::force_tracker_request, aux::time_now() + seconds(s), idx, flags);
}
std::vector<open_file_state> torrent_handle::file_status() const

View File

@ -263,8 +263,6 @@ namespace libtorrent {
TORRENT_ASSERT(req.num_want >= 0);
TORRENT_ASSERT(!m_abort || req.event == tracker_request::stopped);
if (m_abort && req.event != tracker_request::stopped) return;
if (req.event == tracker_request::stopped)
req.num_want = 0;
#ifndef TORRENT_DISABLE_LOGGING
std::shared_ptr<request_callback> cb = c.lock();

View File

@ -147,6 +147,87 @@ TORRENT_TEST(implicit_construct)
}
#if TORRENT_ABI_VERSION == 1
TORRENT_TEST(print_dict_single_line)
{
entry e;
e["foo"] = "bar";
e["bar"] = "foo";
TEST_EQUAL(e.to_string(true), "{ 'bar': 'foo', 'foo': 'bar' }");
}
TORRENT_TEST(print_dict)
{
entry e;
e["foo"] = "bar";
e["bar"] = "foo";
TEST_EQUAL(e.to_string(), "{\n 'bar': 'foo',\n 'foo': 'bar' }");
}
TORRENT_TEST(print_list_single_line)
{
entry e;
e.list().push_back(entry("foo"));
e.list().push_back(entry("bar"));
TEST_EQUAL(e.to_string(true), "[ 'foo', 'bar' ]");
}
TORRENT_TEST(print_list)
{
entry e;
e.list().push_back(entry("foo"));
e.list().push_back(entry("bar"));
TEST_EQUAL(e.to_string(), "[\n 'foo',\n 'bar' ]");
}
TORRENT_TEST(print_int_single_line)
{
entry e(1337);
TEST_EQUAL(e.to_string(true), "1337");
}
TORRENT_TEST(print_int)
{
entry e(1337);
TEST_EQUAL(e.to_string(), "1337");
}
TORRENT_TEST(print_string_single_line)
{
entry e("foobar");
TEST_EQUAL(e.to_string(true), "'foobar'");
}
TORRENT_TEST(print_string)
{
entry e("foobar");
TEST_EQUAL(e.to_string(), "'foobar'");
}
TORRENT_TEST(print_deep_dict_single_line)
{
entry e;
e["strings"].list().push_back(entry("foo"));
e["strings"].list().push_back(entry("bar"));
e["ints"].list().push_back(entry(1));
e["ints"].list().push_back(entry(2));
e["ints"].list().push_back(entry(3));
e["a"] = "foobar";
TEST_EQUAL(e.to_string(true), "{ 'a': 'foobar', 'ints': [ 1, 2, 3 ], 'strings': [ 'foo', 'bar' ] }");
}
TORRENT_TEST(print_deep_dict)
{
entry e;
e["strings"].list().push_back(entry("foo"));
e["strings"].list().push_back(entry("bar"));
e["ints"].list().push_back(entry(1));
e["ints"].list().push_back(entry(2));
e["ints"].list().push_back(entry(3));
e["a"] = "foobar";
TEST_EQUAL(e.to_string(), "{\n 'a': 'foobar',\n 'ints': [\n 1,\n 2,\n 3 ],\n 'strings': [\n 'foo',\n 'bar' ] }");
}
TORRENT_TEST(lazy_entry)
{
{

View File

@ -132,7 +132,7 @@ void test_remove_torrent(remove_flags_t const remove_options
|| st2.state == torrent_status::checking_resume_data);
// if nothing is being transferred after 3 seconds, we're failing the test
if (st1.upload_payload_rate == 0 && i > 30)
if (st1.total_payload_upload == 0 && i > 30)
{
TEST_ERROR("no transfer");
return;