Replace port_posix with port_stdcxx.
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
This commit is contained in:
parent
14cce848e7
commit
d177a0263c
@ -79,33 +79,10 @@ if(BUILD_SHARED_LIBS)
|
|||||||
add_compile_options(-fvisibility=hidden)
|
add_compile_options(-fvisibility=hidden)
|
||||||
endif(BUILD_SHARED_LIBS)
|
endif(BUILD_SHARED_LIBS)
|
||||||
|
|
||||||
# POSIX code is specified separately so we can leave it out in the future.
|
|
||||||
add_library(leveldb_port_posix OBJECT "")
|
|
||||||
target_sources(leveldb_port_posix
|
|
||||||
PRIVATE
|
|
||||||
"${PROJECT_SOURCE_DIR}/port/port_posix.cc"
|
|
||||||
|
|
||||||
PUBLIC
|
|
||||||
# The headers below are dependencies for leveldb, but aren't needed by users
|
|
||||||
# that link to the installed version of leveldb and rely on its public API.
|
|
||||||
$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/${LEVELDB_PORT_CONFIG_DIR}/port_config.h>
|
|
||||||
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/port/atomic_pointer.h>
|
|
||||||
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/port/port_posix.h>
|
|
||||||
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/port/port.h>
|
|
||||||
)
|
|
||||||
if (NOT HAVE_CXX17_HAS_INCLUDE)
|
|
||||||
target_compile_definitions(leveldb_port_posix
|
|
||||||
PRIVATE
|
|
||||||
LEVELDB_HAS_PORT_CONFIG_H=1
|
|
||||||
)
|
|
||||||
endif(NOT HAVE_CXX17_HAS_INCLUDE)
|
|
||||||
if(BUILD_SHARED_LIBS)
|
|
||||||
set_property(TARGET leveldb_port_posix PROPERTY POSITION_INDEPENDENT_CODE ON)
|
|
||||||
endif(BUILD_SHARED_LIBS)
|
|
||||||
|
|
||||||
add_library(leveldb "")
|
add_library(leveldb "")
|
||||||
target_sources(leveldb
|
target_sources(leveldb
|
||||||
PRIVATE
|
PRIVATE
|
||||||
|
"${PROJECT_BINARY_DIR}/${LEVELDB_PORT_CONFIG_DIR}/port_config.h"
|
||||||
"${PROJECT_SOURCE_DIR}/db/builder.cc"
|
"${PROJECT_SOURCE_DIR}/db/builder.cc"
|
||||||
"${PROJECT_SOURCE_DIR}/db/builder.h"
|
"${PROJECT_SOURCE_DIR}/db/builder.h"
|
||||||
"${PROJECT_SOURCE_DIR}/db/c.cc"
|
"${PROJECT_SOURCE_DIR}/db/c.cc"
|
||||||
@ -136,6 +113,8 @@ target_sources(leveldb
|
|||||||
"${PROJECT_SOURCE_DIR}/db/version_set.h"
|
"${PROJECT_SOURCE_DIR}/db/version_set.h"
|
||||||
"${PROJECT_SOURCE_DIR}/db/write_batch_internal.h"
|
"${PROJECT_SOURCE_DIR}/db/write_batch_internal.h"
|
||||||
"${PROJECT_SOURCE_DIR}/db/write_batch.cc"
|
"${PROJECT_SOURCE_DIR}/db/write_batch.cc"
|
||||||
|
"${PROJECT_SOURCE_DIR}/port/atomic_pointer.h"
|
||||||
|
"${PROJECT_SOURCE_DIR}/port/port_stdcxx.h"
|
||||||
"${PROJECT_SOURCE_DIR}/port/port.h"
|
"${PROJECT_SOURCE_DIR}/port/port.h"
|
||||||
"${PROJECT_SOURCE_DIR}/port/thread_annotations.h"
|
"${PROJECT_SOURCE_DIR}/port/thread_annotations.h"
|
||||||
"${PROJECT_SOURCE_DIR}/table/block_builder.cc"
|
"${PROJECT_SOURCE_DIR}/table/block_builder.cc"
|
||||||
@ -163,7 +142,6 @@ target_sources(leveldb
|
|||||||
"${PROJECT_SOURCE_DIR}/util/comparator.cc"
|
"${PROJECT_SOURCE_DIR}/util/comparator.cc"
|
||||||
"${PROJECT_SOURCE_DIR}/util/crc32c.cc"
|
"${PROJECT_SOURCE_DIR}/util/crc32c.cc"
|
||||||
"${PROJECT_SOURCE_DIR}/util/crc32c.h"
|
"${PROJECT_SOURCE_DIR}/util/crc32c.h"
|
||||||
"${PROJECT_SOURCE_DIR}/util/env_posix.cc"
|
|
||||||
"${PROJECT_SOURCE_DIR}/util/env.cc"
|
"${PROJECT_SOURCE_DIR}/util/env.cc"
|
||||||
"${PROJECT_SOURCE_DIR}/util/filter_policy.cc"
|
"${PROJECT_SOURCE_DIR}/util/filter_policy.cc"
|
||||||
"${PROJECT_SOURCE_DIR}/util/hash.cc"
|
"${PROJECT_SOURCE_DIR}/util/hash.cc"
|
||||||
@ -172,10 +150,8 @@ target_sources(leveldb
|
|||||||
"${PROJECT_SOURCE_DIR}/util/logging.h"
|
"${PROJECT_SOURCE_DIR}/util/logging.h"
|
||||||
"${PROJECT_SOURCE_DIR}/util/mutexlock.h"
|
"${PROJECT_SOURCE_DIR}/util/mutexlock.h"
|
||||||
"${PROJECT_SOURCE_DIR}/util/options.cc"
|
"${PROJECT_SOURCE_DIR}/util/options.cc"
|
||||||
"${PROJECT_SOURCE_DIR}/util/posix_logger.h"
|
|
||||||
"${PROJECT_SOURCE_DIR}/util/random.h"
|
"${PROJECT_SOURCE_DIR}/util/random.h"
|
||||||
"${PROJECT_SOURCE_DIR}/util/status.cc"
|
"${PROJECT_SOURCE_DIR}/util/status.cc"
|
||||||
$<TARGET_OBJECTS:leveldb_port_posix>
|
|
||||||
|
|
||||||
# Only CMake 3.3+ supports PUBLIC sources in targets exported by "install".
|
# Only CMake 3.3+ supports PUBLIC sources in targets exported by "install".
|
||||||
$<$<VERSION_GREATER:CMAKE_VERSION,3.2>:PUBLIC>
|
$<$<VERSION_GREATER:CMAKE_VERSION,3.2>:PUBLIC>
|
||||||
@ -195,12 +171,21 @@ target_sources(leveldb
|
|||||||
"${LEVELDB_PUBLIC_INCLUDE_DIR}/table.h"
|
"${LEVELDB_PUBLIC_INCLUDE_DIR}/table.h"
|
||||||
"${LEVELDB_PUBLIC_INCLUDE_DIR}/write_batch.h"
|
"${LEVELDB_PUBLIC_INCLUDE_DIR}/write_batch.h"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# POSIX code is specified separately so we can leave it out in the future.
|
||||||
|
target_sources(leveldb
|
||||||
|
PRIVATE
|
||||||
|
"${PROJECT_SOURCE_DIR}/util/env_posix.cc"
|
||||||
|
"${PROJECT_SOURCE_DIR}/util/posix_logger.h"
|
||||||
|
)
|
||||||
|
|
||||||
# MemEnv is not part of the interface and could be pulled to a separate library.
|
# MemEnv is not part of the interface and could be pulled to a separate library.
|
||||||
target_sources(leveldb
|
target_sources(leveldb
|
||||||
PRIVATE
|
PRIVATE
|
||||||
"${PROJECT_SOURCE_DIR}/helpers/memenv/memenv.cc"
|
"${PROJECT_SOURCE_DIR}/helpers/memenv/memenv.cc"
|
||||||
"${PROJECT_SOURCE_DIR}/helpers/memenv/memenv.h"
|
"${PROJECT_SOURCE_DIR}/helpers/memenv/memenv.h"
|
||||||
)
|
)
|
||||||
|
|
||||||
target_include_directories(leveldb
|
target_include_directories(leveldb
|
||||||
PUBLIC
|
PUBLIC
|
||||||
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
|
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
|
||||||
@ -234,11 +219,6 @@ if(HAVE_CLANG_THREAD_SAFETY)
|
|||||||
-Werror -Wthread-safety)
|
-Werror -Wthread-safety)
|
||||||
endif(HAVE_CLANG_THREAD_SAFETY)
|
endif(HAVE_CLANG_THREAD_SAFETY)
|
||||||
|
|
||||||
# TODO(costan): This is only needed for port_posix.
|
|
||||||
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
|
||||||
find_package(Threads REQUIRED)
|
|
||||||
target_link_libraries(leveldb Threads::Threads)
|
|
||||||
|
|
||||||
if(HAVE_CRC32C)
|
if(HAVE_CRC32C)
|
||||||
target_link_libraries(leveldb crc32c)
|
target_link_libraries(leveldb crc32c)
|
||||||
endif(HAVE_CRC32C)
|
endif(HAVE_CRC32C)
|
||||||
@ -249,6 +229,10 @@ if(HAVE_TCMALLOC)
|
|||||||
target_link_libraries(leveldb tcmalloc)
|
target_link_libraries(leveldb tcmalloc)
|
||||||
endif(HAVE_TCMALLOC)
|
endif(HAVE_TCMALLOC)
|
||||||
|
|
||||||
|
# Needed by port_stdcxx.h
|
||||||
|
find_package(Threads REQUIRED)
|
||||||
|
target_link_libraries(leveldb Threads::Threads)
|
||||||
|
|
||||||
add_executable(leveldbutil
|
add_executable(leveldbutil
|
||||||
"${PROJECT_SOURCE_DIR}/db/leveldbutil.cc"
|
"${PROJECT_SOURCE_DIR}/db/leveldbutil.cc"
|
||||||
)
|
)
|
||||||
@ -271,14 +255,6 @@ if(LEVELDB_BUILD_TESTS)
|
|||||||
|
|
||||||
"${test_file}"
|
"${test_file}"
|
||||||
)
|
)
|
||||||
if(BUILD_SHARED_LIBS)
|
|
||||||
# Port functions aren't exposed in the shared library build.
|
|
||||||
target_sources("${test_target_name}"
|
|
||||||
PRIVATE
|
|
||||||
$<TARGET_OBJECTS:leveldb_port_posix>
|
|
||||||
)
|
|
||||||
endif(BUILD_SHARED_LIBS)
|
|
||||||
|
|
||||||
target_link_libraries("${test_target_name}" leveldb)
|
target_link_libraries("${test_target_name}" leveldb)
|
||||||
target_compile_definitions("${test_target_name}"
|
target_compile_definitions("${test_target_name}"
|
||||||
PRIVATE
|
PRIVATE
|
||||||
@ -351,14 +327,6 @@ if(LEVELDB_BUILD_BENCHMARKS)
|
|||||||
|
|
||||||
"${bench_file}"
|
"${bench_file}"
|
||||||
)
|
)
|
||||||
if(BUILD_SHARED_LIBS)
|
|
||||||
# Port functions aren't exposed in the shared library build.
|
|
||||||
target_sources("${bench_target_name}"
|
|
||||||
PRIVATE
|
|
||||||
$<TARGET_OBJECTS:leveldb_port_posix>
|
|
||||||
)
|
|
||||||
endif(BUILD_SHARED_LIBS)
|
|
||||||
|
|
||||||
target_link_libraries("${bench_target_name}" leveldb)
|
target_link_libraries("${bench_target_name}" leveldb)
|
||||||
target_compile_definitions("${bench_target_name}"
|
target_compile_definitions("${bench_target_name}"
|
||||||
PRIVATE
|
PRIVATE
|
||||||
|
@ -5,6 +5,6 @@ Code in the rest of the package includes "port.h" from this directory.
|
|||||||
"port.h" in turn includes a platform specific "port_<platform>.h" file
|
"port.h" in turn includes a platform specific "port_<platform>.h" file
|
||||||
that provides the platform specific implementation.
|
that provides the platform specific implementation.
|
||||||
|
|
||||||
See port_posix.h for an example of what must be provided in a platform
|
See port_stdcxx.h for an example of what must be provided in a platform
|
||||||
specific header file.
|
specific header file.
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
// porting to a new platform, see "port_example.h" for documentation
|
// porting to a new platform, see "port_example.h" for documentation
|
||||||
// of what the new port_<platform>.h file must provide.
|
// of what the new port_<platform>.h file must provide.
|
||||||
#if defined(LEVELDB_PLATFORM_POSIX)
|
#if defined(LEVELDB_PLATFORM_POSIX)
|
||||||
# include "port/port_posix.h"
|
# include "port/port_stdcxx.h"
|
||||||
#elif defined(LEVELDB_PLATFORM_CHROMIUM)
|
#elif defined(LEVELDB_PLATFORM_CHROMIUM)
|
||||||
# include "port/port_chromium.h"
|
# include "port/port_chromium.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,53 +0,0 @@
|
|||||||
// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
|
||||||
// found in the LICENSE file. See the AUTHORS file for names of contributors.
|
|
||||||
|
|
||||||
#include "port/port_posix.h"
|
|
||||||
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
namespace leveldb {
|
|
||||||
namespace port {
|
|
||||||
|
|
||||||
static void PthreadCall(const char* label, int result) {
|
|
||||||
if (result != 0) {
|
|
||||||
fprintf(stderr, "pthread %s: %s\n", label, strerror(result));
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Mutex::Mutex() { PthreadCall("init mutex", pthread_mutex_init(&mu_, nullptr)); }
|
|
||||||
|
|
||||||
Mutex::~Mutex() { PthreadCall("destroy mutex", pthread_mutex_destroy(&mu_)); }
|
|
||||||
|
|
||||||
void Mutex::Lock() { PthreadCall("lock", pthread_mutex_lock(&mu_)); }
|
|
||||||
|
|
||||||
void Mutex::Unlock() { PthreadCall("unlock", pthread_mutex_unlock(&mu_)); }
|
|
||||||
|
|
||||||
CondVar::CondVar(Mutex* mu)
|
|
||||||
: mu_(mu) {
|
|
||||||
PthreadCall("init cv", pthread_cond_init(&cv_, nullptr));
|
|
||||||
}
|
|
||||||
|
|
||||||
CondVar::~CondVar() { PthreadCall("destroy cv", pthread_cond_destroy(&cv_)); }
|
|
||||||
|
|
||||||
void CondVar::Wait() {
|
|
||||||
PthreadCall("wait", pthread_cond_wait(&cv_, &mu_->mu_));
|
|
||||||
}
|
|
||||||
|
|
||||||
void CondVar::Signal() {
|
|
||||||
PthreadCall("signal", pthread_cond_signal(&cv_));
|
|
||||||
}
|
|
||||||
|
|
||||||
void CondVar::SignalAll() {
|
|
||||||
PthreadCall("broadcast", pthread_cond_broadcast(&cv_));
|
|
||||||
}
|
|
||||||
|
|
||||||
void InitOnce(OnceType* once, void (*initializer)()) {
|
|
||||||
PthreadCall("once", pthread_once(once, initializer));
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace port
|
|
||||||
} // namespace leveldb
|
|
@ -1,11 +1,9 @@
|
|||||||
// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
|
// Copyright (c) 2018 The LevelDB Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file. See the AUTHORS file for names of contributors.
|
// found in the LICENSE file. See the AUTHORS file for names of contributors.
|
||||||
//
|
|
||||||
// See port_example.h for documentation for the following types/functions.
|
|
||||||
|
|
||||||
#ifndef STORAGE_LEVELDB_PORT_PORT_POSIX_H_
|
#ifndef STORAGE_LEVELDB_PORT_PORT_STDCXX_H_
|
||||||
#define STORAGE_LEVELDB_PORT_PORT_POSIX_H_
|
#define STORAGE_LEVELDB_PORT_PORT_STDCXX_H_
|
||||||
|
|
||||||
// port/port_config.h availability is automatically detected via __has_include
|
// port/port_config.h availability is automatically detected via __has_include
|
||||||
// in newer compilers. If LEVELDB_HAS_PORT_CONFIG_H is defined, it overrides the
|
// in newer compilers. If LEVELDB_HAS_PORT_CONFIG_H is defined, it overrides the
|
||||||
@ -24,22 +22,22 @@
|
|||||||
|
|
||||||
#endif // defined(LEVELDB_HAS_PORT_CONFIG_H)
|
#endif // defined(LEVELDB_HAS_PORT_CONFIG_H)
|
||||||
|
|
||||||
#include <pthread.h>
|
|
||||||
#if HAVE_CRC32C
|
#if HAVE_CRC32C
|
||||||
#include <crc32c/crc32c.h>
|
#include <crc32c/crc32c.h>
|
||||||
#endif // HAVE_CRC32C
|
#endif // HAVE_CRC32C
|
||||||
#if HAVE_SNAPPY
|
#if HAVE_SNAPPY
|
||||||
#include <snappy.h>
|
#include <snappy.h>
|
||||||
#endif // HAVE_SNAPPY
|
#endif // HAVE_SNAPPY
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <cassert>
|
||||||
|
#include <condition_variable> // NOLINT
|
||||||
|
#include <mutex> // NOLINT
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "port/atomic_pointer.h"
|
#include "port/atomic_pointer.h"
|
||||||
#include "port/thread_annotations.h"
|
#include "port/thread_annotations.h"
|
||||||
|
|
||||||
#if !HAVE_FDATASYNC
|
|
||||||
#define fdatasync fsync
|
|
||||||
#endif // !HAVE_FDATASYNC
|
|
||||||
|
|
||||||
namespace leveldb {
|
namespace leveldb {
|
||||||
namespace port {
|
namespace port {
|
||||||
|
|
||||||
@ -47,39 +45,52 @@ static const bool kLittleEndian = !LEVELDB_IS_BIG_ENDIAN;
|
|||||||
|
|
||||||
class CondVar;
|
class CondVar;
|
||||||
|
|
||||||
|
// Thinly wraps std::mutex.
|
||||||
class LOCKABLE Mutex {
|
class LOCKABLE Mutex {
|
||||||
public:
|
public:
|
||||||
Mutex();
|
Mutex() = default;
|
||||||
~Mutex();
|
~Mutex() = default;
|
||||||
|
|
||||||
void Lock() EXCLUSIVE_LOCK_FUNCTION();
|
Mutex(const Mutex&) = delete;
|
||||||
void Unlock() UNLOCK_FUNCTION();
|
Mutex& operator=(const Mutex&) = delete;
|
||||||
|
|
||||||
|
void Lock() EXCLUSIVE_LOCK_FUNCTION() { mu_.lock(); }
|
||||||
|
void Unlock() UNLOCK_FUNCTION() { mu_.unlock(); }
|
||||||
void AssertHeld() ASSERT_EXCLUSIVE_LOCK() { }
|
void AssertHeld() ASSERT_EXCLUSIVE_LOCK() { }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class CondVar;
|
friend class CondVar;
|
||||||
pthread_mutex_t mu_;
|
std::mutex mu_;
|
||||||
|
|
||||||
// No copying
|
|
||||||
Mutex(const Mutex&);
|
|
||||||
void operator=(const Mutex&);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Thinly wraps std::condition_variable.
|
||||||
class CondVar {
|
class CondVar {
|
||||||
public:
|
public:
|
||||||
explicit CondVar(Mutex* mu);
|
explicit CondVar(Mutex* mu) : mu_(mu) { assert(mu != nullptr); }
|
||||||
~CondVar();
|
~CondVar() = default;
|
||||||
void Wait();
|
|
||||||
void Signal();
|
CondVar(const CondVar&) = delete;
|
||||||
void SignalAll();
|
CondVar& operator=(const CondVar&) = delete;
|
||||||
|
|
||||||
|
void Wait() {
|
||||||
|
std::unique_lock<std::mutex> lock(mu_->mu_, std::adopt_lock);
|
||||||
|
cv_.wait(lock);
|
||||||
|
lock.release();
|
||||||
|
}
|
||||||
|
void Signal() { cv_.notify_one(); }
|
||||||
|
void SignalAll() { cv_.notify_all(); }
|
||||||
private:
|
private:
|
||||||
pthread_cond_t cv_;
|
std::condition_variable cv_;
|
||||||
Mutex* mu_;
|
Mutex* const mu_;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef pthread_once_t OnceType;
|
using OnceType = std::once_flag;
|
||||||
#define LEVELDB_ONCE_INIT PTHREAD_ONCE_INIT
|
#define LEVELDB_ONCE_INIT {}
|
||||||
void InitOnce(OnceType* once, void (*initializer)());
|
|
||||||
|
// Thinly wraps std::call_once.
|
||||||
|
inline void InitOnce(OnceType* once, void (*initializer)()) {
|
||||||
|
std::call_once(*once, *initializer);
|
||||||
|
}
|
||||||
|
|
||||||
inline bool Snappy_Compress(const char* input, size_t length,
|
inline bool Snappy_Compress(const char* input, size_t length,
|
||||||
::std::string* output) {
|
::std::string* output) {
|
||||||
@ -103,8 +114,7 @@ inline bool Snappy_GetUncompressedLength(const char* input, size_t length,
|
|||||||
#endif // HAVE_SNAPPY
|
#endif // HAVE_SNAPPY
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool Snappy_Uncompress(const char* input, size_t length,
|
inline bool Snappy_Uncompress(const char* input, size_t length, char* output) {
|
||||||
char* output) {
|
|
||||||
#if HAVE_SNAPPY
|
#if HAVE_SNAPPY
|
||||||
return snappy::RawUncompress(input, length, output);
|
return snappy::RawUncompress(input, length, output);
|
||||||
#else
|
#else
|
||||||
@ -127,4 +137,4 @@ inline uint32_t AcceleratedCRC32C(uint32_t crc, const char* buf, size_t size) {
|
|||||||
} // namespace port
|
} // namespace port
|
||||||
} // namespace leveldb
|
} // namespace leveldb
|
||||||
|
|
||||||
#endif // STORAGE_LEVELDB_PORT_PORT_POSIX_H_
|
#endif // STORAGE_LEVELDB_PORT_PORT_STDCXX_H_
|
@ -28,6 +28,12 @@
|
|||||||
#include "util/posix_logger.h"
|
#include "util/posix_logger.h"
|
||||||
#include "util/env_posix_test_helper.h"
|
#include "util/env_posix_test_helper.h"
|
||||||
|
|
||||||
|
// HAVE_FDATASYNC is defined in the auto-generated port_config.h, which is
|
||||||
|
// included by port_stdcxx.h.
|
||||||
|
#if !HAVE_FDATASYNC
|
||||||
|
#define fdatasync fsync
|
||||||
|
#endif // !HAVE_FDATASYNC
|
||||||
|
|
||||||
namespace leveldb {
|
namespace leveldb {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user