Skip to content

Commit

Permalink
explicitly FlushViewOfFile() on windows when closing a file
Browse files Browse the repository at this point in the history
  • Loading branch information
arvidn committed Nov 5, 2021
1 parent d281301 commit 085be91
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 7 deletions.
8 changes: 8 additions & 0 deletions include/libtorrent/aux_/file_view_pool.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,10 @@ namespace aux {

void close_oldest();

#if TORRENT_HAVE_MAP_VIEW_OF_FILE
void flush_next_file();
#endif

private:

std::shared_ptr<file_mapping> remove_oldest(std::unique_lock<std::mutex>&);
Expand Down Expand Up @@ -150,6 +154,10 @@ namespace aux {
mi::ordered_unique<mi::member<file_entry, file_id, &file_entry::key>>,
// look up files by least recently used
mi::sequenced<>
#if TORRENT_HAVE_MAP_VIEW_OF_FILE
// look up files by least recently flushed
, mi::sequenced<>
#endif
>
>;

Expand Down
4 changes: 4 additions & 0 deletions include/libtorrent/aux_/mmap.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,10 @@ namespace aux {
#endif
);

#if TORRENT_HAVE_MAP_VIEW_OF_FILE
void flush();
#endif

// non-copyable
file_mapping(file_mapping const&) = delete;
file_mapping& operator=(file_mapping const&) = delete;
Expand Down
12 changes: 12 additions & 0 deletions src/file_view_pool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,18 @@ namespace libtorrent { namespace aux {
std::unique_lock<std::mutex> l(m_mutex);
deferred_destruction = remove_oldest(l);
}

#if TORRENT_HAVE_MAP_VIEW_OF_FILE
void file_view_pool::flush_next_file()
{
std::unique_lock<std::mutex> l(m_mutex);
auto& flush_view = m_files.get<2>();
if (flush_view.size() == 0) return;

flush_view.begin()->mapping->flush();
flush_view.relocate(m_files.project<2>(flush_view.begin()), flush_view.end());
}
#endif
}
}

Expand Down
9 changes: 9 additions & 0 deletions src/mmap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -638,9 +638,18 @@ file_mapping::file_mapping(file_handle file, open_mode_t const mode
throw_ex<storage_error>(error_code(GetLastError(), system_category()), operation_t::file_mmap);
}

void file_mapping::flush()
{
if (m_mapping == nullptr) return;

// ignore errors, this is best-effort
FlushViewOfFile(m_mapping, static_cast<std::size_t>(m_size));
}

void file_mapping::close()
{
if (m_mapping == nullptr) return;
flush();
std::lock_guard<std::mutex> l(*m_open_unmap_lock);
UnmapViewOfFile(m_mapping);
m_mapping = nullptr;
Expand Down
28 changes: 21 additions & 7 deletions src/mmap_disk_io.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -322,10 +322,6 @@ struct TORRENT_EXTRA_EXPORT mmap_disk_io final

settings_interface const& m_settings;

// we call close_oldest_file on the file_pool regularly. This is the next
// time we should call it
time_point m_next_close_oldest_file = min_time();

// LRU cache of open files
aux::file_view_pool m_file_pool;

Expand Down Expand Up @@ -1525,6 +1521,14 @@ TORRENT_EXPORT std::unique_ptr<disk_interface> mmap_disk_io_constructor(
++m_num_running_threads;
m_stats_counters.inc_stats_counter(counters::num_running_threads, 1);

// we call close_oldest_file on the file_pool regularly. This is the next
// time we should call it
time_point next_close_oldest_file = min_time();

#if TORRENT_HAVE_MAP_VIEW_OF_FILE
time_point next_flush_file = min_time();
#endif

for (;;)
{
aux::disk_io_job* j = nullptr;
Expand Down Expand Up @@ -1553,20 +1557,30 @@ TORRENT_EXPORT std::unique_ptr<disk_interface> mmap_disk_io_constructor(
}
}

if (now > m_next_close_oldest_file)
if (now > next_close_oldest_file)
{
seconds const interval(m_settings.get_int(settings_pack::close_file_interval));
if (interval <= seconds(0))
{
// check again in one minute, in case the setting changed
m_next_close_oldest_file = now + minutes(1);
next_close_oldest_file = now + minutes(1);
}
else
{
m_next_close_oldest_file = now + interval;
next_close_oldest_file = now + interval;
m_file_pool.close_oldest();
}
}

#if TORRENT_HAVE_MAP_VIEW_OF_FILE
if (now > next_flush_file)
{
// on windows we need to explicitly ask the operating system to flush
// dirty pages from time to time
m_file_pool.flush_next_file();
next_flush_file = now + seconds(30);
}
#endif
}

execute_job(j);
Expand Down

0 comments on commit 085be91

Please sign in to comment.