From 94701c24da1f1071afc98c70d27ea5c75d6ac56f Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Thu, 25 May 2017 14:58:29 -0400 Subject: [PATCH 1/2] when stopping a torrent, never perform a name lookup on the tracker (#2021) when stopping a torrent, never perform a name lookup on the tracker, only announce to trackers whose IP we already know. This is expected to make shutdowns not hang --- ChangeLog | 1 + include/libtorrent/resolver_interface.hpp | 9 +++--- src/http_tracker_connection.cpp | 4 +-- src/resolver.cpp | 36 ++++++++++++++--------- src/udp_tracker_connection.cpp | 7 ++--- 5 files changed, 33 insertions(+), 24 deletions(-) diff --git a/ChangeLog b/ChangeLog index e975c7308..13311c0f1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,4 @@ + * improve shutdown time by only announcing to trackers whose IP we know * fix python3 portability issue in python binding * delay 5 seconds before reconnecting socks5 proxy for UDP ASSOCIATE * fix NAT-PMP crash when removing a mapping at the wrong time diff --git a/include/libtorrent/resolver_interface.hpp b/include/libtorrent/resolver_interface.hpp index b410465c6..95fedde3b 100644 --- a/include/libtorrent/resolver_interface.hpp +++ b/include/libtorrent/resolver_interface.hpp @@ -53,10 +53,11 @@ struct TORRENT_EXTRA_EXPORT resolver_interface enum flags_t { - // this flag will make async_resolve() always use the cache if we have an - // entry, regardless of how old it is. This is usefull when completing the - // lookup quickly is more important than accuracy - prefer_cache = 1, + // this flag will make async_resolve() only use the cache and fail if we + // don't have a cache entry, regardless of how old it is. This is usefull + // when completing the lookup quickly is more important than accuracy, + // like on shutdown + cache_only = 1, // set this flag for lookups that are not critical during shutdown. i.e. // for looking up tracker names _except_ when stopping a tracker. diff --git a/src/http_tracker_connection.cpp b/src/http_tracker_connection.cpp index 472c1714c..ad39f1e60 100644 --- a/src/http_tracker_connection.cpp +++ b/src/http_tracker_connection.cpp @@ -229,8 +229,8 @@ namespace libtorrent , ps.proxy_tracker_connections ? &ps : NULL , 5, user_agent, bind_interface() , tracker_req().event == tracker_request::stopped - ? resolver_interface::prefer_cache - : resolver_interface::abort_on_shutdown + ? resolver_interface::cache_only : 0 + | resolver_interface::abort_on_shutdown #ifndef TORRENT_NO_DEPRECATE , tracker_req().auth #else diff --git a/src/resolver.cpp b/src/resolver.cpp index a493386eb..4a444ace9 100644 --- a/src/resolver.cpp +++ b/src/resolver.cpp @@ -87,22 +87,9 @@ namespace libtorrent } } - void resolver::async_resolve(std::string const& host, int flags + void resolver::async_resolve(std::string const& host, int const flags , resolver_interface::callback_t const& h) { - cache_t::iterator i = m_cache.find(host); - if (i != m_cache.end()) - { - // keep cache entries valid for m_timeout seconds - if ((flags & resolver_interface::prefer_cache) - || i->second.last_seen + m_timeout >= aux::time_now()) - { - error_code ec; - m_ios.post(boost::bind(h, ec, i->second.addresses)); - return; - } - } - // special handling for raw IP addresses. There's no need to get in line // behind actual lookups if we can just resolve it immediately. error_code ec; @@ -114,6 +101,27 @@ namespace libtorrent m_ios.post(boost::bind(h, ec, addresses)); return; } + ec.clear(); + + cache_t::iterator i = m_cache.find(host); + if (i != m_cache.end()) + { + // keep cache entries valid for m_timeout seconds + if ((flags & resolver_interface::cache_only) + || i->second.last_seen + m_timeout >= aux::time_now()) + { + m_ios.post(boost::bind(h, ec, i->second.addresses)); + return; + } + } + + if (flags & resolver_interface::cache_only) + { + // we did not find a cache entry, fail the lookup + m_ios.post(boost::bind(h, boost::asio::error::host_not_found + , std::vector
())); + return; + } // the port is ignored tcp::resolver::query q(host, "80"); diff --git a/src/udp_tracker_connection.cpp b/src/udp_tracker_connection.cpp index 141f81b34..785ebcbc1 100644 --- a/src/udp_tracker_connection.cpp +++ b/src/udp_tracker_connection.cpp @@ -112,13 +112,12 @@ namespace libtorrent #if defined TORRENT_ASIO_DEBUGGING add_outstanding_async("udp_tracker_connection::name_lookup"); #endif - // when stopping, pass in the prefer cache flag, because we + // when stopping, pass in the cache-only flag, because we // don't want to get stuck on DNS lookups when shutting down - // if we can avoid it m_man.host_resolver().async_resolve(hostname , tracker_req().event == tracker_request::stopped - ? resolver_interface::prefer_cache - : resolver_interface::abort_on_shutdown + ? resolver_interface::cache_only : 0 + | resolver_interface::abort_on_shutdown , boost::bind(&udp_tracker_connection::name_lookup , shared_from_this(), _1, _2, port)); From 7e653b9669e3f839e1a8794bcd07724f5625308a Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Sun, 28 May 2017 11:16:15 -0400 Subject: [PATCH 2/2] extend documentation to cover start_when_ready (#2032) extend documentation to cover start_when_ready and the trick to set all file priorities to 0 on a magnet link --- docs/manual.rst | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/docs/manual.rst b/docs/manual.rst index 678e66e23..63b36bbab 100644 --- a/docs/manual.rst +++ b/docs/manual.rst @@ -186,6 +186,19 @@ The format of the magnet URI is: **magnet:?xt=urn:btih:** *Base16 encoded info-hash* [ **&dn=** *name of download* ] [ **&tr=** *tracker URL* ]* +In order to download *just* the metadata (.torrent file) from a magnet link, set +file priorities to 0 in add_torrent_params::file_priorities. It's OK to set the +priority for more files than what is in the torrent. It may not be trivial to +know how many files a torrent has before the metadata has been downloaded. +Additional file priorities will be ignored. By setting a large number of files +to priority 0, chances are that they will all be set to 0 once the metadata is +received (and we know how many files there are). + +In this case, when the metadata is received from the swarm, the torrent will +still be running, but it will disconnect the majority of peers (since connections +to peers that already have the metadata are redundant). It will keep seeding the +*metadata* only. + queuing ======= @@ -263,9 +276,25 @@ Once a torrent completes checking and moves into a diffferent state, the next in line will be started for checking. Any torrent added force-started or force-stopped (i.e. the auto managed flag is -_not_ set), will not be subject to this limit and they will all check +*not* set), will not be subject to this limit and they will all check independently and in parallel. +Once a torrent completes the checking of its files, or fastresume data, it will +be put in the queue for downloading and potentially start downloading immediately. +In order to add a torrent and check its files without starting the download, it +can be added in ``stop_when_ready`` mode. +See add_torrent_params::flag_stop_when_ready. This flag will stop the torrent +once it is ready to start downloading. + +This is conceptually the same as waiting for the ``torrent_checked_alert`` and +then call:: + + h.auto_managed(false); + h.pause(); + +With the important distinction that it entirely avoids the brief window where +the torrent is in downloading state. + downloading queue -----------------