diff --git a/ChangeLog b/ChangeLog index 9c1393027..35a3ae734 100644 --- a/ChangeLog +++ b/ChangeLog @@ -73,6 +73,7 @@ * require C++11 to build libtorrent + * 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/docs/manual.rst b/docs/manual.rst index 1b4b716ba..2ba85b546 100644 --- a/docs/manual.rst +++ b/docs/manual.rst @@ -184,6 +184,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 ======= @@ -261,9 +274,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 ----------------- diff --git a/include/libtorrent/resolver_interface.hpp b/include/libtorrent/resolver_interface.hpp index b01d8724c..3b4590ce1 100644 --- a/include/libtorrent/resolver_interface.hpp +++ b/include/libtorrent/resolver_interface.hpp @@ -48,10 +48,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 useful 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 153021cc9..5940b0566 100644 --- a/src/http_tracker_connection.cpp +++ b/src/http_tracker_connection.cpp @@ -224,8 +224,8 @@ namespace libtorrent { , ps.proxy_tracker_connections ? &ps : nullptr , 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 1ad558368..9c3783dc6 100644 --- a/src/resolver.cpp +++ b/src/resolver.cpp @@ -86,19 +86,6 @@ namespace libtorrent { void resolver::async_resolve(std::string const& host, int const flags , resolver_interface::callback_t const& h) { - auto const 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(std::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; @@ -110,6 +97,27 @@ namespace libtorrent { m_ios.post(std::bind(h, ec, addresses)); return; } + ec.clear(); + + auto const 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(std::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(std::bind(h, boost::asio::error::host_not_found + , std::vector
())); + return; + } // the port is ignored tcp::resolver::query const q(host, "80"); diff --git a/src/udp_tracker_connection.cpp b/src/udp_tracker_connection.cpp index ab188ce9e..fc16bfcac 100644 --- a/src/udp_tracker_connection.cpp +++ b/src/udp_tracker_connection.cpp @@ -103,13 +103,12 @@ namespace libtorrent { { using namespace std::placeholders; ADD_OUTSTANDING_ASYNC("udp_tracker_connection::name_lookup"); - // 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 , std::bind(&udp_tracker_connection::name_lookup , shared_from_this(), _1, _2, port));