leveldb-ruby 0.7 → 0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. data/README +1 -1
  2. data/leveldb/Makefile +70 -29
  3. data/leveldb/build_detect_platform +74 -0
  4. data/leveldb/db/builder.cc +2 -4
  5. data/leveldb/db/builder.h +4 -6
  6. data/leveldb/db/c.cc +471 -0
  7. data/leveldb/db/corruption_test.cc +21 -16
  8. data/leveldb/db/db_bench.cc +400 -200
  9. data/leveldb/db/db_impl.cc +276 -131
  10. data/leveldb/db/db_impl.h +22 -10
  11. data/leveldb/db/db_iter.cc +2 -1
  12. data/leveldb/db/db_test.cc +391 -43
  13. data/leveldb/db/dbformat.cc +31 -0
  14. data/leveldb/db/dbformat.h +51 -1
  15. data/leveldb/db/filename.h +1 -1
  16. data/leveldb/db/log_format.h +1 -1
  17. data/leveldb/db/log_reader.cc +16 -11
  18. data/leveldb/db/memtable.cc +37 -0
  19. data/leveldb/db/memtable.h +6 -0
  20. data/leveldb/db/repair.cc +17 -14
  21. data/leveldb/db/skiplist_test.cc +2 -2
  22. data/leveldb/db/version_edit.cc +7 -9
  23. data/leveldb/db/version_edit.h +2 -1
  24. data/leveldb/db/version_set.cc +416 -104
  25. data/leveldb/db/version_set.h +78 -14
  26. data/leveldb/db/version_set_test.cc +179 -0
  27. data/leveldb/db/write_batch_internal.h +2 -0
  28. data/leveldb/include/leveldb/c.h +246 -0
  29. data/leveldb/include/leveldb/db.h +14 -2
  30. data/leveldb/include/leveldb/env.h +31 -10
  31. data/leveldb/include/leveldb/options.h +7 -18
  32. data/leveldb/include/leveldb/slice.h +2 -2
  33. data/leveldb/include/leveldb/status.h +1 -1
  34. data/leveldb/port/atomic_pointer.h +144 -0
  35. data/leveldb/port/port.h +0 -2
  36. data/leveldb/port/port_android.h +7 -1
  37. data/leveldb/port/port_example.h +11 -1
  38. data/leveldb/port/port_posix.h +56 -38
  39. data/leveldb/table/format.cc +12 -8
  40. data/leveldb/table/table_test.cc +16 -7
  41. data/leveldb/util/cache.cc +173 -100
  42. data/leveldb/util/cache_test.cc +28 -11
  43. data/leveldb/util/coding.h +4 -4
  44. data/leveldb/util/comparator.cc +1 -0
  45. data/leveldb/util/env.cc +10 -5
  46. data/leveldb/util/env_posix.cc +48 -87
  47. data/leveldb/util/histogram.cc +11 -0
  48. data/leveldb/util/histogram.h +1 -0
  49. data/leveldb/util/posix_logger.h +98 -0
  50. data/leveldb/util/testharness.cc +12 -0
  51. data/leveldb/util/testharness.h +10 -1
  52. data/lib/leveldb.rb +11 -3
  53. metadata +41 -22
data/README CHANGED
@@ -10,7 +10,7 @@ And then run this:
10
10
  require 'rubygems' # on ruby < 1.9
11
11
  require 'leveldb'
12
12
 
13
- db = LevelDB.new "/tmp/asdf"
13
+ db = LevelDB::DB.new "/tmp/asdf"
14
14
  db.put "it", "works"
15
15
  db.get "it"
16
16
 
data/leveldb/Makefile CHANGED
@@ -13,27 +13,36 @@ OPT = -O2 -DNDEBUG -fPIC # (A) Production use (optimized mode)
13
13
  # OPT = -O2 -g2 -DNDEBUG # (C) Profiling mode: opt, but w/debugging symbols
14
14
  #-----------------------------------------------
15
15
 
16
+ # detect what platform we're building on
17
+ $(shell sh ./build_detect_platform)
18
+ # this file is generated by build_detect_platform to set build flags
19
+ include build_config.mk
20
+
21
+ # If Snappy is installed, add compilation and linker flags
22
+ # (see http://code.google.com/p/snappy/)
23
+ ifeq ($(SNAPPY), 1)
24
+ SNAPPY_CFLAGS=-DSNAPPY
25
+ SNAPPY_LDFLAGS=-lsnappy
26
+ else
27
+ SNAPPY_CFLAGS=
28
+ SNAPPY_LDFLAGS=
29
+ endif
16
30
 
17
- UNAME := $(shell uname)
18
-
19
- ifeq ($(UNAME), Darwin)
20
- # To build for iOS, set PLATFORM=IOS.
21
- ifndef PLATFORM
22
- PLATFORM=OSX
23
- endif # PLATFORM
24
- PLATFORM_CFLAGS = -DLEVELDB_PLATFORM_OSX
25
- PORT_MODULE = port_osx.o
26
- else # UNAME
27
- PLATFORM_CFLAGS = -DLEVELDB_PLATFORM_POSIX -std=c++0x
28
- PORT_MODULE = port_posix.o
29
- endif # UNAME
31
+ # If Google Perf Tools are installed, add compilation and linker flags
32
+ # (see http://code.google.com/p/google-perftools/)
33
+ ifeq ($(GOOGLE_PERFTOOLS), 1)
34
+ GOOGLE_PERFTOOLS_LDFLAGS=-ltcmalloc
35
+ else
36
+ GOOGLE_PERFTOOLS_LDFLAGS=
37
+ endif
30
38
 
31
- CFLAGS = -c -I. -I./include $(PLATFORM_CFLAGS) $(OPT) -DUSE_SNAPPY=1
39
+ CFLAGS = -c -I. -I./include $(PORT_CFLAGS) $(PLATFORM_CFLAGS) $(OPT) $(SNAPPY_CFLAGS)
32
40
 
33
- LDFLAGS=-lpthread
41
+ LDFLAGS=$(PLATFORM_LDFLAGS) $(SNAPPY_LDFLAGS) $(GOOGLE_PERFTOOLS_LDFLAGS)
34
42
 
35
43
  LIBOBJECTS = \
36
44
  ./db/builder.o \
45
+ ./db/c.o \
37
46
  ./db/db_impl.o \
38
47
  ./db/db_iter.o \
39
48
  ./db/filename.o \
@@ -46,7 +55,7 @@ LIBOBJECTS = \
46
55
  ./db/version_edit.o \
47
56
  ./db/version_set.o \
48
57
  ./db/write_batch.o \
49
- ./port/$(PORT_MODULE) \
58
+ ./port/port_posix.o \
50
59
  ./table/block.o \
51
60
  ./table/block_builder.o \
52
61
  ./table/format.o \
@@ -73,6 +82,7 @@ TESTHARNESS = ./util/testharness.o $(TESTUTIL)
73
82
 
74
83
  TESTS = \
75
84
  arena_test \
85
+ c_test \
76
86
  cache_test \
77
87
  coding_test \
78
88
  corruption_test \
@@ -82,28 +92,28 @@ TESTS = \
82
92
  env_test \
83
93
  filename_test \
84
94
  log_test \
95
+ memenv_test \
85
96
  skiplist_test \
86
97
  table_test \
87
98
  version_edit_test \
99
+ version_set_test \
88
100
  write_batch_test
89
101
 
90
102
  PROGRAMS = db_bench $(TESTS)
103
+ BENCHMARKS = db_bench_sqlite3 db_bench_tree_db
91
104
 
92
105
  LIBRARY = libleveldb.a
106
+ MEMENVLIBRARY = libmemenv.a
93
107
 
94
- ifeq ($(PLATFORM), IOS)
95
- # Only XCode can build executable applications for iOS.
96
108
  all: $(LIBRARY)
97
- else
98
- all: $(PROGRAMS) $(LIBRARY)
99
- endif
100
109
 
101
- check: $(TESTS)
110
+ check: $(PROGRAMS) $(TESTS)
102
111
  for t in $(TESTS); do echo "***** Running $$t"; ./$$t || exit 1; done
103
112
 
104
113
  clean:
105
- -rm -f $(PROGRAMS) $(LIBRARY) */*.o ios-x86/*/*.o ios-arm/*/*.o
106
- -rmdir -p ios-x86/* ios-arm/*
114
+ -rm -f $(PROGRAMS) $(BENCHMARKS) $(LIBRARY) $(MEMENVLIBRARY) */*.o */*/*.o ios-x86/*/*.o ios-arm/*/*.o
115
+ -rm -rf ios-x86/* ios-arm/*
116
+ -rm build_config.mk
107
117
 
108
118
  $(LIBRARY): $(LIBOBJECTS)
109
119
  rm -f $@
@@ -112,9 +122,18 @@ $(LIBRARY): $(LIBOBJECTS)
112
122
  db_bench: db/db_bench.o $(LIBOBJECTS) $(TESTUTIL)
113
123
  $(CC) $(LDFLAGS) db/db_bench.o $(LIBOBJECTS) $(TESTUTIL) -o $@
114
124
 
125
+ db_bench_sqlite3: doc/bench/db_bench_sqlite3.o $(LIBOBJECTS) $(TESTUTIL)
126
+ $(CC) $(LDFLAGS) -lsqlite3 doc/bench/db_bench_sqlite3.o $(LIBOBJECTS) $(TESTUTIL) -o $@
127
+
128
+ db_bench_tree_db: doc/bench/db_bench_tree_db.o $(LIBOBJECTS) $(TESTUTIL)
129
+ $(CC) $(LDFLAGS) -lkyotocabinet doc/bench/db_bench_tree_db.o $(LIBOBJECTS) $(TESTUTIL) -o $@
130
+
115
131
  arena_test: util/arena_test.o $(LIBOBJECTS) $(TESTHARNESS)
116
132
  $(CC) $(LDFLAGS) util/arena_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@
117
133
 
134
+ c_test: db/c_test.o $(LIBOBJECTS) $(TESTHARNESS)
135
+ $(CC) $(LDFLAGS) db/c_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@
136
+
118
137
  cache_test: util/cache_test.o $(LIBOBJECTS) $(TESTHARNESS)
119
138
  $(CC) $(LDFLAGS) util/cache_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@
120
139
 
@@ -151,22 +170,44 @@ skiplist_test: db/skiplist_test.o $(LIBOBJECTS) $(TESTHARNESS)
151
170
  version_edit_test: db/version_edit_test.o $(LIBOBJECTS) $(TESTHARNESS)
152
171
  $(CC) $(LDFLAGS) db/version_edit_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@
153
172
 
173
+ version_set_test: db/version_set_test.o $(LIBOBJECTS) $(TESTHARNESS)
174
+ $(CC) $(LDFLAGS) db/version_set_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@
175
+
154
176
  write_batch_test: db/write_batch_test.o $(LIBOBJECTS) $(TESTHARNESS)
155
177
  $(CC) $(LDFLAGS) db/write_batch_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@
156
178
 
179
+ $(MEMENVLIBRARY) : helpers/memenv/memenv.o
180
+ rm -f $@
181
+ $(AR) -rs $@ helpers/memenv/memenv.o
182
+
183
+ memenv_test : helpers/memenv/memenv_test.o $(MEMENVLIBRARY) $(LIBRARY) $(TESTHARNESS)
184
+ $(CC) $(LDFLAGS) helpers/memenv/memenv_test.o $(MEMENVLIBRARY) $(LIBRARY) $(TESTHARNESS) -o $@
185
+
157
186
  ifeq ($(PLATFORM), IOS)
158
187
  # For iOS, create universal object files to be used on both the simulator and
159
188
  # a device.
189
+ SIMULATORROOT=/Developer/Platforms/iPhoneSimulator.platform/Developer
190
+ DEVICEROOT=/Developer/Platforms/iPhoneOS.platform/Developer
191
+ IOSVERSION=$(shell defaults read /Developer/Platforms/iPhoneOS.platform/version CFBundleShortVersionString)
192
+
160
193
  .cc.o:
161
194
  mkdir -p ios-x86/$(dir $@)
162
- $(CC) $(CFLAGS) -isysroot /Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator4.3.sdk -arch i686 $< -o ios-x86/$@
195
+ $(SIMULATORROOT)/usr/bin/$(CC) $(CFLAGS) -isysroot $(SIMULATORROOT)/SDKs/iPhoneSimulator$(IOSVERSION).sdk -arch i686 $< -o ios-x86/$@
196
+ mkdir -p ios-arm/$(dir $@)
197
+ $(DEVICEROOT)/usr/bin/$(CC) $(CFLAGS) -isysroot $(DEVICEROOT)/SDKs/iPhoneOS$(IOSVERSION).sdk -arch armv6 -arch armv7 $< -o ios-arm/$@
198
+ lipo ios-x86/$@ ios-arm/$@ -create -output $@
199
+
200
+ .c.o:
201
+ mkdir -p ios-x86/$(dir $@)
202
+ $(SIMULATORROOT)/usr/bin/$(CC) $(CFLAGS) -isysroot $(SIMULATORROOT)/SDKs/iPhoneSimulator$(IOSVERSION).sdk -arch i686 $< -o ios-x86/$@
163
203
  mkdir -p ios-arm/$(dir $@)
164
- $(CC) $(CFLAGS) -isysroot /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS4.3.sdk -arch armv6 -arch armv7 $< -o ios-arm/$@
204
+ $(DEVICEROOT)/usr/bin/$(CC) $(CFLAGS) -isysroot $(DEVICEROOT)/SDKs/iPhoneOS$(IOSVERSION).sdk -arch armv6 -arch armv7 $< -o ios-arm/$@
165
205
  lipo ios-x86/$@ ios-arm/$@ -create -output $@
206
+
166
207
  else
167
208
  .cc.o:
168
209
  $(CC) $(CFLAGS) $< -o $@
169
- endif
170
210
 
171
- # TODO(gabor): dependencies for .o files
172
- # TODO(gabor): Build library
211
+ .c.o:
212
+ $(CC) $(CFLAGS) $< -o $@
213
+ endif
@@ -0,0 +1,74 @@
1
+ #!/bin/sh
2
+
3
+ # Detects OS we're compiling on and generates build_config.mk,
4
+ # which in turn gets read while processing Makefile.
5
+
6
+ # build_config.mk will set the following variables:
7
+ # - PORT_CFLAGS will either set:
8
+ # -DLEVELDB_PLATFORM_POSIX if cstatomic is present
9
+ # -DLEVELDB_PLATFORM_NOATOMIC if it is not
10
+ # - PLATFORM_CFLAGS with compiler flags for the platform
11
+ # - PLATFORM_LDFLAGS with linker flags for the platform
12
+
13
+ # Delete existing build_config.mk
14
+ rm -f build_config.mk
15
+
16
+ # Detect OS
17
+ case `uname -s` in
18
+ Darwin)
19
+ PLATFORM=OS_MACOSX
20
+ echo "PLATFORM_CFLAGS=-DOS_MACOSX" >> build_config.mk
21
+ echo "PLATFORM_LDFLAGS=" >> build_config.mk
22
+ ;;
23
+ Linux)
24
+ PLATFORM=OS_LINUX
25
+ echo "PLATFORM_CFLAGS=-pthread -DOS_LINUX" >> build_config.mk
26
+ echo "PLATFORM_LDFLAGS=-lpthread" >> build_config.mk
27
+ ;;
28
+ SunOS)
29
+ PLATFORM=OS_SOLARIS
30
+ echo "PLATFORM_CFLAGS=-D_REENTRANT -DOS_SOLARIS" >> build_config.mk
31
+ echo "PLATFORM_LDFLAGS=-lpthread -lrt" >> build_config.mk
32
+ ;;
33
+ FreeBSD)
34
+ PLATFORM=OS_FREEBSD
35
+ echo "PLATFORM_CFLAGS=-D_REENTRANT -DOS_FREEBSD" >> build_config.mk
36
+ echo "PLATFORM_LDFLAGS=-lpthread" >> build_config.mk
37
+ ;;
38
+ *)
39
+ echo "Unknown platform!"
40
+ exit 1
41
+ esac
42
+
43
+ echo "PLATFORM=$PLATFORM" >> build_config.mk
44
+
45
+ # On GCC, use libc's memcmp, not GCC's memcmp
46
+ PORT_CFLAGS="-fno-builtin-memcmp"
47
+
48
+ # Detect C++0x -- this determines whether we'll use port_noatomic.h
49
+ # or port_posix.h by:
50
+ # 1. Rrying to compile with -std=c++0x and including <cstdatomic>.
51
+ # 2. If g++ returns error code, we know to use port_posix.h
52
+ g++ $CFLAGS -std=c++0x -x c++ - -o /dev/null 2>/dev/null <<EOF
53
+ #include <cstdatomic>
54
+ int main() {}
55
+ EOF
56
+ if [ "$?" = 0 ]; then
57
+ PORT_CFLAGS="$PORT_CFLAGS -DLEVELDB_PLATFORM_POSIX -DLEVELDB_CSTDATOMIC_PRESENT -std=c++0x"
58
+ else
59
+ PORT_CFLAGS="$PORT_CFLAGS -DLEVELDB_PLATFORM_POSIX"
60
+ fi
61
+
62
+ # Test whether Snappy library is installed
63
+ # http://code.google.com/p/snappy/
64
+ g++ $CFLAGS -x c++ - -o /dev/null 2>/dev/null <<EOF
65
+ #include <snappy.h>
66
+ int main() {}
67
+ EOF
68
+ if [ "$?" = 0 ]; then
69
+ echo "SNAPPY=1" >> build_config.mk
70
+ else
71
+ echo "SNAPPY=0" >> build_config.mk
72
+ fi
73
+
74
+ echo "PORT_CFLAGS=$PORT_CFLAGS" >> build_config.mk
@@ -19,8 +19,7 @@ Status BuildTable(const std::string& dbname,
19
19
  const Options& options,
20
20
  TableCache* table_cache,
21
21
  Iterator* iter,
22
- FileMetaData* meta,
23
- VersionEdit* edit) {
22
+ FileMetaData* meta) {
24
23
  Status s;
25
24
  meta->file_size = 0;
26
25
  iter->SeekToFirst();
@@ -79,8 +78,7 @@ Status BuildTable(const std::string& dbname,
79
78
  }
80
79
 
81
80
  if (s.ok() && meta->file_size > 0) {
82
- edit->AddFile(0, meta->number, meta->file_size,
83
- meta->smallest, meta->largest);
81
+ // Keep it
84
82
  } else {
85
83
  env->DeleteFile(fname);
86
84
  }
data/leveldb/db/builder.h CHANGED
@@ -19,17 +19,15 @@ class VersionEdit;
19
19
 
20
20
  // Build a Table file from the contents of *iter. The generated file
21
21
  // will be named according to meta->number. On success, the rest of
22
- // *meta will be filled with metadata about the generated table, and
23
- // the file information will be added to *edit. If no data is present
24
- // in *iter, meta->file_size will be set to zero, and no Table file
25
- // will be produced.
22
+ // *meta will be filled with metadata about the generated table.
23
+ // If no data is present in *iter, meta->file_size will be set to
24
+ // zero, and no Table file will be produced.
26
25
  extern Status BuildTable(const std::string& dbname,
27
26
  Env* env,
28
27
  const Options& options,
29
28
  TableCache* table_cache,
30
29
  Iterator* iter,
31
- FileMetaData* meta,
32
- VersionEdit* edit);
30
+ FileMetaData* meta);
33
31
 
34
32
  }
35
33
 
data/leveldb/db/c.cc ADDED
@@ -0,0 +1,471 @@
1
+ // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
2
+ // Use of this source code is governed by a BSD-style license that can be
3
+ // found in the LICENSE file. See the AUTHORS file for names of contributors.
4
+
5
+ #include "leveldb/c.h"
6
+
7
+ #include <stdlib.h>
8
+ #include <unistd.h>
9
+ #include "leveldb/cache.h"
10
+ #include "leveldb/comparator.h"
11
+ #include "leveldb/db.h"
12
+ #include "leveldb/env.h"
13
+ #include "leveldb/iterator.h"
14
+ #include "leveldb/options.h"
15
+ #include "leveldb/status.h"
16
+ #include "leveldb/write_batch.h"
17
+
18
+ using leveldb::Cache;
19
+ using leveldb::Comparator;
20
+ using leveldb::CompressionType;
21
+ using leveldb::DB;
22
+ using leveldb::Env;
23
+ using leveldb::FileLock;
24
+ using leveldb::Iterator;
25
+ using leveldb::Logger;
26
+ using leveldb::NewLRUCache;
27
+ using leveldb::Options;
28
+ using leveldb::RandomAccessFile;
29
+ using leveldb::Range;
30
+ using leveldb::ReadOptions;
31
+ using leveldb::SequentialFile;
32
+ using leveldb::Slice;
33
+ using leveldb::Snapshot;
34
+ using leveldb::Status;
35
+ using leveldb::WritableFile;
36
+ using leveldb::WriteBatch;
37
+ using leveldb::WriteOptions;
38
+
39
+ extern "C" {
40
+
41
+ struct leveldb_t { DB* rep; };
42
+ struct leveldb_iterator_t { Iterator* rep; };
43
+ struct leveldb_writebatch_t { WriteBatch rep; };
44
+ struct leveldb_snapshot_t { const Snapshot* rep; };
45
+ struct leveldb_readoptions_t { ReadOptions rep; };
46
+ struct leveldb_writeoptions_t { WriteOptions rep; };
47
+ struct leveldb_options_t { Options rep; };
48
+ struct leveldb_cache_t { Cache* rep; };
49
+ struct leveldb_seqfile_t { SequentialFile* rep; };
50
+ struct leveldb_randomfile_t { RandomAccessFile* rep; };
51
+ struct leveldb_writablefile_t { WritableFile* rep; };
52
+ struct leveldb_logger_t { Logger* rep; };
53
+ struct leveldb_filelock_t { FileLock* rep; };
54
+
55
+ struct leveldb_comparator_t : public Comparator {
56
+ void* state_;
57
+ void (*destructor_)(void*);
58
+ int (*compare_)(
59
+ void*,
60
+ const char* a, size_t alen,
61
+ const char* b, size_t blen);
62
+ const char* (*name_)(void*);
63
+
64
+ virtual ~leveldb_comparator_t() {
65
+ (*destructor_)(state_);
66
+ }
67
+
68
+ virtual int Compare(const Slice& a, const Slice& b) const {
69
+ return (*compare_)(state_, a.data(), a.size(), b.data(), b.size());
70
+ }
71
+
72
+ virtual const char* Name() const {
73
+ return (*name_)(state_);
74
+ }
75
+
76
+ // No-ops since the C binding does not support key shortening methods.
77
+ virtual void FindShortestSeparator(std::string*, const Slice&) const { }
78
+ virtual void FindShortSuccessor(std::string* key) const { }
79
+ };
80
+
81
+ struct leveldb_env_t {
82
+ Env* rep;
83
+ bool is_default;
84
+ };
85
+
86
+ static bool SaveError(char** errptr, const Status& s) {
87
+ assert(errptr != NULL);
88
+ if (s.ok()) {
89
+ return false;
90
+ } else if (*errptr == NULL) {
91
+ *errptr = strdup(s.ToString().c_str());
92
+ } else {
93
+ // TODO(sanjay): Merge with existing error?
94
+ free(*errptr);
95
+ *errptr = strdup(s.ToString().c_str());
96
+ }
97
+ return true;
98
+ }
99
+
100
+ static char* CopyString(const std::string& str) {
101
+ char* result = reinterpret_cast<char*>(malloc(sizeof(char) * str.size()));
102
+ memcpy(result, str.data(), sizeof(char) * str.size());
103
+ return result;
104
+ }
105
+
106
+ leveldb_t* leveldb_open(
107
+ const leveldb_options_t* options,
108
+ const char* name,
109
+ char** errptr) {
110
+ DB* db;
111
+ if (SaveError(errptr, DB::Open(options->rep, std::string(name), &db))) {
112
+ return NULL;
113
+ }
114
+ leveldb_t* result = new leveldb_t;
115
+ result->rep = db;
116
+ return result;
117
+ }
118
+
119
+ void leveldb_close(leveldb_t* db) {
120
+ delete db->rep;
121
+ delete db;
122
+ }
123
+
124
+ void leveldb_put(
125
+ leveldb_t* db,
126
+ const leveldb_writeoptions_t* options,
127
+ const char* key, size_t keylen,
128
+ const char* val, size_t vallen,
129
+ char** errptr) {
130
+ SaveError(errptr,
131
+ db->rep->Put(options->rep, Slice(key, keylen), Slice(val, vallen)));
132
+ }
133
+
134
+ void leveldb_delete(
135
+ leveldb_t* db,
136
+ const leveldb_writeoptions_t* options,
137
+ const char* key, size_t keylen,
138
+ char** errptr) {
139
+ SaveError(errptr, db->rep->Delete(options->rep, Slice(key, keylen)));
140
+ }
141
+
142
+
143
+ void leveldb_write(
144
+ leveldb_t* db,
145
+ const leveldb_writeoptions_t* options,
146
+ leveldb_writebatch_t* batch,
147
+ char** errptr) {
148
+ SaveError(errptr, db->rep->Write(options->rep, &batch->rep));
149
+ }
150
+
151
+ char* leveldb_get(
152
+ leveldb_t* db,
153
+ const leveldb_readoptions_t* options,
154
+ const char* key, size_t keylen,
155
+ size_t* vallen,
156
+ char** errptr) {
157
+ char* result = NULL;
158
+ std::string tmp;
159
+ Status s = db->rep->Get(options->rep, Slice(key, keylen), &tmp);
160
+ if (s.ok()) {
161
+ *vallen = tmp.size();
162
+ result = CopyString(tmp);
163
+ } else {
164
+ *vallen = 0;
165
+ if (!s.IsNotFound()) {
166
+ SaveError(errptr, s);
167
+ }
168
+ }
169
+ return result;
170
+ }
171
+
172
+ leveldb_iterator_t* leveldb_create_iterator(
173
+ leveldb_t* db,
174
+ const leveldb_readoptions_t* options) {
175
+ leveldb_iterator_t* result = new leveldb_iterator_t;
176
+ result->rep = db->rep->NewIterator(options->rep);
177
+ return result;
178
+ }
179
+
180
+ const leveldb_snapshot_t* leveldb_create_snapshot(
181
+ leveldb_t* db) {
182
+ leveldb_snapshot_t* result = new leveldb_snapshot_t;
183
+ result->rep = db->rep->GetSnapshot();
184
+ return result;
185
+ }
186
+
187
+ void leveldb_release_snapshot(
188
+ leveldb_t* db,
189
+ const leveldb_snapshot_t* snapshot) {
190
+ db->rep->ReleaseSnapshot(snapshot->rep);
191
+ delete snapshot;
192
+ }
193
+
194
+ char* leveldb_property_value(
195
+ leveldb_t* db,
196
+ const char* propname) {
197
+ std::string tmp;
198
+ if (db->rep->GetProperty(Slice(propname), &tmp)) {
199
+ // We use strdup() since we expect human readable output.
200
+ return strdup(tmp.c_str());
201
+ } else {
202
+ return NULL;
203
+ }
204
+ }
205
+
206
+ void leveldb_approximate_sizes(
207
+ leveldb_t* db,
208
+ int num_ranges,
209
+ const char* const* range_start_key, const size_t* range_start_key_len,
210
+ const char* const* range_limit_key, const size_t* range_limit_key_len,
211
+ uint64_t* sizes) {
212
+ Range* ranges = new Range[num_ranges];
213
+ for (int i = 0; i < num_ranges; i++) {
214
+ ranges[i].start = Slice(range_start_key[i], range_start_key_len[i]);
215
+ ranges[i].limit = Slice(range_limit_key[i], range_limit_key_len[i]);
216
+ }
217
+ db->rep->GetApproximateSizes(ranges, num_ranges, sizes);
218
+ delete[] ranges;
219
+ }
220
+
221
+ void leveldb_destroy_db(
222
+ const leveldb_options_t* options,
223
+ const char* name,
224
+ char** errptr) {
225
+ SaveError(errptr, DestroyDB(name, options->rep));
226
+ }
227
+
228
+ void leveldb_repair_db(
229
+ const leveldb_options_t* options,
230
+ const char* name,
231
+ char** errptr) {
232
+ SaveError(errptr, RepairDB(name, options->rep));
233
+ }
234
+
235
+ void leveldb_iter_destroy(leveldb_iterator_t* iter) {
236
+ delete iter->rep;
237
+ delete iter;
238
+ }
239
+
240
+ unsigned char leveldb_iter_valid(const leveldb_iterator_t* iter) {
241
+ return iter->rep->Valid();
242
+ }
243
+
244
+ void leveldb_iter_seek_to_first(leveldb_iterator_t* iter) {
245
+ iter->rep->SeekToFirst();
246
+ }
247
+
248
+ void leveldb_iter_seek_to_last(leveldb_iterator_t* iter) {
249
+ iter->rep->SeekToLast();
250
+ }
251
+
252
+ void leveldb_iter_seek(leveldb_iterator_t* iter, const char* k, size_t klen) {
253
+ iter->rep->Seek(Slice(k, klen));
254
+ }
255
+
256
+ void leveldb_iter_next(leveldb_iterator_t* iter) {
257
+ iter->rep->Next();
258
+ }
259
+
260
+ void leveldb_iter_prev(leveldb_iterator_t* iter) {
261
+ iter->rep->Prev();
262
+ }
263
+
264
+ const char* leveldb_iter_key(const leveldb_iterator_t* iter, size_t* klen) {
265
+ Slice s = iter->rep->key();
266
+ *klen = s.size();
267
+ return s.data();
268
+ }
269
+
270
+ const char* leveldb_iter_value(const leveldb_iterator_t* iter, size_t* vlen) {
271
+ Slice s = iter->rep->value();
272
+ *vlen = s.size();
273
+ return s.data();
274
+ }
275
+
276
+ void leveldb_iter_get_error(const leveldb_iterator_t* iter, char** errptr) {
277
+ SaveError(errptr, iter->rep->status());
278
+ }
279
+
280
+ leveldb_writebatch_t* leveldb_writebatch_create() {
281
+ return new leveldb_writebatch_t;
282
+ }
283
+
284
+ void leveldb_writebatch_destroy(leveldb_writebatch_t* b) {
285
+ delete b;
286
+ }
287
+
288
+ void leveldb_writebatch_clear(leveldb_writebatch_t* b) {
289
+ b->rep.Clear();
290
+ }
291
+
292
+ void leveldb_writebatch_put(
293
+ leveldb_writebatch_t* b,
294
+ const char* key, size_t klen,
295
+ const char* val, size_t vlen) {
296
+ b->rep.Put(Slice(key, klen), Slice(val, vlen));
297
+ }
298
+
299
+ void leveldb_writebatch_delete(
300
+ leveldb_writebatch_t* b,
301
+ const char* key, size_t klen) {
302
+ b->rep.Delete(Slice(key, klen));
303
+ }
304
+
305
+ void leveldb_writebatch_iterate(
306
+ leveldb_writebatch_t* b,
307
+ void* state,
308
+ void (*put)(void*, const char* k, size_t klen, const char* v, size_t vlen),
309
+ void (*deleted)(void*, const char* k, size_t klen)) {
310
+ class H : public WriteBatch::Handler {
311
+ public:
312
+ void* state_;
313
+ void (*put_)(void*, const char* k, size_t klen, const char* v, size_t vlen);
314
+ void (*deleted_)(void*, const char* k, size_t klen);
315
+ virtual void Put(const Slice& key, const Slice& value) {
316
+ (*put_)(state_, key.data(), key.size(), value.data(), value.size());
317
+ }
318
+ virtual void Delete(const Slice& key) {
319
+ (*deleted_)(state_, key.data(), key.size());
320
+ }
321
+ };
322
+ H handler;
323
+ handler.state_ = state;
324
+ handler.put_ = put;
325
+ handler.deleted_ = deleted;
326
+ b->rep.Iterate(&handler);
327
+ }
328
+
329
+ leveldb_options_t* leveldb_options_create() {
330
+ return new leveldb_options_t;
331
+ }
332
+
333
+ void leveldb_options_destroy(leveldb_options_t* options) {
334
+ delete options;
335
+ }
336
+
337
+ void leveldb_options_set_comparator(
338
+ leveldb_options_t* opt,
339
+ leveldb_comparator_t* cmp) {
340
+ opt->rep.comparator = cmp;
341
+ }
342
+
343
+ void leveldb_options_set_create_if_missing(
344
+ leveldb_options_t* opt, unsigned char v) {
345
+ opt->rep.create_if_missing = v;
346
+ }
347
+
348
+ void leveldb_options_set_error_if_exists(
349
+ leveldb_options_t* opt, unsigned char v) {
350
+ opt->rep.error_if_exists = v;
351
+ }
352
+
353
+ void leveldb_options_set_paranoid_checks(
354
+ leveldb_options_t* opt, unsigned char v) {
355
+ opt->rep.paranoid_checks = v;
356
+ }
357
+
358
+ void leveldb_options_set_env(leveldb_options_t* opt, leveldb_env_t* env) {
359
+ opt->rep.env = (env ? env->rep : NULL);
360
+ }
361
+
362
+ void leveldb_options_set_info_log(leveldb_options_t* opt, leveldb_logger_t* l) {
363
+ opt->rep.info_log = (l ? l->rep : NULL);
364
+ }
365
+
366
+ void leveldb_options_set_write_buffer_size(leveldb_options_t* opt, size_t s) {
367
+ opt->rep.write_buffer_size = s;
368
+ }
369
+
370
+ void leveldb_options_set_max_open_files(leveldb_options_t* opt, int n) {
371
+ opt->rep.max_open_files = n;
372
+ }
373
+
374
+ void leveldb_options_set_cache(leveldb_options_t* opt, leveldb_cache_t* c) {
375
+ opt->rep.block_cache = c->rep;
376
+ }
377
+
378
+ void leveldb_options_set_block_size(leveldb_options_t* opt, size_t s) {
379
+ opt->rep.block_size = s;
380
+ }
381
+
382
+ void leveldb_options_set_block_restart_interval(leveldb_options_t* opt, int n) {
383
+ opt->rep.block_restart_interval = n;
384
+ }
385
+
386
+ void leveldb_options_set_compression(leveldb_options_t* opt, int t) {
387
+ opt->rep.compression = static_cast<CompressionType>(t);
388
+ }
389
+
390
+ leveldb_comparator_t* leveldb_comparator_create(
391
+ void* state,
392
+ void (*destructor)(void*),
393
+ int (*compare)(
394
+ void*,
395
+ const char* a, size_t alen,
396
+ const char* b, size_t blen),
397
+ const char* (*name)(void*)) {
398
+ leveldb_comparator_t* result = new leveldb_comparator_t;
399
+ result->state_ = state;
400
+ result->destructor_ = destructor;
401
+ result->compare_ = compare;
402
+ result->name_ = name;
403
+ return result;
404
+ }
405
+
406
+ void leveldb_comparator_destroy(leveldb_comparator_t* cmp) {
407
+ delete cmp;
408
+ }
409
+
410
+ leveldb_readoptions_t* leveldb_readoptions_create() {
411
+ return new leveldb_readoptions_t;
412
+ }
413
+
414
+ void leveldb_readoptions_destroy(leveldb_readoptions_t* opt) {
415
+ delete opt;
416
+ }
417
+
418
+ void leveldb_readoptions_set_verify_checksums(
419
+ leveldb_readoptions_t* opt,
420
+ unsigned char v) {
421
+ opt->rep.verify_checksums = v;
422
+ }
423
+
424
+ void leveldb_readoptions_set_fill_cache(
425
+ leveldb_readoptions_t* opt, unsigned char v) {
426
+ opt->rep.fill_cache = v;
427
+ }
428
+
429
+ void leveldb_readoptions_set_snapshot(
430
+ leveldb_readoptions_t* opt,
431
+ const leveldb_snapshot_t* snap) {
432
+ opt->rep.snapshot = (snap ? snap->rep : NULL);
433
+ }
434
+
435
+ leveldb_writeoptions_t* leveldb_writeoptions_create() {
436
+ return new leveldb_writeoptions_t;
437
+ }
438
+
439
+ void leveldb_writeoptions_destroy(leveldb_writeoptions_t* opt) {
440
+ delete opt;
441
+ }
442
+
443
+ void leveldb_writeoptions_set_sync(
444
+ leveldb_writeoptions_t* opt, unsigned char v) {
445
+ opt->rep.sync = v;
446
+ }
447
+
448
+ leveldb_cache_t* leveldb_cache_create_lru(size_t capacity) {
449
+ leveldb_cache_t* c = new leveldb_cache_t;
450
+ c->rep = NewLRUCache(capacity);
451
+ return c;
452
+ }
453
+
454
+ void leveldb_cache_destroy(leveldb_cache_t* cache) {
455
+ delete cache->rep;
456
+ delete cache;
457
+ }
458
+
459
+ leveldb_env_t* leveldb_create_default_env() {
460
+ leveldb_env_t* result = new leveldb_env_t;
461
+ result->rep = Env::Default();
462
+ result->is_default = true;
463
+ return result;
464
+ }
465
+
466
+ void leveldb_env_destroy(leveldb_env_t* env) {
467
+ if (!env->is_default) delete env->rep;
468
+ delete env;
469
+ }
470
+
471
+ } // end extern "C"