leveldb 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (128) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +22 -0
  3. data/README.md +95 -0
  4. data/ext/Rakefile +11 -0
  5. data/ext/leveldb/LICENSE +27 -0
  6. data/ext/leveldb/Makefile +206 -0
  7. data/ext/leveldb/build_config.mk +13 -0
  8. data/ext/leveldb/db/builder.cc +88 -0
  9. data/ext/leveldb/db/builder.h +34 -0
  10. data/ext/leveldb/db/c.cc +595 -0
  11. data/ext/leveldb/db/c_test.c +390 -0
  12. data/ext/leveldb/db/corruption_test.cc +359 -0
  13. data/ext/leveldb/db/db_bench.cc +979 -0
  14. data/ext/leveldb/db/db_impl.cc +1485 -0
  15. data/ext/leveldb/db/db_impl.h +203 -0
  16. data/ext/leveldb/db/db_iter.cc +299 -0
  17. data/ext/leveldb/db/db_iter.h +26 -0
  18. data/ext/leveldb/db/db_test.cc +2092 -0
  19. data/ext/leveldb/db/dbformat.cc +140 -0
  20. data/ext/leveldb/db/dbformat.h +227 -0
  21. data/ext/leveldb/db/dbformat_test.cc +112 -0
  22. data/ext/leveldb/db/filename.cc +139 -0
  23. data/ext/leveldb/db/filename.h +80 -0
  24. data/ext/leveldb/db/filename_test.cc +122 -0
  25. data/ext/leveldb/db/leveldb_main.cc +238 -0
  26. data/ext/leveldb/db/log_format.h +35 -0
  27. data/ext/leveldb/db/log_reader.cc +259 -0
  28. data/ext/leveldb/db/log_reader.h +108 -0
  29. data/ext/leveldb/db/log_test.cc +500 -0
  30. data/ext/leveldb/db/log_writer.cc +103 -0
  31. data/ext/leveldb/db/log_writer.h +48 -0
  32. data/ext/leveldb/db/memtable.cc +145 -0
  33. data/ext/leveldb/db/memtable.h +91 -0
  34. data/ext/leveldb/db/repair.cc +389 -0
  35. data/ext/leveldb/db/skiplist.h +379 -0
  36. data/ext/leveldb/db/skiplist_test.cc +378 -0
  37. data/ext/leveldb/db/snapshot.h +66 -0
  38. data/ext/leveldb/db/table_cache.cc +121 -0
  39. data/ext/leveldb/db/table_cache.h +61 -0
  40. data/ext/leveldb/db/version_edit.cc +266 -0
  41. data/ext/leveldb/db/version_edit.h +107 -0
  42. data/ext/leveldb/db/version_edit_test.cc +46 -0
  43. data/ext/leveldb/db/version_set.cc +1443 -0
  44. data/ext/leveldb/db/version_set.h +383 -0
  45. data/ext/leveldb/db/version_set_test.cc +179 -0
  46. data/ext/leveldb/db/write_batch.cc +147 -0
  47. data/ext/leveldb/db/write_batch_internal.h +49 -0
  48. data/ext/leveldb/db/write_batch_test.cc +120 -0
  49. data/ext/leveldb/doc/bench/db_bench_sqlite3.cc +718 -0
  50. data/ext/leveldb/doc/bench/db_bench_tree_db.cc +528 -0
  51. data/ext/leveldb/helpers/memenv/memenv.cc +384 -0
  52. data/ext/leveldb/helpers/memenv/memenv.h +20 -0
  53. data/ext/leveldb/helpers/memenv/memenv_test.cc +232 -0
  54. data/ext/leveldb/include/leveldb/c.h +291 -0
  55. data/ext/leveldb/include/leveldb/cache.h +99 -0
  56. data/ext/leveldb/include/leveldb/comparator.h +63 -0
  57. data/ext/leveldb/include/leveldb/db.h +161 -0
  58. data/ext/leveldb/include/leveldb/env.h +333 -0
  59. data/ext/leveldb/include/leveldb/filter_policy.h +70 -0
  60. data/ext/leveldb/include/leveldb/iterator.h +100 -0
  61. data/ext/leveldb/include/leveldb/options.h +195 -0
  62. data/ext/leveldb/include/leveldb/slice.h +109 -0
  63. data/ext/leveldb/include/leveldb/status.h +106 -0
  64. data/ext/leveldb/include/leveldb/table.h +85 -0
  65. data/ext/leveldb/include/leveldb/table_builder.h +92 -0
  66. data/ext/leveldb/include/leveldb/write_batch.h +64 -0
  67. data/ext/leveldb/issues/issue178_test.cc +92 -0
  68. data/ext/leveldb/port/atomic_pointer.h +224 -0
  69. data/ext/leveldb/port/port.h +19 -0
  70. data/ext/leveldb/port/port_example.h +135 -0
  71. data/ext/leveldb/port/port_posix.cc +54 -0
  72. data/ext/leveldb/port/port_posix.h +157 -0
  73. data/ext/leveldb/port/thread_annotations.h +59 -0
  74. data/ext/leveldb/port/win/stdint.h +24 -0
  75. data/ext/leveldb/table/block.cc +268 -0
  76. data/ext/leveldb/table/block.h +44 -0
  77. data/ext/leveldb/table/block_builder.cc +109 -0
  78. data/ext/leveldb/table/block_builder.h +57 -0
  79. data/ext/leveldb/table/filter_block.cc +111 -0
  80. data/ext/leveldb/table/filter_block.h +68 -0
  81. data/ext/leveldb/table/filter_block_test.cc +128 -0
  82. data/ext/leveldb/table/format.cc +145 -0
  83. data/ext/leveldb/table/format.h +108 -0
  84. data/ext/leveldb/table/iterator.cc +67 -0
  85. data/ext/leveldb/table/iterator_wrapper.h +63 -0
  86. data/ext/leveldb/table/merger.cc +197 -0
  87. data/ext/leveldb/table/merger.h +26 -0
  88. data/ext/leveldb/table/table.cc +275 -0
  89. data/ext/leveldb/table/table_builder.cc +270 -0
  90. data/ext/leveldb/table/table_test.cc +868 -0
  91. data/ext/leveldb/table/two_level_iterator.cc +182 -0
  92. data/ext/leveldb/table/two_level_iterator.h +34 -0
  93. data/ext/leveldb/util/arena.cc +68 -0
  94. data/ext/leveldb/util/arena.h +68 -0
  95. data/ext/leveldb/util/arena_test.cc +68 -0
  96. data/ext/leveldb/util/bloom.cc +95 -0
  97. data/ext/leveldb/util/bloom_test.cc +160 -0
  98. data/ext/leveldb/util/cache.cc +325 -0
  99. data/ext/leveldb/util/cache_test.cc +186 -0
  100. data/ext/leveldb/util/coding.cc +194 -0
  101. data/ext/leveldb/util/coding.h +104 -0
  102. data/ext/leveldb/util/coding_test.cc +196 -0
  103. data/ext/leveldb/util/comparator.cc +81 -0
  104. data/ext/leveldb/util/crc32c.cc +332 -0
  105. data/ext/leveldb/util/crc32c.h +45 -0
  106. data/ext/leveldb/util/crc32c_test.cc +72 -0
  107. data/ext/leveldb/util/env.cc +96 -0
  108. data/ext/leveldb/util/env_posix.cc +698 -0
  109. data/ext/leveldb/util/env_test.cc +104 -0
  110. data/ext/leveldb/util/filter_policy.cc +11 -0
  111. data/ext/leveldb/util/hash.cc +52 -0
  112. data/ext/leveldb/util/hash.h +19 -0
  113. data/ext/leveldb/util/histogram.cc +139 -0
  114. data/ext/leveldb/util/histogram.h +42 -0
  115. data/ext/leveldb/util/logging.cc +81 -0
  116. data/ext/leveldb/util/logging.h +47 -0
  117. data/ext/leveldb/util/mutexlock.h +41 -0
  118. data/ext/leveldb/util/options.cc +29 -0
  119. data/ext/leveldb/util/posix_logger.h +98 -0
  120. data/ext/leveldb/util/random.h +59 -0
  121. data/ext/leveldb/util/status.cc +75 -0
  122. data/ext/leveldb/util/testharness.cc +77 -0
  123. data/ext/leveldb/util/testharness.h +138 -0
  124. data/ext/leveldb/util/testutil.cc +51 -0
  125. data/ext/leveldb/util/testutil.h +53 -0
  126. data/lib/leveldb/version.rb +3 -0
  127. data/lib/leveldb.rb +1006 -0
  128. metadata +228 -0
@@ -0,0 +1,203 @@
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_DB_DB_IMPL_H_
6
+ #define STORAGE_LEVELDB_DB_DB_IMPL_H_
7
+
8
+ #include <deque>
9
+ #include <set>
10
+ #include "db/dbformat.h"
11
+ #include "db/log_writer.h"
12
+ #include "db/snapshot.h"
13
+ #include "leveldb/db.h"
14
+ #include "leveldb/env.h"
15
+ #include "port/port.h"
16
+ #include "port/thread_annotations.h"
17
+
18
+ namespace leveldb {
19
+
20
+ class MemTable;
21
+ class TableCache;
22
+ class Version;
23
+ class VersionEdit;
24
+ class VersionSet;
25
+
26
+ class DBImpl : public DB {
27
+ public:
28
+ DBImpl(const Options& options, const std::string& dbname);
29
+ virtual ~DBImpl();
30
+
31
+ // Implementations of the DB interface
32
+ virtual Status Put(const WriteOptions&, const Slice& key, const Slice& value);
33
+ virtual Status Delete(const WriteOptions&, const Slice& key);
34
+ virtual Status Write(const WriteOptions& options, WriteBatch* updates);
35
+ virtual Status Get(const ReadOptions& options,
36
+ const Slice& key,
37
+ std::string* value);
38
+ virtual Iterator* NewIterator(const ReadOptions&);
39
+ virtual const Snapshot* GetSnapshot();
40
+ virtual void ReleaseSnapshot(const Snapshot* snapshot);
41
+ virtual bool GetProperty(const Slice& property, std::string* value);
42
+ virtual void GetApproximateSizes(const Range* range, int n, uint64_t* sizes);
43
+ virtual void CompactRange(const Slice* begin, const Slice* end);
44
+
45
+ // Extra methods (for testing) that are not in the public DB interface
46
+
47
+ // Compact any files in the named level that overlap [*begin,*end]
48
+ void TEST_CompactRange(int level, const Slice* begin, const Slice* end);
49
+
50
+ // Force current memtable contents to be compacted.
51
+ Status TEST_CompactMemTable();
52
+
53
+ // Return an internal iterator over the current state of the database.
54
+ // The keys of this iterator are internal keys (see format.h).
55
+ // The returned iterator should be deleted when no longer needed.
56
+ Iterator* TEST_NewInternalIterator();
57
+
58
+ // Return the maximum overlapping data (in bytes) at next level for any
59
+ // file at a level >= 1.
60
+ int64_t TEST_MaxNextLevelOverlappingBytes();
61
+
62
+ private:
63
+ friend class DB;
64
+ struct CompactionState;
65
+ struct Writer;
66
+
67
+ Iterator* NewInternalIterator(const ReadOptions&,
68
+ SequenceNumber* latest_snapshot);
69
+
70
+ Status NewDB();
71
+
72
+ // Recover the descriptor from persistent storage. May do a significant
73
+ // amount of work to recover recently logged updates. Any changes to
74
+ // be made to the descriptor are added to *edit.
75
+ Status Recover(VersionEdit* edit) EXCLUSIVE_LOCKS_REQUIRED(mutex_);
76
+
77
+ void MaybeIgnoreError(Status* s) const;
78
+
79
+ // Delete any unneeded files and stale in-memory entries.
80
+ void DeleteObsoleteFiles();
81
+
82
+ // Compact the in-memory write buffer to disk. Switches to a new
83
+ // log-file/memtable and writes a new descriptor iff successful.
84
+ Status CompactMemTable()
85
+ EXCLUSIVE_LOCKS_REQUIRED(mutex_);
86
+
87
+ Status RecoverLogFile(uint64_t log_number,
88
+ VersionEdit* edit,
89
+ SequenceNumber* max_sequence)
90
+ EXCLUSIVE_LOCKS_REQUIRED(mutex_);
91
+
92
+ Status WriteLevel0Table(MemTable* mem, VersionEdit* edit, Version* base)
93
+ EXCLUSIVE_LOCKS_REQUIRED(mutex_);
94
+
95
+ Status MakeRoomForWrite(bool force /* compact even if there is room? */)
96
+ EXCLUSIVE_LOCKS_REQUIRED(mutex_);
97
+ WriteBatch* BuildBatchGroup(Writer** last_writer);
98
+
99
+ void MaybeScheduleCompaction() EXCLUSIVE_LOCKS_REQUIRED(mutex_);
100
+ static void BGWork(void* db);
101
+ void BackgroundCall();
102
+ Status BackgroundCompaction() EXCLUSIVE_LOCKS_REQUIRED(mutex_);
103
+ void CleanupCompaction(CompactionState* compact)
104
+ EXCLUSIVE_LOCKS_REQUIRED(mutex_);
105
+ Status DoCompactionWork(CompactionState* compact)
106
+ EXCLUSIVE_LOCKS_REQUIRED(mutex_);
107
+
108
+ Status OpenCompactionOutputFile(CompactionState* compact);
109
+ Status FinishCompactionOutputFile(CompactionState* compact, Iterator* input);
110
+ Status InstallCompactionResults(CompactionState* compact)
111
+ EXCLUSIVE_LOCKS_REQUIRED(mutex_);
112
+
113
+ // Constant after construction
114
+ Env* const env_;
115
+ const InternalKeyComparator internal_comparator_;
116
+ const InternalFilterPolicy internal_filter_policy_;
117
+ const Options options_; // options_.comparator == &internal_comparator_
118
+ bool owns_info_log_;
119
+ bool owns_cache_;
120
+ const std::string dbname_;
121
+
122
+ // table_cache_ provides its own synchronization
123
+ TableCache* table_cache_;
124
+
125
+ // Lock over the persistent DB state. Non-NULL iff successfully acquired.
126
+ FileLock* db_lock_;
127
+
128
+ // State below is protected by mutex_
129
+ port::Mutex mutex_;
130
+ port::AtomicPointer shutting_down_;
131
+ port::CondVar bg_cv_; // Signalled when background work finishes
132
+ MemTable* mem_;
133
+ MemTable* imm_; // Memtable being compacted
134
+ port::AtomicPointer has_imm_; // So bg thread can detect non-NULL imm_
135
+ WritableFile* logfile_;
136
+ uint64_t logfile_number_;
137
+ log::Writer* log_;
138
+
139
+ // Queue of writers.
140
+ std::deque<Writer*> writers_;
141
+ WriteBatch* tmp_batch_;
142
+
143
+ SnapshotList snapshots_;
144
+
145
+ // Set of table files to protect from deletion because they are
146
+ // part of ongoing compactions.
147
+ std::set<uint64_t> pending_outputs_;
148
+
149
+ // Has a background compaction been scheduled or is running?
150
+ bool bg_compaction_scheduled_;
151
+
152
+ // Information for a manual compaction
153
+ struct ManualCompaction {
154
+ int level;
155
+ bool done;
156
+ const InternalKey* begin; // NULL means beginning of key range
157
+ const InternalKey* end; // NULL means end of key range
158
+ InternalKey tmp_storage; // Used to keep track of compaction progress
159
+ };
160
+ ManualCompaction* manual_compaction_;
161
+
162
+ VersionSet* versions_;
163
+
164
+ // Have we encountered a background error in paranoid mode?
165
+ Status bg_error_;
166
+ int consecutive_compaction_errors_;
167
+
168
+ // Per level compaction stats. stats_[level] stores the stats for
169
+ // compactions that produced data for the specified "level".
170
+ struct CompactionStats {
171
+ int64_t micros;
172
+ int64_t bytes_read;
173
+ int64_t bytes_written;
174
+
175
+ CompactionStats() : micros(0), bytes_read(0), bytes_written(0) { }
176
+
177
+ void Add(const CompactionStats& c) {
178
+ this->micros += c.micros;
179
+ this->bytes_read += c.bytes_read;
180
+ this->bytes_written += c.bytes_written;
181
+ }
182
+ };
183
+ CompactionStats stats_[config::kNumLevels];
184
+
185
+ // No copying allowed
186
+ DBImpl(const DBImpl&);
187
+ void operator=(const DBImpl&);
188
+
189
+ const Comparator* user_comparator() const {
190
+ return internal_comparator_.user_comparator();
191
+ }
192
+ };
193
+
194
+ // Sanitize db options. The caller should delete result.info_log if
195
+ // it is not equal to src.info_log.
196
+ extern Options SanitizeOptions(const std::string& db,
197
+ const InternalKeyComparator* icmp,
198
+ const InternalFilterPolicy* ipolicy,
199
+ const Options& src);
200
+
201
+ } // namespace leveldb
202
+
203
+ #endif // STORAGE_LEVELDB_DB_DB_IMPL_H_
@@ -0,0 +1,299 @@
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 "db/db_iter.h"
6
+
7
+ #include "db/filename.h"
8
+ #include "db/dbformat.h"
9
+ #include "leveldb/env.h"
10
+ #include "leveldb/iterator.h"
11
+ #include "port/port.h"
12
+ #include "util/logging.h"
13
+ #include "util/mutexlock.h"
14
+
15
+ namespace leveldb {
16
+
17
+ #if 0
18
+ static void DumpInternalIter(Iterator* iter) {
19
+ for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
20
+ ParsedInternalKey k;
21
+ if (!ParseInternalKey(iter->key(), &k)) {
22
+ fprintf(stderr, "Corrupt '%s'\n", EscapeString(iter->key()).c_str());
23
+ } else {
24
+ fprintf(stderr, "@ '%s'\n", k.DebugString().c_str());
25
+ }
26
+ }
27
+ }
28
+ #endif
29
+
30
+ namespace {
31
+
32
+ // Memtables and sstables that make the DB representation contain
33
+ // (userkey,seq,type) => uservalue entries. DBIter
34
+ // combines multiple entries for the same userkey found in the DB
35
+ // representation into a single entry while accounting for sequence
36
+ // numbers, deletion markers, overwrites, etc.
37
+ class DBIter: public Iterator {
38
+ public:
39
+ // Which direction is the iterator currently moving?
40
+ // (1) When moving forward, the internal iterator is positioned at
41
+ // the exact entry that yields this->key(), this->value()
42
+ // (2) When moving backwards, the internal iterator is positioned
43
+ // just before all entries whose user key == this->key().
44
+ enum Direction {
45
+ kForward,
46
+ kReverse
47
+ };
48
+
49
+ DBIter(const std::string* dbname, Env* env,
50
+ const Comparator* cmp, Iterator* iter, SequenceNumber s)
51
+ : dbname_(dbname),
52
+ env_(env),
53
+ user_comparator_(cmp),
54
+ iter_(iter),
55
+ sequence_(s),
56
+ direction_(kForward),
57
+ valid_(false) {
58
+ }
59
+ virtual ~DBIter() {
60
+ delete iter_;
61
+ }
62
+ virtual bool Valid() const { return valid_; }
63
+ virtual Slice key() const {
64
+ assert(valid_);
65
+ return (direction_ == kForward) ? ExtractUserKey(iter_->key()) : saved_key_;
66
+ }
67
+ virtual Slice value() const {
68
+ assert(valid_);
69
+ return (direction_ == kForward) ? iter_->value() : saved_value_;
70
+ }
71
+ virtual Status status() const {
72
+ if (status_.ok()) {
73
+ return iter_->status();
74
+ } else {
75
+ return status_;
76
+ }
77
+ }
78
+
79
+ virtual void Next();
80
+ virtual void Prev();
81
+ virtual void Seek(const Slice& target);
82
+ virtual void SeekToFirst();
83
+ virtual void SeekToLast();
84
+
85
+ private:
86
+ void FindNextUserEntry(bool skipping, std::string* skip);
87
+ void FindPrevUserEntry();
88
+ bool ParseKey(ParsedInternalKey* key);
89
+
90
+ inline void SaveKey(const Slice& k, std::string* dst) {
91
+ dst->assign(k.data(), k.size());
92
+ }
93
+
94
+ inline void ClearSavedValue() {
95
+ if (saved_value_.capacity() > 1048576) {
96
+ std::string empty;
97
+ swap(empty, saved_value_);
98
+ } else {
99
+ saved_value_.clear();
100
+ }
101
+ }
102
+
103
+ const std::string* const dbname_;
104
+ Env* const env_;
105
+ const Comparator* const user_comparator_;
106
+ Iterator* const iter_;
107
+ SequenceNumber const sequence_;
108
+
109
+ Status status_;
110
+ std::string saved_key_; // == current key when direction_==kReverse
111
+ std::string saved_value_; // == current raw value when direction_==kReverse
112
+ Direction direction_;
113
+ bool valid_;
114
+
115
+ // No copying allowed
116
+ DBIter(const DBIter&);
117
+ void operator=(const DBIter&);
118
+ };
119
+
120
+ inline bool DBIter::ParseKey(ParsedInternalKey* ikey) {
121
+ if (!ParseInternalKey(iter_->key(), ikey)) {
122
+ status_ = Status::Corruption("corrupted internal key in DBIter");
123
+ return false;
124
+ } else {
125
+ return true;
126
+ }
127
+ }
128
+
129
+ void DBIter::Next() {
130
+ assert(valid_);
131
+
132
+ if (direction_ == kReverse) { // Switch directions?
133
+ direction_ = kForward;
134
+ // iter_ is pointing just before the entries for this->key(),
135
+ // so advance into the range of entries for this->key() and then
136
+ // use the normal skipping code below.
137
+ if (!iter_->Valid()) {
138
+ iter_->SeekToFirst();
139
+ } else {
140
+ iter_->Next();
141
+ }
142
+ if (!iter_->Valid()) {
143
+ valid_ = false;
144
+ saved_key_.clear();
145
+ return;
146
+ }
147
+ }
148
+
149
+ // Temporarily use saved_key_ as storage for key to skip.
150
+ std::string* skip = &saved_key_;
151
+ SaveKey(ExtractUserKey(iter_->key()), skip);
152
+ FindNextUserEntry(true, skip);
153
+ }
154
+
155
+ void DBIter::FindNextUserEntry(bool skipping, std::string* skip) {
156
+ // Loop until we hit an acceptable entry to yield
157
+ assert(iter_->Valid());
158
+ assert(direction_ == kForward);
159
+ do {
160
+ ParsedInternalKey ikey;
161
+ if (ParseKey(&ikey) && ikey.sequence <= sequence_) {
162
+ switch (ikey.type) {
163
+ case kTypeDeletion:
164
+ // Arrange to skip all upcoming entries for this key since
165
+ // they are hidden by this deletion.
166
+ SaveKey(ikey.user_key, skip);
167
+ skipping = true;
168
+ break;
169
+ case kTypeValue:
170
+ if (skipping &&
171
+ user_comparator_->Compare(ikey.user_key, *skip) <= 0) {
172
+ // Entry hidden
173
+ } else {
174
+ valid_ = true;
175
+ saved_key_.clear();
176
+ return;
177
+ }
178
+ break;
179
+ }
180
+ }
181
+ iter_->Next();
182
+ } while (iter_->Valid());
183
+ saved_key_.clear();
184
+ valid_ = false;
185
+ }
186
+
187
+ void DBIter::Prev() {
188
+ assert(valid_);
189
+
190
+ if (direction_ == kForward) { // Switch directions?
191
+ // iter_ is pointing at the current entry. Scan backwards until
192
+ // the key changes so we can use the normal reverse scanning code.
193
+ assert(iter_->Valid()); // Otherwise valid_ would have been false
194
+ SaveKey(ExtractUserKey(iter_->key()), &saved_key_);
195
+ while (true) {
196
+ iter_->Prev();
197
+ if (!iter_->Valid()) {
198
+ valid_ = false;
199
+ saved_key_.clear();
200
+ ClearSavedValue();
201
+ return;
202
+ }
203
+ if (user_comparator_->Compare(ExtractUserKey(iter_->key()),
204
+ saved_key_) < 0) {
205
+ break;
206
+ }
207
+ }
208
+ direction_ = kReverse;
209
+ }
210
+
211
+ FindPrevUserEntry();
212
+ }
213
+
214
+ void DBIter::FindPrevUserEntry() {
215
+ assert(direction_ == kReverse);
216
+
217
+ ValueType value_type = kTypeDeletion;
218
+ if (iter_->Valid()) {
219
+ do {
220
+ ParsedInternalKey ikey;
221
+ if (ParseKey(&ikey) && ikey.sequence <= sequence_) {
222
+ if ((value_type != kTypeDeletion) &&
223
+ user_comparator_->Compare(ikey.user_key, saved_key_) < 0) {
224
+ // We encountered a non-deleted value in entries for previous keys,
225
+ break;
226
+ }
227
+ value_type = ikey.type;
228
+ if (value_type == kTypeDeletion) {
229
+ saved_key_.clear();
230
+ ClearSavedValue();
231
+ } else {
232
+ Slice raw_value = iter_->value();
233
+ if (saved_value_.capacity() > raw_value.size() + 1048576) {
234
+ std::string empty;
235
+ swap(empty, saved_value_);
236
+ }
237
+ SaveKey(ExtractUserKey(iter_->key()), &saved_key_);
238
+ saved_value_.assign(raw_value.data(), raw_value.size());
239
+ }
240
+ }
241
+ iter_->Prev();
242
+ } while (iter_->Valid());
243
+ }
244
+
245
+ if (value_type == kTypeDeletion) {
246
+ // End
247
+ valid_ = false;
248
+ saved_key_.clear();
249
+ ClearSavedValue();
250
+ direction_ = kForward;
251
+ } else {
252
+ valid_ = true;
253
+ }
254
+ }
255
+
256
+ void DBIter::Seek(const Slice& target) {
257
+ direction_ = kForward;
258
+ ClearSavedValue();
259
+ saved_key_.clear();
260
+ AppendInternalKey(
261
+ &saved_key_, ParsedInternalKey(target, sequence_, kValueTypeForSeek));
262
+ iter_->Seek(saved_key_);
263
+ if (iter_->Valid()) {
264
+ FindNextUserEntry(false, &saved_key_ /* temporary storage */);
265
+ } else {
266
+ valid_ = false;
267
+ }
268
+ }
269
+
270
+ void DBIter::SeekToFirst() {
271
+ direction_ = kForward;
272
+ ClearSavedValue();
273
+ iter_->SeekToFirst();
274
+ if (iter_->Valid()) {
275
+ FindNextUserEntry(false, &saved_key_ /* temporary storage */);
276
+ } else {
277
+ valid_ = false;
278
+ }
279
+ }
280
+
281
+ void DBIter::SeekToLast() {
282
+ direction_ = kReverse;
283
+ ClearSavedValue();
284
+ iter_->SeekToLast();
285
+ FindPrevUserEntry();
286
+ }
287
+
288
+ } // anonymous namespace
289
+
290
+ Iterator* NewDBIterator(
291
+ const std::string* dbname,
292
+ Env* env,
293
+ const Comparator* user_key_comparator,
294
+ Iterator* internal_iter,
295
+ const SequenceNumber& sequence) {
296
+ return new DBIter(dbname, env, user_key_comparator, internal_iter, sequence);
297
+ }
298
+
299
+ } // 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_DB_DB_ITER_H_
6
+ #define STORAGE_LEVELDB_DB_DB_ITER_H_
7
+
8
+ #include <stdint.h>
9
+ #include "leveldb/db.h"
10
+ #include "db/dbformat.h"
11
+
12
+ namespace leveldb {
13
+
14
+ // Return a new iterator that converts internal keys (yielded by
15
+ // "*internal_iter") that were live at the specified "sequence" number
16
+ // into appropriate user keys.
17
+ extern Iterator* NewDBIterator(
18
+ const std::string* dbname,
19
+ Env* env,
20
+ const Comparator* user_key_comparator,
21
+ Iterator* internal_iter,
22
+ const SequenceNumber& sequence);
23
+
24
+ } // namespace leveldb
25
+
26
+ #endif // STORAGE_LEVELDB_DB_DB_ITER_H_