leveldb-ruby 0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (113) hide show
  1. data/README +17 -0
  2. data/ext/leveldb/extconf.rb +10 -0
  3. data/ext/leveldb/leveldb.cc +181 -0
  4. data/leveldb/Makefile +172 -0
  5. data/leveldb/db/builder.cc +90 -0
  6. data/leveldb/db/builder.h +36 -0
  7. data/leveldb/db/corruption_test.cc +354 -0
  8. data/leveldb/db/db_bench.cc +677 -0
  9. data/leveldb/db/db_impl.cc +1236 -0
  10. data/leveldb/db/db_impl.h +180 -0
  11. data/leveldb/db/db_iter.cc +298 -0
  12. data/leveldb/db/db_iter.h +26 -0
  13. data/leveldb/db/db_test.cc +1192 -0
  14. data/leveldb/db/dbformat.cc +87 -0
  15. data/leveldb/db/dbformat.h +165 -0
  16. data/leveldb/db/dbformat_test.cc +112 -0
  17. data/leveldb/db/filename.cc +135 -0
  18. data/leveldb/db/filename.h +80 -0
  19. data/leveldb/db/filename_test.cc +122 -0
  20. data/leveldb/db/log_format.h +35 -0
  21. data/leveldb/db/log_reader.cc +254 -0
  22. data/leveldb/db/log_reader.h +108 -0
  23. data/leveldb/db/log_test.cc +500 -0
  24. data/leveldb/db/log_writer.cc +103 -0
  25. data/leveldb/db/log_writer.h +48 -0
  26. data/leveldb/db/memtable.cc +108 -0
  27. data/leveldb/db/memtable.h +85 -0
  28. data/leveldb/db/repair.cc +384 -0
  29. data/leveldb/db/skiplist.h +378 -0
  30. data/leveldb/db/skiplist_test.cc +378 -0
  31. data/leveldb/db/snapshot.h +66 -0
  32. data/leveldb/db/table_cache.cc +95 -0
  33. data/leveldb/db/table_cache.h +50 -0
  34. data/leveldb/db/version_edit.cc +268 -0
  35. data/leveldb/db/version_edit.h +106 -0
  36. data/leveldb/db/version_edit_test.cc +46 -0
  37. data/leveldb/db/version_set.cc +1060 -0
  38. data/leveldb/db/version_set.h +306 -0
  39. data/leveldb/db/write_batch.cc +138 -0
  40. data/leveldb/db/write_batch_internal.h +45 -0
  41. data/leveldb/db/write_batch_test.cc +89 -0
  42. data/leveldb/include/leveldb/cache.h +99 -0
  43. data/leveldb/include/leveldb/comparator.h +63 -0
  44. data/leveldb/include/leveldb/db.h +148 -0
  45. data/leveldb/include/leveldb/env.h +302 -0
  46. data/leveldb/include/leveldb/iterator.h +100 -0
  47. data/leveldb/include/leveldb/options.h +198 -0
  48. data/leveldb/include/leveldb/slice.h +109 -0
  49. data/leveldb/include/leveldb/status.h +100 -0
  50. data/leveldb/include/leveldb/table.h +70 -0
  51. data/leveldb/include/leveldb/table_builder.h +91 -0
  52. data/leveldb/include/leveldb/write_batch.h +64 -0
  53. data/leveldb/port/port.h +23 -0
  54. data/leveldb/port/port_android.cc +64 -0
  55. data/leveldb/port/port_android.h +150 -0
  56. data/leveldb/port/port_chromium.cc +80 -0
  57. data/leveldb/port/port_chromium.h +97 -0
  58. data/leveldb/port/port_example.h +115 -0
  59. data/leveldb/port/port_osx.cc +50 -0
  60. data/leveldb/port/port_osx.h +125 -0
  61. data/leveldb/port/port_posix.cc +50 -0
  62. data/leveldb/port/port_posix.h +94 -0
  63. data/leveldb/port/sha1_portable.cc +298 -0
  64. data/leveldb/port/sha1_portable.h +25 -0
  65. data/leveldb/port/sha1_test.cc +39 -0
  66. data/leveldb/port/win/stdint.h +24 -0
  67. data/leveldb/table/block.cc +263 -0
  68. data/leveldb/table/block.h +43 -0
  69. data/leveldb/table/block_builder.cc +109 -0
  70. data/leveldb/table/block_builder.h +57 -0
  71. data/leveldb/table/format.cc +131 -0
  72. data/leveldb/table/format.h +103 -0
  73. data/leveldb/table/iterator.cc +67 -0
  74. data/leveldb/table/iterator_wrapper.h +63 -0
  75. data/leveldb/table/merger.cc +197 -0
  76. data/leveldb/table/merger.h +26 -0
  77. data/leveldb/table/table.cc +175 -0
  78. data/leveldb/table/table_builder.cc +227 -0
  79. data/leveldb/table/table_test.cc +845 -0
  80. data/leveldb/table/two_level_iterator.cc +182 -0
  81. data/leveldb/table/two_level_iterator.h +34 -0
  82. data/leveldb/util/arena.cc +68 -0
  83. data/leveldb/util/arena.h +68 -0
  84. data/leveldb/util/arena_test.cc +68 -0
  85. data/leveldb/util/cache.cc +255 -0
  86. data/leveldb/util/cache_test.cc +169 -0
  87. data/leveldb/util/coding.cc +194 -0
  88. data/leveldb/util/coding.h +104 -0
  89. data/leveldb/util/coding_test.cc +173 -0
  90. data/leveldb/util/comparator.cc +72 -0
  91. data/leveldb/util/crc32c.cc +332 -0
  92. data/leveldb/util/crc32c.h +45 -0
  93. data/leveldb/util/crc32c_test.cc +72 -0
  94. data/leveldb/util/env.cc +77 -0
  95. data/leveldb/util/env_chromium.cc +612 -0
  96. data/leveldb/util/env_posix.cc +606 -0
  97. data/leveldb/util/env_test.cc +102 -0
  98. data/leveldb/util/hash.cc +45 -0
  99. data/leveldb/util/hash.h +19 -0
  100. data/leveldb/util/histogram.cc +128 -0
  101. data/leveldb/util/histogram.h +41 -0
  102. data/leveldb/util/logging.cc +81 -0
  103. data/leveldb/util/logging.h +47 -0
  104. data/leveldb/util/mutexlock.h +39 -0
  105. data/leveldb/util/options.cc +28 -0
  106. data/leveldb/util/random.h +59 -0
  107. data/leveldb/util/status.cc +75 -0
  108. data/leveldb/util/testharness.cc +65 -0
  109. data/leveldb/util/testharness.h +129 -0
  110. data/leveldb/util/testutil.cc +51 -0
  111. data/leveldb/util/testutil.h +53 -0
  112. data/lib/leveldb.rb +36 -0
  113. metadata +183 -0
@@ -0,0 +1,57 @@
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_BLOCK_BUILDER_H_
6
+ #define STORAGE_LEVELDB_TABLE_BLOCK_BUILDER_H_
7
+
8
+ #include <vector>
9
+
10
+ #include <stdint.h>
11
+ #include "leveldb/slice.h"
12
+
13
+ namespace leveldb {
14
+
15
+ struct Options;
16
+
17
+ class BlockBuilder {
18
+ public:
19
+ explicit BlockBuilder(const Options* options);
20
+
21
+ // Reset the contents as if the BlockBuilder was just constructed.
22
+ void Reset();
23
+
24
+ // REQUIRES: Finish() has not been callled since the last call to Reset().
25
+ // REQUIRES: key is larger than any previously added key
26
+ void Add(const Slice& key, const Slice& value);
27
+
28
+ // Finish building the block and return a slice that refers to the
29
+ // block contents. The returned slice will remain valid for the
30
+ // lifetime of this builder or until Reset() is called.
31
+ Slice Finish();
32
+
33
+ // Returns an estimate of the current (uncompressed) size of the block
34
+ // we are building.
35
+ size_t CurrentSizeEstimate() const;
36
+
37
+ // Return true iff no entries have been added since the last Reset()
38
+ bool empty() const {
39
+ return buffer_.empty();
40
+ }
41
+
42
+ private:
43
+ const Options* options_;
44
+ std::string buffer_; // Destination buffer
45
+ std::vector<uint32_t> restarts_; // Restart points
46
+ int counter_; // Number of entries emitted since restart
47
+ bool finished_; // Has Finish() been called?
48
+ std::string last_key_;
49
+
50
+ // No copying allowed
51
+ BlockBuilder(const BlockBuilder&);
52
+ void operator=(const BlockBuilder&);
53
+ };
54
+
55
+ }
56
+
57
+ #endif // STORAGE_LEVELDB_TABLE_BLOCK_BUILDER_H_
@@ -0,0 +1,131 @@
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/format.h"
6
+
7
+ #include "leveldb/env.h"
8
+ #include "port/port.h"
9
+ #include "table/block.h"
10
+ #include "util/coding.h"
11
+ #include "util/crc32c.h"
12
+
13
+ namespace leveldb {
14
+
15
+ void BlockHandle::EncodeTo(std::string* dst) const {
16
+ // Sanity check that all fields have been set
17
+ assert(offset_ != ~static_cast<uint64_t>(0));
18
+ assert(size_ != ~static_cast<uint64_t>(0));
19
+ PutVarint64(dst, offset_);
20
+ PutVarint64(dst, size_);
21
+ }
22
+
23
+ Status BlockHandle::DecodeFrom(Slice* input) {
24
+ if (GetVarint64(input, &offset_) &&
25
+ GetVarint64(input, &size_)) {
26
+ return Status::OK();
27
+ } else {
28
+ return Status::Corruption("bad block handle");
29
+ }
30
+ }
31
+
32
+ void Footer::EncodeTo(std::string* dst) const {
33
+ #ifndef NDEBUG
34
+ const size_t original_size = dst->size();
35
+ #endif
36
+ metaindex_handle_.EncodeTo(dst);
37
+ index_handle_.EncodeTo(dst);
38
+ dst->resize(2 * BlockHandle::kMaxEncodedLength); // Padding
39
+ PutFixed32(dst, static_cast<uint32_t>(kTableMagicNumber & 0xffffffffu));
40
+ PutFixed32(dst, static_cast<uint32_t>(kTableMagicNumber >> 32));
41
+ assert(dst->size() == original_size + kEncodedLength);
42
+ }
43
+
44
+ Status Footer::DecodeFrom(Slice* input) {
45
+ const char* magic_ptr = input->data() + kEncodedLength - 8;
46
+ const uint32_t magic_lo = DecodeFixed32(magic_ptr);
47
+ const uint32_t magic_hi = DecodeFixed32(magic_ptr + 4);
48
+ const uint64_t magic = ((static_cast<uint64_t>(magic_hi) << 32) |
49
+ (static_cast<uint64_t>(magic_lo)));
50
+ if (magic != kTableMagicNumber) {
51
+ return Status::InvalidArgument("not an sstable (bad magic number)");
52
+ }
53
+
54
+ Status result = metaindex_handle_.DecodeFrom(input);
55
+ if (result.ok()) {
56
+ result = index_handle_.DecodeFrom(input);
57
+ }
58
+ if (result.ok()) {
59
+ // We skip over any leftover data (just padding for now) in "input"
60
+ const char* end = magic_ptr + 8;
61
+ *input = Slice(end, input->data() + input->size() - end);
62
+ }
63
+ return result;
64
+ }
65
+
66
+ Status ReadBlock(RandomAccessFile* file,
67
+ const ReadOptions& options,
68
+ const BlockHandle& handle,
69
+ Block** block) {
70
+ *block = NULL;
71
+
72
+ // Read the block contents as well as the type/crc footer.
73
+ // See table_builder.cc for the code that built this structure.
74
+ size_t n = static_cast<size_t>(handle.size());
75
+ char* buf = new char[n + kBlockTrailerSize];
76
+ Slice contents;
77
+ Status s = file->Read(handle.offset(), n + kBlockTrailerSize, &contents, buf);
78
+ if (!s.ok()) {
79
+ delete[] buf;
80
+ return s;
81
+ }
82
+ if (contents.size() != n + kBlockTrailerSize) {
83
+ delete[] buf;
84
+ return Status::Corruption("truncated block read");
85
+ }
86
+
87
+ // Check the crc of the type and the block contents
88
+ const char* data = contents.data(); // Pointer to where Read put the data
89
+ if (options.verify_checksums) {
90
+ const uint32_t crc = crc32c::Unmask(DecodeFixed32(data + n + 1));
91
+ const uint32_t actual = crc32c::Value(data, n + 1);
92
+ if (actual != crc) {
93
+ delete[] buf;
94
+ s = Status::Corruption("block checksum mismatch");
95
+ return s;
96
+ }
97
+ }
98
+
99
+ switch (data[n]) {
100
+ case kNoCompression:
101
+ if (data != buf) {
102
+ // File implementation gave us pointer to some other data.
103
+ // Copy into buf[].
104
+ memcpy(buf, data, n + kBlockTrailerSize);
105
+ }
106
+
107
+ // Ok
108
+ break;
109
+ case kSnappyCompression: {
110
+ std::string decompressed;
111
+ if (!port::Snappy_Uncompress(data, n, &decompressed)) {
112
+ delete[] buf;
113
+ s = Status::Corruption("corrupted compressed block contents");
114
+ return s;
115
+ }
116
+ delete[] buf; // Done with uncompressed data
117
+ buf = new char[decompressed.size()];
118
+ memcpy(buf, decompressed.data(), decompressed.size());
119
+ n = decompressed.size();
120
+ break;
121
+ }
122
+ default:
123
+ delete[] buf;
124
+ return Status::Corruption("bad block type");
125
+ }
126
+
127
+ *block = new Block(buf, n); // Block takes ownership of buf[]
128
+ return Status::OK();
129
+ }
130
+
131
+ }
@@ -0,0 +1,103 @@
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
+ // Read the block identified by "handle" from "file". On success,
87
+ // store a pointer to the heap-allocated result in *block and return
88
+ // OK. On failure store NULL in *block and return non-OK.
89
+ extern Status ReadBlock(RandomAccessFile* file,
90
+ const ReadOptions& options,
91
+ const BlockHandle& handle,
92
+ Block** block);
93
+
94
+ // Implementation details follow. Clients should ignore,
95
+
96
+ inline BlockHandle::BlockHandle()
97
+ : offset_(~static_cast<uint64_t>(0)),
98
+ size_(~static_cast<uint64_t>(0)) {
99
+ }
100
+
101
+ }
102
+
103
+ #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
+ }
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
+ }
@@ -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
+ }
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
+ }