Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/windirstat/llfio.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNiall Douglas (s [underscore] sourceforge {at} nedprod [dot] com) <spamtrap@nedprod.com>2017-09-10 06:24:45 +0300
committerNiall Douglas (s [underscore] sourceforge {at} nedprod [dot] com) <spamtrap@nedprod.com>2017-09-10 06:24:45 +0300
commit5145f65004a7834cb1fc0a57c4e8c53cf97e78ec (patch)
tree3684ce1d52aa13482caafb510e48c724f5c25ca6
parent3afebec0fd8750ff8a83eebc4f8de0480dd67e09 (diff)
Now fully working on POSIX
m---------doc/html8
-rw-r--r--include/afio/revision.hpp6
-rw-r--r--include/afio/v2.0/detail/impl/posix/map_handle.ipp84
-rw-r--r--include/afio/v2.0/detail/impl/posix/mapped_file_handle.ipp10
-rw-r--r--include/afio/v2.0/map_handle.hpp6
-rw-r--r--include/afio/v2.0/mapped_file_handle.hpp21
-rw-r--r--test/tests/mapped_view.cpp7
7 files changed, 97 insertions, 45 deletions
diff --git a/doc/html b/doc/html
-Subproject 29c456437d320dbe7ddbc33e491984af0b14583
+Subproject 1d80781cac7cb087435fb798c636896045b2daa
diff --git a/include/afio/revision.hpp b/include/afio/revision.hpp
index a6b8436c..7be09270 100644
--- a/include/afio/revision.hpp
+++ b/include/afio/revision.hpp
@@ -1,4 +1,4 @@
// Note the second line of this file must ALWAYS be the git SHA, third line ALWAYS the git SHA update time
-#define AFIO_PREVIOUS_COMMIT_REF afa177fe7e944a5adc015d5237a5bed2c9cc5e2e
-#define AFIO_PREVIOUS_COMMIT_DATE "2017-09-10 00:09:57 +00:00"
-#define AFIO_PREVIOUS_COMMIT_UNIQUE afa177fe
+#define AFIO_PREVIOUS_COMMIT_REF 3afebec0fd8750ff8a83eebc4f8de0480dd67e09
+#define AFIO_PREVIOUS_COMMIT_DATE "2017-09-10 01:53:53 +00:00"
+#define AFIO_PREVIOUS_COMMIT_UNIQUE 3afebec0
diff --git a/include/afio/v2.0/detail/impl/posix/map_handle.ipp b/include/afio/v2.0/detail/impl/posix/map_handle.ipp
index 72927cd6..1032421d 100644
--- a/include/afio/v2.0/detail/impl/posix/map_handle.ipp
+++ b/include/afio/v2.0/detail/impl/posix/map_handle.ipp
@@ -29,39 +29,60 @@ Distributed under the Boost Software License, Version 1.0.
AFIO_V2_NAMESPACE_BEGIN
-result<section_handle> section_handle::section(file_handle &backing, extent_type maximum_size, flag _flag) noexcept
+section_handle::~section_handle()
{
- extent_type length = 0;
- if(backing.is_valid())
+ if(_v)
{
- OUTCOME_TRY(_length, backing.length());
- length = _length;
- if(length == 0)
- {
- // Some systems allow zero sized maps, POSIX bans it
- return std::errc::invalid_argument;
- }
- if(maximum_size > 0 && maximum_size > length)
- {
- // For compatibility with Windows, disallow sections larger than the file
- return std::errc::value_too_large;
- }
+ (void) section_handle::close();
}
- if(!maximum_size)
+}
+result<void> section_handle::close() noexcept
+{
+ AFIO_LOG_FUNCTION_CALL(this);
+ // We don't want ~handle() to close our fake handle
+ _v = native_handle_type();
+ return success();
+}
+
+result<section_handle> section_handle::section(file_handle &backing, extent_type maximum_size, flag _flag) noexcept
+{
+ if(!(_flag & flag::posix_skip_length_checks))
{
+ extent_type length = 0;
if(backing.is_valid())
{
- maximum_size = length;
+ OUTCOME_TRY(_length, backing.length());
+ length = _length;
+ if(length == 0)
+ {
+ // Some systems allow zero sized maps, POSIX bans it
+ return std::errc::invalid_argument;
+ }
+ if(maximum_size > 0 && maximum_size > length)
+ {
+ // For compatibility with Windows, disallow sections larger than the file
+ return std::errc::value_too_large;
+ }
}
- else
+ if(!maximum_size)
{
- return std::errc::invalid_argument;
+ if(backing.is_valid())
+ {
+ maximum_size = length;
+ }
+ else
+ {
+ return std::errc::invalid_argument;
+ }
}
}
if(!backing.is_valid())
maximum_size = utils::round_up_to_page_size(maximum_size);
result<section_handle> ret(section_handle(native_handle_type(), backing.is_valid() ? &backing : nullptr, maximum_size, _flag));
// There are no section handles on POSIX, so do nothing
+ native_handle_type &nativeh = ret.value()._v;
+ nativeh.fd = INT_MAX;
+ nativeh.behaviour |= native_handle_type::disposition::section;
AFIO_LOG_FUNCTION_CALL(&ret);
return ret;
}
@@ -75,20 +96,23 @@ result<section_handle::extent_type> section_handle::length() const noexcept
result<section_handle::extent_type> section_handle::truncate(extent_type newsize) noexcept
{
AFIO_LOG_FUNCTION_CALL(this);
- extent_type length = 0;
if(_backing)
{
- OUTCOME_TRY(_length, _backing->length());
- length = _length;
- if(length == 0)
+ extent_type length = 0;
+ if(!(_flag & flag::posix_skip_length_checks))
{
- // Some systems allow zero sized maps, POSIX bans it
- return std::errc::invalid_argument;
- }
- if(newsize > 0 && newsize > length)
- {
- // For compatibility with Windows, disallow sections larger than the file
- return std::errc::value_too_large;
+ OUTCOME_TRY(_length, _backing->length());
+ length = _length;
+ if(length == 0)
+ {
+ // Some systems allow zero sized maps, POSIX bans it
+ return std::errc::invalid_argument;
+ }
+ if(newsize > 0 && newsize > length)
+ {
+ // For compatibility with Windows, disallow sections larger than the file
+ return std::errc::value_too_large;
+ }
}
}
else
diff --git a/include/afio/v2.0/detail/impl/posix/mapped_file_handle.ipp b/include/afio/v2.0/detail/impl/posix/mapped_file_handle.ipp
index eff0ef77..0eac991e 100644
--- a/include/afio/v2.0/detail/impl/posix/mapped_file_handle.ipp
+++ b/include/afio/v2.0/detail/impl/posix/mapped_file_handle.ipp
@@ -30,16 +30,20 @@ AFIO_V2_NAMESPACE_BEGIN
result<mapped_file_handle::size_type> mapped_file_handle::reserve(size_type reservation) noexcept
{
AFIO_LOG_FUNCTION_CALL(this);
+ OUTCOME_TRY(length, underlying_file_length());
+ if(length == 0)
+ {
+ return std::errc::invalid_argument;
+ }
if(reservation == 0)
{
- OUTCOME_TRY(length, underlying_file_length());
reservation = length;
}
reservation = utils::round_up_to_page_size(reservation);
if(!_sh.is_valid())
{
- section_handle::flag sectionflags = section_handle::flag::readwrite;
- OUTCOME_TRY(sh, section_handle::section(*this, 0, sectionflags));
+ section_handle::flag sectionflags = section_handle::flag::readwrite | section_handle::flag::posix_skip_length_checks;
+ OUTCOME_TRY(sh, section_handle::section(*this, length, sectionflags));
_sh = std::move(sh);
}
if(_mh.is_valid() && reservation == _mh.length())
diff --git a/include/afio/v2.0/map_handle.hpp b/include/afio/v2.0/map_handle.hpp
index 1d25974e..e2f44685 100644
--- a/include/afio/v2.0/map_handle.hpp
+++ b/include/afio/v2.0/map_handle.hpp
@@ -63,6 +63,8 @@ public:
barrier_on_close = 1 << 16, //!< Maps of this section, if writable, issue a `barrier()` when destructed blocking until data (not metadata) reaches physical storage.
// NOTE: IF UPDATING THIS UPDATE THE std::ostream PRINTER BELOW!!!
+
+ posix_skip_length_checks = 1 << 28,
readwrite = (read | write)};
QUICKCPPLIB_BITFIELD_END(flag);
@@ -73,6 +75,10 @@ protected:
flag _flag;
public:
+#ifndef _WIN32
+ AFIO_HEADERS_ONLY_VIRTUAL_SPEC ~section_handle();
+ AFIO_HEADERS_ONLY_VIRTUAL_SPEC result<void> close() noexcept override;
+#endif
//! Default constructor
constexpr section_handle()
: _backing(nullptr)
diff --git a/include/afio/v2.0/mapped_file_handle.hpp b/include/afio/v2.0/mapped_file_handle.hpp
index 64d79a44..ff1b8b5c 100644
--- a/include/afio/v2.0/mapped_file_handle.hpp
+++ b/include/afio/v2.0/mapped_file_handle.hpp
@@ -84,6 +84,7 @@ data, you can call `update_map()` which guarantees that the mapping your
process sees is up to date, rather than relying on any kernel-specific automatic mapping.
Whether automatic or enforced by `update_map()`, the reservation limit will not be exceeded
nor will `address()` suddenly return something different.
+
It is thus up to you to detect that the reservation has been exhausted, and to
reserve a new reservation which will change the value returned by `address()`. This
entirely manual system is a bit tedious and cumbersome to use, but as mapping files
@@ -100,9 +101,15 @@ Automatic mapping of growing files on various kernels:
<dl>
<dt>Microsoft Windows</dt>
<dd>For the current Terminal Services Session, the first `mapped_file_handle::truncate()` or
-`mapped_file_handle::update_map()` by any process update maps in all processes simultaneously.</dd>
+`mapped_file_handle::update_map()` by any process update maps in all processes simultaneously.
+Other methods for extending the file will require a `mapped_file_handle::update_map()`
+by any process per Terminal Services Session to synchronise.
+</dd>
<dt>Linux</dt>
-<dd>?</dd>
+<dd>The Linux kernel automatically maps newly appended data to a file into all over extended
+maps of that file. `mapped_file_handle::length()` will continue to return the old value until
+`mapped_file_handle::update_map()` is called to refresh it.
+</dd>
<dt>FreeBSD</dt>
<dd>?</dd>
<dt>Apple MacOS</dt>
@@ -115,7 +122,13 @@ Automatic mapping of shrinking files on various kernels:
<dd>All maps and open section handles on the file anywhere in the system must be removed before
any shrinkage of a file is permitted.</dd>
<dt>Linux</dt>
-<dd>?</dd>
+<dd>Data written after the maximum extent up to the page boundary appears to be zeroed on flush
+and any pages thereafter appear to be unmapped. Just to be safe, on all POSIX platforms
+`mapped_file_handle::truncate()` specifically
+undirties any pages about to be freed on newer kernels, or specifically deallocates them from
+memory and physical storage on older kernels before doing the file shrink. This ensures
+truncated pages don't get zombified.
+</dd>
<dt>FreeBSD</dt>
<dd>?</dd>
<dt>Apple MacOS</dt>
@@ -152,7 +165,7 @@ public:
mapped_file_handle() = default;
//! Implicit move construction of mapped_file_handle permitted
- mapped_file_handle(mapped_file_handle &&o) noexcept : file_handle(std::move(o)), _sh(std::move(o._sh)), _mh(std::move(o._mh))
+ mapped_file_handle(mapped_file_handle &&o) noexcept : file_handle(std::move(o)), _reservation(std::move(o._reservation)), _sh(std::move(o._sh)), _mh(std::move(o._mh))
{
_sh.set_backing(this);
_mh.set_section(&_sh);
diff --git a/test/tests/mapped_view.cpp b/test/tests/mapped_view.cpp
index f849d4ec..124a5865 100644
--- a/test/tests/mapped_view.cpp
+++ b/test/tests/mapped_view.cpp
@@ -65,6 +65,10 @@ static inline void TestMappedView2()
{
using namespace AFIO_V2_NAMESPACE;
using AFIO_V2_NAMESPACE::file_handle;
+ {
+ std::error_code ec;
+ filesystem::remove("testfile", ec);
+ }
mapped_file_handle mfh = mapped_file_handle::mapped_file(1024 * 1024, {}, "testfile", file_handle::mode::write, file_handle::creation::if_needed, file_handle::caching::all, file_handle::flag::unlink_on_close).value();
BOOST_CHECK(mfh.address() == nullptr);
mfh.truncate(10000 * sizeof(int)).value();
@@ -106,7 +110,8 @@ static inline void TestMappedView2()
BOOST_CHECK(v1.size() == 10000);
v1[0] = 78;
v1[9999] = 79;
- // Should have auto informed mfh of the change and remapped it for us
+ // On Windows this will have updated the mapping, on POSIX it will not, so prod POSIX
+ mfh.update_map().value();
v1 = mfh;
BOOST_CHECK(v1.size() == 10000);
BOOST_CHECK(v1[0] == 78);