add feature to periodically close files (to make windows clear disk cache)
This commit is contained in:
parent
af07ce1f25
commit
faa2029f8b
|
@ -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
|
* fix issue with peers not updated on metadata from magnet links
|
||||||
|
|
||||||
1.1.2 release
|
1.1.2 release
|
||||||
|
|
|
@ -649,6 +649,7 @@ namespace libtorrent
|
||||||
void update_privileged_ports();
|
void update_privileged_ports();
|
||||||
void update_auto_sequential();
|
void update_auto_sequential();
|
||||||
void update_max_failcount();
|
void update_max_failcount();
|
||||||
|
void update_close_file_interval();
|
||||||
|
|
||||||
void update_upnp();
|
void update_upnp();
|
||||||
void update_natpmp();
|
void update_natpmp();
|
||||||
|
@ -976,6 +977,7 @@ namespace libtorrent
|
||||||
int m_peak_down_rate;
|
int m_peak_down_rate;
|
||||||
|
|
||||||
void on_tick(error_code const& e);
|
void on_tick(error_code const& e);
|
||||||
|
void on_close_file(error_code const& e);
|
||||||
|
|
||||||
void try_connect_more_peers();
|
void try_connect_more_peers();
|
||||||
void auto_manage_checking_torrents(std::vector<torrent*>& list
|
void auto_manage_checking_torrents(std::vector<torrent*>& list
|
||||||
|
@ -1123,6 +1125,11 @@ namespace libtorrent
|
||||||
// by Local service discovery
|
// by Local service discovery
|
||||||
deadline_timer m_lsd_announce_timer;
|
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;
|
resolver m_host_resolver;
|
||||||
|
|
||||||
// the index of the torrent that will be offered to
|
// the index of the torrent that will be offered to
|
||||||
|
|
|
@ -109,6 +109,12 @@ namespace libtorrent
|
||||||
void set_low_prio_io(bool b) { m_low_prio_io = b; }
|
void set_low_prio_io(bool b) { m_low_prio_io = b; }
|
||||||
void get_status(std::vector<pool_file_status>* files, void* st) const;
|
void get_status(std::vector<pool_file_status>* 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
|
#if TORRENT_USE_ASSERTS
|
||||||
bool assert_idle_files(void* st) const;
|
bool assert_idle_files(void* st) const;
|
||||||
|
|
||||||
|
@ -127,8 +133,12 @@ namespace libtorrent
|
||||||
|
|
||||||
struct lru_file_entry
|
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;
|
file_handle file_ptr;
|
||||||
|
time_point const opened;
|
||||||
time_point last_use;
|
time_point last_use;
|
||||||
int mode;
|
int mode;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1594,6 +1594,15 @@ namespace libtorrent
|
||||||
// time to wait until a new retry of a web seed name lookup
|
// time to wait until a new retry of a web seed name lookup
|
||||||
web_seed_name_lookup_retry,
|
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
|
max_int_setting_internal
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -46,5 +46,6 @@ alias libtorrent-sims :
|
||||||
[ run test_tracker.cpp ]
|
[ run test_tracker.cpp ]
|
||||||
[ run test_ip_filter.cpp ]
|
[ run test_ip_filter.cpp ]
|
||||||
[ run test_fast_extensions.cpp ]
|
[ run test_fast_extensions.cpp ]
|
||||||
|
[ run 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<pool_file_status> 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);
|
||||||
|
}
|
||||||
|
|
|
@ -329,5 +329,22 @@ namespace libtorrent
|
||||||
remove_oldest(l);
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -426,6 +426,7 @@ namespace aux {
|
||||||
, m_boost_connections(0)
|
, m_boost_connections(0)
|
||||||
, m_timer(m_io_service)
|
, m_timer(m_io_service)
|
||||||
, m_lsd_announce_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_host_resolver(m_io_service)
|
||||||
, m_next_downloading_connect_torrent(0)
|
, m_next_downloading_connect_torrent(0)
|
||||||
, m_next_finished_connect_torrent(0)
|
, m_next_finished_connect_torrent(0)
|
||||||
|
@ -1094,6 +1095,8 @@ namespace aux {
|
||||||
// about to send event=stopped to
|
// about to send event=stopped to
|
||||||
m_host_resolver.abort();
|
m_host_resolver.abort();
|
||||||
|
|
||||||
|
m_close_file_timer.cancel();
|
||||||
|
|
||||||
// abort the main thread
|
// abort the main thread
|
||||||
m_abort = true;
|
m_abort = true;
|
||||||
error_code ec;
|
error_code ec;
|
||||||
|
@ -3565,6 +3568,16 @@ retry:
|
||||||
// m_peer_pool.release_memory();
|
// 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 {
|
namespace {
|
||||||
// returns the index of the first set bit.
|
// returns the index of the first set bit.
|
||||||
int log2(boost::uint32_t v)
|
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()
|
void session_impl::update_proxy()
|
||||||
{
|
{
|
||||||
// in case we just set a socks proxy, we might have to
|
// in case we just set a socks proxy, we might have to
|
||||||
|
|
|
@ -124,6 +124,12 @@ namespace libtorrent
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
#pragma GCC diagnostic push
|
#pragma GCC diagnostic push
|
||||||
#pragma GCC diagnostic ignored "-Winvalid-offsetof"
|
#pragma GCC diagnostic ignored "-Winvalid-offsetof"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef TORRENT_WINDOWS
|
||||||
|
#define CLOSE_FILE_INTERVAL 120
|
||||||
|
#else
|
||||||
|
#define CLOSE_FILE_INTERVAL 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -350,6 +356,7 @@ namespace libtorrent
|
||||||
SET_NOPREV(cache_size_volatile, 256, 0),
|
SET_NOPREV(cache_size_volatile, 256, 0),
|
||||||
SET_NOPREV(urlseed_max_request_bytes, 16 * 1024 * 1024, 0),
|
SET_NOPREV(urlseed_max_request_bytes, 16 * 1024 * 1024, 0),
|
||||||
SET_NOPREV(web_seed_name_lookup_retry, 1800, 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
|
#undef SET
|
||||||
|
|
|
@ -733,7 +733,7 @@ namespace libtorrent
|
||||||
boost::shared_ptr<torrent> t = m_torrent.lock();
|
boost::shared_ptr<torrent> t = m_torrent.lock();
|
||||||
if (!t || !t->has_storage()) return;
|
if (!t || !t->has_storage()) return;
|
||||||
session_impl& ses = static_cast<session_impl&>(t->session());
|
session_impl& ses = static_cast<session_impl&>(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
|
void torrent_handle::scrape_tracker(int idx) const
|
||||||
|
|
Loading…
Reference in New Issue