filiptepper-leveldb-ruby 0.14
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 +72 -0
- data/ext/leveldb/extconf.rb +14 -0
- data/ext/leveldb/leveldb.cc +530 -0
- data/ext/leveldb/platform.rb +83 -0
- data/leveldb/Makefile +191 -0
- data/leveldb/build_detect_platform +160 -0
- data/leveldb/db/builder.cc +88 -0
- data/leveldb/db/builder.h +34 -0
- data/leveldb/db/c.cc +581 -0
- data/leveldb/db/corruption_test.cc +359 -0
- data/leveldb/db/db_bench.cc +970 -0
- data/leveldb/db/db_impl.cc +1448 -0
- data/leveldb/db/db_impl.h +194 -0
- data/leveldb/db/db_iter.cc +299 -0
- data/leveldb/db/db_iter.h +26 -0
- data/leveldb/db/db_test.cc +1901 -0
- data/leveldb/db/dbformat.cc +140 -0
- data/leveldb/db/dbformat.h +227 -0
- data/leveldb/db/dbformat_test.cc +112 -0
- data/leveldb/db/filename.cc +139 -0
- data/leveldb/db/filename.h +80 -0
- data/leveldb/db/filename_test.cc +122 -0
- data/leveldb/db/log_format.h +35 -0
- data/leveldb/db/log_reader.cc +259 -0
- data/leveldb/db/log_reader.h +108 -0
- data/leveldb/db/log_test.cc +500 -0
- data/leveldb/db/log_writer.cc +103 -0
- data/leveldb/db/log_writer.h +48 -0
- data/leveldb/db/memtable.cc +145 -0
- data/leveldb/db/memtable.h +91 -0
- data/leveldb/db/repair.cc +389 -0
- data/leveldb/db/skiplist.h +379 -0
- data/leveldb/db/skiplist_test.cc +378 -0
- data/leveldb/db/snapshot.h +66 -0
- data/leveldb/db/table_cache.cc +121 -0
- data/leveldb/db/table_cache.h +61 -0
- data/leveldb/db/version_edit.cc +266 -0
- data/leveldb/db/version_edit.h +107 -0
- data/leveldb/db/version_edit_test.cc +46 -0
- data/leveldb/db/version_set.cc +1402 -0
- data/leveldb/db/version_set.h +370 -0
- data/leveldb/db/version_set_test.cc +179 -0
- data/leveldb/db/write_batch.cc +147 -0
- data/leveldb/db/write_batch_internal.h +49 -0
- data/leveldb/db/write_batch_test.cc +120 -0
- data/leveldb/helpers/memenv/memenv.cc +374 -0
- data/leveldb/helpers/memenv/memenv.h +20 -0
- data/leveldb/helpers/memenv/memenv_test.cc +232 -0
- data/leveldb/include/leveldb/c.h +275 -0
- data/leveldb/include/leveldb/cache.h +99 -0
- data/leveldb/include/leveldb/comparator.h +63 -0
- data/leveldb/include/leveldb/db.h +161 -0
- data/leveldb/include/leveldb/env.h +323 -0
- data/leveldb/include/leveldb/filter_policy.h +70 -0
- data/leveldb/include/leveldb/iterator.h +100 -0
- data/leveldb/include/leveldb/options.h +195 -0
- data/leveldb/include/leveldb/slice.h +109 -0
- data/leveldb/include/leveldb/status.h +106 -0
- data/leveldb/include/leveldb/table.h +85 -0
- data/leveldb/include/leveldb/table_builder.h +92 -0
- data/leveldb/include/leveldb/write_batch.h +64 -0
- data/leveldb/port/atomic_pointer.h +144 -0
- data/leveldb/port/port.h +21 -0
- data/leveldb/port/port_android.cc +64 -0
- data/leveldb/port/port_android.h +159 -0
- data/leveldb/port/port_example.h +125 -0
- data/leveldb/port/port_posix.cc +50 -0
- data/leveldb/port/port_posix.h +129 -0
- data/leveldb/port/win/stdint.h +24 -0
- data/leveldb/table/block.cc +267 -0
- data/leveldb/table/block.h +44 -0
- data/leveldb/table/block_builder.cc +109 -0
- data/leveldb/table/block_builder.h +57 -0
- 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 +145 -0
- data/leveldb/table/format.h +108 -0
- data/leveldb/table/iterator.cc +67 -0
- data/leveldb/table/iterator_wrapper.h +63 -0
- data/leveldb/table/merger.cc +197 -0
- data/leveldb/table/merger.h +26 -0
- data/leveldb/table/table.cc +276 -0
- data/leveldb/table/table_builder.cc +270 -0
- data/leveldb/table/table_test.cc +838 -0
- data/leveldb/table/two_level_iterator.cc +182 -0
- data/leveldb/table/two_level_iterator.h +34 -0
- data/leveldb/util/arena.cc +68 -0
- data/leveldb/util/arena.h +68 -0
- data/leveldb/util/arena_test.cc +68 -0
- data/leveldb/util/bloom.cc +95 -0
- data/leveldb/util/bloom_test.cc +159 -0
- data/leveldb/util/cache.cc +328 -0
- data/leveldb/util/cache_test.cc +186 -0
- data/leveldb/util/coding.cc +194 -0
- data/leveldb/util/coding.h +104 -0
- data/leveldb/util/coding_test.cc +173 -0
- data/leveldb/util/comparator.cc +76 -0
- data/leveldb/util/crc32c.cc +332 -0
- data/leveldb/util/crc32c.h +45 -0
- data/leveldb/util/crc32c_test.cc +72 -0
- data/leveldb/util/env.cc +96 -0
- data/leveldb/util/env_posix.cc +609 -0
- data/leveldb/util/env_test.cc +104 -0
- data/leveldb/util/filter_policy.cc +11 -0
- data/leveldb/util/hash.cc +45 -0
- data/leveldb/util/hash.h +19 -0
- data/leveldb/util/histogram.cc +139 -0
- data/leveldb/util/histogram.h +42 -0
- data/leveldb/util/logging.cc +81 -0
- data/leveldb/util/logging.h +47 -0
- data/leveldb/util/mutexlock.h +39 -0
- data/leveldb/util/options.cc +29 -0
- data/leveldb/util/posix_logger.h +98 -0
- data/leveldb/util/random.h +59 -0
- data/leveldb/util/status.cc +75 -0
- data/leveldb/util/testharness.cc +77 -0
- data/leveldb/util/testharness.h +138 -0
- data/leveldb/util/testutil.cc +51 -0
- data/leveldb/util/testutil.h +53 -0
- data/lib/leveldb.rb +76 -0
- metadata +175 -0
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
|
|
2
|
+
// Use of this source code is governed by a BSD-style license that can be
|
|
3
|
+
// found in the LICENSE file. See the AUTHORS file for names of contributors.
|
|
4
|
+
|
|
5
|
+
#ifndef STORAGE_LEVELDB_TABLE_FORMAT_H_
|
|
6
|
+
#define STORAGE_LEVELDB_TABLE_FORMAT_H_
|
|
7
|
+
|
|
8
|
+
#include <string>
|
|
9
|
+
#include <stdint.h>
|
|
10
|
+
#include "leveldb/slice.h"
|
|
11
|
+
#include "leveldb/status.h"
|
|
12
|
+
#include "leveldb/table_builder.h"
|
|
13
|
+
|
|
14
|
+
namespace leveldb {
|
|
15
|
+
|
|
16
|
+
class Block;
|
|
17
|
+
class RandomAccessFile;
|
|
18
|
+
struct ReadOptions;
|
|
19
|
+
|
|
20
|
+
// BlockHandle is a pointer to the extent of a file that stores a data
|
|
21
|
+
// block or a meta block.
|
|
22
|
+
class BlockHandle {
|
|
23
|
+
public:
|
|
24
|
+
BlockHandle();
|
|
25
|
+
|
|
26
|
+
// The offset of the block in the file.
|
|
27
|
+
uint64_t offset() const { return offset_; }
|
|
28
|
+
void set_offset(uint64_t offset) { offset_ = offset; }
|
|
29
|
+
|
|
30
|
+
// The size of the stored block
|
|
31
|
+
uint64_t size() const { return size_; }
|
|
32
|
+
void set_size(uint64_t size) { size_ = size; }
|
|
33
|
+
|
|
34
|
+
void EncodeTo(std::string* dst) const;
|
|
35
|
+
Status DecodeFrom(Slice* input);
|
|
36
|
+
|
|
37
|
+
// Maximum encoding length of a BlockHandle
|
|
38
|
+
enum { kMaxEncodedLength = 10 + 10 };
|
|
39
|
+
|
|
40
|
+
private:
|
|
41
|
+
uint64_t offset_;
|
|
42
|
+
uint64_t size_;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
// Footer encapsulates the fixed information stored at the tail
|
|
46
|
+
// end of every table file.
|
|
47
|
+
class Footer {
|
|
48
|
+
public:
|
|
49
|
+
Footer() { }
|
|
50
|
+
|
|
51
|
+
// The block handle for the metaindex block of the table
|
|
52
|
+
const BlockHandle& metaindex_handle() const { return metaindex_handle_; }
|
|
53
|
+
void set_metaindex_handle(const BlockHandle& h) { metaindex_handle_ = h; }
|
|
54
|
+
|
|
55
|
+
// The block handle for the index block of the table
|
|
56
|
+
const BlockHandle& index_handle() const {
|
|
57
|
+
return index_handle_;
|
|
58
|
+
}
|
|
59
|
+
void set_index_handle(const BlockHandle& h) {
|
|
60
|
+
index_handle_ = h;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
void EncodeTo(std::string* dst) const;
|
|
64
|
+
Status DecodeFrom(Slice* input);
|
|
65
|
+
|
|
66
|
+
// Encoded length of a Footer. Note that the serialization of a
|
|
67
|
+
// Footer will always occupy exactly this many bytes. It consists
|
|
68
|
+
// of two block handles and a magic number.
|
|
69
|
+
enum {
|
|
70
|
+
kEncodedLength = 2*BlockHandle::kMaxEncodedLength + 8
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
private:
|
|
74
|
+
BlockHandle metaindex_handle_;
|
|
75
|
+
BlockHandle index_handle_;
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
// kTableMagicNumber was picked by running
|
|
79
|
+
// echo http://code.google.com/p/leveldb/ | sha1sum
|
|
80
|
+
// and taking the leading 64 bits.
|
|
81
|
+
static const uint64_t kTableMagicNumber = 0xdb4775248b80fb57ull;
|
|
82
|
+
|
|
83
|
+
// 1-byte type + 32-bit crc
|
|
84
|
+
static const size_t kBlockTrailerSize = 5;
|
|
85
|
+
|
|
86
|
+
struct BlockContents {
|
|
87
|
+
Slice data; // Actual contents of data
|
|
88
|
+
bool cachable; // True iff data can be cached
|
|
89
|
+
bool heap_allocated; // True iff caller should delete[] data.data()
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
// Read the block identified by "handle" from "file". On failure
|
|
93
|
+
// return non-OK. On success fill *result and return OK.
|
|
94
|
+
extern Status ReadBlock(RandomAccessFile* file,
|
|
95
|
+
const ReadOptions& options,
|
|
96
|
+
const BlockHandle& handle,
|
|
97
|
+
BlockContents* result);
|
|
98
|
+
|
|
99
|
+
// Implementation details follow. Clients should ignore,
|
|
100
|
+
|
|
101
|
+
inline BlockHandle::BlockHandle()
|
|
102
|
+
: offset_(~static_cast<uint64_t>(0)),
|
|
103
|
+
size_(~static_cast<uint64_t>(0)) {
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
} // namespace leveldb
|
|
107
|
+
|
|
108
|
+
#endif // STORAGE_LEVELDB_TABLE_FORMAT_H_
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
|
|
2
|
+
// Use of this source code is governed by a BSD-style license that can be
|
|
3
|
+
// found in the LICENSE file. See the AUTHORS file for names of contributors.
|
|
4
|
+
|
|
5
|
+
#include "leveldb/iterator.h"
|
|
6
|
+
|
|
7
|
+
namespace leveldb {
|
|
8
|
+
|
|
9
|
+
Iterator::Iterator() {
|
|
10
|
+
cleanup_.function = NULL;
|
|
11
|
+
cleanup_.next = NULL;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
Iterator::~Iterator() {
|
|
15
|
+
if (cleanup_.function != NULL) {
|
|
16
|
+
(*cleanup_.function)(cleanup_.arg1, cleanup_.arg2);
|
|
17
|
+
for (Cleanup* c = cleanup_.next; c != NULL; ) {
|
|
18
|
+
(*c->function)(c->arg1, c->arg2);
|
|
19
|
+
Cleanup* next = c->next;
|
|
20
|
+
delete c;
|
|
21
|
+
c = next;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
void Iterator::RegisterCleanup(CleanupFunction func, void* arg1, void* arg2) {
|
|
27
|
+
assert(func != NULL);
|
|
28
|
+
Cleanup* c;
|
|
29
|
+
if (cleanup_.function == NULL) {
|
|
30
|
+
c = &cleanup_;
|
|
31
|
+
} else {
|
|
32
|
+
c = new Cleanup;
|
|
33
|
+
c->next = cleanup_.next;
|
|
34
|
+
cleanup_.next = c;
|
|
35
|
+
}
|
|
36
|
+
c->function = func;
|
|
37
|
+
c->arg1 = arg1;
|
|
38
|
+
c->arg2 = arg2;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
namespace {
|
|
42
|
+
class EmptyIterator : public Iterator {
|
|
43
|
+
public:
|
|
44
|
+
EmptyIterator(const Status& s) : status_(s) { }
|
|
45
|
+
virtual bool Valid() const { return false; }
|
|
46
|
+
virtual void Seek(const Slice& target) { }
|
|
47
|
+
virtual void SeekToFirst() { }
|
|
48
|
+
virtual void SeekToLast() { }
|
|
49
|
+
virtual void Next() { assert(false); }
|
|
50
|
+
virtual void Prev() { assert(false); }
|
|
51
|
+
Slice key() const { assert(false); return Slice(); }
|
|
52
|
+
Slice value() const { assert(false); return Slice(); }
|
|
53
|
+
virtual Status status() const { return status_; }
|
|
54
|
+
private:
|
|
55
|
+
Status status_;
|
|
56
|
+
};
|
|
57
|
+
} // namespace
|
|
58
|
+
|
|
59
|
+
Iterator* NewEmptyIterator() {
|
|
60
|
+
return new EmptyIterator(Status::OK());
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
Iterator* NewErrorIterator(const Status& status) {
|
|
64
|
+
return new EmptyIterator(status);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
} // namespace leveldb
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
|
|
2
|
+
// Use of this source code is governed by a BSD-style license that can be
|
|
3
|
+
// found in the LICENSE file. See the AUTHORS file for names of contributors.
|
|
4
|
+
|
|
5
|
+
#ifndef STORAGE_LEVELDB_TABLE_ITERATOR_WRAPPER_H_
|
|
6
|
+
#define STORAGE_LEVELDB_TABLE_ITERATOR_WRAPPER_H_
|
|
7
|
+
|
|
8
|
+
namespace leveldb {
|
|
9
|
+
|
|
10
|
+
// A internal wrapper class with an interface similar to Iterator that
|
|
11
|
+
// caches the valid() and key() results for an underlying iterator.
|
|
12
|
+
// This can help avoid virtual function calls and also gives better
|
|
13
|
+
// cache locality.
|
|
14
|
+
class IteratorWrapper {
|
|
15
|
+
public:
|
|
16
|
+
IteratorWrapper(): iter_(NULL), valid_(false) { }
|
|
17
|
+
explicit IteratorWrapper(Iterator* iter): iter_(NULL) {
|
|
18
|
+
Set(iter);
|
|
19
|
+
}
|
|
20
|
+
~IteratorWrapper() { delete iter_; }
|
|
21
|
+
Iterator* iter() const { return iter_; }
|
|
22
|
+
|
|
23
|
+
// Takes ownership of "iter" and will delete it when destroyed, or
|
|
24
|
+
// when Set() is invoked again.
|
|
25
|
+
void Set(Iterator* iter) {
|
|
26
|
+
delete iter_;
|
|
27
|
+
iter_ = iter;
|
|
28
|
+
if (iter_ == NULL) {
|
|
29
|
+
valid_ = false;
|
|
30
|
+
} else {
|
|
31
|
+
Update();
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
// Iterator interface methods
|
|
37
|
+
bool Valid() const { return valid_; }
|
|
38
|
+
Slice key() const { assert(Valid()); return key_; }
|
|
39
|
+
Slice value() const { assert(Valid()); return iter_->value(); }
|
|
40
|
+
// Methods below require iter() != NULL
|
|
41
|
+
Status status() const { assert(iter_); return iter_->status(); }
|
|
42
|
+
void Next() { assert(iter_); iter_->Next(); Update(); }
|
|
43
|
+
void Prev() { assert(iter_); iter_->Prev(); Update(); }
|
|
44
|
+
void Seek(const Slice& k) { assert(iter_); iter_->Seek(k); Update(); }
|
|
45
|
+
void SeekToFirst() { assert(iter_); iter_->SeekToFirst(); Update(); }
|
|
46
|
+
void SeekToLast() { assert(iter_); iter_->SeekToLast(); Update(); }
|
|
47
|
+
|
|
48
|
+
private:
|
|
49
|
+
void Update() {
|
|
50
|
+
valid_ = iter_->Valid();
|
|
51
|
+
if (valid_) {
|
|
52
|
+
key_ = iter_->key();
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
Iterator* iter_;
|
|
57
|
+
bool valid_;
|
|
58
|
+
Slice key_;
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
} // namespace leveldb
|
|
62
|
+
|
|
63
|
+
#endif // STORAGE_LEVELDB_TABLE_ITERATOR_WRAPPER_H_
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
|
|
2
|
+
// Use of this source code is governed by a BSD-style license that can be
|
|
3
|
+
// found in the LICENSE file. See the AUTHORS file for names of contributors.
|
|
4
|
+
|
|
5
|
+
#include "table/merger.h"
|
|
6
|
+
|
|
7
|
+
#include "leveldb/comparator.h"
|
|
8
|
+
#include "leveldb/iterator.h"
|
|
9
|
+
#include "table/iterator_wrapper.h"
|
|
10
|
+
|
|
11
|
+
namespace leveldb {
|
|
12
|
+
|
|
13
|
+
namespace {
|
|
14
|
+
class MergingIterator : public Iterator {
|
|
15
|
+
public:
|
|
16
|
+
MergingIterator(const Comparator* comparator, Iterator** children, int n)
|
|
17
|
+
: comparator_(comparator),
|
|
18
|
+
children_(new IteratorWrapper[n]),
|
|
19
|
+
n_(n),
|
|
20
|
+
current_(NULL),
|
|
21
|
+
direction_(kForward) {
|
|
22
|
+
for (int i = 0; i < n; i++) {
|
|
23
|
+
children_[i].Set(children[i]);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
virtual ~MergingIterator() {
|
|
28
|
+
delete[] children_;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
virtual bool Valid() const {
|
|
32
|
+
return (current_ != NULL);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
virtual void SeekToFirst() {
|
|
36
|
+
for (int i = 0; i < n_; i++) {
|
|
37
|
+
children_[i].SeekToFirst();
|
|
38
|
+
}
|
|
39
|
+
FindSmallest();
|
|
40
|
+
direction_ = kForward;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
virtual void SeekToLast() {
|
|
44
|
+
for (int i = 0; i < n_; i++) {
|
|
45
|
+
children_[i].SeekToLast();
|
|
46
|
+
}
|
|
47
|
+
FindLargest();
|
|
48
|
+
direction_ = kReverse;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
virtual void Seek(const Slice& target) {
|
|
52
|
+
for (int i = 0; i < n_; i++) {
|
|
53
|
+
children_[i].Seek(target);
|
|
54
|
+
}
|
|
55
|
+
FindSmallest();
|
|
56
|
+
direction_ = kForward;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
virtual void Next() {
|
|
60
|
+
assert(Valid());
|
|
61
|
+
|
|
62
|
+
// Ensure that all children are positioned after key().
|
|
63
|
+
// If we are moving in the forward direction, it is already
|
|
64
|
+
// true for all of the non-current_ children since current_ is
|
|
65
|
+
// the smallest child and key() == current_->key(). Otherwise,
|
|
66
|
+
// we explicitly position the non-current_ children.
|
|
67
|
+
if (direction_ != kForward) {
|
|
68
|
+
for (int i = 0; i < n_; i++) {
|
|
69
|
+
IteratorWrapper* child = &children_[i];
|
|
70
|
+
if (child != current_) {
|
|
71
|
+
child->Seek(key());
|
|
72
|
+
if (child->Valid() &&
|
|
73
|
+
comparator_->Compare(key(), child->key()) == 0) {
|
|
74
|
+
child->Next();
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
direction_ = kForward;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
current_->Next();
|
|
82
|
+
FindSmallest();
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
virtual void Prev() {
|
|
86
|
+
assert(Valid());
|
|
87
|
+
|
|
88
|
+
// Ensure that all children are positioned before key().
|
|
89
|
+
// If we are moving in the reverse direction, it is already
|
|
90
|
+
// true for all of the non-current_ children since current_ is
|
|
91
|
+
// the largest child and key() == current_->key(). Otherwise,
|
|
92
|
+
// we explicitly position the non-current_ children.
|
|
93
|
+
if (direction_ != kReverse) {
|
|
94
|
+
for (int i = 0; i < n_; i++) {
|
|
95
|
+
IteratorWrapper* child = &children_[i];
|
|
96
|
+
if (child != current_) {
|
|
97
|
+
child->Seek(key());
|
|
98
|
+
if (child->Valid()) {
|
|
99
|
+
// Child is at first entry >= key(). Step back one to be < key()
|
|
100
|
+
child->Prev();
|
|
101
|
+
} else {
|
|
102
|
+
// Child has no entries >= key(). Position at last entry.
|
|
103
|
+
child->SeekToLast();
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
direction_ = kReverse;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
current_->Prev();
|
|
111
|
+
FindLargest();
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
virtual Slice key() const {
|
|
115
|
+
assert(Valid());
|
|
116
|
+
return current_->key();
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
virtual Slice value() const {
|
|
120
|
+
assert(Valid());
|
|
121
|
+
return current_->value();
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
virtual Status status() const {
|
|
125
|
+
Status status;
|
|
126
|
+
for (int i = 0; i < n_; i++) {
|
|
127
|
+
status = children_[i].status();
|
|
128
|
+
if (!status.ok()) {
|
|
129
|
+
break;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return status;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
private:
|
|
136
|
+
void FindSmallest();
|
|
137
|
+
void FindLargest();
|
|
138
|
+
|
|
139
|
+
// We might want to use a heap in case there are lots of children.
|
|
140
|
+
// For now we use a simple array since we expect a very small number
|
|
141
|
+
// of children in leveldb.
|
|
142
|
+
const Comparator* comparator_;
|
|
143
|
+
IteratorWrapper* children_;
|
|
144
|
+
int n_;
|
|
145
|
+
IteratorWrapper* current_;
|
|
146
|
+
|
|
147
|
+
// Which direction is the iterator moving?
|
|
148
|
+
enum Direction {
|
|
149
|
+
kForward,
|
|
150
|
+
kReverse
|
|
151
|
+
};
|
|
152
|
+
Direction direction_;
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
void MergingIterator::FindSmallest() {
|
|
156
|
+
IteratorWrapper* smallest = NULL;
|
|
157
|
+
for (int i = 0; i < n_; i++) {
|
|
158
|
+
IteratorWrapper* child = &children_[i];
|
|
159
|
+
if (child->Valid()) {
|
|
160
|
+
if (smallest == NULL) {
|
|
161
|
+
smallest = child;
|
|
162
|
+
} else if (comparator_->Compare(child->key(), smallest->key()) < 0) {
|
|
163
|
+
smallest = child;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
current_ = smallest;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
void MergingIterator::FindLargest() {
|
|
171
|
+
IteratorWrapper* largest = NULL;
|
|
172
|
+
for (int i = n_-1; i >= 0; i--) {
|
|
173
|
+
IteratorWrapper* child = &children_[i];
|
|
174
|
+
if (child->Valid()) {
|
|
175
|
+
if (largest == NULL) {
|
|
176
|
+
largest = child;
|
|
177
|
+
} else if (comparator_->Compare(child->key(), largest->key()) > 0) {
|
|
178
|
+
largest = child;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
current_ = largest;
|
|
183
|
+
}
|
|
184
|
+
} // namespace
|
|
185
|
+
|
|
186
|
+
Iterator* NewMergingIterator(const Comparator* cmp, Iterator** list, int n) {
|
|
187
|
+
assert(n >= 0);
|
|
188
|
+
if (n == 0) {
|
|
189
|
+
return NewEmptyIterator();
|
|
190
|
+
} else if (n == 1) {
|
|
191
|
+
return list[0];
|
|
192
|
+
} else {
|
|
193
|
+
return new MergingIterator(cmp, list, n);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
} // namespace leveldb
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
|
|
2
|
+
// Use of this source code is governed by a BSD-style license that can be
|
|
3
|
+
// found in the LICENSE file. See the AUTHORS file for names of contributors.
|
|
4
|
+
|
|
5
|
+
#ifndef STORAGE_LEVELDB_TABLE_MERGER_H_
|
|
6
|
+
#define STORAGE_LEVELDB_TABLE_MERGER_H_
|
|
7
|
+
|
|
8
|
+
namespace leveldb {
|
|
9
|
+
|
|
10
|
+
class Comparator;
|
|
11
|
+
class Iterator;
|
|
12
|
+
|
|
13
|
+
// Return an iterator that provided the union of the data in
|
|
14
|
+
// children[0,n-1]. Takes ownership of the child iterators and
|
|
15
|
+
// will delete them when the result iterator is deleted.
|
|
16
|
+
//
|
|
17
|
+
// The result does no duplicate suppression. I.e., if a particular
|
|
18
|
+
// key is present in K child iterators, it will be yielded K times.
|
|
19
|
+
//
|
|
20
|
+
// REQUIRES: n >= 0
|
|
21
|
+
extern Iterator* NewMergingIterator(
|
|
22
|
+
const Comparator* comparator, Iterator** children, int n);
|
|
23
|
+
|
|
24
|
+
} // namespace leveldb
|
|
25
|
+
|
|
26
|
+
#endif // STORAGE_LEVELDB_TABLE_MERGER_H_
|