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
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();
|