filiptepper-leveldb-ruby 0.14

Sign up to get free protection for your applications and to get access to all the features.
Files changed (123) hide show
  1. data/LICENSE +24 -0
  2. data/README +72 -0
  3. data/ext/leveldb/extconf.rb +14 -0
  4. data/ext/leveldb/leveldb.cc +530 -0
  5. data/ext/leveldb/platform.rb +83 -0
  6. data/leveldb/Makefile +191 -0
  7. data/leveldb/build_detect_platform +160 -0
  8. data/leveldb/db/builder.cc +88 -0
  9. data/leveldb/db/builder.h +34 -0
  10. data/leveldb/db/c.cc +581 -0
  11. data/leveldb/db/corruption_test.cc +359 -0
  12. data/leveldb/db/db_bench.cc +970 -0
  13. data/leveldb/db/db_impl.cc +1448 -0
  14. data/leveldb/db/db_impl.h +194 -0
  15. data/leveldb/db/db_iter.cc +299 -0
  16. data/leveldb/db/db_iter.h +26 -0
  17. data/leveldb/db/db_test.cc +1901 -0
  18. data/leveldb/db/dbformat.cc +140 -0
  19. data/leveldb/db/dbformat.h +227 -0
  20. data/leveldb/db/dbformat_test.cc +112 -0
  21. data/leveldb/db/filename.cc +139 -0
  22. data/leveldb/db/filename.h +80 -0
  23. data/leveldb/db/filename_test.cc +122 -0
  24. data/leveldb/db/log_format.h +35 -0
  25. data/leveldb/db/log_reader.cc +259 -0
  26. data/leveldb/db/log_reader.h +108 -0
  27. data/leveldb/db/log_test.cc +500 -0
  28. data/leveldb/db/log_writer.cc +103 -0
  29. data/leveldb/db/log_writer.h +48 -0
  30. data/leveldb/db/memtable.cc +145 -0
  31. data/leveldb/db/memtable.h +91 -0
  32. data/leveldb/db/repair.cc +389 -0
  33. data/leveldb/db/skiplist.h +379 -0
  34. data/leveldb/db/skiplist_test.cc +378 -0
  35. data/leveldb/db/snapshot.h +66 -0
  36. data/leveldb/db/table_cache.cc +121 -0
  37. data/leveldb/db/table_cache.h +61 -0
  38. data/leveldb/db/version_edit.cc +266 -0
  39. data/leveldb/db/version_edit.h +107 -0
  40. data/leveldb/db/version_edit_test.cc +46 -0
  41. data/leveldb/db/version_set.cc +1402 -0
  42. data/leveldb/db/version_set.h +370 -0
  43. data/leveldb/db/version_set_test.cc +179 -0
  44. data/leveldb/db/write_batch.cc +147 -0
  45. data/leveldb/db/write_batch_internal.h +49 -0
  46. data/leveldb/db/write_batch_test.cc +120 -0
  47. data/leveldb/helpers/memenv/memenv.cc +374 -0
  48. data/leveldb/helpers/memenv/memenv.h +20 -0
  49. data/leveldb/helpers/memenv/memenv_test.cc +232 -0
  50. data/leveldb/include/leveldb/c.h +275 -0
  51. data/leveldb/include/leveldb/cache.h +99 -0
  52. data/leveldb/include/leveldb/comparator.h +63 -0
  53. data/leveldb/include/leveldb/db.h +161 -0
  54. data/leveldb/include/leveldb/env.h +323 -0
  55. data/leveldb/include/leveldb/filter_policy.h +70 -0
  56. data/leveldb/include/leveldb/iterator.h +100 -0
  57. data/leveldb/include/leveldb/options.h +195 -0
  58. data/leveldb/include/leveldb/slice.h +109 -0
  59. data/leveldb/include/leveldb/status.h +106 -0
  60. data/leveldb/include/leveldb/table.h +85 -0
  61. data/leveldb/include/leveldb/table_builder.h +92 -0
  62. data/leveldb/include/leveldb/write_batch.h +64 -0
  63. data/leveldb/port/atomic_pointer.h +144 -0
  64. data/leveldb/port/port.h +21 -0
  65. data/leveldb/port/port_android.cc +64 -0
  66. data/leveldb/port/port_android.h +159 -0
  67. data/leveldb/port/port_example.h +125 -0
  68. data/leveldb/port/port_posix.cc +50 -0
  69. data/leveldb/port/port_posix.h +129 -0
  70. data/leveldb/port/win/stdint.h +24 -0
  71. data/leveldb/table/block.cc +267 -0
  72. data/leveldb/table/block.h +44 -0
  73. data/leveldb/table/block_builder.cc +109 -0
  74. data/leveldb/table/block_builder.h +57 -0
  75. data/leveldb/table/filter_block.cc +111 -0
  76. data/leveldb/table/filter_block.h +68 -0
  77. data/leveldb/table/filter_block_test.cc +128 -0
  78. data/leveldb/table/format.cc +145 -0
  79. data/leveldb/table/format.h +108 -0
  80. data/leveldb/table/iterator.cc +67 -0
  81. data/leveldb/table/iterator_wrapper.h +63 -0
  82. data/leveldb/table/merger.cc +197 -0
  83. data/leveldb/table/merger.h +26 -0
  84. data/leveldb/table/table.cc +276 -0
  85. data/leveldb/table/table_builder.cc +270 -0
  86. data/leveldb/table/table_test.cc +838 -0
  87. data/leveldb/table/two_level_iterator.cc +182 -0
  88. data/leveldb/table/two_level_iterator.h +34 -0
  89. data/leveldb/util/arena.cc +68 -0
  90. data/leveldb/util/arena.h +68 -0
  91. data/leveldb/util/arena_test.cc +68 -0
  92. data/leveldb/util/bloom.cc +95 -0
  93. data/leveldb/util/bloom_test.cc +159 -0
  94. data/leveldb/util/cache.cc +328 -0
  95. data/leveldb/util/cache_test.cc +186 -0
  96. data/leveldb/util/coding.cc +194 -0
  97. data/leveldb/util/coding.h +104 -0
  98. data/leveldb/util/coding_test.cc +173 -0
  99. data/leveldb/util/comparator.cc +76 -0
  100. data/leveldb/util/crc32c.cc +332 -0
  101. data/leveldb/util/crc32c.h +45 -0
  102. data/leveldb/util/crc32c_test.cc +72 -0
  103. data/leveldb/util/env.cc +96 -0
  104. data/leveldb/util/env_posix.cc +609 -0
  105. data/leveldb/util/env_test.cc +104 -0
  106. data/leveldb/util/filter_policy.cc +11 -0
  107. data/leveldb/util/hash.cc +45 -0
  108. data/leveldb/util/hash.h +19 -0
  109. data/leveldb/util/histogram.cc +139 -0
  110. data/leveldb/util/histogram.h +42 -0
  111. data/leveldb/util/logging.cc +81 -0
  112. data/leveldb/util/logging.h +47 -0
  113. data/leveldb/util/mutexlock.h +39 -0
  114. data/leveldb/util/options.cc +29 -0
  115. data/leveldb/util/posix_logger.h +98 -0
  116. data/leveldb/util/random.h +59 -0
  117. data/leveldb/util/status.cc +75 -0
  118. data/leveldb/util/testharness.cc +77 -0
  119. data/leveldb/util/testharness.h +138 -0
  120. data/leveldb/util/testutil.cc +51 -0
  121. data/leveldb/util/testutil.h +53 -0
  122. data/lib/leveldb.rb +76 -0
  123. metadata +175 -0
@@ -0,0 +1,194 @@
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
+
17
+ namespace leveldb {
18
+
19
+ class MemTable;
20
+ class TableCache;
21
+ class Version;
22
+ class VersionEdit;
23
+ class VersionSet;
24
+
25
+ class DBImpl : public DB {
26
+ public:
27
+ DBImpl(const Options& options, const std::string& dbname);
28
+ virtual ~DBImpl();
29
+
30
+ // Implementations of the DB interface
31
+ virtual Status Put(const WriteOptions&, const Slice& key, const Slice& value);
32
+ virtual Status Delete(const WriteOptions&, const Slice& key);
33
+ virtual Status Write(const WriteOptions& options, WriteBatch* updates);
34
+ virtual Status Get(const ReadOptions& options,
35
+ const Slice& key,
36
+ std::string* value);
37
+ virtual Iterator* NewIterator(const ReadOptions&);
38
+ virtual const Snapshot* GetSnapshot();
39
+ virtual void ReleaseSnapshot(const Snapshot* snapshot);
40
+ virtual bool GetProperty(const Slice& property, std::string* value);
41
+ virtual void GetApproximateSizes(const Range* range, int n, uint64_t* sizes);
42
+ virtual void CompactRange(const Slice* begin, const Slice* end);
43
+
44
+ // Extra methods (for testing) that are not in the public DB interface
45
+
46
+ // Compact any files in the named level that overlap [*begin,*end]
47
+ void TEST_CompactRange(int level, const Slice* begin, const Slice* end);
48
+
49
+ // Force current memtable contents to be compacted.
50
+ Status TEST_CompactMemTable();
51
+
52
+ // Return an internal iterator over the current state of the database.
53
+ // The keys of this iterator are internal keys (see format.h).
54
+ // The returned iterator should be deleted when no longer needed.
55
+ Iterator* TEST_NewInternalIterator();
56
+
57
+ // Return the maximum overlapping data (in bytes) at next level for any
58
+ // file at a level >= 1.
59
+ int64_t TEST_MaxNextLevelOverlappingBytes();
60
+
61
+ private:
62
+ friend class DB;
63
+ struct CompactionState;
64
+ struct Writer;
65
+
66
+ Iterator* NewInternalIterator(const ReadOptions&,
67
+ SequenceNumber* latest_snapshot);
68
+
69
+ Status NewDB();
70
+
71
+ // Recover the descriptor from persistent storage. May do a significant
72
+ // amount of work to recover recently logged updates. Any changes to
73
+ // be made to the descriptor are added to *edit.
74
+ Status Recover(VersionEdit* edit);
75
+
76
+ void MaybeIgnoreError(Status* s) const;
77
+
78
+ // Delete any unneeded files and stale in-memory entries.
79
+ void DeleteObsoleteFiles();
80
+
81
+ // Compact the in-memory write buffer to disk. Switches to a new
82
+ // log-file/memtable and writes a new descriptor iff successful.
83
+ Status CompactMemTable();
84
+
85
+ Status RecoverLogFile(uint64_t log_number,
86
+ VersionEdit* edit,
87
+ SequenceNumber* max_sequence);
88
+
89
+ Status WriteLevel0Table(MemTable* mem, VersionEdit* edit, Version* base);
90
+
91
+ Status MakeRoomForWrite(bool force /* compact even if there is room? */);
92
+ WriteBatch* BuildBatchGroup(Writer** last_writer);
93
+
94
+ void MaybeScheduleCompaction();
95
+ static void BGWork(void* db);
96
+ void BackgroundCall();
97
+ void BackgroundCompaction();
98
+ void CleanupCompaction(CompactionState* compact);
99
+ Status DoCompactionWork(CompactionState* compact);
100
+
101
+ Status OpenCompactionOutputFile(CompactionState* compact);
102
+ Status FinishCompactionOutputFile(CompactionState* compact, Iterator* input);
103
+ Status InstallCompactionResults(CompactionState* compact);
104
+
105
+ // Constant after construction
106
+ Env* const env_;
107
+ const InternalKeyComparator internal_comparator_;
108
+ const InternalFilterPolicy internal_filter_policy_;
109
+ const Options options_; // options_.comparator == &internal_comparator_
110
+ bool owns_info_log_;
111
+ bool owns_cache_;
112
+ const std::string dbname_;
113
+
114
+ // table_cache_ provides its own synchronization
115
+ TableCache* table_cache_;
116
+
117
+ // Lock over the persistent DB state. Non-NULL iff successfully acquired.
118
+ FileLock* db_lock_;
119
+
120
+ // State below is protected by mutex_
121
+ port::Mutex mutex_;
122
+ port::AtomicPointer shutting_down_;
123
+ port::CondVar bg_cv_; // Signalled when background work finishes
124
+ MemTable* mem_;
125
+ MemTable* imm_; // Memtable being compacted
126
+ port::AtomicPointer has_imm_; // So bg thread can detect non-NULL imm_
127
+ WritableFile* logfile_;
128
+ uint64_t logfile_number_;
129
+ log::Writer* log_;
130
+
131
+ // Queue of writers.
132
+ std::deque<Writer*> writers_;
133
+ WriteBatch* tmp_batch_;
134
+
135
+ SnapshotList snapshots_;
136
+
137
+ // Set of table files to protect from deletion because they are
138
+ // part of ongoing compactions.
139
+ std::set<uint64_t> pending_outputs_;
140
+
141
+ // Has a background compaction been scheduled or is running?
142
+ bool bg_compaction_scheduled_;
143
+
144
+ // Information for a manual compaction
145
+ struct ManualCompaction {
146
+ int level;
147
+ bool done;
148
+ const InternalKey* begin; // NULL means beginning of key range
149
+ const InternalKey* end; // NULL means end of key range
150
+ InternalKey tmp_storage; // Used to keep track of compaction progress
151
+ };
152
+ ManualCompaction* manual_compaction_;
153
+
154
+ VersionSet* versions_;
155
+
156
+ // Have we encountered a background error in paranoid mode?
157
+ Status bg_error_;
158
+
159
+ // Per level compaction stats. stats_[level] stores the stats for
160
+ // compactions that produced data for the specified "level".
161
+ struct CompactionStats {
162
+ int64_t micros;
163
+ int64_t bytes_read;
164
+ int64_t bytes_written;
165
+
166
+ CompactionStats() : micros(0), bytes_read(0), bytes_written(0) { }
167
+
168
+ void Add(const CompactionStats& c) {
169
+ this->micros += c.micros;
170
+ this->bytes_read += c.bytes_read;
171
+ this->bytes_written += c.bytes_written;
172
+ }
173
+ };
174
+ CompactionStats stats_[config::kNumLevels];
175
+
176
+ // No copying allowed
177
+ DBImpl(const DBImpl&);
178
+ void operator=(const DBImpl&);
179
+
180
+ const Comparator* user_comparator() const {
181
+ return internal_comparator_.user_comparator();
182
+ }
183
+ };
184
+
185
+ // Sanitize db options. The caller should delete result.info_log if
186
+ // it is not equal to src.info_log.
187
+ extern Options SanitizeOptions(const std::string& db,
188
+ const InternalKeyComparator* icmp,
189
+ const InternalFilterPolicy* ipolicy,
190
+ const Options& src);
191
+
192
+ } // namespace leveldb
193
+
194
+ #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