leveldb-ruby 0.14 → 0.15

Sign up to get free protection for your applications and to get access to all the features.
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;