From a4f9b8b49ee9a586c7cfdccc5ff7e8bf888b5634 Mon Sep 17 00:00:00 2001 From: heyongqiang Date: Sun, 26 Aug 2012 23:45:35 -0700 Subject: [PATCH] merge 1.5 Summary: as subject Test Plan: db_test table_test Reviewers: dhruba --- Makefile | 29 ++++-- build_detect_platform | 32 ++++-- db/c_test.c | 11 ++- db/db_bench.cc | 10 +- db/db_impl.cc | 2 + db/db_test.cc | 21 ++-- db/version_set.cc | 4 +- db/version_set.h | 9 ++ doc/bench/db_bench_sqlite3.cc | 28 +++++- doc/bench/db_bench_tree_db.cc | 30 +++++- include/leveldb/db.h | 2 +- port/atomic_pointer.h | 18 +++- port/port.h | 2 - port/port_android.cc | 64 ------------ port/port_android.h | 180 ---------------------------------- port/port_example.h | 10 ++ port/port_posix.cc | 4 + port/port_posix.h | 33 +++++-- util/coding_test.cc | 23 +++++ util/comparator.cc | 11 ++- 20 files changed, 224 insertions(+), 299 deletions(-) delete mode 100644 port/port_android.cc delete mode 100644 port/port_android.h diff --git a/Makefile b/Makefile index 9de1f1b54..38f4516d4 100644 --- a/Makefile +++ b/Makefile @@ -3,8 +3,6 @@ # found in the LICENSE file. See the AUTHORS file for names of contributors. # Inherit some settings from environment variables, if available -CXX ?= g++ -CC ?= gcc INSTALL_PATH ?= $(CURDIR) #----------------------------------------------- @@ -71,21 +69,31 @@ default: all # Should we build shared libraries? ifneq ($(PLATFORM_SHARED_EXT),) + +ifneq ($(PLATFORM_SHARED_VERSIONED),true) +SHARED1 = libleveldb.$(PLATFORM_SHARED_EXT) +SHARED2 = $(SHARED1) +SHARED3 = $(SHARED1) +SHARED = $(SHARED1) +else # Update db.h if you change these. SHARED_MAJOR = 1 -SHARED_MINOR = 4 +SHARED_MINOR = 5 SHARED1 = libleveldb.$(PLATFORM_SHARED_EXT) SHARED2 = $(SHARED1).$(SHARED_MAJOR) SHARED3 = $(SHARED1).$(SHARED_MAJOR).$(SHARED_MINOR) SHARED = $(SHARED1) $(SHARED2) $(SHARED3) -$(SHARED3): - $(CXX) $(LDFLAGS) $(PLATFORM_SHARED_LDFLAGS)$(INSTALL_PATH)/$(SHARED2) $(CXXFLAGS) $(PLATFORM_SHARED_CFLAGS) $(SOURCES) $(SOURCESCPP) -o $(SHARED3) $(EXEC_LDFLAGS_SHARED) -$(SHARED2): $(SHARED3) - ln -fs $(SHARED3) $(SHARED2) $(SHARED1): $(SHARED3) ln -fs $(SHARED3) $(SHARED1) +$(SHARED2): $(SHARED3) + ln -fs $(SHARED3) $(SHARED2) endif +$(SHARED3): + $(CXX) $(LDFLAGS) $(PLATFORM_SHARED_LDFLAGS)$(SHARED2) $(CXXFLAGS) $(PLATFORM_SHARED_CFLAGS) $(SOURCES) -o $(SHARED3) + +endif # PLATFORM_SHARED_EXT + all: $(VERSIONFILE) $(SHARED) $(LIBRARY) $(THRIFTSERVER) $(TOOLS) check: all $(PROGRAMS) $(TESTS) $(TOOLS) @@ -202,9 +210,10 @@ $(VERSIONFILE): build_detect_version ifeq ($(PLATFORM), IOS) # For iOS, create universal object files to be used on both the simulator and # a device. -SIMULATORROOT=/Developer/Platforms/iPhoneSimulator.platform/Developer -DEVICEROOT=/Developer/Platforms/iPhoneOS.platform/Developer -IOSVERSION=$(shell defaults read /Developer/Platforms/iPhoneOS.platform/version CFBundleShortVersionString) +PLATFORMSROOT=/Applications/Xcode.app/Contents/Developer/Platforms +SIMULATORROOT=$(PLATFORMSROOT)/iPhoneSimulator.platform/Developer +DEVICEROOT=$(PLATFORMSROOT)/iPhoneOS.platform/Developer +IOSVERSION=$(shell defaults read $(PLATFORMSROOT)/iPhoneOS.platform/versionCFBundleShortVersionString) .cc.o: mkdir -p ios-x86/$(dir $@) diff --git a/build_detect_platform b/build_detect_platform index ce33e2c92..b6fafab6c 100755 --- a/build_detect_platform +++ b/build_detect_platform @@ -4,18 +4,27 @@ # argument, which in turn gets read while processing Makefile. # # The output will set the following variables: +# CC C Compiler path +# CXX C++ Compiler path # PLATFORM_LDFLAGS Linker flags # PLATFORM_SHARED_EXT Extension for shared libraries # PLATFORM_SHARED_LDFLAGS Flags for building shared library # PLATFORM_SHARED_CFLAGS Flags for compiling objects for shared library # PLATFORM_CCFLAGS C compiler flags # PLATFORM_CXXFLAGS C++ compiler flags. Will contain: +# PLATFORM_SHARED_VERSIONED Set to 'true' if platform supports versioned +# shared libraries, empty otherwise. +# +# The PLATFORM_CCFLAGS and PLATFORM_CXXFLAGS might include the following: +# # -DLEVELDB_PLATFORM_POSIX if cstdatomic is present # -DLEVELDB_PLATFORM_NOATOMIC if it is not +# -DSNAPPY if the Snappy library is present +# OUTPUT=$1 if test -z "$OUTPUT"; then - echo "usage: $0 " + echo "usage: $0 " >&2 exit 1 fi @@ -23,6 +32,10 @@ fi rm -f $OUTPUT touch $OUTPUT +if test -z "$CC"; then + CC=cc +fi + if test -z "$CXX"; then CXX=g++ fi @@ -33,12 +46,14 @@ if test -z "$TARGET_OS"; then fi COMMON_FLAGS= +CROSS_COMPILE= PLATFORM_CCFLAGS= PLATFORM_CXXFLAGS= PLATFORM_LDFLAGS= PLATFORM_SHARED_EXT="so" PLATFORM_SHARED_LDFLAGS="-shared -Wl,-soname -Wl," PLATFORM_SHARED_CFLAGS="-fPIC" +PLATFORM_SHARED_VERSIONED=true # On GCC, we pick libc's memcmp over GCC's memcmp via -fno-builtin-memcmp case "$TARGET_OS" in @@ -86,13 +101,14 @@ case "$TARGET_OS" in PORT_FILE=port/port_posix.cc ;; OS_ANDROID_CROSSCOMPILE) - PLATFORM="$TARGET_OS" - COMMON_FLAGS="" - PLATFORM_LDFLAGS="" - PORT_FILE=port/port_android.cc + PLATFORM=OS_ANDROID + COMMON_FLAGS="-fno-builtin-memcmp -D_REENTRANT -DOS_ANDROID -DLEVELDB_PLATFORM_POSIX" + PLATFORM_LDFLAGS="" # All pthread features are in the Android C library + PORT_FILE=port/port_posix.cc + CROSS_COMPILE=true ;; *) - echo "Unknown platform!" + echo "Unknown platform!" >&2 exit 1 esac @@ -125,7 +141,7 @@ echo "SOURCES=$PORTABLE_FILES $PORT_FILE" >> $OUTPUT echo "SOURCESCPP=$PORTABLE_CPP" >> $OUTPUT echo "MEMENV_SOURCES=helpers/memenv/memenv.cc" >> $OUTPUT -if [ "$PLATFORM" = "OS_ANDROID_CROSSCOMPILE" ]; then +if [ "$CROSS_COMPILE" = "true" ]; then # Cross-compiling; do not try any compilation tests. true else @@ -212,6 +228,8 @@ fi PLATFORM_CCFLAGS="$PLATFORM_CCFLAGS $COMMON_FLAGS" PLATFORM_CXXFLAGS="$PLATFORM_CXXFLAGS $COMMON_FLAGS" +echo "CC=$CC" >> $OUTPUT +echo "CXX=$CXX" >> $OUTPUT echo "PLATFORM=$PLATFORM" >> $OUTPUT echo "PLATFORM_LDFLAGS=$PLATFORM_LDFLAGS" >> $OUTPUT echo "PLATFORM_CCFLAGS=$PLATFORM_CCFLAGS" >> $OUTPUT diff --git a/db/c_test.c b/db/c_test.c index 12b4424ab..979244715 100644 --- a/db/c_test.c +++ b/db/c_test.c @@ -19,6 +19,13 @@ static void StartPhase(const char* name) { phase = name; } +static const char* GetTempDir(void) { + const char* ret = getenv("TEST_TMPDIR"); + if (ret == NULL || ret[0] == '\0') + ret = "/tmp"; + return ret; +} + #define CheckNoError(err) \ if ((err) != NULL) { \ fprintf(stderr, "%s:%d: %s: %s\n", __FILE__, __LINE__, phase, (err)); \ @@ -158,7 +165,9 @@ int main(int argc, char** argv) { char* err = NULL; int run = -1; - snprintf(dbname, sizeof(dbname), "/tmp/leveldb_c_test-%d", + snprintf(dbname, sizeof(dbname), + "%s/leveldb_c_test-%d", + GetTempDir(), ((int) geteuid())); StartPhase("create_objects"); diff --git a/db/db_bench.cc b/db/db_bench.cc index 7e768a444..4644ed87b 100644 --- a/db/db_bench.cc +++ b/db/db_bench.cc @@ -103,7 +103,7 @@ static int FLAGS_bloom_bits = -1; static bool FLAGS_use_existing_db = false; // Use the db with the following name. -static const char* FLAGS_db = "/tmp/dbbench"; +static const char* FLAGS_db = NULL; // Number of shards for the block cache is 2 ** FLAGS_cache_numshardbits. // Negative means use default settings. This is applied only @@ -1017,6 +1017,7 @@ class Benchmark { int main(int argc, char** argv) { FLAGS_write_buffer_size = leveldb::Options().write_buffer_size; FLAGS_open_files = leveldb::Options().max_open_files; + std::string default_db_path; for (int i = 1; i < argc; i++) { double d; @@ -1106,6 +1107,13 @@ int main(int argc, char** argv) { } } + // Choose a location for the test database if none given with --db= + if (FLAGS_db == NULL) { + leveldb::Env::Default()->GetTestDirectory(&default_db_path); + default_db_path += "/dbbench"; + FLAGS_db = default_db_path.c_str(); + } + leveldb::Benchmark benchmark; benchmark.Run(); return 0; diff --git a/db/db_impl.cc b/db/db_impl.cc index 697296576..b5b08ea9a 100644 --- a/db/db_impl.cc +++ b/db/db_impl.cc @@ -1395,6 +1395,8 @@ Status DBImpl::MakeRoomForWrite(bool force) { WritableFile* lfile = NULL; s = env_->NewWritableFile(LogFileName(dbname_, new_log_number), &lfile); if (!s.ok()) { + // Avoid chewing through file number space in a tight loop. + versions_->ReuseFileNumber(new_log_number); break; } delete log_; diff --git a/db/db_test.cc b/db/db_test.cc index a4f171c66..8e2233936 100644 --- a/db/db_test.cc +++ b/db/db_test.cc @@ -152,6 +152,7 @@ class DBTest { enum OptionConfig { kDefault, kFilter, + kUncompressed, kNumLevel_3, kEnd }; @@ -183,10 +184,10 @@ class DBTest { // Switch to a fresh database with the next option configuration to // test. Return false if there are no more configurations to test. bool ChangeOptions() { - if (option_config_ == kEnd) { + option_config_++; + if (option_config_ >= kEnd) { return false; } else { - option_config_++; DestroyAndReopen(); return true; } @@ -199,6 +200,9 @@ class DBTest { case kFilter: options.filter_policy = filter_policy_; break; + case kUncompressed: + options.compression = kNoCompression; + break; case kNumLevel_3: options.num_levels = 3; break; @@ -575,13 +579,15 @@ TEST(DBTest, GetEncountersEmptyLevel) { ASSERT_EQ(NumTableFilesAtLevel(1), 0); ASSERT_EQ(NumTableFilesAtLevel(2), 1); - // Step 3: read until level 0 compaction disappears. - int read_count = 0; - while (NumTableFilesAtLevel(0) > 0) { - ASSERT_LE(read_count, 10000) << "did not trigger level 0 compaction"; - read_count++; + // Step 3: read a bunch of times + for (int i = 0; i < 1000; i++) { ASSERT_EQ("NOT_FOUND", Get("missing")); } + + // Step 4: Wait for compaction to finish + env_->SleepForMicroseconds(1000000); + + ASSERT_EQ(NumTableFilesAtLevel(0), 0); } while (ChangeOptions()); } @@ -1583,6 +1589,7 @@ TEST(DBTest, NoSpace) { Compact("a", "z"); const int num_files = CountFiles(); env_->no_space_.Release_Store(env_); // Force out-of-space errors + env_->sleep_counter_.Reset(); for (int i = 0; i < 5; i++) { for (int level = 0; level < dbfull()->NumberLevels()-1; level++) { dbfull()->TEST_CompactRange(level, NULL, NULL); diff --git a/db/version_set.cc b/db/version_set.cc index a7a2e2284..4ec9e27b1 100644 --- a/db/version_set.cc +++ b/db/version_set.cc @@ -107,7 +107,7 @@ bool SomeFileOverlapsRange( const Comparator* ucmp = icmp.user_comparator(); if (!disjoint_sorted_files) { // Need to check against all files - for (int i = 0; i < files.size(); i++) { + for (size_t i = 0; i < files.size(); i++) { const FileMetaData* f = files[i]; if (AfterFile(ucmp, smallest_user_key, f) || BeforeFile(ucmp, largest_user_key, f)) { @@ -1479,7 +1479,7 @@ Compaction* VersionSet::CompactRange( // Avoid compacting too much in one shot in case the range is large. const uint64_t limit = MaxFileSizeForLevel(level); uint64_t total = 0; - for (int i = 0; i < inputs.size(); i++) { + for (size_t i = 0; i < inputs.size(); i++) { uint64_t s = inputs[i]->file_size; total += s; if (total >= limit) { diff --git a/db/version_set.h b/db/version_set.h index 2dc889708..e6bca8bf5 100644 --- a/db/version_set.h +++ b/db/version_set.h @@ -167,6 +167,15 @@ class VersionSet { // Allocate and return a new file number uint64_t NewFileNumber() { return next_file_number_++; } + // Arrange to reuse "file_number" unless a newer file number has + // already been allocated. + // REQUIRES: "file_number" was returned by a call to NewFileNumber(). + void ReuseFileNumber(uint64_t file_number) { + if (next_file_number_ == file_number + 1) { + next_file_number_ = file_number; + } + } + // Return the number of Table files at the specified level. int NumLevelFiles(int level) const; diff --git a/doc/bench/db_bench_sqlite3.cc b/doc/bench/db_bench_sqlite3.cc index 6951a1430..256793a9d 100644 --- a/doc/bench/db_bench_sqlite3.cc +++ b/doc/bench/db_bench_sqlite3.cc @@ -75,6 +75,9 @@ static bool FLAGS_transaction = true; // If true, we enable Write-Ahead Logging static bool FLAGS_WAL_enabled = true; +// Use the db with the following name. +static const char* FLAGS_db = NULL; + inline static void ExecErrorCheck(int status, char *err_msg) { if (status != SQLITE_OK) { @@ -317,11 +320,16 @@ class Benchmark { bytes_(0), rand_(301) { std::vector files; - Env::Default()->GetChildren("/tmp", &files); + std::string test_dir; + Env::Default()->GetTestDirectory(&test_dir); + Env::Default()->GetChildren(test_dir, &files); if (!FLAGS_use_existing_db) { for (int i = 0; i < files.size(); i++) { if (Slice(files[i]).starts_with("dbbench_sqlite3")) { - Env::Default()->DeleteFile("/tmp/" + files[i]); + std::string file_name(test_dir); + file_name += "/"; + file_name += files[i]; + Env::Default()->DeleteFile(file_name.c_str()); } } } @@ -415,7 +423,11 @@ class Benchmark { db_num_++; // Open database - snprintf(file_name, sizeof(file_name), "/tmp/dbbench_sqlite3-%d.db", + std::string tmp_dir; + Env::Default()->GetTestDirectory(&tmp_dir); + snprintf(file_name, sizeof(file_name), + "%s/dbbench_sqlite3-%d.db", + tmp_dir.c_str(), db_num_); status = sqlite3_open(file_name, &db_); if (status) { @@ -655,6 +667,7 @@ class Benchmark { } // namespace leveldb int main(int argc, char** argv) { + std::string default_db_path; for (int i = 1; i < argc; i++) { double d; int n; @@ -684,12 +697,21 @@ int main(int argc, char** argv) { } else if (sscanf(argv[i], "--WAL_enabled=%d%c", &n, &junk) == 1 && (n == 0 || n == 1)) { FLAGS_WAL_enabled = n; + } else if (strncmp(argv[i], "--db=", 5) == 0) { + FLAGS_db = argv[i] + 5; } else { fprintf(stderr, "Invalid flag '%s'\n", argv[i]); exit(1); } } + // Choose a location for the test database if none given with --db= + if (FLAGS_db == NULL) { + leveldb::Env::Default()->GetTestDirectory(&default_db_path); + default_db_path += "/dbbench"; + FLAGS_db = default_db_path.c_str(); + } + leveldb::Benchmark benchmark; benchmark.Run(); return 0; diff --git a/doc/bench/db_bench_tree_db.cc b/doc/bench/db_bench_tree_db.cc index 214d9b7a3..ed86f031c 100644 --- a/doc/bench/db_bench_tree_db.cc +++ b/doc/bench/db_bench_tree_db.cc @@ -68,6 +68,9 @@ static bool FLAGS_use_existing_db = false; // is off. static bool FLAGS_compression = true; +// Use the db with the following name. +static const char* FLAGS_db = NULL; + inline static void DBSynchronize(kyotocabinet::TreeDB* db_) { @@ -292,11 +295,16 @@ class Benchmark { bytes_(0), rand_(301) { std::vector files; - Env::Default()->GetChildren("/tmp", &files); + std::string test_dir; + Env::Default()->GetTestDirectory(&test_dir); + Env::Default()->GetChildren(test_dir.c_str(), &files); if (!FLAGS_use_existing_db) { for (int i = 0; i < files.size(); i++) { if (Slice(files[i]).starts_with("dbbench_polyDB")) { - Env::Default()->DeleteFile("/tmp/" + files[i]); + std::string file_name(test_dir); + file_name += "/"; + file_name += files[i]; + Env::Default()->DeleteFile(file_name.c_str()); } } } @@ -385,8 +393,12 @@ class Benchmark { db_ = new kyotocabinet::TreeDB(); char file_name[100]; db_num_++; - snprintf(file_name, sizeof(file_name), "/tmp/dbbench_polyDB-%d.kct", - db_num_); + std::string test_dir; + Env::Default()->GetTestDirectory(&test_dir); + snprintf(file_name, sizeof(file_name), + "%s/dbbench_polyDB-%d.kct", + test_dir.c_str(), + db_num_); // Create tuning options and open the database int open_options = kyotocabinet::PolyDB::OWRITER | @@ -470,6 +482,7 @@ class Benchmark { } // namespace leveldb int main(int argc, char** argv) { + std::string default_db_path; for (int i = 1; i < argc; i++) { double d; int n; @@ -494,12 +507,21 @@ int main(int argc, char** argv) { } else if (sscanf(argv[i], "--compression=%d%c", &n, &junk) == 1 && (n == 0 || n == 1)) { FLAGS_compression = (n == 1) ? true : false; + } else if (strncmp(argv[i], "--db=", 5) == 0) { + FLAGS_db = argv[i] + 5; } else { fprintf(stderr, "Invalid flag '%s'\n", argv[i]); exit(1); } } + // Choose a location for the test database if none given with --db= + if (FLAGS_db == NULL) { + leveldb::Env::Default()->GetTestDirectory(&default_db_path); + default_db_path += "/dbbench"; + FLAGS_db = default_db_path.c_str(); + } + leveldb::Benchmark benchmark; benchmark.Run(); return 0; diff --git a/include/leveldb/db.h b/include/leveldb/db.h index 2764fcfa7..927d420a1 100644 --- a/include/leveldb/db.h +++ b/include/leveldb/db.h @@ -14,7 +14,7 @@ namespace leveldb { // Update Makefile if you change these static const int kMajorVersion = 1; -static const int kMinorVersion = 4; +static const int kMinorVersion = 5; struct Options; struct ReadOptions; diff --git a/port/atomic_pointer.h b/port/atomic_pointer.h index 35ae5500d..c58bffbf1 100644 --- a/port/atomic_pointer.h +++ b/port/atomic_pointer.h @@ -73,13 +73,21 @@ inline void MemoryBarrier() { } #define LEVELDB_HAVE_MEMORY_BARRIER -// ARM -#elif defined(ARCH_CPU_ARM_FAMILY) +// ARM Linux +#elif defined(ARCH_CPU_ARM_FAMILY) && defined(__linux__) typedef void (*LinuxKernelMemoryBarrierFunc)(void); -LinuxKernelMemoryBarrierFunc pLinuxKernelMemoryBarrier __attribute__((weak)) = - (LinuxKernelMemoryBarrierFunc) 0xffff0fa0; +// The Linux ARM kernel provides a highly optimized device-specific memory +// barrier function at a fixed memory address that is mapped in every +// user-level process. +// +// This beats using CPU-specific instructions which are, on single-core +// devices, un-necessary and very costly (e.g. ARMv7-A "dmb" takes more +// than 180ns on a Cortex-A8 like the one on a Nexus One). Benchmarking +// shows that the extra function call cost is completely negligible on +// multi-core devices. +// inline void MemoryBarrier() { - pLinuxKernelMemoryBarrier(); + (*(LinuxKernelMemoryBarrierFunc)0xffff0fa0)(); } #define LEVELDB_HAVE_MEMORY_BARRIER diff --git a/port/port.h b/port/port.h index 816826b34..e667db40d 100644 --- a/port/port.h +++ b/port/port.h @@ -14,8 +14,6 @@ # include "port/port_posix.h" #elif defined(LEVELDB_PLATFORM_CHROMIUM) # include "port/port_chromium.h" -#elif defined(LEVELDB_PLATFORM_ANDROID) -# include "port/port_android.h" #endif #endif // STORAGE_LEVELDB_PORT_PORT_H_ diff --git a/port/port_android.cc b/port/port_android.cc deleted file mode 100644 index 815abf299..000000000 --- a/port/port_android.cc +++ /dev/null @@ -1,64 +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_android.h" - -#include - -extern "C" { -size_t fread_unlocked(void *a, size_t b, size_t c, FILE *d) { - return fread(a, b, c, d); -} - -size_t fwrite_unlocked(const void *a, size_t b, size_t c, FILE *d) { - return fwrite(a, b, c, d); -} - -int fflush_unlocked(FILE *f) { - return fflush(f); -} - -int fdatasync(int fd) { - return fsync(fd); -} -} - -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_, NULL)); } -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_, NULL)); -} - -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_)); -} - -} // namespace port -} // namespace leveldb diff --git a/port/port_android.h b/port/port_android.h deleted file mode 100644 index 0333dc441..000000000 --- a/port/port_android.h +++ /dev/null @@ -1,180 +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. -// -// See port_example.h for documentation for the following types/functions. - -#ifndef STORAGE_LEVELDB_PORT_PORT_ANDROID_H_ -#define STORAGE_LEVELDB_PORT_PORT_ANDROID_H_ - -#include -#include -#include -#include -#include -#include - -// Collapse the plethora of ARM flavors available to an easier to manage set -// Defs reference is at https://wiki.edubuntu.org/ARM/Thumb2PortingHowto -#if defined(__ARM_ARCH_6__) || \ - defined(__ARM_ARCH_6J__) || \ - defined(__ARM_ARCH_6K__) || \ - defined(__ARM_ARCH_6Z__) || \ - defined(__ARM_ARCH_6T2__) || \ - defined(__ARM_ARCH_6ZK__) || \ - defined(__ARM_ARCH_7__) || \ - defined(__ARM_ARCH_7R__) || \ - defined(__ARM_ARCH_7A__) -#define ARMV6_OR_7 1 -#endif - -extern "C" { - size_t fread_unlocked(void *a, size_t b, size_t c, FILE *d); - size_t fwrite_unlocked(const void *a, size_t b, size_t c, FILE *d); - int fflush_unlocked(FILE *f); - int fdatasync (int fd); -} - -namespace leveldb { -namespace port { - -static const bool kLittleEndian = __BYTE_ORDER == __LITTLE_ENDIAN; - -class CondVar; - -class Mutex { - public: - Mutex(); - ~Mutex(); - - void Lock(); - void Unlock(); - void AssertHeld() { - //TODO(gabor): How can I implement this? - } - - private: - friend class CondVar; - pthread_mutex_t mu_; - - // No copying - Mutex(const Mutex&); - void operator=(const Mutex&); -}; - -class CondVar { - public: - explicit CondVar(Mutex* mu); - ~CondVar(); - void Wait(); - void Signal(); - void SignalAll(); - private: - Mutex* mu_; - pthread_cond_t cv_; -}; - -#ifndef ARMV6_OR_7 -// On ARM chipsets = V6 -#ifdef ARMV6_OR_7 - __asm__ __volatile__("dmb" : : : "memory"); -#else - pLinuxKernelMemoryBarrier(); -#endif - } - - public: - AtomicPointer() { } - explicit AtomicPointer(void* v) : rep_(v) { } - inline void* Acquire_Load() const { - void* r = rep_; - MemoryBarrier(); - return r; - } - inline void Release_Store(void* v) { - MemoryBarrier(); - rep_ = v; - } - inline void* NoBarrier_Load() const { - void* r = rep_; - return r; - } - inline void NoBarrier_Store(void* v) { - rep_ = v; - } -}; - -// TODO(gabor): Implement compress -inline bool Snappy_Compress( - const char* input, - size_t input_length, - std::string* output) { - return false; -} - -// TODO(gabor): Implement uncompress -inline bool Snappy_GetUncompressedLength(const char* input, size_t length, - size_t* result) { - return false; -} - -// TODO(gabor): Implement uncompress -inline bool Snappy_Uncompress( - const char* input_data, - size_t input_length, - char* output) { - return false; -} - -inline bool Zlib_Compress(const char* input, size_t length, - ::std::string* output, int windowBits = 15, int level = -1, - int strategy = 0) { - return false; -} - -inline char* Zlib_Uncompress(const char* input_data, size_t input_length, - int* decompress_size, int windowBits = 15) { - return false; -} - -inline bool BZip2_Compress(const char* input, size_t length, - ::std::string* output) { - return false; -} - -inline char* BZip2_Uncompress( const char* input_data, size_t input_length, - int* decompress_size) { - return false; -} - -inline uint64_t ThreadIdentifier() { - pthread_t tid = pthread_self(); - uint64_t r = 0; - memcpy(&r, &tid, sizeof(r) < sizeof(tid) ? sizeof(r) : sizeof(tid)); - return r; -} - -inline bool GetHeapProfile(void (*func)(void*, const char*, int), void* arg) { - return false; -} - -} // namespace port -} // namespace leveldb - -#endif // STORAGE_LEVELDB_PORT_PORT_ANDROID_H_ diff --git a/port/port_example.h b/port/port_example.h index 036c7d1cf..ab9e489b3 100644 --- a/port/port_example.h +++ b/port/port_example.h @@ -60,6 +60,16 @@ class CondVar { void SignallAll(); }; +// Thread-safe initialization. +// Used as follows: +// static port::OnceType init_control = LEVELDB_ONCE_INIT; +// static void Initializer() { ... do something ...; } +// ... +// port::InitOnce(&init_control, &Initializer); +typedef intptr_t OnceType; +#define LEVELDB_ONCE_INIT 0 +extern void InitOnce(port::OnceType*, void (*initializer)()); + // A type that holds a pointer that can be read or written atomically // (i.e., without word-tearing.) class AtomicPointer { diff --git a/port/port_posix.cc b/port/port_posix.cc index c44cc99bd..5ba127a5b 100644 --- a/port/port_posix.cc +++ b/port/port_posix.cc @@ -46,5 +46,9 @@ 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 diff --git a/port/port_posix.h b/port/port_posix.h index c42745437..c8201d8b4 100644 --- a/port/port_posix.h +++ b/port/port_posix.h @@ -7,17 +7,22 @@ #ifndef STORAGE_LEVELDB_PORT_PORT_POSIX_H_ #define STORAGE_LEVELDB_PORT_PORT_POSIX_H_ +#undef PLATFORM_IS_LITTLE_ENDIAN #if defined(OS_MACOSX) #include + #if defined(__DARWIN_LITTLE_ENDIAN) && defined(__DARWIN_BYTE_ORDER) + #define PLATFORM_IS_LITTLE_ENDIAN \ + (__DARWIN_BYTE_ORDER == __DARWIN_LITTLE_ENDIAN) + #endif #elif defined(OS_SOLARIS) #include #ifdef _LITTLE_ENDIAN - #define LITTLE_ENDIAN + #define PLATFORM_IS_LITTLE_ENDIAN true #else - #define BIG_ENDIAN + #define PLATFORM_IS_LITTLE_ENDIAN false #endif #elif defined(OS_FREEBSD) || defined(OS_OPENBSD) || defined(OS_NETBSD) ||\ - defined(OS_DRAGONFLYBSD) + defined(OS_DRAGONFLYBSD) || defined(OS_ANDROID) #include #include #else @@ -41,14 +46,13 @@ #include #include "port/atomic_pointer.h" -#ifdef LITTLE_ENDIAN -#define IS_LITTLE_ENDIAN true -#else -#define IS_LITTLE_ENDIAN (__BYTE_ORDER == __LITTLE_ENDIAN) +#ifndef PLATFORM_IS_LITTLE_ENDIAN +#define PLATFORM_IS_LITTLE_ENDIAN (__BYTE_ORDER == __LITTLE_ENDIAN) #endif #if defined(OS_MACOSX) || defined(OS_SOLARIS) || defined(OS_FREEBSD) ||\ - defined(OS_NETBSD) || defined(OS_OPENBSD) || defined(OS_DRAGONFLYBSD) + defined(OS_NETBSD) || defined(OS_OPENBSD) || defined(OS_DRAGONFLYBSD) ||\ + defined(OS_ANDROID) // Use fread/fwrite/fflush on platforms without _unlocked variants #define fread_unlocked fread #define fwrite_unlocked fwrite @@ -61,10 +65,17 @@ #define fdatasync fsync #endif +#if defined(OS_ANDROID) && __ANDROID_API__ < 9 +// fdatasync() was only introduced in API level 9 on Android. Use fsync() +// when targetting older platforms. +#define fdatasync fsync +#endif + namespace leveldb { namespace port { -static const bool kLittleEndian = IS_LITTLE_ENDIAN; +static const bool kLittleEndian = PLATFORM_IS_LITTLE_ENDIAN; +#undef PLATFORM_IS_LITTLE_ENDIAN class CondVar; @@ -98,6 +109,10 @@ class CondVar { Mutex* mu_; }; +typedef pthread_once_t OnceType; +#define LEVELDB_ONCE_INIT PTHREAD_ONCE_INIT +extern void InitOnce(OnceType* once, void (*initializer)()); + inline bool Snappy_Compress(const char* input, size_t length, ::std::string* output) { #ifdef SNAPPY diff --git a/util/coding_test.cc b/util/coding_test.cc index 4cc856c06..2c52b17b6 100644 --- a/util/coding_test.cc +++ b/util/coding_test.cc @@ -51,6 +51,29 @@ TEST(Coding, Fixed64) { } } +// Test that encoding routines generate little-endian encodings +TEST(Coding, EncodingOutput) { + std::string dst; + PutFixed32(&dst, 0x04030201); + ASSERT_EQ(4, dst.size()); + ASSERT_EQ(0x01, static_cast(dst[0])); + ASSERT_EQ(0x02, static_cast(dst[1])); + ASSERT_EQ(0x03, static_cast(dst[2])); + ASSERT_EQ(0x04, static_cast(dst[3])); + + dst.clear(); + PutFixed64(&dst, 0x0807060504030201ull); + ASSERT_EQ(8, dst.size()); + ASSERT_EQ(0x01, static_cast(dst[0])); + ASSERT_EQ(0x02, static_cast(dst[1])); + ASSERT_EQ(0x03, static_cast(dst[2])); + ASSERT_EQ(0x04, static_cast(dst[3])); + ASSERT_EQ(0x05, static_cast(dst[4])); + ASSERT_EQ(0x06, static_cast(dst[5])); + ASSERT_EQ(0x07, static_cast(dst[6])); + ASSERT_EQ(0x08, static_cast(dst[7])); +} + TEST(Coding, Varint32) { std::string s; for (uint32_t i = 0; i < (32 * 32); i++) { diff --git a/util/comparator.cc b/util/comparator.cc index eed9d2fcd..4b7b5724e 100644 --- a/util/comparator.cc +++ b/util/comparator.cc @@ -6,6 +6,7 @@ #include #include "leveldb/comparator.h" #include "leveldb/slice.h" +#include "port/port.h" #include "util/logging.h" namespace leveldb { @@ -65,11 +66,15 @@ class BytewiseComparatorImpl : public Comparator { }; } // namespace -// Intentionally not destroyed to prevent destructor racing -// with background threads. -static const Comparator* bytewise = new BytewiseComparatorImpl; +static port::OnceType once = LEVELDB_ONCE_INIT; +static const Comparator* bytewise; + +static void InitModule() { + bytewise = new BytewiseComparatorImpl; +} const Comparator* BytewiseComparator() { + port::InitOnce(&once, InitModule); return bytewise; } -- GitLab