leveldb-ruby 0.14 → 0.15

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 (55) hide show
  1. data/LICENSE +24 -0
  2. data/README +60 -16
  3. data/ext/leveldb/extconf.rb +1 -1
  4. data/ext/leveldb/leveldb.cc +187 -18
  5. data/leveldb/Makefile +82 -96
  6. data/leveldb/build_detect_platform +137 -51
  7. data/leveldb/db/c.cc +110 -0
  8. data/leveldb/db/db_bench.cc +105 -4
  9. data/leveldb/db/db_impl.cc +135 -45
  10. data/leveldb/db/db_impl.h +12 -10
  11. data/leveldb/db/db_test.cc +666 -431
  12. data/leveldb/db/dbformat.cc +20 -0
  13. data/leveldb/db/dbformat.h +12 -0
  14. data/leveldb/db/repair.cc +3 -1
  15. data/leveldb/db/skiplist.h +2 -1
  16. data/leveldb/db/table_cache.cc +42 -16
  17. data/leveldb/db/table_cache.h +11 -0
  18. data/leveldb/db/version_set.cc +46 -41
  19. data/leveldb/db/version_set.h +9 -0
  20. data/leveldb/db/write_batch.cc +13 -4
  21. data/leveldb/db/write_batch_internal.h +2 -0
  22. data/leveldb/db/write_batch_test.cc +31 -0
  23. data/leveldb/include/leveldb/c.h +29 -0
  24. data/leveldb/include/leveldb/db.h +2 -1
  25. data/leveldb/include/leveldb/filter_policy.h +70 -0
  26. data/leveldb/include/leveldb/options.h +8 -0
  27. data/leveldb/include/leveldb/status.h +6 -0
  28. data/leveldb/include/leveldb/table.h +15 -0
  29. data/leveldb/include/leveldb/table_builder.h +1 -0
  30. data/leveldb/port/atomic_pointer.h +13 -5
  31. data/leveldb/port/port.h +0 -2
  32. data/leveldb/port/port_example.h +10 -0
  33. data/leveldb/port/port_posix.cc +4 -0
  34. data/leveldb/port/port_posix.h +24 -9
  35. data/leveldb/table/block.cc +8 -4
  36. data/leveldb/table/block.h +3 -2
  37. data/leveldb/table/filter_block.cc +111 -0
  38. data/leveldb/table/filter_block.h +68 -0
  39. data/leveldb/table/filter_block_test.cc +128 -0
  40. data/leveldb/table/format.cc +17 -7
  41. data/leveldb/table/format.h +9 -4
  42. data/leveldb/table/table.cc +107 -6
  43. data/leveldb/table/table_builder.cc +49 -6
  44. data/leveldb/table/table_test.cc +8 -24
  45. data/leveldb/util/bloom.cc +95 -0
  46. data/leveldb/util/bloom_test.cc +159 -0
  47. data/leveldb/util/coding_test.cc +23 -0
  48. data/leveldb/util/comparator.cc +8 -3
  49. data/leveldb/util/env_posix.cc +46 -4
  50. data/leveldb/util/filter_policy.cc +11 -0
  51. data/leveldb/util/options.cc +2 -1
  52. data/lib/leveldb.rb +31 -5
  53. metadata +227 -109
  54. data/leveldb/port/port_android.cc +0 -64
  55. data/leveldb/port/port_android.h +0 -156
@@ -1,93 +1,179 @@
1
1
  #!/bin/sh
2
+ #
3
+ # Detects OS we're compiling on and outputs a file specified by the first
4
+ # argument, which in turn gets read while processing Makefile.
5
+ #
6
+ # The output will set the following variables:
7
+ # CC C Compiler path
8
+ # CXX C++ Compiler path
9
+ # PLATFORM_LDFLAGS Linker flags
10
+ # PLATFORM_SHARED_EXT Extension for shared libraries
11
+ # PLATFORM_SHARED_LDFLAGS Flags for building shared library
12
+ # PLATFORM_SHARED_CFLAGS Flags for compiling objects for shared library
13
+ # PLATFORM_CCFLAGS C compiler flags
14
+ # PLATFORM_CXXFLAGS C++ compiler flags. Will contain:
15
+ # PLATFORM_SHARED_VERSIONED Set to 'true' if platform supports versioned
16
+ # shared libraries, empty otherwise.
17
+ #
18
+ # The PLATFORM_CCFLAGS and PLATFORM_CXXFLAGS might include the following:
19
+ #
20
+ # -DLEVELDB_CSTDATOMIC_PRESENT if <cstdatomic> is present
21
+ # -DLEVELDB_PLATFORM_POSIX for Posix-based platforms
22
+ # -DSNAPPY if the Snappy library is present
23
+ #
2
24
 
3
- # Detects OS we're compiling on and generates build_config.mk,
4
- # which in turn gets read while processing Makefile.
25
+ OUTPUT=$1
26
+ if test -z "$OUTPUT"; then
27
+ echo "usage: $0 <output-filename>" >&2
28
+ exit 1
29
+ fi
5
30
 
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
31
+ # Delete existing output, if it exists
32
+ rm -f $OUTPUT
33
+ touch $OUTPUT
12
34
 
13
- # Delete existing build_config.mk
14
- rm -f build_config.mk
35
+ if test -z "$CC"; then
36
+ CC=cc
37
+ fi
15
38
 
16
39
  if test -z "$CXX"; then
17
40
  CXX=g++
18
41
  fi
19
42
 
20
43
  # Detect OS
21
- case `uname -s` in
44
+ if test -z "$TARGET_OS"; then
45
+ TARGET_OS=`uname -s`
46
+ fi
47
+
48
+ COMMON_FLAGS=
49
+ CROSS_COMPILE=
50
+ PLATFORM_CCFLAGS=
51
+ PLATFORM_CXXFLAGS=
52
+ PLATFORM_LDFLAGS=
53
+ PLATFORM_SHARED_EXT="so"
54
+ PLATFORM_SHARED_LDFLAGS="-shared -Wl,-soname -Wl,"
55
+ PLATFORM_SHARED_CFLAGS="-fPIC"
56
+ PLATFORM_SHARED_VERSIONED=true
57
+
58
+ # On GCC, we pick libc's memcmp over GCC's memcmp via -fno-builtin-memcmp
59
+ case "$TARGET_OS" in
22
60
  Darwin)
23
61
  PLATFORM=OS_MACOSX
24
- echo "PLATFORM_CFLAGS=-DOS_MACOSX" >> build_config.mk
25
- echo "PLATFORM_LDFLAGS=" >> build_config.mk
62
+ COMMON_FLAGS="-fno-builtin-memcmp -DOS_MACOSX"
63
+ PLATFORM_SHARED_EXT=dylib
64
+ PLATFORM_SHARED_LDFLAGS="-dynamiclib -install_name "
65
+ PORT_FILE=port/port_posix.cc
26
66
  ;;
27
67
  Linux)
28
68
  PLATFORM=OS_LINUX
29
- echo "PLATFORM_CFLAGS=-pthread -DOS_LINUX" >> build_config.mk
30
- echo "PLATFORM_LDFLAGS=-pthread" >> build_config.mk
69
+ COMMON_FLAGS="-fno-builtin-memcmp -pthread -DOS_LINUX"
70
+ PLATFORM_LDFLAGS="-pthread"
71
+ PORT_FILE=port/port_posix.cc
31
72
  ;;
32
73
  SunOS)
33
74
  PLATFORM=OS_SOLARIS
34
- echo "PLATFORM_CFLAGS=-D_REENTRANT -DOS_SOLARIS" >> build_config.mk
35
- echo "PLATFORM_LDFLAGS=-lpthread -lrt" >> build_config.mk
75
+ COMMON_FLAGS="-fno-builtin-memcmp -D_REENTRANT -DOS_SOLARIS"
76
+ PLATFORM_LDFLAGS="-lpthread -lrt"
77
+ PORT_FILE=port/port_posix.cc
36
78
  ;;
37
79
  FreeBSD)
38
80
  PLATFORM=OS_FREEBSD
39
- echo "PLATFORM_CFLAGS=-D_REENTRANT -DOS_FREEBSD" >> build_config.mk
40
- echo "PLATFORM_LDFLAGS=-lpthread" >> build_config.mk
81
+ COMMON_FLAGS="-fno-builtin-memcmp -D_REENTRANT -DOS_FREEBSD"
82
+ PLATFORM_LDFLAGS="-lpthread"
83
+ PORT_FILE=port/port_posix.cc
41
84
  ;;
42
85
  NetBSD)
43
86
  PLATFORM=OS_NETBSD
44
- echo "PLATFORM_CFLAGS=-D_REENTRANT -DOS_NETBSD" >> build_config.mk
45
- echo "PLATFORM_LDFLAGS=-lpthread -lgcc_s" >> build_config.mk
87
+ COMMON_FLAGS="-fno-builtin-memcmp -D_REENTRANT -DOS_NETBSD"
88
+ PLATFORM_LDFLAGS="-lpthread -lgcc_s"
89
+ PORT_FILE=port/port_posix.cc
46
90
  ;;
47
91
  OpenBSD)
48
92
  PLATFORM=OS_OPENBSD
49
- echo "PLATFORM_CFLAGS=-D_REENTRANT -DOS_OPENBSD" >> build_config.mk
50
- echo "PLATFORM_LDFLAGS=-pthread" >> build_config.mk
93
+ COMMON_FLAGS="-fno-builtin-memcmp -D_REENTRANT -DOS_OPENBSD"
94
+ PLATFORM_LDFLAGS="-pthread"
95
+ PORT_FILE=port/port_posix.cc
51
96
  ;;
52
97
  DragonFly)
53
98
  PLATFORM=OS_DRAGONFLYBSD
54
- echo "PLATFORM_CFLAGS=-D_REENTRANT -DOS_DRAGONFLYBSD" >> build_config.mk
55
- echo "PLATFORM_LDFLAGS=-lpthread" >> build_config.mk
99
+ COMMON_FLAGS="-fno-builtin-memcmp -D_REENTRANT -DOS_DRAGONFLYBSD"
100
+ PLATFORM_LDFLAGS="-lpthread"
101
+ PORT_FILE=port/port_posix.cc
102
+ ;;
103
+ OS_ANDROID_CROSSCOMPILE)
104
+ PLATFORM=OS_ANDROID
105
+ COMMON_FLAGS="-fno-builtin-memcmp -D_REENTRANT -DOS_ANDROID -DLEVELDB_PLATFORM_POSIX"
106
+ PLATFORM_LDFLAGS="" # All pthread features are in the Android C library
107
+ PORT_FILE=port/port_posix.cc
108
+ CROSS_COMPILE=true
56
109
  ;;
57
110
  *)
58
- echo "Unknown platform!"
111
+ echo "Unknown platform!" >&2
59
112
  exit 1
60
113
  esac
61
114
 
62
- echo "PLATFORM=$PLATFORM" >> build_config.mk
115
+ # We want to make a list of all cc files within util, db, table, and helpers
116
+ # except for the test and benchmark files. By default, find will output a list
117
+ # of all files matching either rule, so we need to append -print to make the
118
+ # prune take effect.
119
+ DIRS="util db table"
120
+ set -f # temporarily disable globbing so that our patterns aren't expanded
121
+ PRUNE_TEST="-name *test*.cc -prune"
122
+ PRUNE_BENCH="-name *_bench.cc -prune"
123
+ PORTABLE_FILES=`find $DIRS $PRUNE_TEST -o $PRUNE_BENCH -o -name '*.cc' -print | sort | tr "\n" " "`
124
+ set +f # re-enable globbing
63
125
 
64
- # On GCC, use libc's memcmp, not GCC's memcmp
65
- PORT_CFLAGS="-fno-builtin-memcmp"
126
+ # The sources consist of the portable files, plus the platform-specific port
127
+ # file.
128
+ echo "SOURCES=$PORTABLE_FILES $PORT_FILE" >> $OUTPUT
129
+ echo "MEMENV_SOURCES=helpers/memenv/memenv.cc" >> $OUTPUT
66
130
 
67
- # Detect C++0x -- this determines whether we'll use port_noatomic.h
68
- # or port_posix.h by:
69
- # 1. Rrying to compile with -std=c++0x and including <cstdatomic>.
70
- # 2. If $CXX returns error code, we know to use port_posix.h
71
- $CXX $CFLAGS -std=c++0x -x c++ - -o /dev/null 2>/dev/null <<EOF
72
- #include <cstdatomic>
73
- int main() {}
74
- EOF
75
- if [ "$?" = 0 ]; then
76
- PORT_CFLAGS="$PORT_CFLAGS -DLEVELDB_PLATFORM_POSIX -DLEVELDB_CSTDATOMIC_PRESENT -std=c++0x"
131
+ if [ "$CROSS_COMPILE" = "true" ]; then
132
+ # Cross-compiling; do not try any compilation tests.
133
+ true
77
134
  else
78
- PORT_CFLAGS="$PORT_CFLAGS -DLEVELDB_PLATFORM_POSIX"
79
- fi
135
+ # If -std=c++0x works, use <cstdatomic>. Otherwise use port_posix.h.
136
+ $CXX $CFLAGS -std=c++0x -x c++ - -o /dev/null 2>/dev/null <<EOF
137
+ #include <cstdatomic>
138
+ int main() {}
139
+ EOF
140
+ if [ "$?" = 0 ]; then
141
+ COMMON_FLAGS="$COMMON_FLAGS -DLEVELDB_PLATFORM_POSIX -DLEVELDB_CSTDATOMIC_PRESENT"
142
+ PLATFORM_CXXFLAGS="-std=c++0x"
143
+ else
144
+ COMMON_FLAGS="$COMMON_FLAGS -DLEVELDB_PLATFORM_POSIX"
145
+ fi
80
146
 
81
- # Test whether Snappy library is installed
82
- # http://code.google.com/p/snappy/
83
- $CXX $CFLAGS -x c++ - -o /dev/null 2>/dev/null <<EOF
84
- #include <snappy.h>
85
- int main() {}
147
+ # Test whether Snappy library is installed
148
+ # http://code.google.com/p/snappy/
149
+ $CXX $CFLAGS -x c++ - -o /dev/null 2>/dev/null <<EOF
150
+ #include <snappy.h>
151
+ int main() {}
86
152
  EOF
87
- if [ "$?" = 0 ]; then
88
- echo "SNAPPY=1" >> build_config.mk
89
- else
90
- echo "SNAPPY=0" >> build_config.mk
153
+ if [ "$?" = 0 ]; then
154
+ COMMON_FLAGS="$COMMON_FLAGS -DSNAPPY"
155
+ PLATFORM_LDFLAGS="$PLATFORM_LDFLAGS -lsnappy"
156
+ fi
157
+
158
+ # Test whether tcmalloc is available
159
+ $CXX $CFLAGS -x c++ - -o /dev/null -ltcmalloc 2>/dev/null <<EOF
160
+ int main() {}
161
+ EOF
162
+ if [ "$?" = 0 ]; then
163
+ PLATFORM_LDFLAGS="$PLATFORM_LDFLAGS -ltcmalloc"
164
+ fi
91
165
  fi
92
166
 
93
- echo "PORT_CFLAGS=$PORT_CFLAGS" >> build_config.mk
167
+ PLATFORM_CCFLAGS="$PLATFORM_CCFLAGS $COMMON_FLAGS"
168
+ PLATFORM_CXXFLAGS="$PLATFORM_CXXFLAGS $COMMON_FLAGS"
169
+
170
+ echo "CC=$CC" >> $OUTPUT
171
+ echo "CXX=$CXX" >> $OUTPUT
172
+ echo "PLATFORM=$PLATFORM" >> $OUTPUT
173
+ echo "PLATFORM_LDFLAGS=$PLATFORM_LDFLAGS" >> $OUTPUT
174
+ echo "PLATFORM_CCFLAGS=$PLATFORM_CCFLAGS" >> $OUTPUT
175
+ echo "PLATFORM_CXXFLAGS=$PLATFORM_CXXFLAGS" >> $OUTPUT
176
+ echo "PLATFORM_SHARED_CFLAGS=$PLATFORM_SHARED_CFLAGS" >> $OUTPUT
177
+ echo "PLATFORM_SHARED_EXT=$PLATFORM_SHARED_EXT" >> $OUTPUT
178
+ echo "PLATFORM_SHARED_LDFLAGS=$PLATFORM_SHARED_LDFLAGS" >> $OUTPUT
179
+ echo "PLATFORM_SHARED_VERSIONED=$PLATFORM_SHARED_VERSIONED" >> $OUTPUT
@@ -10,6 +10,7 @@
10
10
  #include "leveldb/comparator.h"
11
11
  #include "leveldb/db.h"
12
12
  #include "leveldb/env.h"
13
+ #include "leveldb/filter_policy.h"
13
14
  #include "leveldb/iterator.h"
14
15
  #include "leveldb/options.h"
15
16
  #include "leveldb/status.h"
@@ -21,8 +22,10 @@ using leveldb::CompressionType;
21
22
  using leveldb::DB;
22
23
  using leveldb::Env;
23
24
  using leveldb::FileLock;
25
+ using leveldb::FilterPolicy;
24
26
  using leveldb::Iterator;
25
27
  using leveldb::Logger;
28
+ using leveldb::NewBloomFilterPolicy;
26
29
  using leveldb::NewLRUCache;
27
30
  using leveldb::Options;
28
31
  using leveldb::RandomAccessFile;
@@ -78,6 +81,47 @@ struct leveldb_comparator_t : public Comparator {
78
81
  virtual void FindShortSuccessor(std::string* key) const { }
79
82
  };
80
83
 
84
+ struct leveldb_filterpolicy_t : public FilterPolicy {
85
+ void* state_;
86
+ void (*destructor_)(void*);
87
+ const char* (*name_)(void*);
88
+ char* (*create_)(
89
+ void*,
90
+ const char* const* key_array, const size_t* key_length_array,
91
+ int num_keys,
92
+ size_t* filter_length);
93
+ unsigned char (*key_match_)(
94
+ void*,
95
+ const char* key, size_t length,
96
+ const char* filter, size_t filter_length);
97
+
98
+ virtual ~leveldb_filterpolicy_t() {
99
+ (*destructor_)(state_);
100
+ }
101
+
102
+ virtual const char* Name() const {
103
+ return (*name_)(state_);
104
+ }
105
+
106
+ virtual void CreateFilter(const Slice* keys, int n, std::string* dst) const {
107
+ std::vector<const char*> key_pointers(n);
108
+ std::vector<size_t> key_sizes(n);
109
+ for (int i = 0; i < n; i++) {
110
+ key_pointers[i] = keys[i].data();
111
+ key_sizes[i] = keys[i].size();
112
+ }
113
+ size_t len;
114
+ char* filter = (*create_)(state_, &key_pointers[0], &key_sizes[0], n, &len);
115
+ dst->append(filter, len);
116
+ free(filter);
117
+ }
118
+
119
+ virtual bool KeyMayMatch(const Slice& key, const Slice& filter) const {
120
+ return (*key_match_)(state_, key.data(), key.size(),
121
+ filter.data(), filter.size());
122
+ }
123
+ };
124
+
81
125
  struct leveldb_env_t {
82
126
  Env* rep;
83
127
  bool is_default;
@@ -218,6 +262,17 @@ void leveldb_approximate_sizes(
218
262
  delete[] ranges;
219
263
  }
220
264
 
265
+ void leveldb_compact_range(
266
+ leveldb_t* db,
267
+ const char* start_key, size_t start_key_len,
268
+ const char* limit_key, size_t limit_key_len) {
269
+ Slice a, b;
270
+ db->rep->CompactRange(
271
+ // Pass NULL Slice if corresponding "const char*" is NULL
272
+ (start_key ? (a = Slice(start_key, start_key_len), &a) : NULL),
273
+ (limit_key ? (b = Slice(limit_key, limit_key_len), &b) : NULL));
274
+ }
275
+
221
276
  void leveldb_destroy_db(
222
277
  const leveldb_options_t* options,
223
278
  const char* name,
@@ -340,6 +395,12 @@ void leveldb_options_set_comparator(
340
395
  opt->rep.comparator = cmp;
341
396
  }
342
397
 
398
+ void leveldb_options_set_filter_policy(
399
+ leveldb_options_t* opt,
400
+ leveldb_filterpolicy_t* policy) {
401
+ opt->rep.filter_policy = policy;
402
+ }
403
+
343
404
  void leveldb_options_set_create_if_missing(
344
405
  leveldb_options_t* opt, unsigned char v) {
345
406
  opt->rep.create_if_missing = v;
@@ -407,6 +468,55 @@ void leveldb_comparator_destroy(leveldb_comparator_t* cmp) {
407
468
  delete cmp;
408
469
  }
409
470
 
471
+ leveldb_filterpolicy_t* leveldb_filterpolicy_create(
472
+ void* state,
473
+ void (*destructor)(void*),
474
+ char* (*create_filter)(
475
+ void*,
476
+ const char* const* key_array, const size_t* key_length_array,
477
+ int num_keys,
478
+ size_t* filter_length),
479
+ unsigned char (*key_may_match)(
480
+ void*,
481
+ const char* key, size_t length,
482
+ const char* filter, size_t filter_length),
483
+ const char* (*name)(void*)) {
484
+ leveldb_filterpolicy_t* result = new leveldb_filterpolicy_t;
485
+ result->state_ = state;
486
+ result->destructor_ = destructor;
487
+ result->create_ = create_filter;
488
+ result->key_match_ = key_may_match;
489
+ result->name_ = name;
490
+ return result;
491
+ }
492
+
493
+ void leveldb_filterpolicy_destroy(leveldb_filterpolicy_t* filter) {
494
+ delete filter;
495
+ }
496
+
497
+ leveldb_filterpolicy_t* leveldb_filterpolicy_create_bloom(int bits_per_key) {
498
+ // Make a leveldb_filterpolicy_t, but override all of its methods so
499
+ // they delegate to a NewBloomFilterPolicy() instead of user
500
+ // supplied C functions.
501
+ struct Wrapper : public leveldb_filterpolicy_t {
502
+ const FilterPolicy* rep_;
503
+ ~Wrapper() { delete rep_; }
504
+ const char* Name() const { return rep_->Name(); }
505
+ void CreateFilter(const Slice* keys, int n, std::string* dst) const {
506
+ return rep_->CreateFilter(keys, n, dst);
507
+ }
508
+ bool KeyMayMatch(const Slice& key, const Slice& filter) const {
509
+ return rep_->KeyMayMatch(key, filter);
510
+ }
511
+ static void DoNothing(void*) { }
512
+ };
513
+ Wrapper* wrapper = new Wrapper;
514
+ wrapper->rep_ = NewBloomFilterPolicy(bits_per_key);
515
+ wrapper->state_ = NULL;
516
+ wrapper->destructor_ = &Wrapper::DoNothing;
517
+ return wrapper;
518
+ }
519
+
410
520
  leveldb_readoptions_t* leveldb_readoptions_create() {
411
521
  return new leveldb_readoptions_t;
412
522
  }
@@ -25,15 +25,20 @@
25
25
  // overwrite -- overwrite N values in random key order in async mode
26
26
  // fillsync -- write N/100 values in random key order in sync mode
27
27
  // fill100K -- write N/1000 100K values in random order in async mode
28
+ // deleteseq -- delete N keys in sequential order
29
+ // deleterandom -- delete N keys in random order
28
30
  // readseq -- read N times sequentially
29
31
  // readreverse -- read N times in reverse order
30
32
  // readrandom -- read N times in random order
33
+ // readmissing -- read N missing keys in random order
31
34
  // readhot -- read N times in random order from 1% section of DB
35
+ // seekrandom -- N random seeks
32
36
  // crc32c -- repeated crc32c of 4K of data
33
37
  // acquireload -- load N*1000 times
34
38
  // Meta operations:
35
39
  // compact -- Compact the entire DB
36
40
  // stats -- Print DB stats
41
+ // sstables -- Print sstable info
37
42
  // heapprofile -- Dump a heap profile (if supported by this port)
38
43
  static const char* FLAGS_benchmarks =
39
44
  "fillseq,"
@@ -85,13 +90,17 @@ static int FLAGS_cache_size = -1;
85
90
  // Maximum number of files to keep open at the same time (use default if == 0)
86
91
  static int FLAGS_open_files = 0;
87
92
 
93
+ // Bloom filter bits per key.
94
+ // Negative means use default settings.
95
+ static int FLAGS_bloom_bits = -1;
96
+
88
97
  // If true, do not destroy the existing database. If you set this
89
98
  // flag and also specify a benchmark that wants a fresh database, that
90
99
  // benchmark will fail.
91
100
  static bool FLAGS_use_existing_db = false;
92
101
 
93
102
  // Use the db with the following name.
94
- static const char* FLAGS_db = "/tmp/dbbench";
103
+ static const char* FLAGS_db = NULL;
95
104
 
96
105
  namespace leveldb {
97
106
 
@@ -293,6 +302,7 @@ struct ThreadState {
293
302
  class Benchmark {
294
303
  private:
295
304
  Cache* cache_;
305
+ const FilterPolicy* filter_policy_;
296
306
  DB* db_;
297
307
  int num_;
298
308
  int value_size_;
@@ -378,6 +388,9 @@ class Benchmark {
378
388
  public:
379
389
  Benchmark()
380
390
  : cache_(FLAGS_cache_size >= 0 ? NewLRUCache(FLAGS_cache_size) : NULL),
391
+ filter_policy_(FLAGS_bloom_bits >= 0
392
+ ? NewBloomFilterPolicy(FLAGS_bloom_bits)
393
+ : NULL),
381
394
  db_(NULL),
382
395
  num_(FLAGS_num),
383
396
  value_size_(FLAGS_value_size),
@@ -399,6 +412,7 @@ class Benchmark {
399
412
  ~Benchmark() {
400
413
  delete db_;
401
414
  delete cache_;
415
+ delete filter_policy_;
402
416
  }
403
417
 
404
418
  void Run() {
@@ -457,11 +471,19 @@ class Benchmark {
457
471
  method = &Benchmark::ReadReverse;
458
472
  } else if (name == Slice("readrandom")) {
459
473
  method = &Benchmark::ReadRandom;
474
+ } else if (name == Slice("readmissing")) {
475
+ method = &Benchmark::ReadMissing;
476
+ } else if (name == Slice("seekrandom")) {
477
+ method = &Benchmark::SeekRandom;
460
478
  } else if (name == Slice("readhot")) {
461
479
  method = &Benchmark::ReadHot;
462
480
  } else if (name == Slice("readrandomsmall")) {
463
481
  reads_ /= 1000;
464
482
  method = &Benchmark::ReadRandom;
483
+ } else if (name == Slice("deleteseq")) {
484
+ method = &Benchmark::DeleteSeq;
485
+ } else if (name == Slice("deleterandom")) {
486
+ method = &Benchmark::DeleteRandom;
465
487
  } else if (name == Slice("readwhilewriting")) {
466
488
  num_threads++; // Add extra thread for writing
467
489
  method = &Benchmark::ReadWhileWriting;
@@ -478,7 +500,9 @@ class Benchmark {
478
500
  } else if (name == Slice("heapprofile")) {
479
501
  HeapProfile();
480
502
  } else if (name == Slice("stats")) {
481
- PrintStats();
503
+ PrintStats("leveldb.stats");
504
+ } else if (name == Slice("sstables")) {
505
+ PrintStats("leveldb.sstables");
482
506
  } else {
483
507
  if (name != Slice()) { // No error message for empty name
484
508
  fprintf(stderr, "unknown benchmark '%s'\n", name.ToString().c_str());
@@ -669,6 +693,7 @@ class Benchmark {
669
693
  options.create_if_missing = !FLAGS_use_existing_db;
670
694
  options.block_cache = cache_;
671
695
  options.write_buffer_size = FLAGS_write_buffer_size;
696
+ options.filter_policy = filter_policy_;
672
697
  Status s = DB::Open(options, FLAGS_db, &db_);
673
698
  if (!s.ok()) {
674
699
  fprintf(stderr, "open error: %s\n", s.ToString().c_str());
@@ -743,10 +768,28 @@ class Benchmark {
743
768
  void ReadRandom(ThreadState* thread) {
744
769
  ReadOptions options;
745
770
  std::string value;
771
+ int found = 0;
746
772
  for (int i = 0; i < reads_; i++) {
747
773
  char key[100];
748
774
  const int k = thread->rand.Next() % FLAGS_num;
749
775
  snprintf(key, sizeof(key), "%016d", k);
776
+ if (db_->Get(options, key, &value).ok()) {
777
+ found++;
778
+ }
779
+ thread->stats.FinishedSingleOp();
780
+ }
781
+ char msg[100];
782
+ snprintf(msg, sizeof(msg), "(%d of %d found)", found, num_);
783
+ thread->stats.AddMessage(msg);
784
+ }
785
+
786
+ void ReadMissing(ThreadState* thread) {
787
+ ReadOptions options;
788
+ std::string value;
789
+ for (int i = 0; i < reads_; i++) {
790
+ char key[100];
791
+ const int k = thread->rand.Next() % FLAGS_num;
792
+ snprintf(key, sizeof(key), "%016d.", k);
750
793
  db_->Get(options, key, &value);
751
794
  thread->stats.FinishedSingleOp();
752
795
  }
@@ -765,6 +808,54 @@ class Benchmark {
765
808
  }
766
809
  }
767
810
 
811
+ void SeekRandom(ThreadState* thread) {
812
+ ReadOptions options;
813
+ std::string value;
814
+ int found = 0;
815
+ for (int i = 0; i < reads_; i++) {
816
+ Iterator* iter = db_->NewIterator(options);
817
+ char key[100];
818
+ const int k = thread->rand.Next() % FLAGS_num;
819
+ snprintf(key, sizeof(key), "%016d", k);
820
+ iter->Seek(key);
821
+ if (iter->Valid() && iter->key() == key) found++;
822
+ delete iter;
823
+ thread->stats.FinishedSingleOp();
824
+ }
825
+ char msg[100];
826
+ snprintf(msg, sizeof(msg), "(%d of %d found)", found, num_);
827
+ thread->stats.AddMessage(msg);
828
+ }
829
+
830
+ void DoDelete(ThreadState* thread, bool seq) {
831
+ RandomGenerator gen;
832
+ WriteBatch batch;
833
+ Status s;
834
+ for (int i = 0; i < num_; i += entries_per_batch_) {
835
+ batch.Clear();
836
+ for (int j = 0; j < entries_per_batch_; j++) {
837
+ const int k = seq ? i+j : (thread->rand.Next() % FLAGS_num);
838
+ char key[100];
839
+ snprintf(key, sizeof(key), "%016d", k);
840
+ batch.Delete(key);
841
+ thread->stats.FinishedSingleOp();
842
+ }
843
+ s = db_->Write(write_options_, &batch);
844
+ if (!s.ok()) {
845
+ fprintf(stderr, "del error: %s\n", s.ToString().c_str());
846
+ exit(1);
847
+ }
848
+ }
849
+ }
850
+
851
+ void DeleteSeq(ThreadState* thread) {
852
+ DoDelete(thread, true);
853
+ }
854
+
855
+ void DeleteRandom(ThreadState* thread) {
856
+ DoDelete(thread, false);
857
+ }
858
+
768
859
  void ReadWhileWriting(ThreadState* thread) {
769
860
  if (thread->tid > 0) {
770
861
  ReadRandom(thread);
@@ -799,9 +890,9 @@ class Benchmark {
799
890
  db_->CompactRange(NULL, NULL);
800
891
  }
801
892
 
802
- void PrintStats() {
893
+ void PrintStats(const char* key) {
803
894
  std::string stats;
804
- if (!db_->GetProperty("leveldb.stats", &stats)) {
895
+ if (!db_->GetProperty(key, &stats)) {
805
896
  stats = "(failed)";
806
897
  }
807
898
  fprintf(stdout, "\n%s\n", stats.c_str());
@@ -834,6 +925,7 @@ class Benchmark {
834
925
  int main(int argc, char** argv) {
835
926
  FLAGS_write_buffer_size = leveldb::Options().write_buffer_size;
836
927
  FLAGS_open_files = leveldb::Options().max_open_files;
928
+ std::string default_db_path;
837
929
 
838
930
  for (int i = 1; i < argc; i++) {
839
931
  double d;
@@ -861,6 +953,8 @@ int main(int argc, char** argv) {
861
953
  FLAGS_write_buffer_size = n;
862
954
  } else if (sscanf(argv[i], "--cache_size=%d%c", &n, &junk) == 1) {
863
955
  FLAGS_cache_size = n;
956
+ } else if (sscanf(argv[i], "--bloom_bits=%d%c", &n, &junk) == 1) {
957
+ FLAGS_bloom_bits = n;
864
958
  } else if (sscanf(argv[i], "--open_files=%d%c", &n, &junk) == 1) {
865
959
  FLAGS_open_files = n;
866
960
  } else if (strncmp(argv[i], "--db=", 5) == 0) {
@@ -871,6 +965,13 @@ int main(int argc, char** argv) {
871
965
  }
872
966
  }
873
967
 
968
+ // Choose a location for the test database if none given with --db=<path>
969
+ if (FLAGS_db == NULL) {
970
+ leveldb::Env::Default()->GetTestDirectory(&default_db_path);
971
+ default_db_path += "/dbbench";
972
+ FLAGS_db = default_db_path.c_str();
973
+ }
974
+
874
975
  leveldb::Benchmark benchmark;
875
976
  benchmark.Run();
876
977
  return 0;