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.
- data/LICENSE +24 -0
- data/README +60 -16
- data/ext/leveldb/extconf.rb +1 -1
- data/ext/leveldb/leveldb.cc +187 -18
- data/leveldb/Makefile +82 -96
- data/leveldb/build_detect_platform +137 -51
- data/leveldb/db/c.cc +110 -0
- data/leveldb/db/db_bench.cc +105 -4
- data/leveldb/db/db_impl.cc +135 -45
- data/leveldb/db/db_impl.h +12 -10
- data/leveldb/db/db_test.cc +666 -431
- data/leveldb/db/dbformat.cc +20 -0
- data/leveldb/db/dbformat.h +12 -0
- data/leveldb/db/repair.cc +3 -1
- data/leveldb/db/skiplist.h +2 -1
- data/leveldb/db/table_cache.cc +42 -16
- data/leveldb/db/table_cache.h +11 -0
- data/leveldb/db/version_set.cc +46 -41
- data/leveldb/db/version_set.h +9 -0
- data/leveldb/db/write_batch.cc +13 -4
- data/leveldb/db/write_batch_internal.h +2 -0
- data/leveldb/db/write_batch_test.cc +31 -0
- data/leveldb/include/leveldb/c.h +29 -0
- data/leveldb/include/leveldb/db.h +2 -1
- data/leveldb/include/leveldb/filter_policy.h +70 -0
- data/leveldb/include/leveldb/options.h +8 -0
- data/leveldb/include/leveldb/status.h +6 -0
- data/leveldb/include/leveldb/table.h +15 -0
- data/leveldb/include/leveldb/table_builder.h +1 -0
- data/leveldb/port/atomic_pointer.h +13 -5
- data/leveldb/port/port.h +0 -2
- data/leveldb/port/port_example.h +10 -0
- data/leveldb/port/port_posix.cc +4 -0
- data/leveldb/port/port_posix.h +24 -9
- data/leveldb/table/block.cc +8 -4
- data/leveldb/table/block.h +3 -2
- data/leveldb/table/filter_block.cc +111 -0
- data/leveldb/table/filter_block.h +68 -0
- data/leveldb/table/filter_block_test.cc +128 -0
- data/leveldb/table/format.cc +17 -7
- data/leveldb/table/format.h +9 -4
- data/leveldb/table/table.cc +107 -6
- data/leveldb/table/table_builder.cc +49 -6
- data/leveldb/table/table_test.cc +8 -24
- data/leveldb/util/bloom.cc +95 -0
- data/leveldb/util/bloom_test.cc +159 -0
- data/leveldb/util/coding_test.cc +23 -0
- data/leveldb/util/comparator.cc +8 -3
- data/leveldb/util/env_posix.cc +46 -4
- data/leveldb/util/filter_policy.cc +11 -0
- data/leveldb/util/options.cc +2 -1
- data/lib/leveldb.rb +31 -5
- metadata +227 -109
- data/leveldb/port/port_android.cc +0 -64
- 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
|
-
|
4
|
-
|
25
|
+
OUTPUT=$1
|
26
|
+
if test -z "$OUTPUT"; then
|
27
|
+
echo "usage: $0 <output-filename>" >&2
|
28
|
+
exit 1
|
29
|
+
fi
|
5
30
|
|
6
|
-
#
|
7
|
-
|
8
|
-
|
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
|
-
|
14
|
-
|
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
|
-
|
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
|
-
|
25
|
-
|
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
|
-
|
30
|
-
|
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
|
-
|
35
|
-
|
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
|
-
|
40
|
-
|
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
|
-
|
45
|
-
|
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
|
-
|
50
|
-
|
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
|
-
|
55
|
-
|
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
|
-
|
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
|
-
#
|
65
|
-
|
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
|
-
|
68
|
-
#
|
69
|
-
|
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
|
-
|
79
|
-
|
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
|
-
|
85
|
-
|
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
|
-
|
89
|
-
|
90
|
-
|
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
|
-
|
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
|
data/leveldb/db/c.cc
CHANGED
@@ -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
|
}
|
data/leveldb/db/db_bench.cc
CHANGED
@@ -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 =
|
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(
|
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;
|