GithubHelp home page GithubHelp logo

eleveldb's Introduction

eleveldb - Erlang bindings to LevelDB datastore

Erlang CI Actions Status

This project provides erlang bindings to a LevelDB datastore heavily optimised for Riak workloads. See the Basho leveldb wiki for a breakdown of the optimisations.

No further work on optimising the underlying store is currently being undertaken, only minimal fixes necessary for platform compatability.

As an alternative, elrang bindings to RocksDB can be found as part of the BarrellDB project. For Riak-like workloads, especially with large objects, the pure-Erlang Leveled store is also available.

Iterating Records

High-level Iterator Interface

The interface that most clients of eleveldb should use when iterating over a set of records stored in leveldb is fold, since this fits nicely with the Erlang way of doing things.

For those who need more control over the process of iterating over records, you can use direct iterator actions. Use them with great care.

Direct Iterator Actions

seek/next/prev

  • seek: Move iterator to a new position.

  • next: Move forward one position and return the value; do nothing else.

  • prev: Move backward one position and return the value; do nothing else.

prefetc/prefetch_stop

  • prefetch: Perform a next action and then start a parallel call for the subsequent next while Erlang processes the current next. The subsequent prefetch may return immediately with the value already retrieved.

  • prefetch_stop: Stop a sequence of prefetch calls. If there is a parallel prefetch pending, cancel it, since we are about to move the pointer.

Warning

Either use prefetch/prefetch_stop or next/prev. Do not intermix prefetch and next/prev. You must prefetch_stop after one or more prefetch operations before using any of the other operations (seek, next, prev).

eleveldb's People

Contributors

ahf avatar andrewjstone avatar argv0 avatar borshop avatar cmeiklejohn avatar codeadict avatar dizzyd avatar fadushin avatar hmmr avatar jaredmorrow avatar jeetkundoug avatar jj1bdx avatar jmatthew avatar joedevivo avatar jonmeredith avatar jtuple avatar kellymclaughlin avatar llelf avatar martinsumner avatar matthewvon avatar paulplace avatar reiddraper avatar rjmh avatar russelldb avatar rzezeski avatar seancribbs avatar slfritchie avatar vagabond avatar vinoski avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

eleveldb's Issues

Error in using eleveldb

([email protected])1> eleveldb:open("my",[]).

=ERROR REPORT==== 5-Aug-2014::22:38:38 ===
The on_load function for module eleveldb returned {error,
{load_failed,
"Failed to load NIF library: '/usr/ROOT_NEW/APPLICATION/deps/eleveldb/priv/eleveldb.so: Undefined symbol "__sync_sub_and_fetch_8"'"}}
** exception error: undefined function eleveldb:open/2
([email protected])2> eleveldb:open("my",[{create_if_missing, true}]).

=ERROR REPORT==== 5-Aug-2014::22:39:27 ===
The on_load function for module eleveldb returned {error,
{load_failed,
"Failed to load NIF library: '/usr/ROOT_NEW/APPLICATION/deps/eleveldb/priv/eleveldb.so: Undefined symbol "__sync_sub_and_fetch_8"'"}}
** exception error: undefined function eleveldb:open/2
([email protected])3> eleveldb:init().

=ERROR REPORT==== 5-Aug-2014::22:43:56 ===
The on_load function for module eleveldb returned {error,
{load_failed,
"Failed to load NIF library: '/usr/ROOT_NEW/APPLICATION/deps/eleveldb/priv/eleveldb.so: Undefined symbol "__sync_sub_and_fetch_8"'"}}
** exception error: undefined function eleveldb:init/0

iterator next will failed in custom module [JIRA: RIAK-1798]

I found a strange bug or not, when I run eleveldb:iterator_move/2 in Erlang console, it runs succeed, see below:

1> {ok, Ref} = eleveldb:open("0", []).
{ok,<<>>}
2> {ok, Iter} = eleveldb:iterator(Ref, []).
{ok,<<>>}
3> eleveldb:iterator_move(Iter, <<0:64/integer>>).
{ok,<<16,0,0,0,2,12,182,217,0,8,12,179,90,111,22,91,37,
      126,211,110,178,89,111,22,91,152,8>>,
    <<1>>}
4> eleveldb:iterator_move(Iter, next).
{ok,<<16,0,0,0,3,12,183,128,8,18,183,128,8,18,177,75,230,
      18,250,13,14,175,115,166,210,108,180,...>>,
    <<53,1,0,0,0,34,131,108,0,0,0,1,104,2,109,0,0,0,8,255,
      129,13,240,83,198,51,...>>}
5> eleveldb:iterator_move(Iter, next).
{ok,<<16,0,0,0,3,12,183,128,8,18,183,128,8,18,177,75,230,
      18,250,13,162,147,88,178,91,175,85,...>>,
    <<53,1,0,0,0,34,131,108,0,0,0,1,104,2,109,0,0,0,8,255,
      129,13,240,83,198,51,...>>}
6> eleveldb:iterator_move(Iter, next).
{ok,<<16,0,0,0,3,12,183,128,8,18,183,128,8,18,177,75,230,
      18,250,13,190,203,99,165,85,237,180,...>>,
    <<53,1,0,0,0,34,131,108,0,0,0,1,104,2,109,0,0,0,8,255,
      129,13,240,83,198,51,...>>}

But when I put those code to a module, it failed, see below:

module foo.erl

-module(foo).
-compile(export_all).

bar() ->
    {ok, Ref} = eleveldb:open("0", []),
    {ok, Iter} = eleveldb:iterator(Ref, []),
    io:format("~p~n", [eleveldb:iterator_move(Iter, <<0:64/integer>>)]),
    Iter.

bar(Iter) ->
    timer:sleep(10),
    eleveldb:iterator_move(Iter, next).

in console:

1> Iter = foo:bar().
{ok,<<16,0,0,0,2,12,182,217,0,8,12,179,90,111,22,91,37,126,211,110,178,89,111,
      22,91,152,8>>,
    <<1>>}
<<>>
2> foo:bar(Iter).
** exception error: bad argument
     in function  eleveldb:async_iterator_move/3
        called as eleveldb:async_iterator_move(undefined,<<>>,next)
     in call from eleveldb:iterator_move/2 (src/eleveldb.erl, line 202)
3>

I don't know why?, I use Erlang/OTP 17.0, eleveldb 2.0

Compile error on Raspbian [JIRA: RIAK-1830]

On a slightly older version of Raspbian (debian based linux), I see this compiler error during build:

Compiling /home/pi/dev/rinamo/deps/eleveldb/c_src/eleveldb.cc
/home/pi/dev/rinamo/deps/eleveldb/c_src/eleveldb.cc: In function ‘ERL_NIF_TERM parse_init_option(ErlNifEnv*, ERL_NIF_TERM, EleveldbOptions&)’:
/home/pi/dev/rinamo/deps/eleveldb/c_src/eleveldb.cc:242:58: error: invalid conversion from ‘size_t* {aka unsigned int*}’ to ‘long unsigned int*’ [-fpermissive]
/home/pi/.erln8.d/otps/R16B02/dist/lib/erlang/erts-5.10.3/include/erl_nif_api_funcs.h:43:1: error:   initializing argument 3 of ‘int enif_get_ulong(ErlNifEnv*, ERL_NIF_TERM, long unsigned int*)’ [-fpermissive]
/home/pi/dev/rinamo/deps/eleveldb/c_src/eleveldb.cc: In function ‘ERL_NIF_TERM parse_open_option(ErlNifEnv*, ERL_NIF_TERM, leveldb::Options&)’:
/home/pi/dev/rinamo/deps/eleveldb/c_src/eleveldb.cc:330:58: error: invalid conversion from ‘size_t* {aka unsigned int*}’ to ‘long unsigned int*’ [-fpermissive]
/home/pi/.erln8.d/otps/R16B02/dist/lib/erlang/erts-5.10.3/include/erl_nif_api_funcs.h:43:1: error:   initializing argument 3 of ‘int enif_get_ulong(ErlNifEnv*, ERL_NIF_TERM, long unsigned int*)’ [-fpermissive]
/home/pi/dev/rinamo/deps/eleveldb/c_src/eleveldb.cc: In function ‘ERL_NIF_TERM eleveldb::async_open(ErlNifEnv*, int, const ERL_NIF_TERM*)’:
/home/pi/dev/rinamo/deps/eleveldb/c_src/eleveldb.cc:556:25: warning: integer overflow in expression [-Woverflow]
ERROR: compile failed while processing /home/pi/dev/rinamo/deps/eleveldb: rebar_abort
make: *** [compile] Error 1

Anyone know of a possible work around?

Minimize memory usage [JIRA: RIAK-2167]

We're trying to use eleveldb as a backend to RabbitMQ's message index and are seeing some really promising early results! It allows us to have virtually infinitely long queues (by default rabbitmq keeps its message index in-memory which limits the queue length to a few million msgs on normal machines).

But we think that the default configuration might not be ideal for our use case. We want to balance the memory usage between the message storage and the index. We also only have two databases open ever. The index is rebuilt if RabbitMQ wasn't shutdown cleanly so we can skip all verifications etc. What nobs do think is worth fiddling with?

leveldb_repair refused to repair eleveldb, potentially out of sync with eleveldb:repair [JIRA: RIAK-2171]

We are using eleveldb 2.0.0. After sudden server reboot one of our eleveldb instances became broken.

leveldb_repair refused to repair it:

sudo /usr/lib/project/lib/eleveldb-2.0.0/priv/leveldb_repair /var/lib/project/data/some_base
Repair of /var/lib/project/data/some_base failed.

First attempt lasted for several minutes and simply abort with message above. Another one aborted immediately.

I tried

Eshell V6.1 (abort with ^G)
1> {ok, D} = eleveldb:open("/var/lib/project/data/some_base", []).
** exception error: no match of right hand side value {error,{db_open,"Corruption: truncated record at end of file"}}

Eventually I tried:

eleveldb:repair("/var/lib/project/data/some_base", []).

and it fixed the situation. I guess leveldb_repair and eleveldb:repair are out of sync?

On FreeBSD 10.0-STABLE leveldb within eleveldb cannot be built with clang (use gcc from Ports to circumvent) [JIRA: RIAK-1808]

Tested on

  • Commit 63733a9
  • Compiled on FreeBSD 10.0-STABLE r261910 amd64 with Erlang/OTP R16B03-1

Synopsis summary:

  • FreeBSD 10.x clang compiler seems to fail to process some include files in leveldb/
  • Note that running cd c_src && ./build_deps.sh switches the compiler to g++ (GNU cc) and no error will occur (because my system has gcc 4.6.4 installed from the Ports)
  • Building with env CC=gcc46 CXX=g++46 gmake clean will build runnable binaries

The compilation log of gmake clean:

./rebar compile
==> getopt (compile)
Compiled src/getopt.erl
==> goldrush (compile)
Compiled src/glc.erl
Compiled src/glc_lib.erl
Compiled src/gr_app.erl
Compiled src/glc_ops.erl
Compiled src/gr_context.erl
Compiled src/gr_counter_sup.erl
Compiled src/glc_code.erl
Compiled src/gr_manager_sup.erl
Compiled src/gr_manager.erl
Compiled src/gr_counter.erl
Compiled src/gr_param_sup.erl
Compiled src/gr_sup.erl
Compiled src/gre.erl
Compiled src/gr_param.erl
==> lager (compile)
Compiled src/lager_util.erl
Compiled src/lager_transform.erl
Compiled src/lager_app.erl
Compiled src/lager_backend_throttle.erl
Compiled src/lager.erl
Compiled src/lager_config.erl
Compiled src/lager_console_backend.erl
Compiled src/error_logger_lager_h.erl
Compiled src/lager_crash_log.erl
Compiled src/lager_default_formatter.erl
Compiled src/lager_handler_watcher.erl
Compiled src/lager_handler_watcher_sup.erl
Compiled src/lager_msg.erl
Compiled src/lager_file_backend.erl
Compiled src/lager_format.erl
Compiled src/lager_sup.erl
Compiled src/lager_stdlib.erl
Compiled src/lager_trunc_io.erl
==> neotoma (compile)
Compiled src/neotoma.erl
Compiled src/neotoma_parse.erl
==> cuttlefish (compile)
Compiled src/cuttlefish_advanced.erl
Compiled src/cuttlefish_bytesize.erl
Compiled src/cuttlefish.erl
Compiled src/cuttlefish_duration.erl
Compiled src/cuttlefish_error.erl
Compiled src/cuttlefish_conf.erl
Compiled src/cuttlefish_datatypes.erl
Compiled src/cuttlefish_flag.erl
Compiled src/cuttlefish_mapping.erl
Compiled src/cuttlefish_rebar_plugin.erl
Compiled src/cuttlefish_escript.erl
Compiled src/cuttlefish_generator.erl
Compiled src/cuttlefish_translation.erl
Compiled src/cuttlefish_schema.erl
Compiled src/cuttlefish_validator.erl
Compiled src/cuttlefish_util.erl
Compiled src/cuttlefish_vmargs.erl
Compiled src/cuttlefish_variable.erl
Compiled src/cuttlefish_unit.erl
Compiled src/lager_stderr_backend.erl
Compiled src/cuttlefish_duration_parse.erl
Compiled src/conf_parse.erl
==> getopt (escriptize)
==> goldrush (escriptize)
==> lager (escriptize)
==> neotoma (escriptize)
==> cuttlefish (escriptize)
==> eleveldb (compile)
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... ./install-sh -c -d
checking for gawk... gawk
checking whether make sets $(MAKE)... yes
checking build system type... x86_64-unknown-freebsd10.0
checking host system type... x86_64-unknown-freebsd10.0
checking for style of include used by make... GNU
checking for gcc... cc
checking whether the C compiler works... yes
checking for C compiler default output file name... a.out
checking for suffix of executables... 
checking whether we are cross compiling... no
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether cc accepts -g... yes
checking for cc option to accept ISO C89... none needed
checking dependency style of cc... gcc3
checking for a sed that does not truncate output... /usr/local/bin/gsed
checking for grep that handles long lines and -e... /usr/bin/grep
checking for egrep... /usr/bin/grep -E
checking for fgrep... /usr/bin/grep -F
checking for ld used by cc... /usr/bin/ld
checking if the linker (/usr/bin/ld) is GNU ld... yes
checking for BSD- or MS-compatible name lister (nm)... /usr/local/bin/nm -B
checking the name lister (/usr/local/bin/nm -B) interface... BSD nm
checking whether ln -s works... yes
checking the maximum length of command line arguments... 196608
checking whether the shell understands some XSI constructs... yes
checking whether the shell understands "+="... no
checking for /usr/bin/ld option to reload object files... -r
checking for objdump... objdump
checking how to recognize dependent libraries... pass_all
checking for ar... ar
checking for strip... strip
checking for ranlib... ranlib
checking command to parse /usr/local/bin/nm -B output from cc object... ok
checking how to run the C preprocessor... cc -E
checking for ANSI C header files... yes
checking for sys/types.h... yes
checking for sys/stat.h... yes
checking for stdlib.h... yes
checking for string.h... yes
checking for memory.h... yes
checking for strings.h... yes
checking for inttypes.h... yes
checking for stdint.h... yes
checking for unistd.h... yes
checking for dlfcn.h... yes
checking for objdir... .libs
checking if cc supports -fno-rtti -fno-exceptions... yes
checking for cc option to produce PIC... -fPIC -DPIC
checking if cc PIC flag -fPIC -DPIC works... yes
checking if cc static flag -static works... yes
checking if cc supports -c -o file.o... yes
checking if cc supports -c -o file.o... (cached) yes
checking whether the cc linker (/usr/bin/ld) supports shared libraries... yes
checking whether -lc should be explicitly linked in... no
checking dynamic linker characteristics... no
checking how to hardcode library paths into programs... immediate
checking whether stripping libraries is possible... yes
checking if libtool supports shared libraries... no
checking whether to build shared libraries... no
checking whether to build static libraries... yes
checking whether we are using the GNU C++ compiler... yes
checking whether c++ accepts -g... yes
checking dependency style of c++... gcc3
checking whether we are using the GNU C++ compiler... (cached) yes
checking whether c++ accepts -g... (cached) yes
checking dependency style of c++... (cached) gcc3
checking how to run the C++ preprocessor... c++ -E
checking for ld used by c++... /usr/bin/ld
checking if the linker (/usr/bin/ld) is GNU ld... yes
checking whether the c++ linker (/usr/bin/ld) supports shared libraries... no
checking for c++ option to produce PIC... -fPIC -DPIC
checking if c++ PIC flag -fPIC -DPIC works... yes
checking if c++ static flag -static works... yes
checking if c++ supports -c -o file.o... yes
checking if c++ supports -c -o file.o... (cached) yes
checking whether the c++ linker (/usr/bin/ld) supports shared libraries... no
checking dynamic linker characteristics... no
checking how to hardcode library paths into programs... immediate
checking whether byte ordering is bigendian... no
checking for stdint.h... (cached) yes
checking stddef.h usability... yes
checking stddef.h presence... yes
checking for stddef.h... yes
checking sys/mman.h usability... yes
checking sys/mman.h presence... yes
checking for sys/mman.h... yes
checking sys/resource.h usability... yes
checking sys/resource.h presence... yes
checking for sys/resource.h... yes
checking windows.h usability... no
checking windows.h presence... no
checking for windows.h... no
checking byteswap.h usability... no
checking byteswap.h presence... no
checking for byteswap.h... no
checking sys/byteswap.h usability... no
checking sys/byteswap.h presence... no
checking for sys/byteswap.h... no
checking sys/endian.h usability... yes
checking sys/endian.h presence... yes
checking for sys/endian.h... yes
checking for mmap... yes
checking for 'gtest-config'... checking for gtest-config... no
no
checking for pkg-config... /usr/local/bin/pkg-config
checking pkg-config is at least version 0.9.0... yes
checking for gflags... no
checking if the compiler supports __builtin_expect... yes
checking if the compiler supports __builtin_ctzll... yes
checking for zlibVersion in -lz... yes
checking for lzo1x_1_15_compress in -llzo2... no
checking for lzf_compress in -llzf... no
checking for fastlz_compress in -lfastlz... no
checking for qlz_compress in -lquicklz... no
configure: creating ./config.status
config.status: creating Makefile
config.status: creating snappy-stubs-public.h
config.status: creating config.h
config.status: executing depfiles commands
config.status: executing libtool commands
gmake[1]: Entering directory `/home/kenji/src/eleveldb/c_src/snappy-1.0.4'
gmake  all-am
gmake[2]: Entering directory `/home/kenji/src/eleveldb/c_src/snappy-1.0.4'
/bin/sh ./libtool --tag=CXX   --mode=compile c++ -DHAVE_CONFIG_H -I.     -Wall -O3 -fPIC -MT snappy.lo -MD -MP -MF .deps/snappy.Tpo -c -o snappy.lo snappy.cc
libtool: compile:  c++ -DHAVE_CONFIG_H -I. -Wall -O3 -fPIC -MT snappy.lo -MD -MP -MF .deps/snappy.Tpo -c snappy.cc  -fPIC -DPIC -o snappy.o
snappy.cc:516:13: warning: unused function 'ComputeTable' [-Wunused-function]
static void ComputeTable() {
            ^
1 warning generated.
mv -f .deps/snappy.Tpo .deps/snappy.Plo
/bin/sh ./libtool --tag=CXX   --mode=compile c++ -DHAVE_CONFIG_H -I.     -Wall -O3 -fPIC -MT snappy-sinksource.lo -MD -MP -MF .deps/snappy-sinksource.Tpo -c -o snappy-sinksource.lo snappy-sinksource.cc
libtool: compile:  c++ -DHAVE_CONFIG_H -I. -Wall -O3 -fPIC -MT snappy-sinksource.lo -MD -MP -MF .deps/snappy-sinksource.Tpo -c snappy-sinksource.cc  -fPIC -DPIC -o snappy-sinksource.o
mv -f .deps/snappy-sinksource.Tpo .deps/snappy-sinksource.Plo
/bin/sh ./libtool --tag=CXX   --mode=compile c++ -DHAVE_CONFIG_H -I.     -Wall -O3 -fPIC -MT snappy-stubs-internal.lo -MD -MP -MF .deps/snappy-stubs-internal.Tpo -c -o snappy-stubs-internal.lo snappy-stubs-internal.cc
libtool: compile:  c++ -DHAVE_CONFIG_H -I. -Wall -O3 -fPIC -MT snappy-stubs-internal.lo -MD -MP -MF .deps/snappy-stubs-internal.Tpo -c snappy-stubs-internal.cc  -fPIC -DPIC -o snappy-stubs-internal.o
mv -f .deps/snappy-stubs-internal.Tpo .deps/snappy-stubs-internal.Plo
/bin/sh ./libtool --tag=CXX   --mode=compile c++ -DHAVE_CONFIG_H -I.     -Wall -O3 -fPIC -MT snappy-c.lo -MD -MP -MF .deps/snappy-c.Tpo -c -o snappy-c.lo snappy-c.cc
libtool: compile:  c++ -DHAVE_CONFIG_H -I. -Wall -O3 -fPIC -MT snappy-c.lo -MD -MP -MF .deps/snappy-c.Tpo -c snappy-c.cc  -fPIC -DPIC -o snappy-c.o
mv -f .deps/snappy-c.Tpo .deps/snappy-c.Plo
/bin/sh ./libtool --tag=CXX   --mode=link c++  -Wall -O3 -fPIC -version-info 2:2:1  -o libsnappy.la -rpath /home/kenji/src/eleveldb/c_src/system/lib snappy.lo snappy-sinksource.lo snappy-stubs-internal.lo snappy-c.lo  
libtool: link: ar cru .libs/libsnappy.a  snappy.o snappy-sinksource.o snappy-stubs-internal.o snappy-c.o
libtool: link: ranlib .libs/libsnappy.a
libtool: link: ( cd ".libs" && rm -f "libsnappy.la" && ln -s "../libsnappy.la" "libsnappy.la" )
c++ -DHAVE_CONFIG_H -I.      -Wall -O3 -fPIC -MT snappy_unittest-snappy_unittest.o -MD -MP -MF .deps/snappy_unittest-snappy_unittest.Tpo -c -o snappy_unittest-snappy_unittest.o `test -f 'snappy_unittest.cc' || echo './'`snappy_unittest.cc
snappy_unittest.cc:165:1: warning: control may reach end of non-void function [-Wreturn-type]
}
^
In file included from snappy_unittest.cc:39:
./snappy-test.h:148:8: warning: unused function 'ReadFileToStringOrDie' [-Wunused-function]
  void ReadFileToStringOrDie(const string& filename, string* data) {
       ^
2 warnings generated.
mv -f .deps/snappy_unittest-snappy_unittest.Tpo .deps/snappy_unittest-snappy_unittest.Po
c++ -DHAVE_CONFIG_H -I.      -Wall -O3 -fPIC -MT snappy_unittest-snappy-test.o -MD -MP -MF .deps/snappy_unittest-snappy-test.Tpo -c -o snappy_unittest-snappy-test.o `test -f 'snappy-test.cc' || echo './'`snappy-test.cc
snappy-test.cc:356:15: warning: unused variable 'source_bytes_consumed' [-Wunused-variable]
  const uLong source_bytes_consumed = *sourceLen - comp_stream_.avail_in;
              ^
snappy-test.cc:400:16: warning: unused variable 'orig_destLen' [-Wunused-variable]
  const uLongf orig_destLen = *destLen;
               ^
In file included from snappy-test.cc:31:
./snappy-test.h:125:8: warning: unused function 'Init' [-Wunused-function]
  void Init() { }
       ^
./snappy-test.h:152:8: warning: unused function 'WriteStringToFileOrDie' [-Wunused-function]
  void WriteStringToFileOrDie(const string& str, const char* filename) {
       ^
./snappy-test.h:449:13: warning: unused function 'RunSpecifiedBenchmarks' [-Wunused-function]
static void RunSpecifiedBenchmarks() {
            ^
./snappy-test.h:495:13: warning: unused function 'CompressFile' [-Wunused-function]
static void CompressFile(const char* fname);
            ^
./snappy-test.h:496:13: warning: unused function 'UncompressFile' [-Wunused-function]
static void UncompressFile(const char* fname);
            ^
./snappy-test.h:497:13: warning: unused function 'MeasureFile' [-Wunused-function]
static void MeasureFile(const char* fname);
            ^
8 warnings generated.
mv -f .deps/snappy_unittest-snappy-test.Tpo .deps/snappy_unittest-snappy-test.Po
/bin/sh ./libtool --tag=CXX   --mode=link c++  -Wall -O3 -fPIC   -o snappy_unittest snappy_unittest-snappy_unittest.o snappy_unittest-snappy-test.o libsnappy.la -lz    
libtool: link: c++ -Wall -O3 -fPIC -o snappy_unittest snappy_unittest-snappy_unittest.o snappy_unittest-snappy-test.o  ./.libs/libsnappy.a -lz
gmake[2]: Leaving directory `/home/kenji/src/eleveldb/c_src/snappy-1.0.4'
gmake[1]: Leaving directory `/home/kenji/src/eleveldb/c_src/snappy-1.0.4'
gmake[1]: Entering directory `/home/kenji/src/eleveldb/c_src/snappy-1.0.4'
gmake[2]: Entering directory `/home/kenji/src/eleveldb/c_src/snappy-1.0.4'
test -z "/home/kenji/src/eleveldb/c_src/system/lib" || ./install-sh -c -d "/home/kenji/src/eleveldb/c_src/system/lib"
 /bin/sh ./libtool   --mode=install /usr/bin/install -c   libsnappy.la '/home/kenji/src/eleveldb/c_src/system/lib'
libtool: install: /usr/bin/install -c .libs/libsnappy.lai /home/kenji/src/eleveldb/c_src/system/lib/libsnappy.la
libtool: install: /usr/bin/install -c .libs/libsnappy.a /home/kenji/src/eleveldb/c_src/system/lib/libsnappy.a
libtool: install: chmod 644 /home/kenji/src/eleveldb/c_src/system/lib/libsnappy.a
libtool: install: ranlib /home/kenji/src/eleveldb/c_src/system/lib/libsnappy.a
----------------------------------------------------------------------
Libraries have been installed in:
   /home/kenji/src/eleveldb/c_src/system/lib

If you ever happen to want to link against installed libraries
in a given directory, LIBDIR, you must either use libtool, and
specify the full pathname of the library, or use the `-LLIBDIR'
flag during linking and do at least one of the following:
   - add LIBDIR to the `LD_RUN_PATH' environment variable
     during linking
   - use the `-Wl,-rpath -Wl,LIBDIR' linker flag

See any operating system documentation about shared libraries for
more information, such as the ld(1) and ld.so(8) manual pages.
----------------------------------------------------------------------
test -z "/home/kenji/src/eleveldb/c_src/system/share/doc/snappy" || ./install-sh -c -d "/home/kenji/src/eleveldb/c_src/system/share/doc/snappy"
 /usr/bin/install -c -m 644 ChangeLog COPYING INSTALL NEWS README format_description.txt '/home/kenji/src/eleveldb/c_src/system/share/doc/snappy'
test -z "/home/kenji/src/eleveldb/c_src/system/include" || ./install-sh -c -d "/home/kenji/src/eleveldb/c_src/system/include"
 /usr/bin/install -c -m 644 snappy.h snappy-sinksource.h snappy-stubs-public.h snappy-c.h '/home/kenji/src/eleveldb/c_src/system/include'
gmake[2]: Leaving directory `/home/kenji/src/eleveldb/c_src/snappy-1.0.4'
gmake[1]: Leaving directory `/home/kenji/src/eleveldb/c_src/snappy-1.0.4'
gmake[1]: Entering directory `/home/kenji/src/eleveldb/c_src/leveldb'
c++  -L/home/kenji/src/eleveldb/c_src/system/lib -lpthread -lsnappy -shared -Wl,-soname -Wl,libleveldb.so.1  -Wall -O3 -fPIC -I /home/kenji/src/eleveldb/c_src/system/include -I. -I./include -fno-builtin-memcmp -D_REENTRANT -DOS_FREEBSD -DLEVELDB_PLATFORM_POSIX -DSNAPPY -O2 -g -DNDEBUG     -fPIC db/builder.cc db/c.cc db/db_impl.cc db/db_iter.cc db/dbformat.cc db/filename.cc db/log_reader.cc db/log_writer.cc db/memtable.cc db/repair.cc db/table_cache.cc db/version_edit.cc db/version_set.cc db/write_batch.cc table/block.cc table/block_builder.cc table/filter_block.cc table/format.cc table/iterator.cc table/merger.cc table/table.cc table/table_builder.cc table/two_level_iterator.cc util/arena.cc util/bloom.cc util/bloom2.cc util/cache.cc util/cache2.cc util/coding.cc util/comparator.cc util/crc32c.cc util/db_list.cc util/env.cc util/env_posix.cc util/filter_policy.cc util/flexcache.cc util/hash.cc util/histogram.cc util/hot_threads.cc util/logging.cc util/murmurhash.cc util/options.cc util/perf_count.cc util/status.cc util/throttle.cc  port/port_posix.cc -o libleveldb.so.1.9
c++: warning: argument unused during compilation: '-fno-builtin-memcmp'
In file included from db/log_reader.cc:8:
./include/leveldb/env.h:158:11: error: unknown type name 'pthread_t'; did you mean 'pthread'?
  virtual pthread_t StartThread(void (*function)(void* arg), void* arg) = 0;
          ^~~~~~~~~
          pthread
/usr/include/stdio.h:143:9: note: 'pthread' declared here
        struct pthread *_fl_owner;      /* current owner */
               ^
In file included from db/log_reader.cc:8:
./include/leveldb/env.h:365:3: error: unknown type name 'pthread_t'; did you mean 'pthread'?
  pthread_t StartThread(void (*f)(void*), void* a) {
  ^~~~~~~~~
  pthread
/usr/include/stdio.h:143:9: note: 'pthread' declared here
        struct pthread *_fl_owner;      /* current owner */
               ^
In file included from db/log_reader.cc:8:
./include/leveldb/env.h:365:13: error: incomplete result type 'pthread' in function definition
  pthread_t StartThread(void (*f)(void*), void* a) {
            ^
/usr/include/stdio.h:143:9: note: forward declaration of 'pthread'
        struct pthread *_fl_owner;      /* current owner */
               ^
In file included from db/log_reader.cc:8:
./include/leveldb/env.h:366:21: error: calling 'StartThread' with incomplete return type 'pthread'
    return target_->StartThread(f, a);
           ~~~~~~~~~^~~~~~~~~~~~~~~~~
./include/leveldb/env.h:158:21: note: 'StartThread' declared here
  virtual pthread_t StartThread(void (*function)(void* arg), void* arg) = 0;
                    ^
/usr/include/stdio.h:143:9: note: forward declaration of 'pthread'
        struct pthread *_fl_owner;      /* current owner */
               ^
4 errors generated.
In file included from db/log_writer.cc:5:
In file included from ./db/log_writer.h:12:
./include/leveldb/env.h:158:11: error: unknown type name 'pthread_t'; did you mean 'pthread'?
  virtual pthread_t StartThread(void (*function)(void* arg), void* arg) = 0;
          ^~~~~~~~~
          pthread
/usr/include/stdio.h:143:9: note: 'pthread' declared here
        struct pthread *_fl_owner;      /* current owner */
               ^
In file included from db/log_writer.cc:5:
In file included from ./db/log_writer.h:12:
./include/leveldb/env.h:365:3: error: unknown type name 'pthread_t'; did you mean 'pthread'?
  pthread_t StartThread(void (*f)(void*), void* a) {
  ^~~~~~~~~
  pthread
/usr/include/stdio.h:143:9: note: 'pthread' declared here
        struct pthread *_fl_owner;      /* current owner */
               ^
In file included from db/log_writer.cc:5:
In file included from ./db/log_writer.h:12:
./include/leveldb/env.h:365:13: error: incomplete result type 'pthread' in function definition
  pthread_t StartThread(void (*f)(void*), void* a) {
            ^
/usr/include/stdio.h:143:9: note: forward declaration of 'pthread'
        struct pthread *_fl_owner;      /* current owner */
               ^
In file included from db/log_writer.cc:5:
In file included from ./db/log_writer.h:12:
./include/leveldb/env.h:366:21: error: calling 'StartThread' with incomplete return type 'pthread'
    return target_->StartThread(f, a);
           ~~~~~~~~~^~~~~~~~~~~~~~~~~
./include/leveldb/env.h:158:21: note: 'StartThread' declared here
  virtual pthread_t StartThread(void (*function)(void* arg), void* arg) = 0;
                    ^
/usr/include/stdio.h:143:9: note: forward declaration of 'pthread'
        struct pthread *_fl_owner;      /* current owner */
               ^
4 errors generated.
db/repair.cc:171:8: warning: private field 'owns_cache_' is not used [-Wunused-private-field]
  bool owns_cache_;
       ^
db/repair.cc:172:8: warning: private field 'has_level_dirs_' is not used [-Wunused-private-field]
  bool has_level_dirs_;
       ^
2 warnings generated.
db/version_set.cc:80:13: warning: unused function 'IntSetToString' [-Wunused-function]
std::string IntSetToString(const std::set<uint64_t>& s) {
            ^
1 warning generated.
In file included from table/format.cc:7:
./include/leveldb/env.h:158:11: error: unknown type name 'pthread_t'; did you mean 'pthread'?
  virtual pthread_t StartThread(void (*function)(void* arg), void* arg) = 0;
          ^~~~~~~~~
          pthread
/usr/include/stdio.h:143:9: note: 'pthread' declared here
        struct pthread *_fl_owner;      /* current owner */
               ^
In file included from table/format.cc:7:
./include/leveldb/env.h:365:3: error: unknown type name 'pthread_t'; did you mean 'pthread'?
  pthread_t StartThread(void (*f)(void*), void* a) {
  ^~~~~~~~~
  pthread
/usr/include/stdio.h:143:9: note: 'pthread' declared here
        struct pthread *_fl_owner;      /* current owner */
               ^
In file included from table/format.cc:7:
./include/leveldb/env.h:365:13: error: incomplete result type 'pthread' in function definition
  pthread_t StartThread(void (*f)(void*), void* a) {
            ^
/usr/include/stdio.h:143:9: note: forward declaration of 'pthread'
        struct pthread *_fl_owner;      /* current owner */
               ^
In file included from table/format.cc:7:
./include/leveldb/env.h:366:21: error: calling 'StartThread' with incomplete return type 'pthread'
    return target_->StartThread(f, a);
           ~~~~~~~~~^~~~~~~~~~~~~~~~~
./include/leveldb/env.h:158:21: note: 'StartThread' declared here
  virtual pthread_t StartThread(void (*function)(void* arg), void* arg) = 0;
                    ^
/usr/include/stdio.h:143:9: note: forward declaration of 'pthread'
        struct pthread *_fl_owner;      /* current owner */
               ^
4 errors generated.
In file included from table/table.cc:9:
./include/leveldb/env.h:158:11: error: unknown type name 'pthread_t'; did you mean 'pthread'?
  virtual pthread_t StartThread(void (*function)(void* arg), void* arg) = 0;
          ^~~~~~~~~
          pthread
/usr/include/stdio.h:143:9: note: 'pthread' declared here
        struct pthread *_fl_owner;      /* current owner */
               ^
In file included from table/table.cc:9:
./include/leveldb/env.h:365:3: error: unknown type name 'pthread_t'; did you mean 'pthread'?
  pthread_t StartThread(void (*f)(void*), void* a) {
  ^~~~~~~~~
  pthread
/usr/include/stdio.h:143:9: note: 'pthread' declared here
        struct pthread *_fl_owner;      /* current owner */
               ^
In file included from table/table.cc:9:
./include/leveldb/env.h:365:13: error: incomplete result type 'pthread' in function definition
  pthread_t StartThread(void (*f)(void*), void* a) {
            ^
/usr/include/stdio.h:143:9: note: forward declaration of 'pthread'
        struct pthread *_fl_owner;      /* current owner */
               ^
In file included from table/table.cc:9:
./include/leveldb/env.h:366:21: error: calling 'StartThread' with incomplete return type 'pthread'
    return target_->StartThread(f, a);
           ~~~~~~~~~^~~~~~~~~~~~~~~~~
./include/leveldb/env.h:158:21: note: 'StartThread' declared here
  virtual pthread_t StartThread(void (*function)(void* arg), void* arg) = 0;
                    ^
/usr/include/stdio.h:143:9: note: forward declaration of 'pthread'
        struct pthread *_fl_owner;      /* current owner */
               ^
4 errors generated.
In file included from util/cache2.cc:16:
./include/leveldb/env.h:158:11: error: unknown type name 'pthread_t'; did you mean 'pthread'?
  virtual pthread_t StartThread(void (*function)(void* arg), void* arg) = 0;
          ^~~~~~~~~
          pthread
/usr/include/stdio.h:143:9: note: 'pthread' declared here
        struct pthread *_fl_owner;      /* current owner */
               ^
In file included from util/cache2.cc:16:
./include/leveldb/env.h:365:3: error: unknown type name 'pthread_t'; did you mean 'pthread'?
  pthread_t StartThread(void (*f)(void*), void* a) {
  ^~~~~~~~~
  pthread
/usr/include/stdio.h:143:9: note: 'pthread' declared here
        struct pthread *_fl_owner;      /* current owner */
               ^
In file included from util/cache2.cc:16:
./include/leveldb/env.h:365:13: error: incomplete result type 'pthread' in function definition
  pthread_t StartThread(void (*f)(void*), void* a) {
            ^
/usr/include/stdio.h:143:9: note: forward declaration of 'pthread'
        struct pthread *_fl_owner;      /* current owner */
               ^
In file included from util/cache2.cc:16:
./include/leveldb/env.h:366:21: error: calling 'StartThread' with incomplete return type 'pthread'
    return target_->StartThread(f, a);
           ~~~~~~~~~^~~~~~~~~~~~~~~~~
./include/leveldb/env.h:158:21: note: 'StartThread' declared here
  virtual pthread_t StartThread(void (*function)(void* arg), void* arg) = 0;
                    ^
/usr/include/stdio.h:143:9: note: forward declaration of 'pthread'
        struct pthread *_fl_owner;      /* current owner */
               ^
In file included from util/cache2.cc:17:
./util/cache2.h:53:5: error: unknown type name 'time_t'
    time_t GetFileTimeout() {return(m_FileTimeout);};
    ^
./util/cache2.h:54:25: error: unknown type name 'time_t'
    void SetFileTimeout(time_t Timeout) {m_FileTimeout=Timeout;};
                        ^
./util/cache2.h:74:5: error: unknown type name 'time_t'
    time_t m_FileTimeout;       //!< seconds to allow file to stay cached.  default 4 days.
    ^
7 errors generated.
In file included from util/env.cc:5:
./include/leveldb/env.h:158:11: error: unknown type name 'pthread_t'; did you mean 'pthread'?
  virtual pthread_t StartThread(void (*function)(void* arg), void* arg) = 0;
          ^~~~~~~~~
          pthread
/usr/include/stdio.h:143:9: note: 'pthread' declared here
        struct pthread *_fl_owner;      /* current owner */
               ^
In file included from util/env.cc:5:
./include/leveldb/env.h:365:3: error: unknown type name 'pthread_t'; did you mean 'pthread'?
  pthread_t StartThread(void (*f)(void*), void* a) {
  ^~~~~~~~~
  pthread
/usr/include/stdio.h:143:9: note: 'pthread' declared here
        struct pthread *_fl_owner;      /* current owner */
               ^
In file included from util/env.cc:5:
./include/leveldb/env.h:365:13: error: incomplete result type 'pthread' in function definition
  pthread_t StartThread(void (*f)(void*), void* a) {
            ^
/usr/include/stdio.h:143:9: note: forward declaration of 'pthread'
        struct pthread *_fl_owner;      /* current owner */
               ^
In file included from util/env.cc:5:
./include/leveldb/env.h:366:21: error: calling 'StartThread' with incomplete return type 'pthread'
    return target_->StartThread(f, a);
           ~~~~~~~~~^~~~~~~~~~~~~~~~~
./include/leveldb/env.h:158:21: note: 'StartThread' declared here
  virtual pthread_t StartThread(void (*function)(void* arg), void* arg) = 0;
                    ^
/usr/include/stdio.h:143:9: note: forward declaration of 'pthread'
        struct pthread *_fl_owner;      /* current owner */
               ^
4 errors generated.
util/env_posix.cc:811:19: warning: unused variable 'ts' [-Wunused-variable]
  struct timespec ts;
                  ^
util/env_posix.cc:788:8: warning: function 'leveldb::<anonymous namespace>::PosixEnv::BGThread' has internal linkage but is not defined [-Wundefined-internal]
  void BGThread();
       ^
util/env_posix.cc:790:39: note: used here
    reinterpret_cast<PosixEnv*>(arg)->BGThread();
                                      ^
2 warnings generated.
In file included from util/options.cc:11:
./include/leveldb/env.h:158:11: error: unknown type name 'pthread_t'; did you mean 'pthread'?
  virtual pthread_t StartThread(void (*function)(void* arg), void* arg) = 0;
          ^~~~~~~~~
          pthread
/usr/include/stdio.h:143:9: note: 'pthread' declared here
        struct pthread *_fl_owner;      /* current owner */
               ^
In file included from util/options.cc:11:
./include/leveldb/env.h:365:3: error: unknown type name 'pthread_t'; did you mean 'pthread'?
  pthread_t StartThread(void (*f)(void*), void* a) {
  ^~~~~~~~~
  pthread
/usr/include/stdio.h:143:9: note: 'pthread' declared here
        struct pthread *_fl_owner;      /* current owner */
               ^
In file included from util/options.cc:11:
./include/leveldb/env.h:365:13: error: incomplete result type 'pthread' in function definition
  pthread_t StartThread(void (*f)(void*), void* a) {
            ^
/usr/include/stdio.h:143:9: note: forward declaration of 'pthread'
        struct pthread *_fl_owner;      /* current owner */
               ^
In file included from util/options.cc:11:
./include/leveldb/env.h:366:21: error: calling 'StartThread' with incomplete return type 'pthread'
    return target_->StartThread(f, a);
           ~~~~~~~~~^~~~~~~~~~~~~~~~~
./include/leveldb/env.h:158:21: note: 'StartThread' declared here
  virtual pthread_t StartThread(void (*function)(void* arg), void* arg) = 0;
                    ^
/usr/include/stdio.h:143:9: note: forward declaration of 'pthread'
        struct pthread *_fl_owner;      /* current owner */
               ^
In file included from util/options.cc:13:
./util/cache2.h:53:5: error: unknown type name 'time_t'
    time_t GetFileTimeout() {return(m_FileTimeout);};
    ^
./util/cache2.h:54:25: error: unknown type name 'time_t'
    void SetFileTimeout(time_t Timeout) {m_FileTimeout=Timeout;};
                        ^
./util/cache2.h:74:5: error: unknown type name 'time_t'
    time_t m_FileTimeout;       //!< seconds to allow file to stay cached.  default 4 days.
    ^
7 errors generated.
gmake[1]: *** [libleveldb.so.1.9] Error 1
gmake[1]: Leaving directory `/home/kenji/src/eleveldb/c_src/leveldb'
ERROR: Command [compile] failed!
gmake: *** [compile] Error 1

SIGSEGV on series of failed opens

NOTE: I haven't made any effort to try to reduce the number of open attempts before the SIGSEGV. IMHO having such a crash happen at any time is sufficient. Other random generator seeds crash sooner or later.

Based upon develop branch as of fc3f09e

Steps to reproduce on OS X:

git checkout f5d7e903960b44dc94db10cb11b68aae83863866
make
rebar skip_deps=true -v eunit suites=XX
make compile_scenarios
./deps/faulterl/ebin/make_intercept_c.escript trigger_commonpaths yo "perl -npi -e 's/bc_fi_enabled = 1/bc_fi_enabled = 0/'"
env `./deps/faulterl/ebin/example_environment.sh yo` erl -pz .eunit deps/*/ebin

At this point, you've got an Erlang shell with the LD_PRELOAD magic set up to inject EDQUOT faults when opening files for writing. ENOSPC does the same thing.

Now, at the shell, run these:

[begin Rand = 42, faulterl_nif:poke("bc_fi_random_seed", 0, <<Rand:32>>, false), faulterl_nif:poke("bc_fi_random_reseed", 0, <<1:8>>, false), Rand end || true].
[begin io:format("X = ~p, ", [X]), eunit:test ( iterators ) end || X <- lists:seq ( 1,300 ) ].

After the core dump, GDB says that thread 30 has this crazy pointer:

(gdb) thread 30
[Switching to thread 30 (core thread 29)]
0x000000001ce9e2e9 in leveldb::Version::~Version (this=0x7f9c02427f00) at db/version_set.cc:98
98        next_->prev_ = prev_;
(gdb) p next_
$1 = ('leveldb::Version' *) 0x6000000000000000

Eleveldb eleveldb:async_iterator_move bad argument on 2.0.0

Here is the test module:

-module(eleveldb_fail).

-export([fill_db/1,
         foo2/1,
         copy/6
        ]).

fill_db(D) ->
    {ok, DBForm} = eleveldb:open(D, [{create_if_missing, true}]),
    [eleveldb:put(DBForm,
                  iolist_to_binary(io_lib:format("key ~p", [N])),
                  iolist_to_binary(io_lib:format("~p~n", [N])) , [])
     || N <- lists:seq(1,100)],
    eleveldb:close(DBForm).

%%------------------------------------------------------------------------------

foo2(D) ->
    fun() ->
            {ok, DBFrom} = eleveldb:open(D, []),
            {ok, I} = eleveldb:iterator(DBFrom, []),

            eleveldb_fail:copy(I, first, fun(Data) -> ok end, 100, [], 100)
    end.

copy(I, Hint, Fun, 0, Acc, Def) ->
    ok = Fun(Acc),
    copy(I, Hint, Fun, Def, [], Def);
copy(I, Hint, Fun, N, Acc, Def) ->
    case eleveldb:iterator_move(I, Hint) of
        {ok, K, V} ->
            io:format("move: k: ~p v: ~p~n~n", [K,V]),
            copy(I, next, Fun, N-1, [{K,V} | Acc], Def);
        {error, Reason} ->
            case Acc of
                [] -> ok;
                _  -> ok = Fun(Acc)
            end,
            io:format("Copy complete ~p~n", [Reason])
    end.

To reproduce bug:

[me@localdomain:/tmp/test] $ erl -pa ./ -pa eleveldb/ebin
Erlang R16B03-1 (erts-5.10.4) [source] [64-bit] [smp:8:8] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]

Eshell V5.10.4  (abort with ^G)
1> D = "/tmp/test/test_db".
"/tmp/test/test_db"
2> eleveldb_fail:fill_db("/tmp/test/test_db").
ok
3> F = eleveldb_fail:foo2(D).
#Fun<eleveldb_fail.0.59557994>
4> F().
move: k: <<"key 1">> v: <<"1\n">>

move: k: <<"key 10">> v: <<"10\n">>

move: k: <<"key 100">> v: <<"100\n">>

move: k: <<"key 11">> v: <<"11\n">>

move: k: <<"key 12">> v: <<"12\n">>

move: k: <<"key 13">> v: <<"13\n">>

move: k: <<"key 14">> v: <<"14\n">>

** exception error: bad argument
     in function  eleveldb:async_iterator_move/3
        called as eleveldb:async_iterator_move(undefined,<<>>,next)
     in call from eleveldb:iterator_move/2 (src/eleveldb.erl, line 201)
     in call from eleveldb_fail:copy/6 (eleveldb_fail.erl, line 40)
5>

BUT if we copy lambda fun from foo2 to shell:

[me@localdomain:/tmp/test] $ erl -pa ./ -pa eleveldb/ebin
Erlang R16B03-1 (erts-5.10.4) [source] [64-bit] [smp:8:8] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]

Eshell V5.10.4  (abort with ^G)
1> D = "/tmp/test/test_db".
"/tmp/test/test_db"
2> F = fun() ->
2>             {ok, DBFrom} = eleveldb:open(D, []),
2>             {ok, I} = eleveldb:iterator(DBFrom, []),
2>
2>             eleveldb_fail:copy(I, first, fun(Data) -> ok end, 100, [], 100)
2>     end.
#Fun<erl_eval.20.80484245>
3> F().
move: k: <<"key 1">> v: <<"1\n">>

move: k: <<"key 10">> v: <<"10\n">>

move: k: <<"key 100">> v: <<"100\n">>

move: k: <<"key 11">> v: <<"11\n">>

move: k: <<"key 12">> v: <<"12\n">>
...some output skipped...
move: k: <<"key 96">> v: <<"96\n">>

move: k: <<"key 97">> v: <<"97\n">>

move: k: <<"key 98">> v: <<"98\n">>

move: k: <<"key 99">> v: <<"99\n">>

Copy complete invalid_iterator
ok

I'm curious why it's acting like that.
Reproduced under both R16b03-1 and R17 on mac os x and linux.

NIF load error using OS X & Yosemite - test failures

Seeing this exact same error during 'make test' and when using Riak. I'm sure it is somehow Apple's fault & related somehow a recent OS update.

Symbol not found: _ZNSt8__detail15_List_node_base7_M_hookEPS0\n Referenced from: /Users/randy/temp/eleveldb/priv/eleveldb.so\n Expected in: flat namespace\n in /Users/randy/temp/eleveldb/priv/eleveldb.so

Valgrind: invalid reads & writes by compaction thread

All of these messages appear to come from a single test case. I'll try to figure out if this is deterministic or not -- I haven't created a clever way to have QuickCheck recognize when valgrind spots an error. I have a manual way to do it, but it's manual and requires a huge amount of babysitting and is only worthwhile on 100% deterministic cases.

==5359== Thread 121:
==5359== Invalid read of size 4
==5359==    at 0x134778A5: leveldb::LRUCache2::Erase(leveldb::Slice const&, unsigned int) (cache2.cc:106)
==5359==    by 0x13463F0A: leveldb::TableCache::Evict(unsigned long, bool) (table_cache.cc:166)
==5359==    by 0x134555EF: leveldb::DBImpl::DoCompactionWork(leveldb::DBImpl::CompactionState*) (db_impl.cc:1433)
==5359==    by 0x1345582C: leveldb::DBImpl::BackgroundCompaction(leveldb::Compaction*) (db_impl.cc:1032)
==5359==    by 0x13456815: leveldb::DBImpl::BackgroundCall2(leveldb::Compaction*) (db_impl.cc:889)
==5359==    by 0x1345A7D0: leveldb::CompactionTask::operator()() (thread_tasks.h:124)
==5359==    by 0x1347EB7A: leveldb::HotThread::ThreadRoutine() (hot_threads.cc:102)
==5359==    by 0x5767E99: start_thread (pthread_create.c:308)
==5359==  Address 0x7fb03b3c is 60 bytes inside a block of size 87 free'd
==5359==    at 0x4C2A82E: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5359==    by 0x1347796F: leveldb::LRUCache2::Release(leveldb::Cache::Handle*) (cache2.cc:254)
==5359==    by 0x13463F6E: leveldb::TableCache::Evict(unsigned long, bool) (table_cache.cc:162)
==5359==    by 0x134555EF: leveldb::DBImpl::DoCompactionWork(leveldb::DBImpl::CompactionState*) (db_impl.cc:1433)
==5359==    by 0x1345582C: leveldb::DBImpl::BackgroundCompaction(leveldb::Compaction*) (db_impl.cc:1032)
==5359==    by 0x13456815: leveldb::DBImpl::BackgroundCall2(leveldb::Compaction*) (db_impl.cc:889)
==5359==    by 0x1345A7D0: leveldb::CompactionTask::operator()() (thread_tasks.h:124)
==5359==    by 0x1347EB7A: leveldb::HotThread::ThreadRoutine() (hot_threads.cc:102)
==5359==    by 0x5767E99: start_thread (pthread_create.c:308)
==5359== 
==5359== Invalid read of size 8
==5359==    at 0x134778C1: leveldb::LRUCache2::Erase(leveldb::Slice const&, unsigned int) (cache2.cc:46)
==5359==    by 0x13463F0A: leveldb::TableCache::Evict(unsigned long, bool) (table_cache.cc:166)
==5359==    by 0x134555EF: leveldb::DBImpl::DoCompactionWork(leveldb::DBImpl::CompactionState*) (db_impl.cc:1433)
==5359==    by 0x1345582C: leveldb::DBImpl::BackgroundCompaction(leveldb::Compaction*) (db_impl.cc:1032)
==5359==    by 0x13456815: leveldb::DBImpl::BackgroundCall2(leveldb::Compaction*) (db_impl.cc:889)
==5359==    by 0x1345A7D0: leveldb::CompactionTask::operator()() (thread_tasks.h:124)
==5359==    by 0x1347EB7A: leveldb::HotThread::ThreadRoutine() (hot_threads.cc:102)
==5359==    by 0x5767E99: start_thread (pthread_create.c:308)
==5359==  Address 0x7fb03b18 is 24 bytes inside a block of size 87 free'd
==5359==    at 0x4C2A82E: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5359==    by 0x1347796F: leveldb::LRUCache2::Release(leveldb::Cache::Handle*) (cache2.cc:254)
==5359==    by 0x13463F6E: leveldb::TableCache::Evict(unsigned long, bool) (table_cache.cc:162)
==5359==    by 0x134555EF: leveldb::DBImpl::DoCompactionWork(leveldb::DBImpl::CompactionState*) (db_impl.cc:1433)
==5359==    by 0x1345582C: leveldb::DBImpl::BackgroundCompaction(leveldb::Compaction*) (db_impl.cc:1032)
==5359==    by 0x13456815: leveldb::DBImpl::BackgroundCall2(leveldb::Compaction*) (db_impl.cc:889)
==5359==    by 0x1345A7D0: leveldb::CompactionTask::operator()() (thread_tasks.h:124)
==5359==    by 0x1347EB7A: leveldb::HotThread::ThreadRoutine() (hot_threads.cc:102)
==5359==    by 0x5767E99: start_thread (pthread_create.c:308)
==5359== 
==5359== Invalid read of size 8
==5359==    at 0x134778C7: leveldb::LRUCache2::Erase(leveldb::Slice const&, unsigned int) (cache2.cc:49)
==5359==    by 0x13463F0A: leveldb::TableCache::Evict(unsigned long, bool) (table_cache.cc:166)
==5359==    by 0x134555EF: leveldb::DBImpl::DoCompactionWork(leveldb::DBImpl::CompactionState*) (db_impl.cc:1433)
==5359==    by 0x1345582C: leveldb::DBImpl::BackgroundCompaction(leveldb::Compaction*) (db_impl.cc:1032)
==5359==    by 0x13456815: leveldb::DBImpl::BackgroundCall2(leveldb::Compaction*) (db_impl.cc:889)
==5359==    by 0x1345A7D0: leveldb::CompactionTask::operator()() (thread_tasks.h:124)
==5359==    by 0x1347EB7A: leveldb::HotThread::ThreadRoutine() (hot_threads.cc:102)
==5359==    by 0x5767E99: start_thread (pthread_create.c:308)
==5359==  Address 0x7fb03b30 is 48 bytes inside a block of size 87 free'd
==5359==    at 0x4C2A82E: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5359==    by 0x1347796F: leveldb::LRUCache2::Release(leveldb::Cache::Handle*) (cache2.cc:254)
==5359==    by 0x13463F6E: leveldb::TableCache::Evict(unsigned long, bool) (table_cache.cc:162)
==5359==    by 0x134555EF: leveldb::DBImpl::DoCompactionWork(leveldb::DBImpl::CompactionState*) (db_impl.cc:1433)
==5359==    by 0x1345582C: leveldb::DBImpl::BackgroundCompaction(leveldb::Compaction*) (db_impl.cc:1032)
==5359==    by 0x13456815: leveldb::DBImpl::BackgroundCall2(leveldb::Compaction*) (db_impl.cc:889)
==5359==    by 0x1345A7D0: leveldb::CompactionTask::operator()() (thread_tasks.h:124)
==5359==    by 0x1347EB7A: leveldb::HotThread::ThreadRoutine() (hot_threads.cc:102)
==5359==    by 0x5767E99: start_thread (pthread_create.c:308)
==5359== 
==5359== Invalid read of size 1
==5359==    at 0x4C2DCAE: bcmp (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5359==    by 0x134778DC: leveldb::LRUCache2::Erase(leveldb::Slice const&, unsigned int) (slice.h:89)
==5359==    by 0x13463F0A: leveldb::TableCache::Evict(unsigned long, bool) (table_cache.cc:166)
==5359==    by 0x134555EF: leveldb::DBImpl::DoCompactionWork(leveldb::DBImpl::CompactionState*) (db_impl.cc:1433)
==5359==    by 0x1345582C: leveldb::DBImpl::BackgroundCompaction(leveldb::Compaction*) (db_impl.cc:1032)
==5359==    by 0x13456815: leveldb::DBImpl::BackgroundCall2(leveldb::Compaction*) (db_impl.cc:889)
==5359==    by 0x1345A7D0: leveldb::CompactionTask::operator()() (thread_tasks.h:124)
==5359==    by 0x1347EB7A: leveldb::HotThread::ThreadRoutine() (hot_threads.cc:102)
==5359==    by 0x5767E99: start_thread (pthread_create.c:308)
==5359==  Address 0x7fb03b48 is 72 bytes inside a block of size 87 free'd
==5359==    at 0x4C2A82E: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5359==    by 0x1347796F: leveldb::LRUCache2::Release(leveldb::Cache::Handle*) (cache2.cc:254)
==5359==    by 0x13463F6E: leveldb::TableCache::Evict(unsigned long, bool) (table_cache.cc:162)
==5359==    by 0x134555EF: leveldb::DBImpl::DoCompactionWork(leveldb::DBImpl::CompactionState*) (db_impl.cc:1433)
==5359==    by 0x1345582C: leveldb::DBImpl::BackgroundCompaction(leveldb::Compaction*) (db_impl.cc:1032)
==5359==    by 0x13456815: leveldb::DBImpl::BackgroundCall2(leveldb::Compaction*) (db_impl.cc:889)
==5359==    by 0x1345A7D0: leveldb::CompactionTask::operator()() (thread_tasks.h:124)
==5359==    by 0x1347EB7A: leveldb::HotThread::ThreadRoutine() (hot_threads.cc:102)
==5359==    by 0x5767E99: start_thread (pthread_create.c:308)
==5359== 
==5359== Invalid read of size 1
==5359==    at 0x4C2DCC6: bcmp (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5359==    by 0x134778DC: leveldb::LRUCache2::Erase(leveldb::Slice const&, unsigned int) (slice.h:89)
==5359==    by 0x13463F0A: leveldb::TableCache::Evict(unsigned long, bool) (table_cache.cc:166)
==5359==    by 0x134555EF: leveldb::DBImpl::DoCompactionWork(leveldb::DBImpl::CompactionState*) (db_impl.cc:1433)
==5359==    by 0x1345582C: leveldb::DBImpl::BackgroundCompaction(leveldb::Compaction*) (db_impl.cc:1032)
==5359==    by 0x13456815: leveldb::DBImpl::BackgroundCall2(leveldb::Compaction*) (db_impl.cc:889)
==5359==    by 0x1345A7D0: leveldb::CompactionTask::operator()() (thread_tasks.h:124)
==5359==    by 0x1347EB7A: leveldb::HotThread::ThreadRoutine() (hot_threads.cc:102)
==5359==    by 0x5767E99: start_thread (pthread_create.c:308)
==5359==  Address 0x7fb03b49 is 73 bytes inside a block of size 87 free'd
==5359==    at 0x4C2A82E: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5359==    by 0x1347796F: leveldb::LRUCache2::Release(leveldb::Cache::Handle*) (cache2.cc:254)
==5359==    by 0x13463F6E: leveldb::TableCache::Evict(unsigned long, bool) (table_cache.cc:162)
==5359==    by 0x134555EF: leveldb::DBImpl::DoCompactionWork(leveldb::DBImpl::CompactionState*) (db_impl.cc:1433)
==5359==    by 0x1345582C: leveldb::DBImpl::BackgroundCompaction(leveldb::Compaction*) (db_impl.cc:1032)
==5359==    by 0x13456815: leveldb::DBImpl::BackgroundCall2(leveldb::Compaction*) (db_impl.cc:889)
==5359==    by 0x1345A7D0: leveldb::CompactionTask::operator()() (thread_tasks.h:124)
==5359==    by 0x1347EB7A: leveldb::HotThread::ThreadRoutine() (hot_threads.cc:102)
==5359==    by 0x5767E99: start_thread (pthread_create.c:308)
==5359== 
==5359== Invalid read of size 8
==5359==    at 0x134778E6: leveldb::LRUCache2::Erase(leveldb::Slice const&, unsigned int) (cache2.cc:88)
==5359==    by 0x13463F0A: leveldb::TableCache::Evict(unsigned long, bool) (table_cache.cc:166)
==5359==    by 0x134555EF: leveldb::DBImpl::DoCompactionWork(leveldb::DBImpl::CompactionState*) (db_impl.cc:1433)
==5359==    by 0x1345582C: leveldb::DBImpl::BackgroundCompaction(leveldb::Compaction*) (db_impl.cc:1032)
==5359==    by 0x13456815: leveldb::DBImpl::BackgroundCall2(leveldb::Compaction*) (db_impl.cc:889)
==5359==    by 0x1345A7D0: leveldb::CompactionTask::operator()() (thread_tasks.h:124)
==5359==    by 0x1347EB7A: leveldb::HotThread::ThreadRoutine() (hot_threads.cc:102)
==5359==    by 0x5767E99: start_thread (pthread_create.c:308)
==5359==  Address 0x7fb03b10 is 16 bytes inside a block of size 87 free'd
==5359==    at 0x4C2A82E: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5359==    by 0x1347796F: leveldb::LRUCache2::Release(leveldb::Cache::Handle*) (cache2.cc:254)
==5359==    by 0x13463F6E: leveldb::TableCache::Evict(unsigned long, bool) (table_cache.cc:162)
==5359==    by 0x134555EF: leveldb::DBImpl::DoCompactionWork(leveldb::DBImpl::CompactionState*) (db_impl.cc:1433)
==5359==    by 0x1345582C: leveldb::DBImpl::BackgroundCompaction(leveldb::Compaction*) (db_impl.cc:1032)
==5359==    by 0x13456815: leveldb::DBImpl::BackgroundCall2(leveldb::Compaction*) (db_impl.cc:889)
==5359==    by 0x1345A7D0: leveldb::CompactionTask::operator()() (thread_tasks.h:124)
==5359==    by 0x1347EB7A: leveldb::HotThread::ThreadRoutine() (hot_threads.cc:102)
==5359==    by 0x5767E99: start_thread (pthread_create.c:308)
==5359== 
==5359== Invalid read of size 8
==5359==    at 0x13476D80: leveldb::LRUCache2::LRU_Remove(leveldb::LRUHandle2*) (cache2.cc:238)
==5359==    by 0x134778FC: leveldb::LRUCache2::Erase(leveldb::Slice const&, unsigned int) (cache2.cc:271)
==5359==    by 0x13463F0A: leveldb::TableCache::Evict(unsigned long, bool) (table_cache.cc:166)
==5359==    by 0x134555EF: leveldb::DBImpl::DoCompactionWork(leveldb::DBImpl::CompactionState*) (db_impl.cc:1433)
==5359==    by 0x1345582C: leveldb::DBImpl::BackgroundCompaction(leveldb::Compaction*) (db_impl.cc:1032)
==5359==    by 0x13456815: leveldb::DBImpl::BackgroundCall2(leveldb::Compaction*) (db_impl.cc:889)
==5359==    by 0x1345A7D0: leveldb::CompactionTask::operator()() (thread_tasks.h:124)
==5359==    by 0x1347EB7A: leveldb::HotThread::ThreadRoutine() (hot_threads.cc:102)
==5359==    by 0x5767E99: start_thread (pthread_create.c:308)
==5359==  Address 0x7fb03b18 is 24 bytes inside a block of size 87 free'd
==5359==    at 0x4C2A82E: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5359==    by 0x1347796F: leveldb::LRUCache2::Release(leveldb::Cache::Handle*) (cache2.cc:254)
==5359==    by 0x13463F6E: leveldb::TableCache::Evict(unsigned long, bool) (table_cache.cc:162)
==5359==    by 0x134555EF: leveldb::DBImpl::DoCompactionWork(leveldb::DBImpl::CompactionState*) (db_impl.cc:1433)
==5359==    by 0x1345582C: leveldb::DBImpl::BackgroundCompaction(leveldb::Compaction*) (db_impl.cc:1032)
==5359==    by 0x13456815: leveldb::DBImpl::BackgroundCall2(leveldb::Compaction*) (db_impl.cc:889)
==5359==    by 0x1345A7D0: leveldb::CompactionTask::operator()() (thread_tasks.h:124)
==5359==    by 0x1347EB7A: leveldb::HotThread::ThreadRoutine() (hot_threads.cc:102)
==5359==    by 0x5767E99: start_thread (pthread_create.c:308)
==5359== 
==5359== Invalid read of size 8
==5359==    at 0x13476D84: leveldb::LRUCache2::LRU_Remove(leveldb::LRUHandle2*) (cache2.cc:238)
==5359==    by 0x134778FC: leveldb::LRUCache2::Erase(leveldb::Slice const&, unsigned int) (cache2.cc:271)
==5359==    by 0x13463F0A: leveldb::TableCache::Evict(unsigned long, bool) (table_cache.cc:166)
==5359==    by 0x134555EF: leveldb::DBImpl::DoCompactionWork(leveldb::DBImpl::CompactionState*) (db_impl.cc:1433)
==5359==    by 0x1345582C: leveldb::DBImpl::BackgroundCompaction(leveldb::Compaction*) (db_impl.cc:1032)
==5359==    by 0x13456815: leveldb::DBImpl::BackgroundCall2(leveldb::Compaction*) (db_impl.cc:889)
==5359==    by 0x1345A7D0: leveldb::CompactionTask::operator()() (thread_tasks.h:124)
==5359==    by 0x1347EB7A: leveldb::HotThread::ThreadRoutine() (hot_threads.cc:102)
==5359==    by 0x5767E99: start_thread (pthread_create.c:308)
==5359==  Address 0x7fb03b20 is 32 bytes inside a block of size 87 free'd
==5359==    at 0x4C2A82E: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5359==    by 0x1347796F: leveldb::LRUCache2::Release(leveldb::Cache::Handle*) (cache2.cc:254)
==5359==    by 0x13463F6E: leveldb::TableCache::Evict(unsigned long, bool) (table_cache.cc:162)
==5359==    by 0x134555EF: leveldb::DBImpl::DoCompactionWork(leveldb::DBImpl::CompactionState*) (db_impl.cc:1433)
==5359==    by 0x1345582C: leveldb::DBImpl::BackgroundCompaction(leveldb::Compaction*) (db_impl.cc:1032)
==5359==    by 0x13456815: leveldb::DBImpl::BackgroundCall2(leveldb::Compaction*) (db_impl.cc:889)
==5359==    by 0x1345A7D0: leveldb::CompactionTask::operator()() (thread_tasks.h:124)
==5359==    by 0x1347EB7A: leveldb::HotThread::ThreadRoutine() (hot_threads.cc:102)
==5359==    by 0x5767E99: start_thread (pthread_create.c:308)
==5359== 
==5359== Invalid read of size 8
==5359==    at 0x13476D8C: leveldb::LRUCache2::LRU_Remove(leveldb::LRUHandle2*) (cache2.cc:239)
==5359==    by 0x134778FC: leveldb::LRUCache2::Erase(leveldb::Slice const&, unsigned int) (cache2.cc:271)
==5359==    by 0x13463F0A: leveldb::TableCache::Evict(unsigned long, bool) (table_cache.cc:166)
==5359==    by 0x134555EF: leveldb::DBImpl::DoCompactionWork(leveldb::DBImpl::CompactionState*) (db_impl.cc:1433)
==5359==    by 0x1345582C: leveldb::DBImpl::BackgroundCompaction(leveldb::Compaction*) (db_impl.cc:1032)
==5359==    by 0x13456815: leveldb::DBImpl::BackgroundCall2(leveldb::Compaction*) (db_impl.cc:889)
==5359==    by 0x1345A7D0: leveldb::CompactionTask::operator()() (thread_tasks.h:124)
==5359==    by 0x1347EB7A: leveldb::HotThread::ThreadRoutine() (hot_threads.cc:102)
==5359==    by 0x5767E99: start_thread (pthread_create.c:308)
==5359==  Address 0x7fb03b20 is 32 bytes inside a block of size 87 free'd
==5359==    at 0x4C2A82E: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5359==    by 0x1347796F: leveldb::LRUCache2::Release(leveldb::Cache::Handle*) (cache2.cc:254)
==5359==    by 0x13463F6E: leveldb::TableCache::Evict(unsigned long, bool) (table_cache.cc:162)
==5359==    by 0x134555EF: leveldb::DBImpl::DoCompactionWork(leveldb::DBImpl::CompactionState*) (db_impl.cc:1433)
==5359==    by 0x1345582C: leveldb::DBImpl::BackgroundCompaction(leveldb::Compaction*) (db_impl.cc:1032)
==5359==    by 0x13456815: leveldb::DBImpl::BackgroundCall2(leveldb::Compaction*) (db_impl.cc:889)
==5359==    by 0x1345A7D0: leveldb::CompactionTask::operator()() (thread_tasks.h:124)
==5359==    by 0x1347EB7A: leveldb::HotThread::ThreadRoutine() (hot_threads.cc:102)
==5359==    by 0x5767E99: start_thread (pthread_create.c:308)
==5359== 
==5359== Invalid read of size 4
==5359==    at 0x13477448: leveldb::LRUCache2::Unref(leveldb::LRUHandle2*) (cache2.cc:621)
==5359==    by 0x13477907: leveldb::LRUCache2::Erase(leveldb::Slice const&, unsigned int) (cache2.cc:272)
==5359==    by 0x13463F0A: leveldb::TableCache::Evict(unsigned long, bool) (table_cache.cc:166)
==5359==    by 0x134555EF: leveldb::DBImpl::DoCompactionWork(leveldb::DBImpl::CompactionState*) (db_impl.cc:1433)
==5359==    by 0x1345582C: leveldb::DBImpl::BackgroundCompaction(leveldb::Compaction*) (db_impl.cc:1032)
==5359==    by 0x13456815: leveldb::DBImpl::BackgroundCall2(leveldb::Compaction*) (db_impl.cc:889)
==5359==    by 0x1345A7D0: leveldb::CompactionTask::operator()() (thread_tasks.h:124)
==5359==    by 0x1347EB7A: leveldb::HotThread::ThreadRoutine() (hot_threads.cc:102)
==5359==    by 0x5767E99: start_thread (pthread_create.c:308)
==5359==  Address 0x7fb03b38 is 56 bytes inside a block of size 87 free'd
==5359==    at 0x4C2A82E: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5359==    by 0x1347796F: leveldb::LRUCache2::Release(leveldb::Cache::Handle*) (cache2.cc:254)
==5359==    by 0x13463F6E: leveldb::TableCache::Evict(unsigned long, bool) (table_cache.cc:162)
==5359==    by 0x134555EF: leveldb::DBImpl::DoCompactionWork(leveldb::DBImpl::CompactionState*) (db_impl.cc:1433)
==5359==    by 0x1345582C: leveldb::DBImpl::BackgroundCompaction(leveldb::Compaction*) (db_impl.cc:1032)
==5359==    by 0x13456815: leveldb::DBImpl::BackgroundCall2(leveldb::Compaction*) (db_impl.cc:889)
==5359==    by 0x1345A7D0: leveldb::CompactionTask::operator()() (thread_tasks.h:124)
==5359==    by 0x1347EB7A: leveldb::HotThread::ThreadRoutine() (hot_threads.cc:102)
==5359==    by 0x5767E99: start_thread (pthread_create.c:308)
==5359== 
==5359== Invalid write of size 4
==5359==    at 0x13477450: leveldb::LRUCache2::Unref(leveldb::LRUHandle2*) (cache2.cc:621)
==5359==    by 0x13477907: leveldb::LRUCache2::Erase(leveldb::Slice const&, unsigned int) (cache2.cc:272)
==5359==    by 0x13463F0A: leveldb::TableCache::Evict(unsigned long, bool) (table_cache.cc:166)
==5359==    by 0x134555EF: leveldb::DBImpl::DoCompactionWork(leveldb::DBImpl::CompactionState*) (db_impl.cc:1433)
==5359==    by 0x1345582C: leveldb::DBImpl::BackgroundCompaction(leveldb::Compaction*) (db_impl.cc:1032)
==5359==    by 0x13456815: leveldb::DBImpl::BackgroundCall2(leveldb::Compaction*) (db_impl.cc:889)
==5359==    by 0x1345A7D0: leveldb::CompactionTask::operator()() (thread_tasks.h:124)
==5359==    by 0x1347EB7A: leveldb::HotThread::ThreadRoutine() (hot_threads.cc:102)
==5359==    by 0x5767E99: start_thread (pthread_create.c:308)
==5359==  Address 0x7fb03b38 is 56 bytes inside a block of size 87 free'd
==5359==    at 0x4C2A82E: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5359==    by 0x1347796F: leveldb::LRUCache2::Release(leveldb::Cache::Handle*) (cache2.cc:254)
==5359==    by 0x13463F6E: leveldb::TableCache::Evict(unsigned long, bool) (table_cache.cc:162)
==5359==    by 0x134555EF: leveldb::DBImpl::DoCompactionWork(leveldb::DBImpl::CompactionState*) (db_impl.cc:1433)
==5359==    by 0x1345582C: leveldb::DBImpl::BackgroundCompaction(leveldb::Compaction*) (db_impl.cc:1032)
==5359==    by 0x13456815: leveldb::DBImpl::BackgroundCall2(leveldb::Compaction*) (db_impl.cc:889)
==5359==    by 0x1345A7D0: leveldb::CompactionTask::operator()() (thread_tasks.h:124)
==5359==    by 0x1347EB7A: leveldb::HotThread::ThreadRoutine() (hot_threads.cc:102)
==5359==    by 0x5767E99: start_thread (pthread_create.c:308)
==5359== 

SmartOS: able to open same DB twice

See the "slf-bbot-test-fixing1" branch.

The tests/cleanup.erl test assumption_test() is failing by allowing the same database instance to be opened twice. This test passes (i.e., DB cannot be opened twice) on OS X and Linux. It fails on SmartOS.

Example output, note that the erlang:display() output from line 138 does not appear.

module 'cleanup'
  cleanup: assumption_test...
{line,36}
{line,128}
{line,131}
{line,38}
{line,135}
{line,128}   %% This is output from the next EUnit test
*failed*
::{badmatch,{ok,<<>>}}

Deadlock between MakeRoomForWrite() and AwaitCloseAndDestructor()

eleveldb revision: 639f69c
leveldb revision: d553b6c4bf525c0301b3d2f128be0a63df930ee4

I see a deadlock that immobilizes the entire scheduler thread. The first suspicious stacktrace is:

Thread 17 (process 20406):
#0  0x0000000017a5f0fa in __psynch_cvwait ()
#1  0x00000000178f3fb9 in _pthread_cond_wait ()
#2  0x0000000023604bbb in eleveldb::ErlRefObject::AwaitCloseAndDestructor () at /Users/fritchie/b/src/eleveldb/c_src/refobjects.h:155
#3  0x0000000023604bbb in eleveldb::DbObject::DbObjectResourceCleanup (Env=<value temporarily unavailable, due to optimizations>, Arg=0x20a40090) at c_src/refobjects.cc:274
#4  0x000000001714e40c in nif_resource_dtor (bin=0x20a40068) at beam/erl_nif.c:1303
#5  0x000000001706de05 in erts_bin_free (bp=0x20a40068) at erl_binary.h:303
#6  0x000000001706dd2a in erts_cleanup_offheap (offheap=0x211cf110) at beam/erl_message.c:174
#7  0x0000000017081c3b in delete_process (p=0x211ceeb0) at beam/erl_process.c:8001
#8  0x0000000017080fc7 in erts_continue_exit_process (p=0x211ceeb0) at beam/erl_process.c:9034
#9  0x000000001708084d in erts_do_exit_process (p=0x211ceeb0, reason=17035) at beam/erl_process.c:8839
#10 0x00000000171ff749 in terminate_proc (c_p=0x211ceeb0, Value=17035) at beam/beam_emu.c:5281
#11 0x00000000171fc29b in handle_error (c_p=0x211ceeb0, pc=0x0, reg=0x208081c0, bf=0x0) at beam/beam_emu.c:5156
#12 0x00000000171f299d in process_main () at beam/beam_emu.c:3276
#13 0x00000000170764d5 in sched_thread_func (vesdp=0x21414600) at beam/erl_process.c:5801
#14 0x00000000172d29c4 in thr_wrapper (vtwd=0x7fff58c33dd8) at pthread/ethread.c:106
#15 0x00000000178ef772 in _pthread_start ()
#16 0x00000000178dc1a1 in thread_start ()

And the second:

Thread 73 (process 20406):
#0  0x0000000017a5f0fa in __psynch_cvwait ()
#1  0x00000000178f3fb9 in _pthread_cond_wait ()
#2  0x000000002363aa6f in leveldb::port::CondVar::Wait (this=0x7fa493200a30) at port_posix.h:48
#3  0x000000002360fed3 in leveldb::DBImpl::MakeRoomForWrite (this=0x7fa493200880, force=<value temporarily unavailable, due to optimizations>) at db/db_impl.cc:1836
#4  0x000000002360f7a8 in leveldb::DBImpl::Write (this=0x7fa493200880, options=@0x7fa493406140, my_batch=0x7fa493400d60) at db/db_impl.cc:1635
#5  0x00000000236044d9 in leveldb::Status::ok () at /Users/fritchie/b/src/eleveldb/c_src/leveldb/include/leveldb/status.h:159
#6  0x00000000236044d9 in eleveldb::WriteTask::operator() (this=0x7fa493404e10) at workitems.h:161
#7  0x0000000023606893 in eleveldb::eleveldb_thread_pool::notify_caller (work_item=@0x7fa493404e10) at c_src/threading.cc:309
#8  0x0000000023606838 in eleveldb::WorkTask::resubmit () at /Users/fritchie/b/src/eleveldb/c_src/workitems.h:373
#9  0x0000000023606838 in eleveldb::eleveldb_write_thread_worker (args=0x7fa4934028e0) at c_src/threading.cc:374
#10 0x00000000171355b5 in erl_drv_thread_wrapper (vdtid=0x20f845c0) at beam/erl_drv_thread.c:117
#11 0x00000000172d29c4 in thr_wrapper (vtwd=0xb08bb988) at pthread/ethread.c:106
#12 0x00000000178ef772 in _pthread_start ()
#13 0x00000000178dc1a1 in thread_start ()

Iterator corruption in leveldb::MemTableIterator::key

Same fault injection & test parameters & recreation steps as #101, with one small exception: Change the final Erlang shell command to be:

[ok = eunit:test(iterators, [verbose]) || _ <- lists:seq(1,99999)].

A failing test case looks like this:

======================== EUnit ========================
module 'iterators'
  iterators: prev_test_case...[0.001 s] ok
  iterators: seek_and_next_test_case...ok
  iterators: basic_prefetch_test_case...ok
  iterators: seek_and_prefetch_test_case...*failed*
in function iterators:'-seek_and_prefetch_test_case/1-fun-6-'/2 (test/iterators.erl, line 93)
in call from iterators:'-seek_and_prefetch_test_case/1-fun-14-'/1 (test/iterators.erl, line 93)
**error:{assertEqual_failed,[{module,iterators},
                     {line,93},
                     {expression,"eleveldb : iterator_move ( I , << \"a\" >> )"},
                     {expected,{ok,<<"a">>,<<"w">>}},
                     {value,{ok,<<"d">>,<<"z">>}}]}

... which, as far as I can tell, shows the iterator skipping over key <<"a">> as well as b & c and hopping directly to d.

Closing a leveldb

Hi,

I found no way of actually closing a reference to a leveldb. Is there any plan for supporting the close API from leveldb, or is there another way of achieving the same result?

`prop_put_delete_test` fails

➜  eleveldb git:(master) git rev-parse HEAD
f207142cf847663dade428539f3da0f5da1b53ee
➜  eleveldb git:(master) ./rebar eunit skip_deps=true suite=eleveldb
zsh: correct 'eunit' to '.eunit' [nyae]? n
==> eleveldb (eunit)
======================== EUnit ========================
module 'eleveldb'
  eleveldb: open_test...ok
  eleveldb: fold_test...ok
  eleveldb: fold_keys_test...ok
  eleveldb: fold_from_key_test...ok
  eleveldb: destroy_test...ok
  eleveldb: compression_test...ok
  eleveldb: close_test...ok
  eleveldb: close_fold_test...ok
  eleveldb: prop_put_delete_test_............................Failed! Reason:
{'EXIT',{badarg,[{eleveldb,iterator_close,[<<>>],[]},
                 {eleveldb,do_fold,4,[]},
                 {eleveldb,'-prop_put_delete/0-fun-6-',1,
                           [{file,"src/eleveldb.erl"},{line,464}]}]}}
After 26 tests.
[{delete,<<"\f">>,<<"C{4">>}]
Shrinking.(1 times)
Reason:
{'EXIT',{badarg,[{eleveldb,iterator_close,[<<>>],[]},
                 {eleveldb,do_fold,4,[]},
                 {eleveldb,'-prop_put_delete/0-fun-6-',1,
                           [{file,"src/eleveldb.erl"},{line,464}]}]}}
[{delete,<<"\f">>,<<"C{4">>}]
*failed*
::{assertion_failed,[{module,eleveldb},
                   {line,426},
                   {expression,"eqc : quickcheck ( ? QC_OUT ( P ) )"},
                   {expected,true},
                   {value,false}]}
  output:<<"Starting Quviq QuickCheck version 1.27.2
   (compiled at {{2012,9,6},{9,50,27}})
Licence for Basho reserved until {{2013,5,8},{15,1,29}}
">>

  [done in 2.579 s]
=======================================================
  Failed: 1.  Skipped: 0.  Passed: 8.

=INFO REPORT==== 8-May-2013::14:13:02 ===
    application: inets
    exited: stopped
    type: temporary
ERROR: One or more eunit tests failed.

enif_send: env==NULL on non-SMP VM

When loading eleveldb on a single core ubuntu 14.04 machine with erlang 17.1 it crashes with

enif_send: env==NULL on non-SMP VM
Aborted (core dumped)

Any ideas?

error building on macosx lion with snappy support

The error trace

4> {ok, Ref} = eleveldb:open("/tmp/eleveldb.open.test", [{create_if_missing, true}]).
** exception error: undefined function eleveldb:open/2

=ERROR REPORT==== 31-Aug-2011::10:58:54 ===
The on_load function for module eleveldb returned {error,
                                                   {load_failed,
                                                    "Failed to load NIF library: 'dlopen(ebin/../priv/eleveldb.so, 2): Symbol not found: __ZN6snappy11RawCompressEPKcmPcPm\n  Referenced from: /Users/benoitc/upondata/eleveldb/priv/eleveldb.so\n  Expected in: flat namespace\n in /Users/benoitc/upondata/eleveldb/priv/eleveldb.so'"}}
5> 

I have installed last snappy version with homebrew.

Fix build on OpenSUSE 64bit

In OpenSUSE 64 bit libsnappy is built into "c_src/system/lib64/" but the build proces later looks for it in "c_src/system/lib/". This breaks the build.

The problem propagates downstream to the downloadable Riak 1.4.0 and all previous releases, which is quite bad as no prebuilds of OpenSUSE 64bit are provided by basho or the OpenSUSE package maintainers, so the only way to install riak is currently hacking the installation scripts.

The problem can be fixed by either forcing libsnappy to be built into c_src/system/lib/ or by fixing the hardcoded references to "/system/lib/". "The latter is done by changing the hardcoded references to "/system/lib" from "c_src/build_deps.sh" and "rebar.config". Changing "lib" to "lib64" in these two files fixes the build.

Fault injection: get() incorrectly returns not_found

Fault injection parameters:

  • ftruncate(2): 7% chance (triggered once)
  • pread(2): 7% chance (triggered once)
  • other intercepted system calls: also 7% chance, but they are triggered 0 times in this test case.

Failing test case:

5> C1.
[{[{set,{var,1},
        {call,generic_qc_fsm,set_keys,
              [[<<9,217,162,128,149,197,176,236,10,163,247,68,141>>]]}},
   {set,{var,2},
        {call,generic_qc_fsm,open,
              ["/tmp/generic.qc",
               [read_write,
                {open_timeout,0},
                {max_file_size,100},
                {sync_strategy,none}]]}},
   {set,{var,15},
        {call,generic_qc_fsm,put,[{var,2},<<"k">>,<<>>]}},
   {set,{var,17},
        {call,generic_qc_fsm,put,
              [{var,2},
               <<9,217,162,128,149,197,176,236,10,163,247,68,141>>,
               <<>>]}},
   {set,{var,27},{call,generic_qc_fsm,close,[{var,2}]}},
   {set,{var,28},
        {call,generic_qc_fsm,open,
              ["/tmp/generic.qc",
               [read_write,
                {open_timeout,0},
                {max_file_size,100},
                {sync_strategy,none}]]}},
   {set,{var,29},{call,generic_qc_fsm,get,[{var,28},<<"k">>]}},
   {set,{var,30},
        {call,generic_qc_fsm,put,[{var,28},<<"k">>,<<>>]}},
   {set,{var,31},{call,generic_qc_fsm,close,[{var,28}]}},
   {set,{var,32},
        {call,generic_qc_fsm,open,
              ["/tmp/generic.qc",
               [read_write,
                {open_timeout,0},
                {max_file_size,100},
                {sync_strategy,none}]]}},
   {set,{var,33},
        {call,generic_qc_fsm,delete,[{var,32},<<"k">>]}},
   {set,{var,34},
        {call,generic_qc_fsm,get,
              [{var,32},<<9,217,162,128,149,197,...>>]}}],
  7354},
 [{verify_trace,[]}]]

The successful fault injection triggers are:

  1. An ftruncate(2) call returns -1, errno ENOSPC
  2. A pread(2) call returns -1, errno EIO

Test case trace of results:

Trace: [{set_keys,[<<9,217,162,128,149,197,176,236,10,163,247,68,141>>]},
        open,
        {put,yes,<<"k">>,<<>>},
        {put,yes,<<9,217,162,128,149,197,176,236,10,163,247,68,141>>,<<>>},
        close,open,
        {get,<<"k">>,<<>>},
        {put,yes,<<"k">>,<<>>},
        close,open,
        {delete,yes,<<"k">>},
        {get,<<9,217,162,128,149,197,176,236,10,163,247,68,141>>,not_found},
        close]
verify_trace: {get,expected,[<<>>],got,not_found}
verify_trace: failed

All of the DB mutations have status yes, meaning that the eleveldb API responded affirmatively to each call: i.e. there were no errors returned by the API.

This is probably not a truly minimal failing test case: the nature how the random number generator is used means that a certain number of commands needed to happen "in the middle" before a lucky 7% event happened at a crucial time. The two close & open cycles in the middle of the test case: they might be truly necessary, but they might not.

To reproduce, cut-and-paste to execute these commands. Tested with OS X. It ought to work with Linux, but honestly I haven't tested the faulterl library very much on Linux.

mkdir /tmp/e
cd /tmp/e
git clone [email protected]:basho/eleveldb.git
cd eleveldb
git checkout -f 391b885abb2005e4b3f4f96a16822c9b1f31601f
make ; rebar skip_deps=true eunit suites=NONE ; erlc -o deps/faulterl/ebin -I deps/faulterl/include priv/scenario/*erl ; deps/faulterl/ebin/make_intercept_c.escript trigger_commonpaths yo ; env `deps/faulterl/ebin/example_environment.sh $PWD/yo` erl -pz .eunit deps/*/ebin

You now have an Erlang shell running with a fault-injectable VM. Cut-and-paste to execute the following three commands.

C1 = [{[{set,{var,1},{call,generic_qc_fsm,set_keys,[[<<9,217,162,128,149,197,176,236,10,163,247,68,141>>]]}},{set,{var,2},{call,generic_qc_fsm,open,[[47,116,109,112,47,103,101,110,101,114,105,99,46,113,99],[read_write,{open_timeout,0},{max_file_size,100},{sync_strategy,none}]]}},{set,{var,15},{call,generic_qc_fsm,put,[{var,2},<<107>>,<<>>]}},{set,{var,17},{call,generic_qc_fsm,put,[{var,2},<<9,217,162,128,149,197,176,236,10,163,247,68,141>>,<<>>]}},{set,{var,27},{call,generic_qc_fsm,close,[{var,2}]}},{set,{var,28},{call,generic_qc_fsm,open,[[47,116,109,112,47,103,101,110,101,114,105,99,46,113,99],[read_write,{open_timeout,0},{max_file_size,100},{sync_strategy,none}]]}},{set,{var,29},{call,generic_qc_fsm,get,[{var,28},<<107>>]}},{set,{var,30},{call,generic_qc_fsm,put,[{var,28},<<107>>,<<>>]}},{set,{var,31},{call,generic_qc_fsm,close,[{var,28}]}},{set,{var,32},{call,generic_qc_fsm,open,[[47,116,109,112,47,103,101,110,101,114,105,99,46,113,99],[read_write,{open_timeout,0},{max_file_size,100},{sync_strategy,none}]]}},{set,{var,33},{call,generic_qc_fsm,delete,[{var,32},<<107>>]}},{set,{var,34},{call,generic_qc_fsm,get,[{var,32},<<9,217,162,128,149,197,176,236,10,163,247,68,141>>]}}],7354},[{verify_trace,[]}]].
eqc:check(eqc:testing_time(30, generic_qc_fsm:prop(false, false)), C1).
eqc:check(eqc:testing_time(30, generic_qc_fsm:prop(true, false)), C1).

SIGSEGV in leveldb::MemTableIterator::key

Fault injection parameters:

  • EIO on pread() 25% of the time
  • EIO on stat() 25% of the time

Based upon develop branch as of fc3f09e

Steps to reproduce on OS X:

git checkout 74b272f861b73d49044f2046ebebd0538a87af78
make
rebar skip_deps=true -v eunit suites=XX
make compile_scenarios
./deps/faulterl/ebin/make_intercept_c.escript trigger_commonpaths yo "perl -npi -e 's/bc_fi_enabled = 1/bc_fi_enabled = 0/'"
env `./deps/faulterl/ebin/example_environment.sh yo` erl -pz .eunit deps/*/ebin

Then run in the Erlang shell:

[begin Rand = random:uniform(1 bsl 27), faulterl_nif:poke("bc_fi_random_seed", 0, <<Rand:32>>, false), faulterl_nif:poke("bc_fi_random_reseed", 0, <<1:8>>, false), Rand end || true].
[eunit:test(iterators, [verbose]) || _ <- lists:seq(1,99999)].

It will likely take several hundred iterations to hit a SIGSEGV crash. If you don't get one, try the last Erlang command again.

GDB says:

(gdb) where
#0  leveldb::MemTableIterator::key (this=0x7fe673101340) at db/memtable.cc:61
#1  0x0000000021bd506e in leveldb::(anonymous namespace)::DBIter::key (this=<value temporarily unavailable, due to optimizations>) at db/db_iter.cc:67
#2  0x0000000021bc77f3 in eleveldb::MoveTask::operator() (this=0x7fe671c20fd0) at c_src/workitems.cc:298
#3  0x0000000021bc6873 in eleveldb::eleveldb_thread_pool::notify_caller (work_item=@0x7fe671c20fd0) at c_src/threading.cc:309
#4  0x0000000021bc6818 in eleveldb::WorkTask::resubmit () at /Users/fritchie/b/src/eleveldb/c_src/workitems.h:373
#5  0x0000000021bc6818 in eleveldb::eleveldb_write_thread_worker (args=0x7fe6732022b0) at c_src/threading.cc:374
#6  0x00000000160255b5 in erl_drv_thread_wrapper (vdtid=0x1ff03ed0) at beam/erl_drv_thread.c:117
#7  0x00000000161c29c4 in thr_wrapper (vtwd=0xb0eca988) at pthread/ethread.c:106
#8  0x00000000167e9772 in _pthread_start ()
#9  0x00000000167d61a1 in thread_start ()
(gdb) list
56        virtual void Seek(const Slice& k) { iter_.Seek(EncodeKey(&tmp_, k)); }
57        virtual void SeekToFirst() { iter_.SeekToFirst(); }
58        virtual void SeekToLast() { iter_.SeekToLast(); }
59        virtual void Next() { iter_.Next(); }
60        virtual void Prev() { iter_.Prev(); }
61        virtual Slice key() const { return GetLengthPrefixedSlice(iter_.key()); }
62        virtual Slice value() const {
63          Slice key_slice = GetLengthPrefixedSlice(iter_.key());
64          return GetLengthPrefixedSlice(key_slice.data() + key_slice.size());
65        }
(gdb) p iter_
$2 = {
  list_ = 0x7fe673100e68, 
  node_ = 0x0
}

memory access problem in iterator_db_close_test with Erlang 17.1

Under Erlang 17.1, the latest develop branch (commit 8f1d1f6) shows a memory access problem in the iterator_db_close_test. This doesn't show up for me with the current Riak 2.0 preferred version of Erlang, which is R16B02 with Basho's patches. Valgrind details are below.

cleanup: iterator_db_close_test...
==22983== Thread 123:
==22983== Invalid read of size 8
==22983==    at 0x482CDA: size_object (copy.c:93)
==22983==    by 0x57877D: enif_make_copy (erl_nif.c:380)
==22983==    by 0x17B879C7: eleveldb::MoveTask::local_env() (workitems.cc:323)
==22983==    by 0x17B88075: eleveldb::MoveTask::operator()() (workitems.cc:302)
==22983==    by 0x17B8676B: eleveldb::eleveldb_thread_pool::notify_caller(eleveldb::WorkTask&) (threading.cc:309)
==22983==    by 0x17B86860: eleveldb::eleveldb_write_thread_worker(void*) (threading.cc:373)
==22983==    by 0x563CD8: erl_drv_thread_wrapper (erl_drv_thread.c:115)
==22983==    by 0x67B840: thr_wrapper (ethread.c:106)
==22983==    by 0x5560E99: start_thread (pthread_create.c:308)
==22983==  Address 0x15eea9b0 is 32 bytes inside a block of size 1,656 free'd
==22983==    at 0x4C2A82E: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==22983==    by 0x5C90A3: erts_sys_free (sys.c:2637)
==22983==    by 0x4B7620: erts_free (erl_alloc.h:249)
==22983==    by 0x4B834D: free_message_buffer (erl_message.c:200)
==22983==    by 0x57855F: enif_clear_env (erl_nif.c:297)
==22983==    by 0x5784C4: enif_free_env (erl_nif.c:277)
==22983==    by 0x17B85E29: eleveldb::ItrObject::Shutdown() (refobjects.cc:575)
==22983==    by 0x17B85509: eleveldb::ErlRefObject::InitiateCloseRequest() (refobjects.cc:136)
==22983==    by 0x17B85643: eleveldb::DbObject::Shutdown() (refobjects.cc:373)
==22983==    by 0x17B85509: eleveldb::ErlRefObject::InitiateCloseRequest() (refobjects.cc:136)
==22983==    by 0x17B84C02: eleveldb::CloseTask::operator()() (workitems.h:377)
==22983==    by 0x17B8676B: eleveldb::eleveldb_thread_pool::notify_caller(eleveldb::WorkTask&) (threading.cc:309)

compression unit test fails with latest eleveldb

The latest version of leveldb+Bbasho mods has changed when compression happens so the test now fails. The intent of the eleveldb test is to check that the option gets passed down to leveldb correctly.

This basho/leveldb#17 pull request adds LOG entries, modify the compression_test in eleveldb:compression_test () to check the flag is set correctly in the two LOG files.

Asynchronous implementation of iterator_move () was slower.

After the implementation of the iterator_move() method using thread_pool reading values from ​​leveldb was about 10 times slower. In synchronous variant it was approximately 300,000 records per second, and in asynchronous - 30 000. Maybe you should add to the API method for get a list of records at once, not to pick one by one? This should solve the problem.

Check arity when inspecting erlang tuples

There are some places in the elveldb code that process tuples passed in from Erlang and access elements in that tuple before checking its arity. If bad Erlang code passed in 1 or zero length tuples, the code could crash. This is a blanket issue to clean up these places and make sure it's crash proofed.

Test uses deprecated erlang:now() function. [JIRA: RIAK-2075]

The erlang:now() function was deprecated in Erlang 18. The rebar.config sets warnings_as_errors which causes the tests to fail on compilation.

Looking for some direction as to the best way to fix this. An easy way out would be to ignore deprecation warnings for the file using the compile flag, but could result in missing other warnings in the future.

The failing testfile is test/rand_gen_1.erl

extractor.cc: warning on linux build [JIRA: RIAK-2300]

Compiling c_src/extractor.cc
c_src/extractor.cc: In member function ‘virtual void ExtractorMsgpack::extract(const char_, size_t, ExpressionNode_)’:
c_src/extractor.cc:541:22: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]

compatibility with Erlang 17

eleveldb is not compatible with erlang 17 right now

cuttlefish rebar.config needs to be updated to build with it but tests are still failing after the update. (iterator_db_close_test fails with a segmentation fault on ubuntu 14.04).

Fault injection: get() incorrectly returns not_found (part II)

NOTE: This was first reported about 5 days ago in issue #107

eleveldb commit: 35f681e of branch slf-faulterl-introduction3 (which is a rebased branch from slf-faulterl-introduction2), which is in turn based upon today's develop branch at 9ab8ed6
leveldb commit: f4cf10d2ba1b999f10805ac35f22145e80932544 of today's develop branch
faulterl commit: 88bd8c8b377f8cdae9683218f229706f4f79ea8e of today's master branch

To recreate, in two cut-and-paste steps. Tested on OS X 10.8.5 and Ubuntu 12.04.2 LTS (GNU/Linux 3.2.0-54-generic x86_64). First:

mkdir /tmp/e
cd /tmp/e
git clone [email protected]:basho/eleveldb.git
cd eleveldb
git checkout -f 35f681e6e936a7f036e661b24fc73e7fe6f3e18f
./rebar get-deps ; (cd deps/faulterl ; git checkout -f 88bd8c8b377f8cdae9683218f229706f4f79ea8e) ; make ; rm priv/*.so ; (cd c_src/leveldb ; git checkout -f f4cf10d2ba1b999f10805ac35f22145e80932544) ; make ; ./rebar skip_deps=true eunit suites=NONE ; erlc -o deps/faulterl/ebin -I deps/faulterl/include priv/scenario/*erl ; deps/faulterl/ebin/make_intercept_c.escript trigger_commonpaths yo ; env `deps/faulterl/ebin/example_environment.sh $PWD/yo` erl -pz .eunit deps/*/ebin

And second. This one fails for OS X (Ubu case part 2 is below):

C4 = [{[{set,{var,1},{call,generic_qc_fsm,set_keys,[[<<173,0,0,0,0>>],{var,parameter_test_dir}]}},{set,{var,2},{call,generic_qc_fsm,open,[{var,parameter_test_dir},[read_write,{paranoid_checks,true},{open_timeout,0},{max_file_size,100},{sync_strategy,none},{create_if_missing,true},{limited_developer_mem,true},{compression,false},{write_buffer_size,16000000}]]}},{set,{var,3},{call,generic_qc_fsm,put,[{var,2},<<173,0,0,0,0>>,<<>>]}},{set,{var,4},{call,generic_qc_fsm,put_filler,[{var,2},{2245,<<22>>},54214]}},{set,{var,6},{call,generic_qc_fsm,fold_all,[{var,2}]}},{set,{var,7},{call,generic_qc_fsm,close,[{var,2}]}},{set,{var,8},{call,generic_qc_fsm,open,[{var,parameter_test_dir},[read_write,{paranoid_checks,true},{open_timeout,0},{max_file_size,100},{sync_strategy,none},{create_if_missing,true},{limited_developer_mem,true},{compression,false},{write_buffer_size,16000000}]]}},{set,{var,9},{call,generic_qc_fsm,get,[{var,8},<<173,0,0,0,0>>]}},{set,{var,10},{call,generic_qc_fsm,fold_all,[{var,8}]}}],1023},[{verify_trace,[]}]].
eqc:check(eqc:testing_time(30, generic_qc_fsm:prop(false, false)), C4).
[true = eqc:check(eqc:testing_time(30, generic_qc_fsm:prop(true, false)), C4) || _ <- lists:seq(1,30)].

The Ubuntu 12 Linux part 2 is:

C4c = [{[{set,{var,1},{call,generic_qc_fsm,set_keys,[[<<173,0,0,0,0>>],{var,parameter_test_dir}]}},{set,{var,2},{call,generic_qc_fsm,open,[{var,parameter_test_dir},[read_write,{paranoid_checks,true},{open_timeout,0},{max_file_size,100},{sync_strategy,none},{create_if_missing,true},{limited_developer_mem,true},{compression,false},{write_buffer_size,16000000}]]}},{set,{var,3},{call,generic_qc_fsm,put,[{var,2},<<173,0,0,0,0>>,<<>>]}},{set,{var,4},{call,generic_qc_fsm,put_filler,[{var,2},{2245,<<22>>},54214]}},{set,{var,6},{call,generic_qc_fsm,fold_all,[{var,2}]}},{set,{var,7},{call,generic_qc_fsm,close,[{var,2}]}},{set,{var,8},{call,generic_qc_fsm,open,[{var,parameter_test_dir},[read_write,{paranoid_checks,true},{open_timeout,0},{max_file_size,100},{sync_strategy,none},{create_if_missing,true},{limited_developer_mem,true},{compression,false},{write_buffer_size,16000000}]]}},{set,{var,9},{call,generic_qc_fsm,get,[{var,8},<<173,0,0,0,0>>]}},{set,{var,10},{call,generic_qc_fsm,fold_all,[{var,8}]}}],9023},[{verify_trace,[]}]].
eqc:check(eqc:testing_time(30, generic_qc_fsm:prop(false, false)), C4c).
[true = eqc:check(eqc:testing_time(30, generic_qc_fsm:prop(true, false)), C4c) || _ <- lists:seq(1,30)].

Here's an easier-to-read-for-humans formatting of the test case and failing diagnostic output:

{[{set,{var,1},
       {call,generic_qc_fsm,set_keys,
             [[<<173,0,0,0,0>>],{var,parameter_test_dir}]}},
  {set,{var,2},
       {call,generic_qc_fsm,open,
             [{var,parameter_test_dir},
              [read_write,
               {paranoid_checks,true},
               {open_timeout,0},
               {max_file_size,100},
               {sync_strategy,none},
               {create_if_missing,true},
               {limited_developer_mem,true},
               {compression,false},
               {write_buffer_size,16000000}]]}},
  {set,{var,3},{call,generic_qc_fsm,put,[{var,2},<<173,0,0,0,0>>,<<>>]}},
  {set,{var,4},{call,generic_qc_fsm,put_filler,[{var,2},{2245,<<22>>},54214]}},
  {set,{var,6},{call,generic_qc_fsm,fold_all,[{var,2}]}},
  {set,{var,7},{call,generic_qc_fsm,close,[{var,2}]}},
  {set,{var,8},
       {call,generic_qc_fsm,open,
             [{var,parameter_test_dir},
              [read_write,
               {paranoid_checks,true},
               {open_timeout,0},
               {max_file_size,100},
               {sync_strategy,none},
               {create_if_missing,true},
               {limited_developer_mem,true},
               {compression,false},
               {write_buffer_size,16000000}]]}},
  {set,{var,9},{call,generic_qc_fsm,get,[{var,8},<<173,0,0,0,0>>]}},
  {set,{var,10},{call,generic_qc_fsm,fold_all,[{var,8}]}}],
 1023}
Trace: [{open,ok},
        {put,yes,<<173,0,0,0,0>>,<<>>},
        {get,fold,<<173,0,0,0,0>>,<<>>},
        {close,ok},
        {open,ok},
        {get,get,<<173,0,0,0,0>>,not_found},
        {close,ok}]
verify_trace: {get,get,<<173,0,0,0,0>>,expected,[<<>>],got,not_found}
final_close_ok: true
verify_trace: failed

Thread pool synchronizing problem? [JIRA: RIAK-1912]

in, submit(eleveldb_thread_pool::submit) :

 else if (!FindWaitingThread(item))
         {
             // no waiting threads, put on backlog queue
             lock();
             eleveldb::inc_and_fetch(&work_queue_atomic);
             work_queue.push_back(item);
             unlock();

             // to address race condition, thread might be waiting now
             FindWaitingThread(NULL);

             perf()->Inc(leveldb::ePerfElevelQueued);
             ret_flag=true;
         }   // if 

It first check if there's an waiting thread to submit directly(and pthread_cond_broadcast in FindWaitingThread), or it will add item to work_queue.

On the other hand, in eleveldb_write_thread_worker(threading.cc), when a working thread cannot find a work item, it will wait on its condition variable.

            pthread_mutex_lock(&tdata.m_Mutex);
            tdata.m_DirectWork=NULL; // safety

            // only wait if we are really sure no work pending
            if (0==h.work_queue_atomic)
        {
                // yes, thread going to wait. set available now.
            tdata.m_Available=1;
                pthread_cond_wait(&tdata.m_Condition, &tdata.m_Mutex);
        }    // if

            tdata.m_Available=0;    // safety
            submission=(eleveldb::WorkTask *)tdata.m_DirectWork; // NULL is valid
            tdata.m_DirectWork=NULL;// safety

            pthread_mutex_unlock(&tdata.m_Mutex);

after checking the working queue is empty(work_queue_atomic==0), it sets its available to 1.

The problem is, if an working thread has checked that the working queue is empty , and before it's setting available, submit maybe cannot find a waiting thread, add an item to queue. At this moment, the working thread starts waiting, then this working thread will wait forever.(The second FindWaitingThread(NULL) doesn't help, it also maybe executed in this period). In fact, if the working thread has setting its available, and before waiting on its condition, and submit set its direct_work, broadcast the condition variable, and the working thread wait, it will wait forever too.

Fix the following dialyzer errors

We aren't checking return values for these which implies we should just match on ok and fail fast.

dialyzer -Wno_return -Wunmatched_returns -Wrace_conditions \
        --plt /Users/ajs/.eleveldb_dialyzer_plt ebin | tee .dialyzer.raw-output
  Checking whether the PLT /Users/ajs/.eleveldb_dialyzer_plt is up-to-date... yes
  Proceeding with analysis...
eleveldb.erl:126: Expression produces a value of type {'error',_} | {'ok',eleveldb:db_ref()}, but this value is unmatched
eleveldb.erl:156: Expression produces a value of type 'ok' | {'error',_}, but this value is unmatched
eleveldb.erl:174: Expression produces a value of type {_,'ok',eleveldb:itr_ref()}, but this value is unmatched
eleveldb.erl:180: Expression produces a value of type {_,'ok',eleveldb:itr_ref()}, but this value is unmatched
 done in 0m1.24s
done (warnings were emitted)

Valgrind: invalid read by iterator during shutdown

After a multi-day run of fault injection testing without a single error, I shut down the Erlang VM using the q(). command to do it nicely. During the shutdown sequence, Valgrind issued these two complaints:

Eshell V5.10.3  (abort with ^G)
1> q().
ok
2> ==16859== Thread 46:
==16859== Invalid read of size 8
==16859==    at 0x134850BB: leveldb::InternalKeyComparator::Compare(leveldb::Slice const&, leveldb::Slice const&) const (dbformat.cc:67)
==16859==    by 0x13473E97: leveldb::(anonymous namespace)::MergingIterator::FindSmallest() (merger.cc:162)
==16859==    by 0x13474329: leveldb::(anonymous namespace)::MergingIterator::Next() (merger.cc:82)
==16859==    by 0x1345717A: leveldb::DBImpl::DoCompactionWork(leveldb::DBImpl::CompactionState*) (db_impl.cc:1438)
==16859==    by 0x1345773C: leveldb::DBImpl::BackgroundCompaction(leveldb::Compaction*) (db_impl.cc:1045)
==16859==    by 0x13458725: leveldb::DBImpl::BackgroundCall2(leveldb::Compaction*) (db_impl.cc:902)
==16859==    by 0x1345C820: leveldb::CompactionTask::operator()() (thread_tasks.h:124)
==16859==    by 0x134818DA: leveldb::HotThread::ThreadRoutine() (hot_threads.cc:102)
==16859==    by 0x5767E99: start_thread (pthread_create.c:308)
==16859==  Address 0x1085bdf0 is 0 bytes inside a block of size 8 free'd
==16859==    at 0x4C2A4BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==16859==    by 0x1347C045: leveldb::ComparatorShutdown() (comparator.cc:83)
==16859==    by 0x13480362: leveldb::Env::Shutdown() (env_posix.cc:1114)
==16859==    by 0x55E0C8: close_lib (erl_nif.c:1213)
==16859==    by 0x55FF0F: erts_unload_nif (erl_nif.c:1838)
==16859==    by 0x599A8D: purge_module_1 (beam_bif_load.c:971)
==16859==    by 0x577E80: process_main (beam_emu.c:2579)
==16859==    by 0x4B6244: sched_thread_func (erl_process.c:5801)
==16859==    by 0x612A14: thr_wrapper (ethread.c:106)
==16859==    by 0x5767E99: start_thread (pthread_create.c:308)
==16859==
pure virtual method called
terminate called without an active exception

The source history on this is:

commit 94178e0f119ca199032df1cdcbcf8e417cedfd47
Merge: 8d48564 c673b55
Author: sfritchie <[email protected]>
Date:   Thu Jun 26 12:27:39 2014 -0400

    Merge branch 'slf-faulterl-introduction3' into develop20140619

commit 8d48564225ff92d05b858b18837e0b1e44659a55
Author: Matthew V <[email protected]>
Date:   Mon Jun 23 15:02:39 2014 -0400

    change casting for atomic operations to match osx/smartOS needs
[....]

Error in compiling (current elevel2.0), Freebsd 9.2 [JIRA: RIAK-2046]

c++ -Wall -O3 -fPIC -I /usr/FROBILL/ROOT_NEW/APPLICATION/deps/eleveldb/c_src/system/include -I. -I./include -fno-builtin-memcmp -D_REENTRANT -DOS_FREEBSD -DLEVELDB_PLATFORM_POSIX -DSNAPPY -O2 -g -DNDEBUG -fPIC -c port/port_posix.cc -o port/port_posix.o
rm -f libleveldb.a
ar -rs libleveldb.a db/builder.o db/c.o db/db_impl.o db/db_iter.o db/dbformat.o db/filename.o db/log_reader.o db/log_writer.o db/memtable.o db/repair.o db/table_cache.o db/version_edit.o db/version_set.o db/write_batch.o table/block.o table/block_builder.o table/filter_block.o table/format.o table/iterator.o table/merger.o table/table.o table/table_builder.o table/two_level_iterator.o util/arena.o util/bloom.o util/bloom2.o util/cache.o util/cache2.o util/coding.o util/comparator.o util/crc32c.o util/db_list.o util/env.o util/env_posix.o util/filter_policy.o util/flexcache.o util/hash.o util/histogram.o util/hot_threads.o util/logging.o util/murmurhash.o util/options.o util/perf_count.o util/status.o util/throttle.o port/port_posix.o
ar: warning: creating libleveldb.a
gmake[1]: Leaving directory `/usr/FROBILL/ROOT_NEW/APPLICATION/deps/eleveldb/c_src/leveldb'
Compiled src/eleveldb_bump.erl
Compiled src/eleveldb.erl
Compiling /usr/FROBILL/ROOT_NEW/APPLICATION/deps/eleveldb/c_src/eleveldb.cc
/usr/FROBILL/ROOT_NEW/APPLICATION/deps/eleveldb/c_src/eleveldb.cc: In function 'ERL_NIF_TERM parse_init_option(ErlNifEnv_, ERL_NIF_TERM, EleveldbOptions&)':
/usr/FROBILL/ROOT_NEW/APPLICATION/deps/eleveldb/c_src/eleveldb.cc:244: error: invalid conversion from 'size_t_' to 'long unsigned int_'
/usr/FROBILL/ROOT_NEW/APPLICATION/deps/eleveldb/c_src/eleveldb.cc:244: error: initializing argument 3 of 'int enif_get_ulong(ErlNifEnv_, ERL_NIF_TERM, long unsigned int_)'
/usr/FROBILL/ROOT_NEW/APPLICATION/deps/eleveldb/c_src/eleveldb.cc: In function 'ERL_NIF_TERM parse_open_option(ErlNifEnv_, ERL_NIF_TERM, leveldb::Options&)':
/usr/FROBILL/ROOT_NEW/APPLICATION/deps/eleveldb/c_src/eleveldb.cc:332: error: invalid conversion from 'size_t_' to 'long unsigned int_'
/usr/FROBILL/ROOT_NEW/APPLICATION/deps/eleveldb/c_src/eleveldb.cc:332: error: initializing argument 3 of 'int enif_get_ulong(ErlNifEnv_, ERL_NIF_TERM, long unsigned int_)'
ERROR: compile failed while processing /usr/FROBILL/ROOT_NEW/APPLICATION/deps/eleveldb: rebar_abort
gmake: *** [deps] Error 1

detail.hpp atomic functions called with unsigend types [JIRA: RIAK-2237]

detail.hpp was added with the prototype range scan code. This collects together atomic add/inc/dec functions for different platforms. However, calls to atomic_add_32/64, which expect signed delta arguments, are prototyped with unsigned arguments.

This raises the issue of whether a) these functions could ever get called with unsigned values that could overflow the corresponding signed types, and b) whether the higher-level code that calls these functions can overflow their memory buffers, both of which should be checked

Iterator move prev unsupported?

As I noticed every type of iterator move works except prev. I got a bad argument exception anytime I call eleveldb:iterator_move(Iter, prev).
I saw in the source this message:

    // prefetch logic broke PREV and not fixing for Riak
    if(NULL==itr_ptr.get()
       || (enif_is_atom(env, action_or_target) && ATOM_PREV==action_or_target))
        return enif_make_badarg(env);

Is there any change that somewhere in the near future it is fixed?

Q: master branch [JIRA: RIAK-2397]

Hello,

This is mainly question then real issue. The master branch has not been update for 2 years. It looks to be broken with resent R18 release. What is the right branch for production level solutions?

Best Regards,
Dmitry

closing and reopening eleveldb may deadlock

When testing a patched mnesia using eleveldb as a backend, I noticed that some test cases could hang forever. I believe the problem is as follows:

  1. The test process creates a table (leveldb database instance) and does some reads and writes
  2. The database is closed and deleted (eleveldb:destroy/2 followed by rm -rf ... just to be sure)
  3. The same process reopens the database. In this particular case, the open() consistently hangs on an IO error.

The key is that the 'client' process reads from the database, i.e. using the Ref. If the Ref remains as garbage on the heap when mnesia is restarted (which triggers a lot of work, but not in the calling process), the Ref will not be freed, as the destructor isn't called until the GC clears out the last reference.

Calling erlang:garbage_collect() in the test process before restarting mnesia fixes the problem in this particular case (with luck, adding debug printouts can achieve the same thing by triggering the GC). But it's not safe to assume that the Ref will ever be completely freed by GC, as some processes may perform work and then idle forever without performing the final GC.

One idea is to let a worker thread call AwaitCloseAndDestructor() [1] right after InitiateCloseRequest() has been called, then have it remove the LevelDB env from the magic binary. I assume this would release the LevelDB lock entry?

[1] https://github.com/basho/eleveldb/blob/master/c_src/refobjects.cc#L137

Allow for offline builds

When packaging the source tarball for Riak, there needs to be a way to build from this tarball offline. Currently eleveldb fetches code from git in its build step which breaks source tarball building.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.