Apple doesn't follow POSIX specifications for fsync(). Instead, fsync() guarantees to flush the buffer cache to the device, which means the data will survive kernel panics, but may not survive power outages. Applications that need stronger guarantees (like databases) need to use fcntl(F_FULLFSYNC).
This CL switches PosixWritableFile::Sync() to get the stronger guarantees on Apple systems. The improved implementation follows the same principles as SQLite [1] and node.js [2].
Research for the fcntl() to fsync() fallback strategy:
Apple's released source code at https://opensource.apple.com/ shows at least three different error codes being returned when a filesystem does not support F_FULLFSYNC.
fcntl() is implemented in xnu-4903.221.2 in bsd/kern/kern_descrip.c, where it delegates to fcntl_nocancel(). The documentation for fcntl_nocancel() mentions error codes for some operations, but does not include F_FULLFSYNC. The F_FULLSYNC branch in fcntl_nocancel() calls VNOP_IOCTL(_, F_FULLSYNC, NULL, 0, _), whose return value sets the error
code.
VNOP_IOCTL() is implemented in bsd/vfs/kpi_vfs.c and calls the ioctl function in the vnode's operation vector. The per-filesystem function names follow the pattern _vnop_ioctl() for all the instances in opensource code: {hfs,msdosfs,nfs,ntfs,smbfs,webdav,zfs}_vnop_ioctl().
hfs-407.30.1, msdosfs-229.200.3, and nfs in xnu-4903.221.2 handle F_FULLFSYNC. ntfs-94.200.1 and smb-759.40.1 do not handle F_FULLFSYNC, and the default branch returns ENOSUP. webdav-380.200.1 also does not handle F_FULLFSYNC, but the default branch returns EINVAL. zfs-59 also does not handle F_FULLSYNC, and its default branch returns ENOTTY.
From a different angle, Apple's ntfs-94.200.1 includes utility code that uses fcntl(F_FULLFSYNC) and falls back to fsync() just like we do, supporting the hypothesis that there is no good way to detect lack of F_FULLFSYNC support. Also, Apple's fcntl() man page [3] does not mention a way to detect lack of F_FULLFSYNC support.
[1] https://www.sqlite.org/src/doc/trunk/src/os_unix.c
[2] https://github.com/libuv/libuv/blob/master/src/unix/fs.c
[3] https://developer.apple.com/library/archive/documentatiVon/System/Conceptual/ManPages_iPhoneOS/man2/fcntl.2.html
Tested:
https://travis-ci.org/pwnall/leveldb/builds/477318498
TAP global presubmit
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=228593729
The CMake feature-detection code used check_symbol_exists(), which
invokes the C compiler. However, some glibc versions don't expose the
fdatasync() declaration when compiled with -std=c11, but do expose it
when compiled with -std=c++11. This most likely comes down to how
_POSIX_SOURCE is defined -- it needs to be >= 201112L for <unistd.h> to
expose fdatasync().
This CL switches to check_cxx_symbol_exists(), which uses the C++
compiler. Asides from fixing the problem above, this is the right thing
to do, because we use <unistd.h> in env_posix.cc, which is compiled with
the C++ compiler.
This CL also fixes a previously introduced inconsistency, where the
macro indicating the fdatasync() feature detection result was referred
to as HAVE_FDATASYNC and HAVE_FUNC_FDATASYNC. The former appears to be
used in other libraries, so this CL switches all our references to
HAVE_FDATASYNC.
Fixes https://github.com/google/leveldb/issues/629
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=228392612
The space in between the header and log message was mistakenly omitted
in a prior commit. Re-adding.
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=228202737
General cleanup principles:
* Use override when applicable.
* Remove static when redundant (methods and globals in anonymous
namespaces).
* Use const on class members where possible.
* Standardize on "status" for Status local variables.
* Renames where clarity can be improved.
* Qualify standard library names with std:: when possible, to
distinguish from POSIX names.
* Qualify POSIX names with the global namespace (::) when possible, to
distinguish from standard library names.
This also refactors the background thread synchronization logic so that
it's statically analyzable.
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=219212089
C++11 guarantees thread-safe initialization of static variables inside
functions. This is a more restricted form of std::call_once or
pthread_once_t (e.g., single call site), so the compiler might be able
to generate better code [1]. Equally important, having less
platform-dependent code in env_posix.cc makes it easier to port to other
platforms.
Due to the change above, this CL introduced a new approach for storing
the singleton PosixEnv instance returned by Env::Default(). The new
approach avoids a dynamic memory allocation, which eliminates the false
positive from LeakSanitizer reported in
https://github.com/google/leveldb/issues/539 and
https://github.com/google/leveldb/issues/113
[1] https://stackoverflow.com/a/27206650/
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=214293129
The version in the repository covers the Makefile build. The new version
is simpler and contains entries relevant to the CMake build.
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=212661504
This commit replaces the use of pthreads in the POSIX port with std::thread
and port::Mutex + port::CondVar. This is intended to simplify porting
the env to a different platform.
The indirect use of pthreads in PosixLogger is replaced with
std:🧵:id(), based on an approach prototyped by @cmumfordx@.
The pthreads dependency in CMakeFiles is not removed, because some C++
standard library implementations must be linked against pthreads for
std::thread use. Figuring out this dependency is left for future work.
Switching away from pthreads also fixes
https://github.com/google/leveldb/issues/381
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=212478311
This is not an API-breaking change, because it reduces the API that the
leveldb embedder must implement. The project will build just fine
against ports that still implement InitOnce.
C++11 guarantees thread-safe initialization of static variables inside
functions. This is a more restricted form of std::call_once or
pthread_once_t (e.g., single call site), so the compiler might be able
to generate better code [1]. Equally important, having less code in
port_example.h makes it easier to port to other platforms.
Due to the change above, this CL introduces a new approach for storing
the singleton BytewiseComparatorImpl instance returned by
BytewiseComparator(). The new approach avoids a dynamic memory
allocation, which eliminates the false positive from LeakSanitizer
reported in https://github.com/google/leveldb/issues/200
[1] https://stackoverflow.com/a/27206650/
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=212348004
This is separated from the general cleanup because of the logic changes
in SyncDirIfManifest().
General cleanup principles:
* Use override when applicable.
* Remove static when redundant (methods and globals in anonymous
namespaces).
* Use const on class members where possible.
* Standardize on "status" for Status local variables.
* Renames where clarity can be improved.
* Qualify standard library names with std:: when possible, to
distinguish from POSIX names.
* Qualify POSIX names with the global namespace (::) when possible, to
distinguish from standard library names.
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=211709673
General cleanup principles:
* Use override when applicable.
* Use const on class members where possible.
* Renames where clarity can be improved.
* Qualify standard library names with std:: when possible, to
distinguish from POSIX names.
* Qualify POSIX names with the global namespace (::) when possible, to
distinguish from standard library names.
This also revamps the logic for putting together a message into the
in-memory buffer before that is passed to fwrite(). While correct in
practice, the current implementation advances a char pointer past the
size of its buffer, which is technically undefined behavior.
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=211472570
ssize_t is not standard C++. It is a POSIX extension. Therefore, it does
not belong in generic code.
This change tweaks the logic in DBIter to remove the need for signed
integers, so ssize_t can be replaced with size_t. The impacted method
and private member are renamed to better express their purpose.
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=211471606
Now that we require C++11, we can use std::atomic<int>, which has
primitives for most of the logic we need. As a bonus, the happy path for
Limiter::Acquire() and Limiter::Release() only performs one atomic
operation.
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=211469518
"Create a brand new [adjective] file" seems like the description for a
method that will create a new file, but is used for methods that open
existing files for read access.
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=211468002
WriteBatchInternal has a method for efficiently concatenating two
WriteBatches. This commit exposes the method to the public API.
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=208724311
This CL renames the private struct Iterator::Cleanup ->
Iterator::CleanupNode, to better reflect that it's a linked list node,
and extracts duplicated code from its user in IsEmpty() and Run()
methods.
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=199175058
* Omit SnapshotImpl::list_ when assert() isn't on
* Make SnapshotImpl::number_ const and set it in the constructor
* Make SnapshotImpl::number_ private and access it via a getter
* Rename SnapshotImpl::number_ to SnapshotImpl::sequence_number_
* Rename SnapshotList::list_ to SnapshotList::head_
* Wrap casting from Snapshot* to SnapshotImpl* in ToSnapshotImpl()
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=194852828
The default size was changed in #f779e7a5 but the documentation was
never updated.
This fixes#566 reported on GitHub.
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=194547959
The porting layer implements threading primitives: atomic pointers,
condition variables, mutexes, thread-safe initialization. These are all
specified in C++11, so the reference open source port implementation can
become platform-independent.
The porting layer will remain in place to allow the use of other
implementations with more features, such as the built-in deadlock
detection in abseil's Mutex.
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=193245934
Commit a0008deb67 introduced
std::numeric_limits usage in logging.cc, but didn't #include <limits>
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=192840190
The old implementation caused odd crashes on ARM, which were fixed by
changing a local variable type. The main suspect is the use of a static
local variable. This CL replaces the static local variable with
constexpr, which still ensures the compiler sees the expressions as
constants.
The CL also replaces Slice operations in the functions' inner loop with
iterator-style pointer operations, which can help the compiler generate
less code.
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=192832175
ConsumeDecimalNumber has fairly non-trivial logic, and a previous
version has crashed inexplicably on Android. Having some test coverage
will make it easier to tweak / simplify the function later on.
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=192821751
This is an accidental leftover from the CMake migration. The macro has
been replaced with LEVELDB_IS_BIG_ENDIAN.
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=192364918
The CMake-based build relies on __has_include, which is standardized in
C++17. Unfortunately, __has_include is available without requiring
--std=c++17 on all the compilers on CI, so this problem was not caught.
Fixes https://github.com/google/leveldb/issues/572
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=192208842
After this CL, all classes with Mutex members should be covered by annotations. Exceptions are atomic members, which shouldn't need locking, and DBImpl members that cause errors when annotated, which will be tackled separately.
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=190260865
C++11 requires <atomic>. This lets us remove the header detection
(LEVELDB_ATOMIC_PRESENT) and simplify port/atomic_pointer.h.
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=189919098
This CL switches the public headers to C++11 default and deleted constructors, and adds override to the relevant leveldb::EnvWrapper methods. This should be a good test for C++11 compiler support.
Once this CL settles, the rest of the codebase can be safely modernized to C++11.
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=189873212
helpers/memenv/memenv.cc used SIZE_MAX without including <stdint.h>.
Since we're fixing this problem, replace SIZE_MAX with
std::numeric_limits<size_t>::max(), which is clearer.
Fixes https://github.com/google/leveldb/issues/562
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=189821707
This CL makes it easier to reason about thread safety by:
1) Adding Clang thread safety annotations according to comments.
2) Expanding a couple of variable names, without adding extra lines of code.
3) Adding const in a couple of places.
4) Replacing an always-non-null const pointer with a reference.
5) Fixing style warnings in the modified files.
This CL does not annotate the DBImpl members that claim to be protected
by the instance mutex, but are accessed without the mutex being held.
Those members (and their unprotected accesses) will be addressed in
future CLs.
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=189354657
This CL removes unused headers included by util/testharness.h, adds
precise includes where the build breaks, and fixes style errors in the
edited files.
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=189331061
External linkage is the default for function declarations in C++.
This also fixes ClangTidy errors generated by removing the "extern"
keyword as described above.
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=188730416
This is a stopgap for removing warnings on Mac builds, so -Werror can be
turned on. C++11 will be required in the nearby future, which guarantees
<atomic> support. Once that happens, the simplified version of this will
match https://github.com/google/leveldb/pull/503
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=188553251
This aligns the Travis CI configuration with google/crc32c and
google/snappy, to simplify maintenance.
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=188547648