Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Replace leveldb/ with vanilla 1.7.0

  • Loading branch information...
commit bf6a13f04687766f8b56cfe9db7c0ed5579a09e9 1 parent 2c78473
@sipa authored Pieter Wuille committed
Showing with 481 additions and 1,216 deletions.
  1. +36 −37 src/leveldb/Makefile
  2. +17 −0 src/leveldb/NEWS
  3. +0 −8 src/leveldb/README
  4. +1 −0  src/leveldb/TODO
  5. +63 −52 src/leveldb/build_detect_platform
  6. +14 −0 src/leveldb/db/c.cc
  7. +9 −0 src/leveldb/db/c_test.c
  8. +1 −0  src/leveldb/db/db_bench.cc
  9. +5 −1 src/leveldb/db/db_impl.cc
  10. +18 −10 src/leveldb/db/db_impl.h
  11. +6 −0 src/leveldb/db/db_test.cc
  12. +1 −1  src/leveldb/db/version_set.cc
  13. +3 −1 src/leveldb/db/version_set.h
  14. +1 −1  src/leveldb/doc/bench/db_bench_sqlite3.cc
  15. +4 −4 src/leveldb/doc/index.html
  16. +2 −2 src/leveldb/doc/log_format.txt
  17. +7 −5 src/leveldb/doc/table_format.txt
  18. +10 −0 src/leveldb/helpers/memenv/memenv.cc
  19. +16 −0 src/leveldb/include/leveldb/c.h
  20. +1 −1  src/leveldb/include/leveldb/db.h
  21. +10 −0 src/leveldb/include/leveldb/env.h
  22. +72 −0 src/leveldb/port/atomic_pointer.h
  23. +0 −2  src/leveldb/port/port.h
  24. +0 −182 src/leveldb/port/port_win.cc
  25. +0 −161 src/leveldb/port/port_win.h
  26. +59 −0 src/leveldb/port/thread_annotations.h
  27. +2 −2 src/leveldb/table/block.cc
  28. +3 −2 src/leveldb/util/bloom_test.cc
  29. +20 −20 src/leveldb/util/coding.cc
  30. +0 −591 src/leveldb/util/env_boost.cc
  31. +95 −6 src/leveldb/util/env_posix.cc
  32. +5 −3 src/leveldb/util/mutexlock.h
  33. +0 −96 src/leveldb/util/win_logger.cc
  34. +0 −28 src/leveldb/util/win_logger.h
View
73 src/leveldb/Makefile 100755 → 100644
@@ -2,9 +2,6 @@
# 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.
-# Inherit some settings from environment variables, if available
-INSTALL_PATH ?= $(CURDIR)
-
#-----------------------------------------------
# Uncomment exactly one of the lines labelled (A), (B), and (C) below
# to switch between compilation modes.
@@ -15,14 +12,16 @@ OPT ?= -O2 -DNDEBUG # (A) Production use (optimized mode)
#-----------------------------------------------
# detect what platform we're building on
-$(shell ./build_detect_platform build_config.mk)
+$(shell CC=$(CC) CXX=$(CXX) TARGET_OS=$(TARGET_OS) \
+ ./build_detect_platform build_config.mk ./)
# this file is generated by the previous line to set build flags and sources
include build_config.mk
-xCFLAGS = -I. -I./include $(PLATFORM_CCFLAGS) $(OPT) $(CFLAGS)
-xCXXFLAGS = -I. -I./include $(PLATFORM_CXXFLAGS) $(OPT) $(CXXFLAGS)
+CFLAGS += -I. -I./include $(PLATFORM_CCFLAGS) $(OPT)
+CXXFLAGS += -I. -I./include $(PLATFORM_CXXFLAGS) $(OPT)
-xLDFLAGS = $(PLATFORM_LDFLAGS) $(LDFLAGS)
+LDFLAGS += $(PLATFORM_LDFLAGS)
+LIBS += $(PLATFORM_LIBS)
LIBOBJECTS = $(SOURCES:.cc=.o)
MEMENVOBJECTS = $(MEMENV_SOURCES:.cc=.o)
@@ -70,7 +69,7 @@ SHARED = $(SHARED1)
else
# Update db.h if you change these.
SHARED_MAJOR = 1
-SHARED_MINOR = 5
+SHARED_MINOR = 7
SHARED1 = libleveldb.$(PLATFORM_SHARED_EXT)
SHARED2 = $(SHARED1).$(SHARED_MAJOR)
SHARED3 = $(SHARED1).$(SHARED_MAJOR).$(SHARED_MINOR)
@@ -82,7 +81,7 @@ $(SHARED2): $(SHARED3)
endif
$(SHARED3):
- $(CXX) $(xLDFLAGS) $(PLATFORM_SHARED_LDFLAGS)$(SHARED2) $(xCXXFLAGS) $(PLATFORM_SHARED_CFLAGS) $(SOURCES) $(PLATFORM_EXTRALIBS) -o $(SHARED3)
+ $(CXX) $(LDFLAGS) $(PLATFORM_SHARED_LDFLAGS)$(SHARED2) $(CXXFLAGS) $(PLATFORM_SHARED_CFLAGS) $(SOURCES) -o $(SHARED3) $(LIBS)
endif # PLATFORM_SHARED_EXT
@@ -100,74 +99,74 @@ $(LIBRARY): $(LIBOBJECTS)
$(AR) -rs $@ $(LIBOBJECTS)
db_bench: db/db_bench.o $(LIBOBJECTS) $(TESTUTIL)
- $(CXX) db/db_bench.o $(LIBOBJECTS) $(TESTUTIL) -o $@ $(xLDFLAGS) $(PLATFORM_EXTRALIBS)
+ $(CXX) $(LDFLAGS) db/db_bench.o $(LIBOBJECTS) $(TESTUTIL) -o $@ $(LIBS)
db_bench_sqlite3: doc/bench/db_bench_sqlite3.o $(LIBOBJECTS) $(TESTUTIL)
- $(CXX) doc/bench/db_bench_sqlite3.o $(LIBOBJECTS) $(TESTUTIL) -o $@ $(xLDFLAGS) $(PLATFORM_EXTRALIBS) -lsqlite3
+ $(CXX) $(LDFLAGS) doc/bench/db_bench_sqlite3.o $(LIBOBJECTS) $(TESTUTIL) -o $@ -lsqlite3 $(LIBS)
db_bench_tree_db: doc/bench/db_bench_tree_db.o $(LIBOBJECTS) $(TESTUTIL)
- $(CXX) doc/bench/db_bench_tree_db.o $(LIBOBJECTS) $(TESTUTIL) -o $@ $(xLDFLAGS) $(PLATFORM_EXTRALIBS) -lkyotocabinet
+ $(CXX) $(LDFLAGS) doc/bench/db_bench_tree_db.o $(LIBOBJECTS) $(TESTUTIL) -o $@ -lkyotocabinet $(LIBS)
arena_test: util/arena_test.o $(LIBOBJECTS) $(TESTHARNESS)
- $(CXX) util/arena_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(xLDFLAGS) $(PLATFORM_EXTRALIBS)
+ $(CXX) $(LDFLAGS) util/arena_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS)
bloom_test: util/bloom_test.o $(LIBOBJECTS) $(TESTHARNESS)
- $(CXX) util/bloom_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(xLDFLAGS) $(PLATFORM_EXTRALIBS)
+ $(CXX) $(LDFLAGS) util/bloom_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS)
c_test: db/c_test.o $(LIBOBJECTS) $(TESTHARNESS)
- $(CXX) db/c_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(xLDFLAGS) $(PLATFORM_EXTRALIBS)
+ $(CXX) $(LDFLAGS) db/c_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS)
cache_test: util/cache_test.o $(LIBOBJECTS) $(TESTHARNESS)
- $(CXX) util/cache_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(xLDFLAGS) $(PLATFORM_EXTRALIBS)
+ $(CXX) $(LDFLAGS) util/cache_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS)
coding_test: util/coding_test.o $(LIBOBJECTS) $(TESTHARNESS)
- $(CXX) util/coding_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(xLDFLAGS) $(PLATFORM_EXTRALIBS)
+ $(CXX) $(LDFLAGS) util/coding_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS)
corruption_test: db/corruption_test.o $(LIBOBJECTS) $(TESTHARNESS)
- $(CXX) db/corruption_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(xLDFLAGS) $(PLATFORM_EXTRALIBS)
+ $(CXX) $(LDFLAGS) db/corruption_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS)
crc32c_test: util/crc32c_test.o $(LIBOBJECTS) $(TESTHARNESS)
- $(CXX) util/crc32c_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(xLDFLAGS) $(PLATFORM_EXTRALIBS)
+ $(CXX) $(LDFLAGS) util/crc32c_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS)
db_test: db/db_test.o $(LIBOBJECTS) $(TESTHARNESS)
- $(CXX) db/db_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(xLDFLAGS) $(PLATFORM_EXTRALIBS)
+ $(CXX) $(LDFLAGS) db/db_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS)
dbformat_test: db/dbformat_test.o $(LIBOBJECTS) $(TESTHARNESS)
- $(CXX) db/dbformat_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(xLDFLAGS) $(PLATFORM_EXTRALIBS)
+ $(CXX) $(LDFLAGS) db/dbformat_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS)
env_test: util/env_test.o $(LIBOBJECTS) $(TESTHARNESS)
- $(CXX) util/env_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(xLDFLAGS) $(PLATFORM_EXTRALIBS)
+ $(CXX) $(LDFLAGS) util/env_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS)
filename_test: db/filename_test.o $(LIBOBJECTS) $(TESTHARNESS)
- $(CXX) db/filename_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(xLDFLAGS) $(PLATFORM_EXTRALIBS)
+ $(CXX) $(LDFLAGS) db/filename_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS)
filter_block_test: table/filter_block_test.o $(LIBOBJECTS) $(TESTHARNESS)
- $(CXX) table/filter_block_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(xLDFLAGS) $(PLATFORM_EXTRALIBS)
+ $(CXX) $(LDFLAGS) table/filter_block_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS)
log_test: db/log_test.o $(LIBOBJECTS) $(TESTHARNESS)
- $(CXX) db/log_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(xLDFLAGS) $(PLATFORM_EXTRALIBS)
+ $(CXX) $(LDFLAGS) db/log_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS)
table_test: table/table_test.o $(LIBOBJECTS) $(TESTHARNESS)
- $(CXX) table/table_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(xLDFLAGS) $(PLATFORM_EXTRALIBS)
+ $(CXX) $(LDFLAGS) table/table_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS)
skiplist_test: db/skiplist_test.o $(LIBOBJECTS) $(TESTHARNESS)
- $(CXX) db/skiplist_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(xLDFLAGS) $(PLATFORM_EXTRALIBS)
+ $(CXX) $(LDFLAGS) db/skiplist_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS)
version_edit_test: db/version_edit_test.o $(LIBOBJECTS) $(TESTHARNESS)
- $(CXX) db/version_edit_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(xLDFLAGS) $(PLATFORM_EXTRALIBS)
+ $(CXX) $(LDFLAGS) db/version_edit_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS)
version_set_test: db/version_set_test.o $(LIBOBJECTS) $(TESTHARNESS)
- $(CXX) db/version_set_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(xLDFLAGS) $(PLATFORM_EXTRALIBS)
+ $(CXX) $(LDFLAGS) db/version_set_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS)
write_batch_test: db/write_batch_test.o $(LIBOBJECTS) $(TESTHARNESS)
- $(CXX) db/write_batch_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(xLDFLAGS) $(PLATFORM_EXTRALIBS)
+ $(CXX) $(LDFLAGS) db/write_batch_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS)
$(MEMENVLIBRARY) : $(MEMENVOBJECTS)
rm -f $@
$(AR) -rs $@ $(MEMENVOBJECTS)
memenv_test : helpers/memenv/memenv_test.o $(MEMENVLIBRARY) $(LIBRARY) $(TESTHARNESS)
- $(CXX) helpers/memenv/memenv_test.o $(MEMENVLIBRARY) $(LIBRARY) $(TESTHARNESS) -o $@ $(xLDFLAGS) $(PLATFORM_EXTRALIBS)
+ $(CXX) $(LDFLAGS) helpers/memenv/memenv_test.o $(MEMENVLIBRARY) $(LIBRARY) $(TESTHARNESS) -o $@ $(LIBS)
ifeq ($(PLATFORM), IOS)
# For iOS, create universal object files to be used on both the simulator and
@@ -179,22 +178,22 @@ IOSVERSION=$(shell defaults read $(PLATFORMSROOT)/iPhoneOS.platform/version CFBu
.cc.o:
mkdir -p ios-x86/$(dir $@)
- $(SIMULATORROOT)/usr/bin/$(CXX) $(xCXXFLAGS) -isysroot $(SIMULATORROOT)/SDKs/iPhoneSimulator$(IOSVERSION).sdk -arch i686 -c $< -o ios-x86/$@
+ $(CXX) $(CXXFLAGS) -isysroot $(SIMULATORROOT)/SDKs/iPhoneSimulator$(IOSVERSION).sdk -arch i686 -c $< -o ios-x86/$@
mkdir -p ios-arm/$(dir $@)
- $(DEVICEROOT)/usr/bin/$(CXX) $(xCXXFLAGS) -isysroot $(DEVICEROOT)/SDKs/iPhoneOS$(IOSVERSION).sdk -arch armv6 -arch armv7 -c $< -o ios-arm/$@
+ $(DEVICEROOT)/usr/bin/$(CXX) $(CXXFLAGS) -isysroot $(DEVICEROOT)/SDKs/iPhoneOS$(IOSVERSION).sdk -arch armv6 -arch armv7 -c $< -o ios-arm/$@
lipo ios-x86/$@ ios-arm/$@ -create -output $@
.c.o:
mkdir -p ios-x86/$(dir $@)
- $(SIMULATORROOT)/usr/bin/$(CC) $(xCFLAGS) -isysroot $(SIMULATORROOT)/SDKs/iPhoneSimulator$(IOSVERSION).sdk -arch i686 -c $< -o ios-x86/$@
+ $(CC) $(CFLAGS) -isysroot $(SIMULATORROOT)/SDKs/iPhoneSimulator$(IOSVERSION).sdk -arch i686 -c $< -o ios-x86/$@
mkdir -p ios-arm/$(dir $@)
- $(DEVICEROOT)/usr/bin/$(CC) $(xCFLAGS) -isysroot $(DEVICEROOT)/SDKs/iPhoneOS$(IOSVERSION).sdk -arch armv6 -arch armv7 -c $< -o ios-arm/$@
+ $(DEVICEROOT)/usr/bin/$(CC) $(CFLAGS) -isysroot $(DEVICEROOT)/SDKs/iPhoneOS$(IOSVERSION).sdk -arch armv6 -arch armv7 -c $< -o ios-arm/$@
lipo ios-x86/$@ ios-arm/$@ -create -output $@
else
.cc.o:
- $(CXX) $(xCXXFLAGS) -c $< -o $@
+ $(CXX) $(CXXFLAGS) -c $< -o $@
.c.o:
- $(CC) $(xCFLAGS) -c $< -o $@
+ $(CC) $(CFLAGS) -c $< -o $@
endif
View
17 src/leveldb/NEWS
@@ -0,0 +1,17 @@
+Release 1.2 2011-05-16
+----------------------
+
+Fixes for larger databases (tested up to one billion 100-byte entries,
+i.e., ~100GB).
+
+(1) Place hard limit on number of level-0 files. This fixes errors
+of the form "too many open files".
+
+(2) Fixed memtable management. Before the fix, a heavy write burst
+could cause unbounded memory usage.
+
+A fix for a logging bug where the reader would incorrectly complain
+about corruption.
+
+Allow public access to WriteBatch contents so that users can easily
+wrap a DB.
View
8 src/leveldb/README
@@ -1,11 +1,3 @@
-LevelDB is a third party library used for the transaction database.
-It is imported into the Bitcoin codebase due to being relatively new
-and not widely packaged.
-
-
-
----------------------------------------------------------------------
-
leveldb: A key-value store
Authors: Sanjay Ghemawat (sanjay@google.com) and Jeff Dean (jeff@google.com)
View
1  src/leveldb/TODO
@@ -7,6 +7,7 @@ db
within [start_key..end_key]? For Chrome, deletion of obsolete
object stores, etc. can be done in the background anyway, so
probably not that important.
+- There have been requests for MultiGet.
After a range is completely deleted, what gets rid of the
corresponding files if we do no future changes to that range. Make
View
115 src/leveldb/build_detect_platform
@@ -7,8 +7,11 @@
# CC C Compiler path
# CXX C++ Compiler path
# PLATFORM_LDFLAGS Linker flags
+# PLATFORM_LIBS Libraries flags
# PLATFORM_SHARED_EXT Extension for shared libraries
# PLATFORM_SHARED_LDFLAGS Flags for building shared library
+# This flag is embedded just before the name
+# of the shared library without intervening spaces
# PLATFORM_SHARED_CFLAGS Flags for compiling objects for shared library
# PLATFORM_CCFLAGS C compiler flags
# PLATFORM_CXXFLAGS C++ compiler flags. Will contain:
@@ -23,8 +26,9 @@
#
OUTPUT=$1
-if test -z "$OUTPUT"; then
- echo "usage: $0 <output-filename>" >&2
+PREFIX=$2
+if test -z "$OUTPUT" || test -z "$PREFIX"; then
+ echo "usage: $0 <output-filename> <directory_prefix>" >&2
exit 1
fi
@@ -50,85 +54,79 @@ CROSS_COMPILE=
PLATFORM_CCFLAGS=
PLATFORM_CXXFLAGS=
PLATFORM_LDFLAGS=
-PLATFORM_EXTRALIBS=
-PLATFORM_SOURCES=
+PLATFORM_LIBS=
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
+MEMCMP_FLAG=
+if [ "$CXX" = "g++" ]; then
+ # Use libc's memcmp instead of GCC's memcmp. This results in ~40%
+ # performance improvement on readrandom under gcc 4.4.3 on Linux/x86.
+ MEMCMP_FLAG="-fno-builtin-memcmp"
+fi
+
case "$TARGET_OS" in
Darwin)
PLATFORM=OS_MACOSX
- COMMON_FLAGS="-fno-builtin-memcmp -DOS_MACOSX"
+ COMMON_FLAGS="$MEMCMP_FLAG -DOS_MACOSX"
PLATFORM_SHARED_EXT=dylib
- PLATFORM_SHARED_LDFLAGS="-dynamiclib -install_name "
- PLATFORM_SOURCES="port/port_posix.cc util/env_posix.cc"
+ [ -z "$INSTALL_PATH" ] && INSTALL_PATH=`pwd`
+ PLATFORM_SHARED_LDFLAGS="-dynamiclib -install_name $INSTALL_PATH/"
+ PORT_FILE=port/port_posix.cc
;;
Linux)
PLATFORM=OS_LINUX
- COMMON_FLAGS="-fno-builtin-memcmp -pthread -DOS_LINUX"
+ COMMON_FLAGS="$MEMCMP_FLAG -pthread -DOS_LINUX"
PLATFORM_LDFLAGS="-pthread"
- PLATFORM_SOURCES="port/port_posix.cc util/env_posix.cc"
+ PORT_FILE=port/port_posix.cc
;;
SunOS)
PLATFORM=OS_SOLARIS
- COMMON_FLAGS="-fno-builtin-memcmp -D_REENTRANT -DOS_SOLARIS"
- PLATFORM_LDFLAGS="-lpthread -lrt"
- PLATFORM_SOURCES="port/port_posix.cc util/env_posix.cc"
+ COMMON_FLAGS="$MEMCMP_FLAG -D_REENTRANT -DOS_SOLARIS"
+ PLATFORM_LIBS="-lpthread -lrt"
+ PORT_FILE=port/port_posix.cc
;;
FreeBSD)
PLATFORM=OS_FREEBSD
- COMMON_FLAGS="-fno-builtin-memcmp -D_REENTRANT -DOS_FREEBSD"
- PLATFORM_LDFLAGS="-lpthread"
- PLATFORM_SOURCES="port/port_posix.cc util/env_posix.cc"
+ COMMON_FLAGS="$MEMCMP_FLAG -D_REENTRANT -DOS_FREEBSD"
+ PLATFORM_LIBS="-lpthread"
+ PORT_FILE=port/port_posix.cc
;;
NetBSD)
PLATFORM=OS_NETBSD
- COMMON_FLAGS="-fno-builtin-memcmp -D_REENTRANT -DOS_NETBSD"
- PLATFORM_LDFLAGS="-lpthread -lgcc_s"
- PLATFORM_SOURCES="port/port_posix.cc util/env_posix.cc"
+ COMMON_FLAGS="$MEMCMP_FLAG -D_REENTRANT -DOS_NETBSD"
+ PLATFORM_LIBS="-lpthread -lgcc_s"
+ PORT_FILE=port/port_posix.cc
;;
OpenBSD)
PLATFORM=OS_OPENBSD
- COMMON_FLAGS="-fno-builtin-memcmp -D_REENTRANT -DOS_OPENBSD"
+ COMMON_FLAGS="$MEMCMP_FLAG -D_REENTRANT -DOS_OPENBSD"
PLATFORM_LDFLAGS="-pthread"
- PLATFORM_SOURCES="port/port_posix.cc util/env_posix.cc"
+ PORT_FILE=port/port_posix.cc
;;
DragonFly)
PLATFORM=OS_DRAGONFLYBSD
- COMMON_FLAGS="-fno-builtin-memcmp -D_REENTRANT -DOS_DRAGONFLYBSD"
- PLATFORM_LDFLAGS="-lpthread"
- PLATFORM_SOURCES="port/port_posix.cc util/env_posix.cc"
+ COMMON_FLAGS="$MEMCMP_FLAG -D_REENTRANT -DOS_DRAGONFLYBSD"
+ PLATFORM_LIBS="-lpthread"
+ PORT_FILE=port/port_posix.cc
;;
OS_ANDROID_CROSSCOMPILE)
PLATFORM=OS_ANDROID
- COMMON_FLAGS="-fno-builtin-memcmp -D_REENTRANT -DOS_ANDROID -DLEVELDB_PLATFORM_POSIX"
+ COMMON_FLAGS="$MEMCMP_FLAG -D_REENTRANT -DOS_ANDROID -DLEVELDB_PLATFORM_POSIX"
PLATFORM_LDFLAGS="" # All pthread features are in the Android C library
- PLATFORM_SOURCES="port/port_posix.cc util/env_posix.cc"
+ PORT_FILE=port/port_posix.cc
CROSS_COMPILE=true
;;
- OS_WINDOWS_CROSSCOMPILE)
- PLATFORM=OS_WINDOWS
- COMMON_FLAGS="-fno-builtin-memcmp -D_REENTRANT -DOS_WINDOWS -DLEVELDB_PLATFORM_WINDOWS -DBOOST_THREAD_USE_LIB"
- PLATFORM_CXXFLAGS=""
- PLATFORM_LDFLAGS=""
- PLATFORM_SHARED_CFLAGS=""
- PLATFORM_SOURCES="port/port_win.cc util/env_boost.cc util/win_logger.cc"
- PLATFORM_EXTRALIBS="-lboost_system-mt-s -lboost_filesystem-mt-s -lboost_thread_win32-mt-s"
- CROSS_COMPILE=true
+ HP-UX)
+ PLATFORM=OS_HPUX
+ COMMON_FLAGS="$MEMCMP_FLAG -D_REENTRANT -DOS_HPUX"
+ PLATFORM_LDFLAGS="-pthread"
+ PORT_FILE=port/port_posix.cc
+ # man ld: +h internal_name
+ PLATFORM_SHARED_LDFLAGS="-shared -Wl,+h -Wl,"
;;
- NATIVE_WINDOWS)
- PLATFORM=OS_WINDOWS
- COMMON_FLAGS="-fno-builtin-memcmp -D_REENTRANT -DOS_WINDOWS -DLEVELDB_PLATFORM_WINDOWS -DBOOST_THREAD_USE_LIB"
- PLATFORM_CXXFLAGS=""
- PLATFORM_LDFLAGS=""
- PLATFORM_SHARED_CFLAGS=""
- PLATFORM_SOURCES="port/port_win.cc util/env_boost.cc util/win_logger.cc"
- PLATFORM_EXTRALIBS="-lboost_system-mgw45-mt-s-1_50 -lboost_filesystem-mgw45-mt-s-1_50 -lboost_thread-mgw45-mt-s-1_50 -lboost_chrono-mgw45-mt-s-1_50"
- CROSS_COMPILE=true
- ;;
*)
echo "Unknown platform!" >&2
exit 1
@@ -138,16 +136,18 @@ esac
# except for the test and benchmark files. By default, find will output a list
# of all files matching either rule, so we need to append -print to make the
# prune take effect.
-DIRS="util db table"
+DIRS="$PREFIX/db $PREFIX/util $PREFIX/table"
+
set -f # temporarily disable globbing so that our patterns aren't expanded
PRUNE_TEST="-name *test*.cc -prune"
PRUNE_BENCH="-name *_bench.cc -prune"
-PORTABLE_FILES=`find $DIRS $PRUNE_TEST -o $PRUNE_BENCH -o -name '*.cc' -not -name 'env_*.cc' -not -name '*_logger.cc' -print | sort | tr "\n" " "`
+PORTABLE_FILES=`find $DIRS $PRUNE_TEST -o $PRUNE_BENCH -o -name '*.cc' -print | sort | sed "s,^$PREFIX/,," | tr "\n" " "`
+
set +f # re-enable globbing
# The sources consist of the portable files, plus the platform-specific port
# file.
-echo "SOURCES=$PORTABLE_FILES $PLATFORM_SOURCES" >> $OUTPUT
+echo "SOURCES=$PORTABLE_FILES $PORT_FILE" >> $OUTPUT
echo "MEMENV_SOURCES=helpers/memenv/memenv.cc" >> $OUTPUT
if [ "$CROSS_COMPILE" = "true" ]; then
@@ -155,7 +155,7 @@ if [ "$CROSS_COMPILE" = "true" ]; then
true
else
# If -std=c++0x works, use <cstdatomic>. Otherwise use port_posix.h.
- $CXX $CFLAGS -std=c++0x -x c++ - -o /dev/null 2>/dev/null <<EOF
+ $CXX $CXXFLAGS -std=c++0x -x c++ - -o /dev/null 2>/dev/null <<EOF
#include <cstdatomic>
int main() {}
EOF
@@ -166,12 +166,23 @@ EOF
COMMON_FLAGS="$COMMON_FLAGS -DLEVELDB_PLATFORM_POSIX"
fi
+ # Test whether Snappy library is installed
+ # http://code.google.com/p/snappy/
+ $CXX $CXXFLAGS -x c++ - -o /dev/null 2>/dev/null <<EOF
+ #include <snappy.h>
+ int main() {}
+EOF
+ if [ "$?" = 0 ]; then
+ COMMON_FLAGS="$COMMON_FLAGS -DSNAPPY"
+ PLATFORM_LIBS="$PLATFORM_LIBS -lsnappy"
+ fi
+
# Test whether tcmalloc is available
- $CXX $CFLAGS -x c++ - -o /dev/null -ltcmalloc 2>/dev/null <<EOF
+ $CXX $CXXFLAGS -x c++ - -o /dev/null -ltcmalloc 2>/dev/null <<EOF
int main() {}
EOF
if [ "$?" = 0 ]; then
- PLATFORM_LDFLAGS="$PLATFORM_LDFLAGS -ltcmalloc"
+ PLATFORM_LIBS="$PLATFORM_LIBS -ltcmalloc"
fi
fi
@@ -182,9 +193,9 @@ echo "CC=$CC" >> $OUTPUT
echo "CXX=$CXX" >> $OUTPUT
echo "PLATFORM=$PLATFORM" >> $OUTPUT
echo "PLATFORM_LDFLAGS=$PLATFORM_LDFLAGS" >> $OUTPUT
+echo "PLATFORM_LIBS=$PLATFORM_LIBS" >> $OUTPUT
echo "PLATFORM_CCFLAGS=$PLATFORM_CCFLAGS" >> $OUTPUT
echo "PLATFORM_CXXFLAGS=$PLATFORM_CXXFLAGS" >> $OUTPUT
-echo "PLATFORM_EXTRALIBS=$PLATFORM_EXTRALIBS" >> $OUTPUT
echo "PLATFORM_SHARED_CFLAGS=$PLATFORM_SHARED_CFLAGS" >> $OUTPUT
echo "PLATFORM_SHARED_EXT=$PLATFORM_SHARED_EXT" >> $OUTPUT
echo "PLATFORM_SHARED_LDFLAGS=$PLATFORM_SHARED_LDFLAGS" >> $OUTPUT
View
14 src/leveldb/db/c.cc
@@ -24,6 +24,8 @@ using leveldb::Env;
using leveldb::FileLock;
using leveldb::FilterPolicy;
using leveldb::Iterator;
+using leveldb::kMajorVersion;
+using leveldb::kMinorVersion;
using leveldb::Logger;
using leveldb::NewBloomFilterPolicy;
using leveldb::NewLRUCache;
@@ -578,4 +580,16 @@ void leveldb_env_destroy(leveldb_env_t* env) {
delete env;
}
+void leveldb_free(void* ptr) {
+ free(ptr);
+}
+
+int leveldb_major_version() {
+ return kMajorVersion;
+}
+
+int leveldb_minor_version() {
+ return kMinorVersion;
+}
+
} // end extern "C"
View
9 src/leveldb/db/c_test.c
@@ -165,6 +165,9 @@ int main(int argc, char** argv) {
char* err = NULL;
int run = -1;
+ CheckCondition(leveldb_major_version() >= 1);
+ CheckCondition(leveldb_minor_version() >= 1);
+
snprintf(dbname, sizeof(dbname),
"%s/leveldb_c_test-%d",
GetTempDir(),
@@ -204,6 +207,12 @@ int main(int argc, char** argv) {
CheckCondition(err != NULL);
Free(&err);
+ StartPhase("leveldb_free");
+ db = leveldb_open(options, dbname, &err);
+ CheckCondition(err != NULL);
+ leveldb_free(err);
+ err = NULL;
+
StartPhase("open");
leveldb_options_set_create_if_missing(options, 1);
db = leveldb_open(options, dbname, &err);
View
1  src/leveldb/db/db_bench.cc
@@ -693,6 +693,7 @@ class Benchmark {
options.create_if_missing = !FLAGS_use_existing_db;
options.block_cache = cache_;
options.write_buffer_size = FLAGS_write_buffer_size;
+ options.max_open_files = FLAGS_open_files;
options.filter_policy = filter_policy_;
Status s = DB::Open(options, FLAGS_db, &db_);
if (!s.ok()) {
View
6 src/leveldb/db/db_impl.cc
@@ -609,7 +609,11 @@ void DBImpl::BackgroundCall() {
assert(bg_compaction_scheduled_);
if (!shutting_down_.Acquire_Load()) {
Status s = BackgroundCompaction();
- if (!s.ok()) {
+ if (s.ok()) {
+ // Success
+ } else if (shutting_down_.Acquire_Load()) {
+ // Error most likely due to shutdown; do not wait
+ } else {
// Wait a little bit before retrying background compaction in
// case this is an environmental problem and we do not want to
// chew up resources for failed compactions for the duration of
View
28 src/leveldb/db/db_impl.h
@@ -13,6 +13,7 @@
#include "leveldb/db.h"
#include "leveldb/env.h"
#include "port/port.h"
+#include "port/thread_annotations.h"
namespace leveldb {
@@ -71,7 +72,7 @@ class DBImpl : public DB {
// Recover the descriptor from persistent storage. May do a significant
// amount of work to recover recently logged updates. Any changes to
// be made to the descriptor are added to *edit.
- Status Recover(VersionEdit* edit);
+ Status Recover(VersionEdit* edit) EXCLUSIVE_LOCKS_REQUIRED(mutex_);
void MaybeIgnoreError(Status* s) const;
@@ -80,27 +81,34 @@ class DBImpl : public DB {
// Compact the in-memory write buffer to disk. Switches to a new
// log-file/memtable and writes a new descriptor iff successful.
- Status CompactMemTable();
+ Status CompactMemTable()
+ EXCLUSIVE_LOCKS_REQUIRED(mutex_);
Status RecoverLogFile(uint64_t log_number,
VersionEdit* edit,
- SequenceNumber* max_sequence);
+ SequenceNumber* max_sequence)
+ EXCLUSIVE_LOCKS_REQUIRED(mutex_);
- Status WriteLevel0Table(MemTable* mem, VersionEdit* edit, Version* base);
+ Status WriteLevel0Table(MemTable* mem, VersionEdit* edit, Version* base)
+ EXCLUSIVE_LOCKS_REQUIRED(mutex_);
- Status MakeRoomForWrite(bool force /* compact even if there is room? */);
+ Status MakeRoomForWrite(bool force /* compact even if there is room? */)
+ EXCLUSIVE_LOCKS_REQUIRED(mutex_);
WriteBatch* BuildBatchGroup(Writer** last_writer);
- void MaybeScheduleCompaction();
+ void MaybeScheduleCompaction() EXCLUSIVE_LOCKS_REQUIRED(mutex_);
static void BGWork(void* db);
void BackgroundCall();
- Status BackgroundCompaction();
- void CleanupCompaction(CompactionState* compact);
- Status DoCompactionWork(CompactionState* compact);
+ Status BackgroundCompaction() EXCLUSIVE_LOCKS_REQUIRED(mutex_);
+ void CleanupCompaction(CompactionState* compact)
+ EXCLUSIVE_LOCKS_REQUIRED(mutex_);
+ Status DoCompactionWork(CompactionState* compact)
+ EXCLUSIVE_LOCKS_REQUIRED(mutex_);
Status OpenCompactionOutputFile(CompactionState* compact);
Status FinishCompactionOutputFile(CompactionState* compact, Iterator* input);
- Status InstallCompactionResults(CompactionState* compact);
+ Status InstallCompactionResults(CompactionState* compact)
+ EXCLUSIVE_LOCKS_REQUIRED(mutex_);
// Constant after construction
Env* const env_;
View
6 src/leveldb/db/db_test.cc
@@ -1442,6 +1442,12 @@ TEST(DBTest, DBOpen_Options) {
db = NULL;
}
+TEST(DBTest, Locking) {
+ DB* db2 = NULL;
+ Status s = DB::Open(CurrentOptions(), dbname_, &db2);
+ ASSERT_TRUE(!s.ok()) << "Locking did not prevent re-opening db";
+}
+
// Check that number of files does not grow when we are out of space
TEST(DBTest, NoSpace) {
Options options = CurrentOptions();
View
2  src/leveldb/db/version_set.cc
@@ -865,7 +865,7 @@ Status VersionSet::Recover() {
if (edit.has_comparator_ &&
edit.comparator_ != icmp_.user_comparator()->Name()) {
s = Status::InvalidArgument(
- edit.comparator_ + "does not match existing comparator ",
+ edit.comparator_ + " does not match existing comparator ",
icmp_.user_comparator()->Name());
}
}
View
4 src/leveldb/db/version_set.h
@@ -21,6 +21,7 @@
#include "db/dbformat.h"
#include "db/version_edit.h"
#include "port/port.h"
+#include "port/thread_annotations.h"
namespace leveldb {
@@ -159,7 +160,8 @@ class VersionSet {
// current version. Will release *mu while actually writing to the file.
// REQUIRES: *mu is held on entry.
// REQUIRES: no other thread concurrently calls LogAndApply()
- Status LogAndApply(VersionEdit* edit, port::Mutex* mu);
+ Status LogAndApply(VersionEdit* edit, port::Mutex* mu)
+ EXCLUSIVE_LOCKS_REQUIRED(mu);
// Recover the last saved descriptor from persistent storage.
Status Recover();
View
2  src/leveldb/doc/bench/db_bench_sqlite3.cc
@@ -618,7 +618,7 @@ class Benchmark {
ErrorCheck(status);
// Execute read statement
- while ((status = sqlite3_step(read_stmt)) == SQLITE_ROW);
+ while ((status = sqlite3_step(read_stmt)) == SQLITE_ROW) {}
StepErrorCheck(status);
// Reset SQLite statement for another use
View
8 src/leveldb/doc/index.html
@@ -408,7 +408,7 @@
the number of disk reads substantially.
<pre>
leveldb::Options options;
- options.filter_policy = NewBloomFilter(10);
+ options.filter_policy = NewBloomFilterPolicy(10);
leveldb::DB* db;
leveldb::DB::Open(options, "/tmp/testdb", &amp;db);
... use the database ...
@@ -420,7 +420,7 @@
based filtering policy with the database. Bloom filter based
filtering relies on keeping some number of bits of data in memory per
key (in this case 10 bits per key since that is the argument we passed
-to NewBloomFilter). This filter will reduce the number of unnecessary
+to NewBloomFilterPolicy). This filter will reduce the number of unnecessary
disk reads needed for <code>Get()</code> calls by a factor of
approximately a 100. Increasing the bits per key will lead to a
larger reduction at the cost of more memory usage. We recommend that
@@ -430,7 +430,7 @@
If you are using a custom comparator, you should ensure that the filter
policy you are using is compatible with your comparator. For example,
consider a comparator that ignores trailing spaces when comparing keys.
-<code>NewBloomFilter</code> must not be used with such a comparator.
+<code>NewBloomFilterPolicy</code> must not be used with such a comparator.
Instead, the application should provide a custom filter policy that
also ignores trailing spaces. For example:
<pre>
@@ -438,7 +438,7 @@
private:
FilterPolicy* builtin_policy_;
public:
- CustomFilterPolicy() : builtin_policy_(NewBloomFilter(10)) { }
+ CustomFilterPolicy() : builtin_policy_(NewBloomFilterPolicy(10)) { }
~CustomFilterPolicy() { delete builtin_policy_; }
const char* Name() const { return "IgnoreTrailingSpacesFilter"; }
View
4 src/leveldb/doc/log_format.txt
@@ -4,8 +4,8 @@ exception is that the tail of the file may contain a partial block.
Each block consists of a sequence of records:
block := record* trailer?
record :=
- checksum: uint32 // crc32c of type and data[]
- length: uint16
+ checksum: uint32 // crc32c of type and data[] ; little-endian
+ length: uint16 // little-endian
type: uint8 // One of FULL, FIRST, MIDDLE, LAST
data: uint8[length]
View
12 src/leveldb/doc/table_format.txt
@@ -18,6 +18,8 @@ The file contains internal pointers. Each such pointer is called
a BlockHandle and contains the following information:
offset: varint64
size: varint64
+See https://developers.google.com/protocol-buffers/docs/encoding#varints
+for an explanation of varint64 format.
(1) The sequence of key/value pairs in the file are stored in sorted
order and partitioned into a sequence of data blocks. These blocks
@@ -41,11 +43,11 @@ BlockHandle for the data block.
(6) At the very end of the file is a fixed length footer that contains
the BlockHandle of the metaindex and index blocks as well as a magic number.
- metaindex_handle: char[p]; // Block handle for metaindex
- index_handle: char[q]; // Block handle for index
- padding: char[40-p-q]; // 0 bytes to make fixed length
- // (40==2*BlockHandle::kMaxEncodedLength)
- magic: fixed64; // == 0xdb4775248b80fb57
+ metaindex_handle: char[p]; // Block handle for metaindex
+ index_handle: char[q]; // Block handle for index
+ padding: char[40-p-q]; // zeroed bytes to make fixed length
+ // (40==2*BlockHandle::kMaxEncodedLength)
+ magic: fixed64; // == 0xdb4775248b80fb57 (little-endian)
"filter" Meta Block
-------------------
View
10 src/leveldb/helpers/memenv/memenv.cc
@@ -221,6 +221,11 @@ class WritableFileImpl : public WritableFile {
FileState* file_;
};
+class NoOpLogger : public Logger {
+ public:
+ virtual void Logv(const char* format, va_list ap) { }
+};
+
class InMemoryEnv : public EnvWrapper {
public:
explicit InMemoryEnv(Env* base_env) : EnvWrapper(base_env) { }
@@ -358,6 +363,11 @@ class InMemoryEnv : public EnvWrapper {
return Status::OK();
}
+ virtual Status NewLogger(const std::string& fname, Logger** result) {
+ *result = new NoOpLogger;
+ return Status::OK();
+ }
+
private:
// Map from filenames to FileState objects, representing a simple file system.
typedef std::map<std::string, FileState*> FileSystem;
View
16 src/leveldb/include/leveldb/c.h
@@ -28,6 +28,7 @@
be true on entry:
*errptr == NULL
*errptr points to a malloc()ed null-terminated error message
+ (On Windows, *errptr must have been malloc()-ed by this library.)
On success, a leveldb routine leaves *errptr unchanged.
On failure, leveldb frees the old value of *errptr and
set *errptr to a malloc()ed error message.
@@ -268,6 +269,21 @@ extern void leveldb_cache_destroy(leveldb_cache_t* cache);
extern leveldb_env_t* leveldb_create_default_env();
extern void leveldb_env_destroy(leveldb_env_t*);
+/* Utility */
+
+/* Calls free(ptr).
+ REQUIRES: ptr was malloc()-ed and returned by one of the routines
+ in this file. Note that in certain cases (typically on Windows), you
+ may need to call this routine instead of free(ptr) to dispose of
+ malloc()-ed memory returned by this library. */
+extern void leveldb_free(void* ptr);
+
+/* Return the major version number for this release. */
+extern int leveldb_major_version();
+
+/* Return the minor version number for this release. */
+extern int leveldb_minor_version();
+
#ifdef __cplusplus
} /* end extern "C" */
#endif
View
2  src/leveldb/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 = 5;
+static const int kMinorVersion = 7;
struct Options;
struct ReadOptions;
View
10 src/leveldb/include/leveldb/env.h
@@ -175,6 +175,11 @@ class SequentialFile {
//
// REQUIRES: External synchronization
virtual Status Skip(uint64_t n) = 0;
+
+ private:
+ // No copying allowed
+ SequentialFile(const SequentialFile&);
+ void operator=(const SequentialFile&);
};
// A file abstraction for randomly reading the contents of a file.
@@ -194,6 +199,11 @@ class RandomAccessFile {
// Safe for concurrent use by multiple threads.
virtual Status Read(uint64_t offset, size_t n, Slice* result,
char* scratch) const = 0;
+
+ private:
+ // No copying allowed
+ RandomAccessFile(const RandomAccessFile&);
+ void operator=(const RandomAccessFile&);
};
// A file abstraction for sequential writing. The implementation
View
72 src/leveldb/port/atomic_pointer.h
@@ -36,6 +36,8 @@
#define ARCH_CPU_X86_FAMILY 1
#elif defined(__ARMEL__)
#define ARCH_CPU_ARM_FAMILY 1
+#elif defined(__ppc__) || defined(__powerpc__) || defined(__powerpc64__)
+#define ARCH_CPU_PPC_FAMILY 1
#endif
namespace leveldb {
@@ -91,6 +93,15 @@ inline void MemoryBarrier() {
}
#define LEVELDB_HAVE_MEMORY_BARRIER
+// PPC
+#elif defined(ARCH_CPU_PPC_FAMILY) && defined(__GNUC__)
+inline void MemoryBarrier() {
+ // TODO for some powerpc expert: is there a cheaper suitable variant?
+ // Perhaps by having separate barriers for acquire and release ops.
+ asm volatile("sync" : : : "memory");
+}
+#define LEVELDB_HAVE_MEMORY_BARRIER
+
#endif
// AtomicPointer built using platform-specific MemoryBarrier()
@@ -136,6 +147,66 @@ class AtomicPointer {
}
};
+// Atomic pointer based on sparc memory barriers
+#elif defined(__sparcv9) && defined(__GNUC__)
+class AtomicPointer {
+ private:
+ void* rep_;
+ public:
+ AtomicPointer() { }
+ explicit AtomicPointer(void* v) : rep_(v) { }
+ inline void* Acquire_Load() const {
+ void* val;
+ __asm__ __volatile__ (
+ "ldx [%[rep_]], %[val] \n\t"
+ "membar #LoadLoad|#LoadStore \n\t"
+ : [val] "=r" (val)
+ : [rep_] "r" (&rep_)
+ : "memory");
+ return val;
+ }
+ inline void Release_Store(void* v) {
+ __asm__ __volatile__ (
+ "membar #LoadStore|#StoreStore \n\t"
+ "stx %[v], [%[rep_]] \n\t"
+ :
+ : [rep_] "r" (&rep_), [v] "r" (v)
+ : "memory");
+ }
+ inline void* NoBarrier_Load() const { return rep_; }
+ inline void NoBarrier_Store(void* v) { rep_ = v; }
+};
+
+// Atomic pointer based on ia64 acq/rel
+#elif defined(__ia64) && defined(__GNUC__)
+class AtomicPointer {
+ private:
+ void* rep_;
+ public:
+ AtomicPointer() { }
+ explicit AtomicPointer(void* v) : rep_(v) { }
+ inline void* Acquire_Load() const {
+ void* val ;
+ __asm__ __volatile__ (
+ "ld8.acq %[val] = [%[rep_]] \n\t"
+ : [val] "=r" (val)
+ : [rep_] "r" (&rep_)
+ : "memory"
+ );
+ return val;
+ }
+ inline void Release_Store(void* v) {
+ __asm__ __volatile__ (
+ "st8.rel [%[rep_]] = %[v] \n\t"
+ :
+ : [rep_] "r" (&rep_), [v] "r" (v)
+ : "memory"
+ );
+ }
+ inline void* NoBarrier_Load() const { return rep_; }
+ inline void NoBarrier_Store(void* v) { rep_ = v; }
+};
+
// We have neither MemoryBarrier(), nor <cstdatomic>
#else
#error Please implement AtomicPointer for this platform.
@@ -145,6 +216,7 @@ class AtomicPointer {
#undef LEVELDB_HAVE_MEMORY_BARRIER
#undef ARCH_CPU_X86_FAMILY
#undef ARCH_CPU_ARM_FAMILY
+#undef ARCH_CPU_PPC_FAMILY
} // namespace port
} // namespace leveldb
View
2  src/leveldb/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_WINDOWS)
-# include "port/port_win.h"
#endif
#endif // STORAGE_LEVELDB_PORT_PORT_H_
View
182 src/leveldb/port/port_win.cc
@@ -1,182 +0,0 @@
-// LevelDB 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.
-
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above copyright
-// notice, this list of conditions and the following disclaimer in the
-// documentation and/or other materials provided with the distribution.
-// * Neither the name of the University of California, Berkeley nor the
-// names of its contributors may be used to endorse or promote products
-// derived from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
-// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
-// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-
-#include "port/port_win.h"
-
-#include <windows.h>
-#include <cassert>
-
-namespace leveldb {
-namespace port {
-
-Mutex::Mutex() :
- mutex_(::CreateMutex(NULL, FALSE, NULL)) {
- assert(mutex_);
-}
-
-Mutex::~Mutex() {
- assert(mutex_);
- ::CloseHandle(mutex_);
-}
-
-void Mutex::Lock() {
- assert(mutex_);
- ::WaitForSingleObject(mutex_, INFINITE);
-}
-
-void Mutex::Unlock() {
- assert(mutex_);
- ::ReleaseMutex(mutex_);
-}
-
-void Mutex::AssertHeld() {
- assert(mutex_);
- assert(1);
-}
-
-CondVar::CondVar(Mutex* mu) :
- waiting_(0),
- mu_(mu),
- sema_(::CreateSemaphore(NULL, 0, 0x7fffffff, NULL)),
- event_(::CreateEvent(NULL, FALSE, FALSE, NULL)),
- broadcasted_(false){
- assert(mu_);
-}
-
-CondVar::~CondVar() {
- ::CloseHandle(sema_);
- ::CloseHandle(event_);
-}
-
-void CondVar::Wait() {
- wait_mtx_.Lock();
- ++waiting_;
- assert(waiting_ > 0);
- wait_mtx_.Unlock();
-
- ::SignalObjectAndWait(mu_->mutex_, sema_, INFINITE, FALSE);
-
- wait_mtx_.Lock();
- bool last = broadcasted_ && (--waiting_ == 0);
- assert(waiting_ >= 0);
- wait_mtx_.Unlock();
-
- // we leave this function with the mutex held
- if (last)
- {
- ::SignalObjectAndWait(event_, mu_->mutex_, INFINITE, FALSE);
- }
- else
- {
- ::WaitForSingleObject(mu_->mutex_, INFINITE);
- }
-}
-
-void CondVar::Signal() {
- wait_mtx_.Lock();
- bool waiters = waiting_ > 0;
- wait_mtx_.Unlock();
-
- if (waiters)
- {
- ::ReleaseSemaphore(sema_, 1, 0);
- }
-}
-
-void CondVar::SignalAll() {
- wait_mtx_.Lock();
-
- broadcasted_ = (waiting_ > 0);
-
- if (broadcasted_)
- {
- // release all
- ::ReleaseSemaphore(sema_, waiting_, 0);
- wait_mtx_.Unlock();
- ::WaitForSingleObject(event_, INFINITE);
- broadcasted_ = false;
- }
- else
- {
- wait_mtx_.Unlock();
- }
-}
-
-AtomicPointer::AtomicPointer(void* v) {
- Release_Store(v);
-}
-
-void* AtomicPointer::Acquire_Load() const {
- void * p = NULL;
- InterlockedExchangePointer(&p, rep_);
- return p;
-}
-
-void AtomicPointer::Release_Store(void* v) {
- InterlockedExchangePointer(&rep_, v);
-}
-
-void* AtomicPointer::NoBarrier_Load() const {
- return rep_;
-}
-
-void AtomicPointer::NoBarrier_Store(void* v) {
- rep_ = v;
-}
-
-enum InitializationState
-{
- Uninitialized = 0,
- Running = 1,
- Initialized = 2
-};
-
-void InitOnce(OnceType* once, void (*initializer)()) {
-
- assert(Uninitialized == LEVELDB_ONCE_INIT);
-
- InitializationState state = static_cast<InitializationState>(InterlockedCompareExchange(once, Running, Uninitialized));
-
- if (state == Uninitialized) {
- initializer();
- *once = Initialized;
- }
-
- if (state == Running) {
- while(*once != Initialized) {
- Sleep(0); // yield
- }
- }
-
- assert(*once == Initialized);
-}
-
-}
-}
View
161 src/leveldb/port/port_win.h
@@ -1,161 +0,0 @@
-// LevelDB 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.
-
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above copyright
-// notice, this list of conditions and the following disclaimer in the
-// documentation and/or other materials provided with the distribution.
-// * Neither the name of the University of California, Berkeley nor the
-// names of its contributors may be used to endorse or promote products
-// derived from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
-// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
-// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-
-#ifndef STORAGE_LEVELDB_PORT_PORT_WIN_H_
-#define STORAGE_LEVELDB_PORT_PORT_WIN_H_
-
-#ifdef _MSC_VER
-#define snprintf _snprintf
-#define close _close
-#define fread_unlocked _fread_nolock
-#endif
-
-
-#ifdef SNAPPY
-#include <snappy/snappy.h>
-#endif
-
-#include <string>
-
-#include <stdint.h>
-
-namespace leveldb {
-namespace port {
-
-// Windows is little endian (for now :p)
-static const bool kLittleEndian = true;
-
-class CondVar;
-
-class Mutex {
- public:
- Mutex();
- ~Mutex();
-
- void Lock();
- void Unlock();
- void AssertHeld();
-
- private:
- friend class CondVar;
- // critical sections are more efficient than mutexes
- // but they are not recursive and can only be used to synchronize threads within the same process
- // additionnaly they cannot be used with SignalObjectAndWait that we use for CondVar
- // we use opaque void * to avoid including windows.h in port_win.h
- void * mutex_;
-
- // No copying
- Mutex(const Mutex&);
- void operator=(const Mutex&);
-};
-
-// the Win32 API offers a dependable condition variable mechanism, but only starting with
-// Windows 2008 and Vista
-// no matter what we will implement our own condition variable with a semaphore
-// implementation as described in a paper written by Douglas C. Schmidt and Irfan Pyarali
-class CondVar {
- public:
- explicit CondVar(Mutex* mu);
- ~CondVar();
- void Wait();
- void Signal();
- void SignalAll();
- private:
- Mutex* mu_;
-
- Mutex wait_mtx_;
- long waiting_;
-
- void * sema_;
- void * event_;
-
- bool broadcasted_;
-};
-
-// Storage for a lock-free pointer
-class AtomicPointer {
- private:
- void * rep_;
- public:
- AtomicPointer() : rep_(NULL) { }
- explicit AtomicPointer(void* v);
- void* Acquire_Load() const;
-
- void Release_Store(void* v);
-
- void* NoBarrier_Load() const;
-
- void NoBarrier_Store(void* v);
-};
-
-typedef volatile long OnceType;
-#define LEVELDB_ONCE_INIT (0)
-
-extern void InitOnce(OnceType* once, void (*initializer)());
-
-inline bool Snappy_Compress(const char* input, size_t length,
- ::std::string* output) {
-#ifdef SNAPPY
- output->resize(snappy::MaxCompressedLength(length));
- size_t outlen;
- snappy::RawCompress(input, length, &(*output)[0], &outlen);
- output->resize(outlen);
- return true;
-#endif
-
- return false;
-}
-
-inline bool Snappy_GetUncompressedLength(const char* input, size_t length,
- size_t* result) {
-#ifdef SNAPPY
- return snappy::GetUncompressedLength(input, length, result);
-#else
- return false;
-#endif
-}
-
-inline bool Snappy_Uncompress(const char* input, size_t length,
- char* output) {
-#ifdef SNAPPY
- return snappy::RawUncompress(input, length, output);
-#else
- return false;
-#endif
-}
-
-inline bool GetHeapProfile(void (*func)(void*, const char*, int), void* arg) {
- return false;
-}
-
-}
-}
-
-#endif // STORAGE_LEVELDB_PORT_PORT_WIN_H_
View
59 src/leveldb/port/thread_annotations.h
@@ -0,0 +1,59 @@
+// Copyright (c) 2012 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.
+
+#ifndef STORAGE_LEVELDB_PORT_THREAD_ANNOTATIONS_H
+
+// Some environments provide custom macros to aid in static thread-safety
+// analysis. Provide empty definitions of such macros unless they are already
+// defined.
+
+#ifndef EXCLUSIVE_LOCKS_REQUIRED
+#define EXCLUSIVE_LOCKS_REQUIRED(...)
+#endif
+
+#ifndef SHARED_LOCKS_REQUIRED
+#define SHARED_LOCKS_REQUIRED(...)
+#endif
+
+#ifndef LOCKS_EXCLUDED
+#define LOCKS_EXCLUDED(...)
+#endif
+
+#ifndef LOCK_RETURNED
+#define LOCK_RETURNED(x)
+#endif
+
+#ifndef LOCKABLE
+#define LOCKABLE
+#endif
+
+#ifndef SCOPED_LOCKABLE
+#define SCOPED_LOCKABLE
+#endif
+
+#ifndef EXCLUSIVE_LOCK_FUNCTION
+#define EXCLUSIVE_LOCK_FUNCTION(...)
+#endif
+
+#ifndef SHARED_LOCK_FUNCTION
+#define SHARED_LOCK_FUNCTION(...)
+#endif
+
+#ifndef EXCLUSIVE_TRYLOCK_FUNCTION
+#define EXCLUSIVE_TRYLOCK_FUNCTION(...)
+#endif
+
+#ifndef SHARED_TRYLOCK_FUNCTION
+#define SHARED_TRYLOCK_FUNCTION(...)
+#endif
+
+#ifndef UNLOCK_FUNCTION
+#define UNLOCK_FUNCTION(...)
+#endif
+
+#ifndef NO_THREAD_SAFETY_ANALYSIS
+#define NO_THREAD_SAFETY_ANALYSIS
+#endif
+
+#endif // STORAGE_LEVELDB_PORT_THREAD_ANNOTATIONS_H
View
4 src/leveldb/table/block.cc
@@ -162,8 +162,8 @@ class Block::Iter : public Iterator {
}
virtual void Seek(const Slice& target) {
- // Binary search in restart array to find the first restart point
- // with a key >= target
+ // Binary search in restart array to find the last restart point
+ // with a key < target
uint32_t left = 0;
uint32_t right = num_restarts_ - 1;
while (left < right) {
View
5 src/leveldb/util/bloom_test.cc
@@ -4,6 +4,7 @@
#include "leveldb/filter_policy.h"
+#include "util/coding.h"
#include "util/logging.h"
#include "util/testharness.h"
#include "util/testutil.h"
@@ -13,8 +14,8 @@ namespace leveldb {
static const int kVerbose = 1;
static Slice Key(int i, char* buffer) {
- memcpy(buffer, &i, sizeof(i));
- return Slice(buffer, sizeof(i));
+ EncodeFixed32(buffer, i);
+ return Slice(buffer, sizeof(uint32_t));
}
class BloomTest {
View
40 src/leveldb/util/coding.cc
@@ -7,29 +7,29 @@
namespace leveldb {
void EncodeFixed32(char* buf, uint32_t value) {
-#if __BYTE_ORDER == __LITTLE_ENDIAN
- memcpy(buf, &value, sizeof(value));
-#else
- buf[0] = value & 0xff;
- buf[1] = (value >> 8) & 0xff;
- buf[2] = (value >> 16) & 0xff;
- buf[3] = (value >> 24) & 0xff;
-#endif
+ if (port::kLittleEndian) {
+ memcpy(buf, &value, sizeof(value));
+ } else {
+ buf[0] = value & 0xff;
+ buf[1] = (value >> 8) & 0xff;
+ buf[2] = (value >> 16) & 0xff;
+ buf[3] = (value >> 24) & 0xff;
+ }
}
void EncodeFixed64(char* buf, uint64_t value) {
-#if __BYTE_ORDER == __LITTLE_ENDIAN
- memcpy(buf, &value, sizeof(value));
-#else
- buf[0] = value & 0xff;
- buf[1] = (value >> 8) & 0xff;
- buf[2] = (value >> 16) & 0xff;
- buf[3] = (value >> 24) & 0xff;
- buf[4] = (value >> 32) & 0xff;
- buf[5] = (value >> 40) & 0xff;
- buf[6] = (value >> 48) & 0xff;
- buf[7] = (value >> 56) & 0xff;
-#endif
+ if (port::kLittleEndian) {
+ memcpy(buf, &value, sizeof(value));
+ } else {
+ buf[0] = value & 0xff;
+ buf[1] = (value >> 8) & 0xff;
+ buf[2] = (value >> 16) & 0xff;
+ buf[3] = (value >> 24) & 0xff;
+ buf[4] = (value >> 32) & 0xff;
+ buf[5] = (value >> 40) & 0xff;
+ buf[6] = (value >> 48) & 0xff;
+ buf[7] = (value >> 56) & 0xff;
+ }
}
void PutFixed32(std::string* dst, uint32_t value) {
View
591 src/leveldb/util/env_boost.cc
@@ -1,591 +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 <deque>
-
-#ifdef LEVELDB_PLATFORM_WINDOWS
-#include <windows.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <time.h>
-#include <io.h>
-#else
-#include <dirent.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <pthread.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/param.h>
-#include <time.h>
-#include <unistd.h>
-#endif
-#if defined(LEVELDB_PLATFORM_ANDROID)
-#include <sys/stat.h>
-#endif
-#include "leveldb/env.h"
-#include "leveldb/slice.h"
-
-#ifdef LEVELDB_PLATFORM_WINDOWS
-#include "util/win_logger.h"
-#else
-#include "util/posix_logger.h"
-#endif
-#include "port/port.h"
-#include "util/logging.h"
-
-#ifdef __linux
-#include <sys/sysinfo.h>
-#include <linux/unistd.h>
-#endif
-
-#include <fstream>
-
-// Boost includes - see WINDOWS file to see which modules to install
-#include <boost/date_time/gregorian/gregorian.hpp>
-#include <boost/date_time/posix_time/posix_time.hpp>
-#include <boost/filesystem/convenience.hpp>
-#include <boost/thread/once.hpp>
-#include <boost/thread/thread.hpp>
-#include <boost/bind.hpp>
-#include <boost/scoped_ptr.hpp>
-#include <boost/interprocess/sync/file_lock.hpp>
-#include <boost/thread/condition_variable.hpp>
-
-namespace leveldb {
-namespace {
-
-// returns the ID of the current process
-static boost::uint32_t current_process_id(void) {
-#ifdef _WIN32
- return static_cast<boost::uint32_t>(::GetCurrentProcessId());
-#else
- return static_cast<boost::uint32_t>(::getpid());
-#endif
-}
-
-// returns the ID of the current thread
-static boost::uint32_t current_thread_id(void) {
-#ifdef _WIN32
- return static_cast<boost::uint32_t>(::GetCurrentThreadId());
-#else
-#ifdef __linux
- return static_cast<boost::uint32_t>(::syscall(__NR_gettid));
-#else
- // just return the pid
- return current_process_id();
-#endif
-#endif
-}
-
-static char global_read_only_buf[0x8000];
-
-class PosixSequentialFile: public SequentialFile {
- private:
- std::string filename_;
- FILE* file_;
-
- public:
- PosixSequentialFile(const std::string& fname, FILE* f)
- : filename_(fname), file_(f) { }
- virtual ~PosixSequentialFile() { fclose(file_); }
-
- virtual Status Read(size_t n, Slice* result, char* scratch) {
- Status s;
-#if defined(BSD) || defined(__MINGW32__)
- // fread_unlocked doesn't exist on FreeBSD or MingW
- size_t r = fread(scratch, 1, n, file_);
-#else
- size_t r = fread_unlocked(scratch, 1, n, file_);
-#endif
- *result = Slice(scratch, r);
- if (r < n) {
- if (feof(file_)) {
- // We leave status as ok if we hit the end of the file
- } else {
- // A partial read with an error: return a non-ok status
- s = Status::IOError(filename_, strerror(errno));
- }
- }
- return s;
- }
-
- virtual Status Skip(uint64_t n) {
- if (fseek(file_, n, SEEK_CUR)) {
- return Status::IOError(filename_, strerror(errno));
- }
- return Status::OK();
- }
-};
-
-class PosixRandomAccessFile: public RandomAccessFile {
- private:
- std::string filename_;
- int fd_;
- mutable boost::mutex mu_;
-
- public:
- PosixRandomAccessFile(const std::string& fname, int fd)
- : filename_(fname), fd_(fd) { }
- virtual ~PosixRandomAccessFile() { close(fd_); }
-
- virtual Status Read(uint64_t offset, size_t n, Slice* result,
- char* scratch) const {
- Status s;
-#ifdef LEVELDB_PLATFORM_WINDOWS
- // no pread on Windows so we emulate it with a mutex
- boost::unique_lock<boost::mutex> lock(mu_);
-
- if (::_lseeki64(fd_, offset, SEEK_SET) == -1L) {
- return Status::IOError(filename_, strerror(errno));
- }
-
- int r = ::_read(fd_, scratch, n);
- *result = Slice(scratch, (r < 0) ? 0 : r);
- lock.unlock();
-#else
- ssize_t r = pread(fd_, scratch, n, static_cast<off_t>(offset));
- *result = Slice(scratch, (r < 0) ? 0 : r);
-#endif
- if (r < 0) {
- // An error: return a non-ok status
- s = Status::IOError(filename_, strerror(errno));
- }
- return s;
- }
-};
-
-// We preallocate up to an extra megabyte and use memcpy to append new
-// data to the file. This is safe since we either properly close the
-// file before reading from it, or for log files, the reading code
-// knows enough to skip zero suffixes.
-
-class BoostFile : public WritableFile {
-
-public:
- explicit BoostFile(std::string path) : path_(path), written_(0) {
- Open();
- }
-
- virtual ~BoostFile() {
- Close();
- }
-
-private:
- void Open() {
- // we truncate the file as implemented in env_posix
- file_.open(path_.generic_string().c_str(),
- std::ios_base::trunc | std::ios_base::out | std::ios_base::binary);
- written_ = 0;
- }
-
-public:
- virtual Status Append(const Slice& data) {
- Status result;
- file_.write(data.data(), data.size());
- if (!file_.good()) {
- result = Status::IOError(
- path_.generic_string() + " Append", "cannot write");
- }
- return result;
- }
-
- virtual Status Close() {
- Status result;
-
- try {
- if (file_.is_open()) {
- Sync();
- file_.close();
- }
- } catch (const std::exception & e) {
- result = Status::IOError(path_.generic_string() + " close", e.what());
- }
-
- return result;
- }
-
- virtual Status Flush() {
- file_.flush();
- return Status::OK();
- }
-
- virtual Status Sync() {
- Status result;
- try {
- Flush();
- } catch (const std::exception & e) {
- result = Status::IOError(path_.string() + " sync", e.what());
- }
-
- return result;
- }
-
-private:
- boost::filesystem::path path_;
- boost::uint64_t written_;
- std::ofstream file_;
-};
-
-
-
-class BoostFileLock : public FileLock {
- public:
- boost::interprocess::file_lock fl_;
-};
-
-class PosixEnv : public Env {
- public:
- PosixEnv();
- virtual ~PosixEnv() {
- fprintf(stderr, "Destroying Env::Default()\n");
- exit(1);
- }
-
- virtual Status NewSequentialFile(const std::string& fname,
- SequentialFile** result) {
- FILE* f = fopen(fname.c_str(), "rb");
- if (f == NULL) {
- *result = NULL;
- return Status::IOError(fname, strerror(errno));
- } else {
- *result = new PosixSequentialFile(fname, f);
- return Status::OK();
- }
- }
-
- virtual Status NewRandomAccessFile(const std::string& fname,
- RandomAccessFile** result) {
-#ifdef LEVELDB_PLATFORM_WINDOWS
- int fd = _open(fname.c_str(), _O_RDONLY | _O_RANDOM | _O_BINARY);
-#else
- int fd = open(fname.c_str(), O_RDONLY);
-#endif
- if (fd < 0) {
- *result = NULL;
- return Status::IOError(fname, strerror(errno));
- }
- *result = new PosixRandomAccessFile(fname, fd);
- return Status::OK();
- }
-
- virtual Status NewWritableFile(const std::string& fname,
- WritableFile** result) {
- Status s;
- try {
- // will create a new empty file to write to
- *result = new BoostFile(fname);
- }
- catch (const std::exception & e) {
- s = Status::IOError(fname, e.what());
- }
-
- return s;
- }
-
- virtual bool FileExists(const std::string& fname) {
- return boost::filesystem::exists(fname);
- }
-
- virtual Status GetChildren(const std::string& dir,
- std::vector<std::string>* result) {
- result->clear();
-
- boost::system::error_code ec;
- boost::filesystem::directory_iterator current(dir, ec);
- if (ec != 0) {
- return Status::IOError(dir, ec.message());
- }
-
- boost::filesystem::directory_iterator end;
-
- for(; current != end; ++current) {
- result->push_back(current->path().filename().generic_string());
- }
-
- return Status::OK();
- }
-
- virtual Status DeleteFile(const std::string& fname) {
- boost::system::error_code ec;
-
- boost::filesystem::remove(fname, ec);
-
- Status result;
-
- if (ec != 0) {
- result = Status::IOError(fname, ec.message());
- }
-
- return result;
- }
-
- virtual Status CreateDir(const std::string& name) {
- Status result;
-
- if (boost::filesystem::exists(name) &&
- boost::filesystem::is_directory(name)) {
- return result;
- }
-
- boost::system::error_code ec;
-
- if (!boost::filesystem::create_directories(name, ec)) {
- result = Status::IOError(name, ec.message());
- }
-
- return result;
- };
-
- virtual Status DeleteDir(const std::string& name) {
- Status result;
-
- boost::system::error_code ec;
- if (!boost::filesystem::remove_all(name, ec)) {
- result = Status::IOError(name, ec.message());
- }
-
- return result;
- };
-
- virtual Status GetFileSize(const std::string& fname, uint64_t* size) {
- boost::system::error_code ec;
-
- Status result;
-
- *size = static_cast<uint64_t>(boost::filesystem::file_size(fname, ec));
- if (ec != 0) {
- *size = 0;
- result = Status::IOError(fname, ec.message());
- }
-
- return result;
- }
-
- virtual Status RenameFile(const std::string& src, const std::string& target) {
- boost::system::error_code ec;
-
- boost::filesystem::rename(src, target, ec);
-
- Status result;
-
- if (ec != 0) {
- result = Status::IOError(src, ec.message());
- }
-
- return result;
- }
-
- virtual Status LockFile(const std::string& fname, FileLock** lock) {
- *lock = NULL;
-
- Status result;
-
- try {
- if (!boost::filesystem::exists(fname)) {
- std::ofstream of(fname.c_str(), std::ios_base::trunc | std::ios_base::out);
- }
-
- assert(boost::filesystem::exists(fname));
-
- boost::interprocess::file_lock fl(fname.c_str());
- BoostFileLock * my_lock = new BoostFileLock();
- fl.swap(my_lock->fl_);
- if (!my_lock->fl_.try_lock()) {
- return Status::IOError("database already in use: could not acquire exclusive lock");
- }
- *lock = my_lock;
- } catch (const std::exception & e) {
- result = Status::IOError("lock " + fname, e.what());
- }
-
- return result;
- }
-
- virtual Status UnlockFile(FileLock* lock) {
-
- Status result;
-
- try {
- BoostFileLock * my_lock = static_cast<BoostFileLock *>(lock);
- my_lock->fl_.unlock();
- delete my_lock;
- } catch (const std::exception & e) {
- result = Status::IOError("unlock", e.what());
- }
-
- return result;
- }
-
- virtual void Schedule(void (*function)(void*), void* arg);
-
- virtual void StartThread(void (*function)(void* arg), void* arg);
-
- virtual Status GetTestDirectory(std::string* result) {
- boost::system::error_code ec;
- boost::filesystem::path temp_dir =
- boost::filesystem::temp_directory_path(ec);
- if (ec != 0) {
- temp_dir = "tmp";
- }
-
- temp_dir /= "leveldb_tests";
- temp_dir /= boost::lexical_cast<std::string>(current_process_id());
-
- // Directory may already exist
- CreateDir(temp_dir.generic_string());
-
- *result = temp_dir.generic_string();
-
- return Status::OK();
- }
-
-#ifndef LEVELDB_PLATFORM_WINDOWS
- static uint64_t gettid() {
- pthread_t tid = pthread_self();
- uint64_t thread_id = 0;
- memcpy(&thread_id, &tid, std::min(sizeof(thread_id), sizeof(tid)));
- return thread_id;
- }
-#endif
-
- virtual Status NewLogger(const std::string& fname, Logger** result) {
- FILE* f = fopen(fname.c_str(), "wt");
- if (f == NULL) {
- *result = NULL;
- return Status::IOError(fname, strerror(errno));
- } else {
-#ifdef LEVELDB_PLATFORM_WINDOWS
- *result = new WinLogger(f);
-#else
- *result = new PosixLogger(f, &PosixEnv::gettid);
-#endif
- return Status::OK();
- }
- }
-
- virtual uint64_t NowMicros() {
- return static_cast<uint64_t>(
- boost::posix_time::microsec_clock::universal_time()
- .time_of_day().total_microseconds());
- }
-
- virtual void SleepForMicroseconds(int micros) {
- boost::this_thread::sleep(boost::posix_time::microseconds(micros));
- }
-
- private:
- void PthreadCall(const char* label, int result) {
- if (result != 0) {
- fprintf(stderr, "pthread %s: %s\n", label, strerror(result));
- exit(1);
- }
- }
-
- // BGThread() is the body of the background thread
- void BGThread();
-
- static void* BGThreadWrapper(void* arg) {
- reinterpret_cast<PosixEnv*>(arg)->BGThread();
- return NULL;
- }
-
- boost::mutex mu_;
- boost::condition_variable bgsignal_;
- boost::scoped_ptr<boost::thread> bgthread_;
-
- // Entry per Schedule() call
- struct BGItem { void* arg; void (*function)(void*); };
- typedef std::deque<BGItem> BGQueue;
- BGQueue queue_;
-};
-
-PosixEnv::PosixEnv() { }
-
-void PosixEnv::Schedule(void (*function)(void*), void* arg) {
- boost::unique_lock<boost::mutex> lock(mu_);
-
- // Start background thread if necessary
- if (!bgthread_) {
- bgthread_.reset(
- new boost::thread(boost::bind(&PosixEnv::BGThreadWrapper, this)));
- }
-
- // Add to priority queue
- queue_.push_back(BGItem());
- queue_.back().function = function;
- queue_.back().arg = arg;
-
- lock.unlock();
-
- bgsignal_.notify_one();
-
-}
-
-void PosixEnv::BGThread() {
- while (true) {
- // Wait until there is an item that is ready to run
- boost::unique_lock<boost::mutex> lock(mu_);
-
- while (queue_.empty()) {
- bgsignal_.wait(lock);
- }
-
- void (*function)(void*) = queue_.front().function;
- void* arg = queue_.front().arg;
- queue_.pop_front();
-
- lock.unlock();
- (*function)(arg);
- }
-}
-
-namespace {
-struct StartThreadState {
- void (*user_function)(void*);
- void* arg;
-};
-}
-
-static void* StartThreadWrapper(void* arg) {
- StartThreadState* state = reinterpret_cast<StartThreadState*>(arg);
- state->user_function(state->arg);
- delete state;
- return NULL;
-}
-
-void PosixEnv::StartThread(void (*function)(void* arg), void* arg) {
- StartThreadState* state = new StartThreadState;
- state->user_function = function;
- state->arg = arg;
-
- boost::thread t(boost::bind(&StartThreadWrapper, state));
-}
-
-}
-
-static boost::once_flag once = BOOST_ONCE_INIT;
-static Env* default_env;
-static void InitDefaultEnv() {
- ::memset(global_read_only_buf, 0, sizeof(global_read_only_buf));
- default_env = new PosixEnv;
-}
-
-Env* Env::Default() {
- boost::call_once(once, InitDefaultEnv);
-
- return default_env;
-}
-
-}
View
101 src/leveldb/util/env_posix.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file. See the AUTHORS file for names of contributors.
#include <deque>
+#include <set>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
@@ -23,6 +24,7 @@
#include "leveldb/slice.h"
#include "port/port.h"
#include "util/logging.h"
+#include "util/mutexlock.h"
#include "util/posix_logger.h"
namespace leveldb {
@@ -90,18 +92,75 @@ class PosixRandomAccessFile: public RandomAccessFile {
}
};
+// Helper class to limit mmap file usage so that we do not end up
+// running out virtual memory or running into kernel performance
+// problems for very large databases.
+class MmapLimiter {
+ public:
+ // Up to 1000 mmaps for 64-bit binaries; none for smaller pointer sizes.
+ MmapLimiter() {
+ SetAllowed(sizeof(void*) >= 8 ? 1000 : 0);
+ }
+
+ // If another mmap slot is available, acquire it and return true.
+ // Else return false.
+ bool Acquire() {
+ if (GetAllowed() <= 0) {
+ return false;
+ }
+ MutexLock l(&mu_);
+ intptr_t x = GetAllowed();
+ if (x <= 0) {
+ return false;
+ } else {
+ SetAllowed(x - 1);
+ return true;
+ }
+ }
+
+ // Release a slot acquired by a previous call to Acquire() that returned true.
+ void Release() {
+ MutexLock l(&mu_);
+ SetAllowed(GetAllowed() + 1);
+ }
+
+ private:
+ port::Mutex mu_;
+ port::AtomicPointer allowed_;
+
+ intptr_t GetAllowed() const {
+ return reinterpret_cast<intptr_t>(allowed_.Acquire_Load());
+ }
+
+ // REQUIRES: mu_ must be held
+ void SetAllowed(intptr_t v) {
+ allowed_.Release_Store(reinterpret_cast<void*>(v));
+ }
+
+ MmapLimiter(const MmapLimiter&);
+ void operator=(const MmapLimiter&);
+};
+
// mmap() based random-access
class PosixMmapReadableFile: public RandomAccessFile {
private:
std::string filename_;
void* mmapped_region_;
size_t length_;
+ MmapLimiter* limiter_;
public:
// base[0,length-1] contains the mmapped contents of the file.
- PosixMmapReadableFile(const std::string& fname, void* base, size_t length)
- : filename_(fname), mmapped_region_(base), length_(length) { }
- virtual ~PosixMmapReadableFile() { munmap(mmapped_region_, length_); }
+ PosixMmapReadableFile(const std::string& fname, void* base, size_t length,
+ MmapLimiter* limiter)
+ : filename_(fname), mmapped_region_(base), length_(length),
+ limiter_(limiter) {
+ }
+
+ virtual ~PosixMmapReadableFile() {
+ munmap(mmapped_region_, length_);
+ limiter_->Release();
+ }
virtual Status Read(uint64_t offset, size_t n, Slice* result,
char* scratch) const {
@@ -300,6 +359,25 @@ static int LockOrUnlock(int fd, bool lock) {
class PosixFileLock : public FileLock {
public:
int fd_;
+ std::string name_;
+};
+
+// Set of locked files. We keep a separate set instead of just
+// relying on fcntrl(F_SETLK) since fcntl(F_SETLK) does not provide
+// any protection against multiple uses from the same process.
+class PosixLockTable {
+ private:
+ port::Mutex mu_;
+ std::set<std::string> locked_files_;
+ public:
+ bool Insert(const std::string& fname) {
+ MutexLock l(&mu_);
+ return locked_files_.insert(fname).second;
+ }
+ void Remove(const std::string& fname) {
+ MutexLock l(&mu_);
+ locked_files_.erase(fname);
+ }
};
class PosixEnv : public Env {
@@ -329,19 +407,21 @@ class PosixEnv : public Env {
int fd = open(fname.c_str(), O_RDONLY);
if (fd < 0) {
s = IOError(fname, errno);
- } else if (sizeof(void*) >= 8) {
- // Use mmap when virtual address-space is plentiful.
+ } else if (mmap_limit_.Acquire()) {
uint64_t size;
s = GetFileSize(fname, &size);
if (s.ok()) {
void* base = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
if (base != MAP_FAILED) {
- *result = new PosixMmapReadableFile(fname, base, size);
+ *result = new PosixMmapReadableFile(fname, base, size, &mmap_limit_);
} else {
s = IOError(fname, errno);
}
}
close(fd);
+ if (!s.ok()) {
+ mmap_limit_.Release();
+ }
} else {
*result = new PosixRandomAccessFile(fname, fd);
}
@@ -430,12 +510,17 @@ class PosixEnv : public Env {
int fd = open(fname.c_str(), O_RDWR | O_CREAT, 0644);
if (fd < 0) {
result = IOError(fname, errno);
+ } else if (!locks_.Insert(fname)) {
+ close(fd);
+ result = Status::IOError("lock " + fname, "already held by process");
} else if (LockOrUnlock(fd, true) == -1) {
result = IOError("lock " + fname, errno);
close(fd);
+ locks_.Remove(fname);
} else {
PosixFileLock* my_lock = new PosixFileLock;
my_lock->fd_ = fd;
+ my_lock->name_ = fname;
*lock = my_lock;
}
return result;
@@ -447,6 +532,7 @@ class PosixEnv : public Env {
if (LockOrUnlock(my_lock->fd_, false) == -1) {
result = IOError("unlock", errno);
}
+ locks_.Remove(my_lock->name_);
close(my_lock->fd_);
delete my_lock;
return result;
@@ -523,6 +609,9 @@ class PosixEnv : public Env {
struct BGItem { void* arg; void (*function)(void*); };
typedef std::deque<BGItem> BGQueue;
BGQueue queue_;
+
+ PosixLockTable locks_;
+ MmapLimiter mmap_limit_;
};
PosixEnv::PosixEnv() : page_size_(getpagesize()),
View
8 src/leveldb/util/mutexlock.h
@@ -6,6 +6,7 @@
#define STORAGE_LEVELDB_UTIL_MUTEXLOCK_H_
#include "port/port.h"
+#include "port/thread_annotations.h"
namespace leveldb {
@@ -19,12 +20,13 @@ namespace leveldb {
// ... some complex code, possibly with multiple return paths ...
// }
-class MutexLock {
+class SCOPED_LOCKABLE MutexLock {