From 56925ee8f3d0ded7a44f00260aa59c4b75901c33 Mon Sep 17 00:00:00 2001 From: arvidn Date: Sun, 26 Feb 2017 09:31:27 -0500 Subject: [PATCH 1/6] fix openssl include in makefile --- examples/Makefile.am | 2 +- test/Makefile.am | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/Makefile.am b/examples/Makefile.am index 5b65febbf..7d8b11a5c 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -30,7 +30,7 @@ upnp_test_SOURCES = upnp_test.cpp LDADD = $(top_builddir)/src/libtorrent-rasterbar.la -AM_CPPFLAGS = -ftemplate-depth-50 -I$(top_srcdir)/include @DEBUGFLAGS@ +AM_CPPFLAGS = -ftemplate-depth-50 -I$(top_srcdir)/include @DEBUGFLAGS@ @OPENSSL_INCLUDES@ AM_LDFLAGS = @BOOST_SYSTEM_LIB@ @BOOST_CHRONO_LIB@ @BOOST_RANDOM_LIB@ @OPENSSL_LDFLAGS@ @OPENSSL_LIBS@ diff --git a/test/Makefile.am b/test/Makefile.am index b7b6cc0f1..66eacbcc4 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -239,7 +239,7 @@ test_ed25519_SOURCES = test_ed25519.cpp LDADD = libtest.la $(top_builddir)/src/libtorrent-rasterbar.la #AM_CXXFLAGS=-ftemplate-depth-50 -I$(top_srcdir)/include -I$(top_srcdir)/include/libtorrent @DEBUGFLAGS@ @PTHREAD_CFLAGS@ -AM_CPPFLAGS=-ftemplate-depth-50 -I$(top_srcdir)/include @DEBUGFLAGS@ +AM_CPPFLAGS=-ftemplate-depth-50 -I$(top_srcdir)/include @DEBUGFLAGS@ @OPENSSL_INCLUDES@ AM_LDFLAGS=@BOOST_SYSTEM_LIB@ @PTHREAD_LIBS@ @OPENSSL_LDFLAGS@ @OPENSSL_LIBS@ \ @BOOST_CHRONO_LIB@ From 9d645055ff9ee28833f3309e3ef68519734e8e57 Mon Sep 17 00:00:00 2001 From: arvidn Date: Sun, 26 Feb 2017 17:57:12 -0500 Subject: [PATCH 2/6] fix storage tick invariant check failure --- src/torrent.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/torrent.cpp b/src/torrent.cpp index 56109e1af..de58f8e28 100644 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -10295,11 +10295,14 @@ namespace libtorrent if (m_storage_tick > 0 && is_loaded()) { --m_storage_tick; - if (m_storage_tick == 0 && m_storage) + if (m_storage_tick == 0) { - m_ses.disk_thread().async_tick_torrent(&storage() - , boost::bind(&torrent::on_disk_tick_done - , shared_from_this(), _1)); + if (m_storage) + { + m_ses.disk_thread().async_tick_torrent(&storage() + , boost::bind(&torrent::on_disk_tick_done + , shared_from_this(), _1)); + } update_want_tick(); } } From a42d4390c0e10e8f23556abe1e9cefdb383a2488 Mon Sep 17 00:00:00 2001 From: arvidn Date: Sun, 26 Feb 2017 23:38:57 -0500 Subject: [PATCH 3/6] remove unused images from docs --- Makefile.am | 4 ---- docs/disk_io.png | Bin 4393 -> 0 bytes docs/im_thumb.jpg | Bin 12093 -> 0 bytes docs/session_stats_peers.png | Bin 3902 -> 0 bytes docs/ziptorrent_thumb.gif | Bin 6827 -> 0 bytes 5 files changed, 4 deletions(-) delete mode 100644 docs/disk_io.png delete mode 100644 docs/im_thumb.jpg delete mode 100644 docs/session_stats_peers.png delete mode 100644 docs/ziptorrent_thumb.gif diff --git a/Makefile.am b/Makefile.am index 2cc50a7a8..aa8bd6aa5 100644 --- a/Makefile.am +++ b/Makefile.am @@ -10,20 +10,16 @@ DOCS_IMAGES = \ docs/cwnd_thumb.png \ docs/delays.png \ docs/delays_thumb.png \ - docs/disk_io.png \ docs/hacking.html \ - docs/im_thumb.jpg \ docs/merkle_tree.png \ docs/our_delay_base.png \ docs/our_delay_base_thumb.png \ docs/read_disk_buffers.png \ docs/read_disk_buffers.diagram \ - docs/session_stats_peers.png \ docs/storage.png \ docs/todo.html \ docs/write_disk_buffers.png \ docs/write_disk_buffers.diagram \ - docs/ziptorrent_thumb.gif \ docs/ip_id_v4.png \ docs/ip_id_v6.png \ docs/hash_distribution.png \ diff --git a/docs/disk_io.png b/docs/disk_io.png deleted file mode 100644 index 0ec82d167b789fa1cc5d6523896ee8c7342a26ea..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4393 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 UJ!8IhfySoOL1PE@Iyr0y) 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 I0D$)Y06UXIumAu6 From 9a63d4696ebec5743418181ef3411371d8e31b04 Mon Sep 17 00:00:00 2001 From: Steven Siloti Date: Tue, 28 Feb 2017 20:25:41 -0800 Subject: [PATCH 4/6] mark connection as upload only manually instead of with set_upload_only() We can't call set_upload_only() in this context because it can trigger an invariant check in the torrent and m_num_connecting is not consistent. --- src/web_connection_base.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/web_connection_base.cpp b/src/web_connection_base.cpp index 9391db38e..a3f0683d6 100644 --- a/src/web_connection_base.cpp +++ b/src/web_connection_base.cpp @@ -113,7 +113,11 @@ namespace libtorrent void web_connection_base::start() { - set_upload_only(true); + // avoid calling torrent::set_seed because it calls torrent::check_invariant + // which fails because the m_num_connecting count is not consistent until + // after we call peer_connection::start + m_upload_only = true; + disconnect_if_redundant(); if (is_disconnecting()) return; peer_connection::start(); } From af07ce1f2533f52e9d21a9952308d8cd753db3c3 Mon Sep 17 00:00:00 2001 From: arvidn Date: Sun, 5 Mar 2017 19:23:10 -0500 Subject: [PATCH 5/6] fix issue with peers not updated on metadata from magnet links --- ChangeLog | 2 ++ src/torrent.cpp | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index a17b19d93..cc9f76f34 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,5 @@ + * fix issue with peers not updated on metadata from magnet links + 1.1.2 release * default TOS marking to 0x20 diff --git a/src/torrent.cpp b/src/torrent.cpp index de58f8e28..a447f271e 100644 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -8770,6 +8770,7 @@ namespace libtorrent } #endif + bool const notify_initialized = !m_connections_initialized; m_connections_initialized = true; m_files_checked = true; @@ -8783,7 +8784,7 @@ namespace libtorrent // all peer connections have to initialize themselves now that the metadata // is available - if (!m_connections_initialized) + if (notify_initialized) { if (pc->is_disconnecting()) continue; pc->on_metadata_impl(); From faa2029f8b1ff390b82437ff4aacbeaceeb1a69e Mon Sep 17 00:00:00 2001 From: arvidn Date: Tue, 28 Feb 2017 18:06:02 -0500 Subject: [PATCH 6/6] add feature to periodically close files (to make windows clear disk cache) --- ChangeLog | 2 + include/libtorrent/aux_/session_impl.hpp | 7 ++ include/libtorrent/file_pool.hpp | 12 +++- include/libtorrent/settings_pack.hpp | 9 +++ simulation/Jamfile | 1 + simulation/test_file_pool.cpp | 86 ++++++++++++++++++++++++ src/file_pool.cpp | 17 +++++ src/session_impl.cpp | 26 +++++++ src/settings_pack.cpp | 7 ++ src/torrent_handle.cpp | 2 +- 10 files changed, 167 insertions(+), 2 deletions(-) create mode 100644 simulation/test_file_pool.cpp diff --git a/ChangeLog b/ChangeLog index cc9f76f34..5f9a48279 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,5 @@ + * add feature to periodically close files (to make windows clear disk cache) + * fix bug in torrent_handle::file_status * fix issue with peers not updated on metadata from magnet links 1.1.2 release diff --git a/include/libtorrent/aux_/session_impl.hpp b/include/libtorrent/aux_/session_impl.hpp index 1e43d38d2..11e067604 100644 --- a/include/libtorrent/aux_/session_impl.hpp +++ b/include/libtorrent/aux_/session_impl.hpp @@ -649,6 +649,7 @@ namespace libtorrent void update_privileged_ports(); void update_auto_sequential(); void update_max_failcount(); + void update_close_file_interval(); void update_upnp(); void update_natpmp(); @@ -976,6 +977,7 @@ namespace libtorrent int m_peak_down_rate; void on_tick(error_code const& e); + void on_close_file(error_code const& e); void try_connect_more_peers(); void auto_manage_checking_torrents(std::vector& list @@ -1123,6 +1125,11 @@ namespace libtorrent // by Local service discovery deadline_timer m_lsd_announce_timer; + // this is the timer used to call ``close_oldest`` on the ``file_pool`` + // object. This closes the file that's been opened the longest every + // time it's called, to force the windows disk cache to be flushed + deadline_timer m_close_file_timer; + resolver m_host_resolver; // the index of the torrent that will be offered to diff --git a/include/libtorrent/file_pool.hpp b/include/libtorrent/file_pool.hpp index c213898b9..f4bfe2c75 100644 --- a/include/libtorrent/file_pool.hpp +++ b/include/libtorrent/file_pool.hpp @@ -109,6 +109,12 @@ namespace libtorrent void set_low_prio_io(bool b) { m_low_prio_io = b; } void get_status(std::vector* files, void* st) const; + // close the file that was opened least recently (i.e. not *accessed* + // least recently). The purpose is to make the OS (really just windows) + // clear and flush its disk cache associated with this file. We don't want + // any file to stay open for too long, allowing the disk cache to accrue. + void close_oldest(); + #if TORRENT_USE_ASSERTS bool assert_idle_files(void* st) const; @@ -127,8 +133,12 @@ namespace libtorrent struct lru_file_entry { - lru_file_entry(): last_use(aux::time_now()), mode(0) {} + lru_file_entry() + : opened(aux::time_now()) + , last_use(opened) + , mode(0) {} file_handle file_ptr; + time_point const opened; time_point last_use; int mode; }; diff --git a/include/libtorrent/settings_pack.hpp b/include/libtorrent/settings_pack.hpp index 0dc760402..6938a200d 100644 --- a/include/libtorrent/settings_pack.hpp +++ b/include/libtorrent/settings_pack.hpp @@ -1594,6 +1594,15 @@ namespace libtorrent // time to wait until a new retry of a web seed name lookup web_seed_name_lookup_retry, + // the number of seconds between closing the file opened the longest + // ago. 0 means to disable the feature. The purpose of this is to + // periodically close files to trigger the operating system flushing + // disk cache. Specifically it has been observed to be required on + // windows to not have the disk cache grow indefinitely. + // This defaults to 120 seconds on windows, and disabled on other + // systems. + close_file_interval, + max_int_setting_internal }; diff --git a/simulation/Jamfile b/simulation/Jamfile index 09b85f76b..6c7f0c74b 100644 --- a/simulation/Jamfile +++ b/simulation/Jamfile @@ -46,5 +46,6 @@ alias libtorrent-sims : [ run test_tracker.cpp ] [ run test_ip_filter.cpp ] [ run test_fast_extensions.cpp ] + [ run test_file_pool.cpp ] ; diff --git a/simulation/test_file_pool.cpp b/simulation/test_file_pool.cpp new file mode 100644 index 000000000..16d8eb051 --- /dev/null +++ b/simulation/test_file_pool.cpp @@ -0,0 +1,86 @@ +/* + +Copyright (c) 2008, Arvid Norberg +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + * Neither the name of the author nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +*/ + +#include "setup_swarm.hpp" +#include "test.hpp" +#include "utils.hpp" +#include "libtorrent/alert.hpp" +#include "libtorrent/alert_types.hpp" +#include "libtorrent/session.hpp" +#include "libtorrent/session_stats.hpp" +#include "libtorrent/file.hpp" + +using namespace libtorrent; + +TORRENT_TEST(close_file_interval) +{ + bool ran_to_completion = false; + + // with seed mode + setup_swarm(2, swarm_test::download + // add session + , [](lt::settings_pack& pack) { + pack.set_int(settings_pack::close_file_interval, 20); + } + // add torrent + , [](lt::add_torrent_params&) {} + // on alert + , [](lt::alert const* a, lt::session& ses) {} + // terminate + , [&](int ticks, lt::session& ses) -> bool + { + // terminate after 40 seconds + if (ticks > 25) + { + ran_to_completion = true; + return true; + } + + torrent_handle h = ses.get_torrents().front(); + std::vector file_status; + h.file_status(file_status); + printf("%d: %d files\n", ticks, int(file_status.size())); + if (ticks > 0 && ticks < 19) + { + TEST_EQUAL(file_status.size(), 1); + } + else if (ticks > 21) + { + // the close file timer shuold have kicked in at 20 seconds + // and closed the file + TEST_EQUAL(file_status.size(), 0); + } + return false; + }); + TEST_CHECK(ran_to_completion); +} + diff --git a/src/file_pool.cpp b/src/file_pool.cpp index cf644dd39..3582798aa 100644 --- a/src/file_pool.cpp +++ b/src/file_pool.cpp @@ -329,5 +329,22 @@ namespace libtorrent remove_oldest(l); } + void file_pool::close_oldest() + { + mutex::scoped_lock l(m_mutex); + + file_set::iterator i = std::min_element(m_files.begin(), m_files.end() + , boost::bind(&lru_file_entry::opened, boost::bind(&file_set::value_type::second, _1)) + < boost::bind(&lru_file_entry::opened, boost::bind(&file_set::value_type::second, _2))); + if (i == m_files.end()) return; + + file_handle file_ptr = i->second.file_ptr; + m_files.erase(i); + + // closing a file may be long running operation (mac os x) + l.unlock(); + file_ptr.reset(); + l.lock(); + } } diff --git a/src/session_impl.cpp b/src/session_impl.cpp index bd0f29d4e..10d632263 100644 --- a/src/session_impl.cpp +++ b/src/session_impl.cpp @@ -426,6 +426,7 @@ namespace aux { , m_boost_connections(0) , m_timer(m_io_service) , m_lsd_announce_timer(m_io_service) + , m_close_file_timer(m_io_service) , m_host_resolver(m_io_service) , m_next_downloading_connect_torrent(0) , m_next_finished_connect_torrent(0) @@ -1094,6 +1095,8 @@ namespace aux { // about to send event=stopped to m_host_resolver.abort(); + m_close_file_timer.cancel(); + // abort the main thread m_abort = true; error_code ec; @@ -3565,6 +3568,16 @@ retry: // m_peer_pool.release_memory(); } + void session_impl::on_close_file(error_code const& e) + { + if (e) return; + + m_disk_thread.files().close_oldest(); + + // re-issue the timer + update_close_file_interval(); + } + namespace { // returns the index of the first set bit. int log2(boost::uint32_t v) @@ -5454,6 +5467,19 @@ retry: } } + void session_impl::update_close_file_interval() + { + int const interval = m_settings.get_int(settings_pack::close_file_interval); + if (interval == 0 || m_abort) + { + m_close_file_timer.cancel(); + return; + } + error_code ec; + m_close_file_timer.expires_from_now(seconds(interval), ec); + m_close_file_timer.async_wait(make_tick_handler(boost::bind(&session_impl::on_close_file, this, _1))); + } + void session_impl::update_proxy() { // in case we just set a socks proxy, we might have to diff --git a/src/settings_pack.cpp b/src/settings_pack.cpp index a51419dfb..8513d5132 100644 --- a/src/settings_pack.cpp +++ b/src/settings_pack.cpp @@ -124,6 +124,12 @@ namespace libtorrent #ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Winvalid-offsetof" +#endif + +#ifdef TORRENT_WINDOWS +#define CLOSE_FILE_INTERVAL 120 +#else +#define CLOSE_FILE_INTERVAL 0 #endif namespace { @@ -350,6 +356,7 @@ namespace libtorrent SET_NOPREV(cache_size_volatile, 256, 0), SET_NOPREV(urlseed_max_request_bytes, 16 * 1024 * 1024, 0), SET_NOPREV(web_seed_name_lookup_retry, 1800, 0), + SET_NOPREV(close_file_interval, CLOSE_FILE_INTERVAL, &session_impl::update_close_file_interval), }; #undef SET diff --git a/src/torrent_handle.cpp b/src/torrent_handle.cpp index b5f72cfbc..04d20a9be 100644 --- a/src/torrent_handle.cpp +++ b/src/torrent_handle.cpp @@ -733,7 +733,7 @@ namespace libtorrent boost::shared_ptr t = m_torrent.lock(); if (!t || !t->has_storage()) return; session_impl& ses = static_cast(t->session()); - ses.disk_thread().files().get_status(&status, &t->storage()); + ses.disk_thread().files().get_status(&status, t->get_storage()); } void torrent_handle::scrape_tracker(int idx) const