leveldb-ruby 0.14 → 0.15
Sign up to get free protection for your applications and to get access to all the features.
- 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
data/leveldb/db/dbformat.cc
CHANGED
@@ -98,6 +98,26 @@ void InternalKeyComparator::FindShortSuccessor(std::string* key) const {
|
|
98
98
|
}
|
99
99
|
}
|
100
100
|
|
101
|
+
const char* InternalFilterPolicy::Name() const {
|
102
|
+
return user_policy_->Name();
|
103
|
+
}
|
104
|
+
|
105
|
+
void InternalFilterPolicy::CreateFilter(const Slice* keys, int n,
|
106
|
+
std::string* dst) const {
|
107
|
+
// We rely on the fact that the code in table.cc does not mind us
|
108
|
+
// adjusting keys[].
|
109
|
+
Slice* mkey = const_cast<Slice*>(keys);
|
110
|
+
for (int i = 0; i < n; i++) {
|
111
|
+
mkey[i] = ExtractUserKey(keys[i]);
|
112
|
+
// TODO(sanjay): Suppress dups?
|
113
|
+
}
|
114
|
+
user_policy_->CreateFilter(keys, n, dst);
|
115
|
+
}
|
116
|
+
|
117
|
+
bool InternalFilterPolicy::KeyMayMatch(const Slice& key, const Slice& f) const {
|
118
|
+
return user_policy_->KeyMayMatch(ExtractUserKey(key), f);
|
119
|
+
}
|
120
|
+
|
101
121
|
LookupKey::LookupKey(const Slice& user_key, SequenceNumber s) {
|
102
122
|
size_t usize = user_key.size();
|
103
123
|
size_t needed = usize + 13; // A conservative estimate
|
data/leveldb/db/dbformat.h
CHANGED
@@ -8,6 +8,7 @@
|
|
8
8
|
#include <stdio.h>
|
9
9
|
#include "leveldb/comparator.h"
|
10
10
|
#include "leveldb/db.h"
|
11
|
+
#include "leveldb/filter_policy.h"
|
11
12
|
#include "leveldb/slice.h"
|
12
13
|
#include "leveldb/table_builder.h"
|
13
14
|
#include "util/coding.h"
|
@@ -123,6 +124,17 @@ class InternalKeyComparator : public Comparator {
|
|
123
124
|
int Compare(const InternalKey& a, const InternalKey& b) const;
|
124
125
|
};
|
125
126
|
|
127
|
+
// Filter policy wrapper that converts from internal keys to user keys
|
128
|
+
class InternalFilterPolicy : public FilterPolicy {
|
129
|
+
private:
|
130
|
+
const FilterPolicy* const user_policy_;
|
131
|
+
public:
|
132
|
+
explicit InternalFilterPolicy(const FilterPolicy* p) : user_policy_(p) { }
|
133
|
+
virtual const char* Name() const;
|
134
|
+
virtual void CreateFilter(const Slice* keys, int n, std::string* dst) const;
|
135
|
+
virtual bool KeyMayMatch(const Slice& key, const Slice& filter) const;
|
136
|
+
};
|
137
|
+
|
126
138
|
// Modules in this directory should keep internal keys wrapped inside
|
127
139
|
// the following class instead of plain strings so that we do not
|
128
140
|
// incorrectly use string comparisons instead of an InternalKeyComparator.
|
data/leveldb/db/repair.cc
CHANGED
@@ -48,7 +48,8 @@ class Repairer {
|
|
48
48
|
: dbname_(dbname),
|
49
49
|
env_(options.env),
|
50
50
|
icmp_(options.comparator),
|
51
|
-
|
51
|
+
ipolicy_(options.filter_policy),
|
52
|
+
options_(SanitizeOptions(dbname, &icmp_, &ipolicy_, options)),
|
52
53
|
owns_info_log_(options_.info_log != options.info_log),
|
53
54
|
owns_cache_(options_.block_cache != options.block_cache),
|
54
55
|
next_file_number_(1) {
|
@@ -99,6 +100,7 @@ class Repairer {
|
|
99
100
|
std::string const dbname_;
|
100
101
|
Env* const env_;
|
101
102
|
InternalKeyComparator const icmp_;
|
103
|
+
InternalFilterPolicy const ipolicy_;
|
102
104
|
Options const options_;
|
103
105
|
bool owns_info_log_;
|
104
106
|
bool owns_cache_;
|
data/leveldb/db/skiplist.h
CHANGED
@@ -105,7 +105,8 @@ class SkipList {
|
|
105
105
|
port::AtomicPointer max_height_; // Height of the entire list
|
106
106
|
|
107
107
|
inline int GetMaxHeight() const {
|
108
|
-
return
|
108
|
+
return static_cast<int>(
|
109
|
+
reinterpret_cast<intptr_t>(max_height_.NoBarrier_Load()));
|
109
110
|
}
|
110
111
|
|
111
112
|
// Read/written only by Insert().
|
data/leveldb/db/table_cache.cc
CHANGED
@@ -42,23 +42,18 @@ TableCache::~TableCache() {
|
|
42
42
|
delete cache_;
|
43
43
|
}
|
44
44
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
Table** tableptr) {
|
49
|
-
if (tableptr != NULL) {
|
50
|
-
*tableptr = NULL;
|
51
|
-
}
|
52
|
-
|
45
|
+
Status TableCache::FindTable(uint64_t file_number, uint64_t file_size,
|
46
|
+
Cache::Handle** handle) {
|
47
|
+
Status s;
|
53
48
|
char buf[sizeof(file_number)];
|
54
49
|
EncodeFixed64(buf, file_number);
|
55
50
|
Slice key(buf, sizeof(buf));
|
56
|
-
|
57
|
-
if (handle == NULL) {
|
51
|
+
*handle = cache_->Lookup(key);
|
52
|
+
if (*handle == NULL) {
|
58
53
|
std::string fname = TableFileName(dbname_, file_number);
|
59
54
|
RandomAccessFile* file = NULL;
|
60
55
|
Table* table = NULL;
|
61
|
-
|
56
|
+
s = env_->NewRandomAccessFile(fname, &file);
|
62
57
|
if (s.ok()) {
|
63
58
|
s = Table::Open(*options_, file, file_size, &table);
|
64
59
|
}
|
@@ -68,13 +63,28 @@ Iterator* TableCache::NewIterator(const ReadOptions& options,
|
|
68
63
|
delete file;
|
69
64
|
// We do not cache error results so that if the error is transient,
|
70
65
|
// or somebody repairs the file, we recover automatically.
|
71
|
-
|
66
|
+
} else {
|
67
|
+
TableAndFile* tf = new TableAndFile;
|
68
|
+
tf->file = file;
|
69
|
+
tf->table = table;
|
70
|
+
*handle = cache_->Insert(key, tf, 1, &DeleteEntry);
|
72
71
|
}
|
72
|
+
}
|
73
|
+
return s;
|
74
|
+
}
|
73
75
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
76
|
+
Iterator* TableCache::NewIterator(const ReadOptions& options,
|
77
|
+
uint64_t file_number,
|
78
|
+
uint64_t file_size,
|
79
|
+
Table** tableptr) {
|
80
|
+
if (tableptr != NULL) {
|
81
|
+
*tableptr = NULL;
|
82
|
+
}
|
83
|
+
|
84
|
+
Cache::Handle* handle = NULL;
|
85
|
+
Status s = FindTable(file_number, file_size, &handle);
|
86
|
+
if (!s.ok()) {
|
87
|
+
return NewErrorIterator(s);
|
78
88
|
}
|
79
89
|
|
80
90
|
Table* table = reinterpret_cast<TableAndFile*>(cache_->Value(handle))->table;
|
@@ -86,6 +96,22 @@ Iterator* TableCache::NewIterator(const ReadOptions& options,
|
|
86
96
|
return result;
|
87
97
|
}
|
88
98
|
|
99
|
+
Status TableCache::Get(const ReadOptions& options,
|
100
|
+
uint64_t file_number,
|
101
|
+
uint64_t file_size,
|
102
|
+
const Slice& k,
|
103
|
+
void* arg,
|
104
|
+
void (*saver)(void*, const Slice&, const Slice&)) {
|
105
|
+
Cache::Handle* handle = NULL;
|
106
|
+
Status s = FindTable(file_number, file_size, &handle);
|
107
|
+
if (s.ok()) {
|
108
|
+
Table* t = reinterpret_cast<TableAndFile*>(cache_->Value(handle))->table;
|
109
|
+
s = t->InternalGet(options, k, arg, saver);
|
110
|
+
cache_->Release(handle);
|
111
|
+
}
|
112
|
+
return s;
|
113
|
+
}
|
114
|
+
|
89
115
|
void TableCache::Evict(uint64_t file_number) {
|
90
116
|
char buf[sizeof(file_number)];
|
91
117
|
EncodeFixed64(buf, file_number);
|
data/leveldb/db/table_cache.h
CHANGED
@@ -35,6 +35,15 @@ class TableCache {
|
|
35
35
|
uint64_t file_size,
|
36
36
|
Table** tableptr = NULL);
|
37
37
|
|
38
|
+
// If a seek to internal key "k" in specified file finds an entry,
|
39
|
+
// call (*handle_result)(arg, found_key, found_value).
|
40
|
+
Status Get(const ReadOptions& options,
|
41
|
+
uint64_t file_number,
|
42
|
+
uint64_t file_size,
|
43
|
+
const Slice& k,
|
44
|
+
void* arg,
|
45
|
+
void (*handle_result)(void*, const Slice&, const Slice&));
|
46
|
+
|
38
47
|
// Evict any entry for the specified file number
|
39
48
|
void Evict(uint64_t file_number);
|
40
49
|
|
@@ -43,6 +52,8 @@ class TableCache {
|
|
43
52
|
const std::string dbname_;
|
44
53
|
const Options* options_;
|
45
54
|
Cache* cache_;
|
55
|
+
|
56
|
+
Status FindTable(uint64_t file_number, uint64_t file_size, Cache::Handle**);
|
46
57
|
};
|
47
58
|
|
48
59
|
} // namespace leveldb
|
data/leveldb/db/version_set.cc
CHANGED
@@ -132,7 +132,7 @@ bool SomeFileOverlapsRange(
|
|
132
132
|
const Comparator* ucmp = icmp.user_comparator();
|
133
133
|
if (!disjoint_sorted_files) {
|
134
134
|
// Need to check against all files
|
135
|
-
for (
|
135
|
+
for (size_t i = 0; i < files.size(); i++) {
|
136
136
|
const FileMetaData* f = files[i];
|
137
137
|
if (AfterFile(ucmp, smallest_user_key, f) ||
|
138
138
|
BeforeFile(ucmp, largest_user_key, f)) {
|
@@ -255,35 +255,34 @@ void Version::AddIterators(const ReadOptions& options,
|
|
255
255
|
}
|
256
256
|
}
|
257
257
|
|
258
|
-
//
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
258
|
+
// Callback from TableCache::Get()
|
259
|
+
namespace {
|
260
|
+
enum SaverState {
|
261
|
+
kNotFound,
|
262
|
+
kFound,
|
263
|
+
kDeleted,
|
264
|
+
kCorrupt,
|
265
|
+
};
|
266
|
+
struct Saver {
|
267
|
+
SaverState state;
|
268
|
+
const Comparator* ucmp;
|
269
|
+
Slice user_key;
|
270
|
+
std::string* value;
|
271
|
+
};
|
272
|
+
}
|
273
|
+
static void SaveValue(void* arg, const Slice& ikey, const Slice& v) {
|
274
|
+
Saver* s = reinterpret_cast<Saver*>(arg);
|
268
275
|
ParsedInternalKey parsed_key;
|
269
|
-
if (!ParseInternalKey(
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
case kTypeDeletion:
|
278
|
-
*s = Status::NotFound(Slice()); // Use an empty error message for speed
|
279
|
-
break;
|
280
|
-
case kTypeValue: {
|
281
|
-
Slice v = iter->value();
|
282
|
-
value->assign(v.data(), v.size());
|
283
|
-
break;
|
276
|
+
if (!ParseInternalKey(ikey, &parsed_key)) {
|
277
|
+
s->state = kCorrupt;
|
278
|
+
} else {
|
279
|
+
if (s->ucmp->Compare(parsed_key.user_key, s->user_key) == 0) {
|
280
|
+
s->state = (parsed_key.type == kTypeValue) ? kFound : kDeleted;
|
281
|
+
if (s->state == kFound) {
|
282
|
+
s->value->assign(v.data(), v.size());
|
283
|
+
}
|
284
284
|
}
|
285
285
|
}
|
286
|
-
return true;
|
287
286
|
}
|
288
287
|
|
289
288
|
static bool NewestFirst(FileMetaData* a, FileMetaData* b) {
|
@@ -361,21 +360,27 @@ Status Version::Get(const ReadOptions& options,
|
|
361
360
|
last_file_read = f;
|
362
361
|
last_file_read_level = level;
|
363
362
|
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
delete iter;
|
363
|
+
Saver saver;
|
364
|
+
saver.state = kNotFound;
|
365
|
+
saver.ucmp = ucmp;
|
366
|
+
saver.user_key = user_key;
|
367
|
+
saver.value = value;
|
368
|
+
s = vset_->table_cache_->Get(options, f->number, f->file_size,
|
369
|
+
ikey, &saver, SaveValue);
|
370
|
+
if (!s.ok()) {
|
373
371
|
return s;
|
374
|
-
}
|
375
|
-
|
376
|
-
|
372
|
+
}
|
373
|
+
switch (saver.state) {
|
374
|
+
case kNotFound:
|
375
|
+
break; // Keep searching in other files
|
376
|
+
case kFound:
|
377
|
+
return s;
|
378
|
+
case kDeleted:
|
379
|
+
s = Status::NotFound(Slice()); // Use empty error message for speed
|
380
|
+
return s;
|
381
|
+
case kCorrupt:
|
382
|
+
s = Status::Corruption("corrupted key for ", user_key);
|
377
383
|
return s;
|
378
|
-
}
|
379
384
|
}
|
380
385
|
}
|
381
386
|
}
|
@@ -1292,7 +1297,7 @@ Compaction* VersionSet::CompactRange(
|
|
1292
1297
|
// Avoid compacting too much in one shot in case the range is large.
|
1293
1298
|
const uint64_t limit = MaxFileSizeForLevel(level);
|
1294
1299
|
uint64_t total = 0;
|
1295
|
-
for (
|
1300
|
+
for (size_t i = 0; i < inputs.size(); i++) {
|
1296
1301
|
uint64_t s = inputs[i]->file_size;
|
1297
1302
|
total += s;
|
1298
1303
|
if (total >= limit) {
|
data/leveldb/db/version_set.h
CHANGED
@@ -173,6 +173,15 @@ class VersionSet {
|
|
173
173
|
// Allocate and return a new file number
|
174
174
|
uint64_t NewFileNumber() { return next_file_number_++; }
|
175
175
|
|
176
|
+
// Arrange to reuse "file_number" unless a newer file number has
|
177
|
+
// already been allocated.
|
178
|
+
// REQUIRES: "file_number" was returned by a call to NewFileNumber().
|
179
|
+
void ReuseFileNumber(uint64_t file_number) {
|
180
|
+
if (next_file_number_ == file_number + 1) {
|
181
|
+
next_file_number_ = file_number;
|
182
|
+
}
|
183
|
+
}
|
184
|
+
|
176
185
|
// Return the number of Table files at the specified level.
|
177
186
|
int NumLevelFiles(int level) const;
|
178
187
|
|
data/leveldb/db/write_batch.cc
CHANGED
@@ -23,6 +23,9 @@
|
|
23
23
|
|
24
24
|
namespace leveldb {
|
25
25
|
|
26
|
+
// WriteBatch header has an 8-byte sequence number followed by a 4-byte count.
|
27
|
+
static const size_t kHeader = 12;
|
28
|
+
|
26
29
|
WriteBatch::WriteBatch() {
|
27
30
|
Clear();
|
28
31
|
}
|
@@ -33,16 +36,16 @@ WriteBatch::Handler::~Handler() { }
|
|
33
36
|
|
34
37
|
void WriteBatch::Clear() {
|
35
38
|
rep_.clear();
|
36
|
-
rep_.resize(
|
39
|
+
rep_.resize(kHeader);
|
37
40
|
}
|
38
41
|
|
39
42
|
Status WriteBatch::Iterate(Handler* handler) const {
|
40
43
|
Slice input(rep_);
|
41
|
-
if (input.size() <
|
44
|
+
if (input.size() < kHeader) {
|
42
45
|
return Status::Corruption("malformed WriteBatch (too small)");
|
43
46
|
}
|
44
47
|
|
45
|
-
input.remove_prefix(
|
48
|
+
input.remove_prefix(kHeader);
|
46
49
|
Slice key, value;
|
47
50
|
int found = 0;
|
48
51
|
while (!input.empty()) {
|
@@ -131,8 +134,14 @@ Status WriteBatchInternal::InsertInto(const WriteBatch* b,
|
|
131
134
|
}
|
132
135
|
|
133
136
|
void WriteBatchInternal::SetContents(WriteBatch* b, const Slice& contents) {
|
134
|
-
assert(contents.size() >=
|
137
|
+
assert(contents.size() >= kHeader);
|
135
138
|
b->rep_.assign(contents.data(), contents.size());
|
136
139
|
}
|
137
140
|
|
141
|
+
void WriteBatchInternal::Append(WriteBatch* dst, const WriteBatch* src) {
|
142
|
+
SetCount(dst, Count(dst) + Count(src));
|
143
|
+
assert(src->rep_.size() >= kHeader);
|
144
|
+
dst->rep_.append(src->rep_.data() + kHeader, src->rep_.size() - kHeader);
|
145
|
+
}
|
146
|
+
|
138
147
|
} // namespace leveldb
|
@@ -39,6 +39,8 @@ class WriteBatchInternal {
|
|
39
39
|
static void SetContents(WriteBatch* batch, const Slice& contents);
|
40
40
|
|
41
41
|
static Status InsertInto(const WriteBatch* batch, MemTable* memtable);
|
42
|
+
|
43
|
+
static void Append(WriteBatch* dst, const WriteBatch* src);
|
42
44
|
};
|
43
45
|
|
44
46
|
} // namespace leveldb
|
@@ -18,6 +18,7 @@ static std::string PrintContents(WriteBatch* b) {
|
|
18
18
|
mem->Ref();
|
19
19
|
std::string state;
|
20
20
|
Status s = WriteBatchInternal::InsertInto(b, mem);
|
21
|
+
int count = 0;
|
21
22
|
Iterator* iter = mem->NewIterator();
|
22
23
|
for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
|
23
24
|
ParsedInternalKey ikey;
|
@@ -29,11 +30,13 @@ static std::string PrintContents(WriteBatch* b) {
|
|
29
30
|
state.append(", ");
|
30
31
|
state.append(iter->value().ToString());
|
31
32
|
state.append(")");
|
33
|
+
count++;
|
32
34
|
break;
|
33
35
|
case kTypeDeletion:
|
34
36
|
state.append("Delete(");
|
35
37
|
state.append(ikey.user_key.ToString());
|
36
38
|
state.append(")");
|
39
|
+
count++;
|
37
40
|
break;
|
38
41
|
}
|
39
42
|
state.append("@");
|
@@ -42,6 +45,8 @@ static std::string PrintContents(WriteBatch* b) {
|
|
42
45
|
delete iter;
|
43
46
|
if (!s.ok()) {
|
44
47
|
state.append("ParseError()");
|
48
|
+
} else if (count != WriteBatchInternal::Count(b)) {
|
49
|
+
state.append("CountMismatch()");
|
45
50
|
}
|
46
51
|
mem->Unref();
|
47
52
|
return state;
|
@@ -82,6 +87,32 @@ TEST(WriteBatchTest, Corruption) {
|
|
82
87
|
PrintContents(&batch));
|
83
88
|
}
|
84
89
|
|
90
|
+
TEST(WriteBatchTest, Append) {
|
91
|
+
WriteBatch b1, b2;
|
92
|
+
WriteBatchInternal::SetSequence(&b1, 200);
|
93
|
+
WriteBatchInternal::SetSequence(&b2, 300);
|
94
|
+
WriteBatchInternal::Append(&b1, &b2);
|
95
|
+
ASSERT_EQ("",
|
96
|
+
PrintContents(&b1));
|
97
|
+
b2.Put("a", "va");
|
98
|
+
WriteBatchInternal::Append(&b1, &b2);
|
99
|
+
ASSERT_EQ("Put(a, va)@200",
|
100
|
+
PrintContents(&b1));
|
101
|
+
b2.Clear();
|
102
|
+
b2.Put("b", "vb");
|
103
|
+
WriteBatchInternal::Append(&b1, &b2);
|
104
|
+
ASSERT_EQ("Put(a, va)@200"
|
105
|
+
"Put(b, vb)@201",
|
106
|
+
PrintContents(&b1));
|
107
|
+
b2.Delete("foo");
|
108
|
+
WriteBatchInternal::Append(&b1, &b2);
|
109
|
+
ASSERT_EQ("Put(a, va)@200"
|
110
|
+
"Put(b, vb)@202"
|
111
|
+
"Put(b, vb)@201"
|
112
|
+
"Delete(foo)@203",
|
113
|
+
PrintContents(&b1));
|
114
|
+
}
|
115
|
+
|
85
116
|
} // namespace leveldb
|
86
117
|
|
87
118
|
int main(int argc, char** argv) {
|
data/leveldb/include/leveldb/c.h
CHANGED
@@ -55,6 +55,7 @@ typedef struct leveldb_cache_t leveldb_cache_t;
|
|
55
55
|
typedef struct leveldb_comparator_t leveldb_comparator_t;
|
56
56
|
typedef struct leveldb_env_t leveldb_env_t;
|
57
57
|
typedef struct leveldb_filelock_t leveldb_filelock_t;
|
58
|
+
typedef struct leveldb_filterpolicy_t leveldb_filterpolicy_t;
|
58
59
|
typedef struct leveldb_iterator_t leveldb_iterator_t;
|
59
60
|
typedef struct leveldb_logger_t leveldb_logger_t;
|
60
61
|
typedef struct leveldb_options_t leveldb_options_t;
|
@@ -127,6 +128,11 @@ extern void leveldb_approximate_sizes(
|
|
127
128
|
const char* const* range_limit_key, const size_t* range_limit_key_len,
|
128
129
|
uint64_t* sizes);
|
129
130
|
|
131
|
+
extern void leveldb_compact_range(
|
132
|
+
leveldb_t* db,
|
133
|
+
const char* start_key, size_t start_key_len,
|
134
|
+
const char* limit_key, size_t limit_key_len);
|
135
|
+
|
130
136
|
/* Management operations */
|
131
137
|
|
132
138
|
extern void leveldb_destroy_db(
|
@@ -177,6 +183,9 @@ extern void leveldb_options_destroy(leveldb_options_t*);
|
|
177
183
|
extern void leveldb_options_set_comparator(
|
178
184
|
leveldb_options_t*,
|
179
185
|
leveldb_comparator_t*);
|
186
|
+
extern void leveldb_options_set_filter_policy(
|
187
|
+
leveldb_options_t*,
|
188
|
+
leveldb_filterpolicy_t*);
|
180
189
|
extern void leveldb_options_set_create_if_missing(
|
181
190
|
leveldb_options_t*, unsigned char);
|
182
191
|
extern void leveldb_options_set_error_if_exists(
|
@@ -209,6 +218,26 @@ extern leveldb_comparator_t* leveldb_comparator_create(
|
|
209
218
|
const char* (*name)(void*));
|
210
219
|
extern void leveldb_comparator_destroy(leveldb_comparator_t*);
|
211
220
|
|
221
|
+
/* Filter policy */
|
222
|
+
|
223
|
+
extern leveldb_filterpolicy_t* leveldb_filterpolicy_create(
|
224
|
+
void* state,
|
225
|
+
void (*destructor)(void*),
|
226
|
+
char* (*create_filter)(
|
227
|
+
void*,
|
228
|
+
const char* const* key_array, const size_t* key_length_array,
|
229
|
+
int num_keys,
|
230
|
+
size_t* filter_length),
|
231
|
+
unsigned char (*key_may_match)(
|
232
|
+
void*,
|
233
|
+
const char* key, size_t length,
|
234
|
+
const char* filter, size_t filter_length),
|
235
|
+
const char* (*name)(void*));
|
236
|
+
extern void leveldb_filterpolicy_destroy(leveldb_filterpolicy_t*);
|
237
|
+
|
238
|
+
extern leveldb_filterpolicy_t* leveldb_filterpolicy_create_bloom(
|
239
|
+
int bits_per_key);
|
240
|
+
|
212
241
|
/* Read options */
|
213
242
|
|
214
243
|
extern leveldb_readoptions_t* leveldb_readoptions_create();
|