leveldb
db_iter.cc
Go to the documentation of this file.
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/db_impl.h"
9 #include "db/dbformat.h"
10 #include "leveldb/env.h"
11 #include "leveldb/iterator.h"
12 #include "port/port.h"
13 #include "util/logging.h"
14 #include "util/mutexlock.h"
15 #include "util/random.h"
16 
17 namespace leveldb {
18 
19 #if 0
20 static void DumpInternalIter(Iterator* iter) {
21  for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
22  ParsedInternalKey k;
23  if (!ParseInternalKey(iter->key(), &k)) {
24  fprintf(stderr, "Corrupt '%s'\n", EscapeString(iter->key()).c_str());
25  } else {
26  fprintf(stderr, "@ '%s'\n", k.DebugString().c_str());
27  }
28  }
29 }
30 #endif
31 
32 namespace {
33 
34 // Memtables and sstables that make the DB representation contain
35 // (userkey,seq,type) => uservalue entries. DBIter
36 // combines multiple entries for the same userkey found in the DB
37 // representation into a single entry while accounting for sequence
38 // numbers, deletion markers, overwrites, etc.
39 class DBIter: public Iterator {
40  public:
41  // Which direction is the iterator currently moving?
42  // (1) When moving forward, the internal iterator is positioned at
43  // the exact entry that yields this->key(), this->value()
44  // (2) When moving backwards, the internal iterator is positioned
45  // just before all entries whose user key == this->key().
46  enum Direction {
48  kReverse
49  };
50 
51  DBIter(DBImpl* db, const Comparator* cmp, Iterator* iter, SequenceNumber s,
52  uint32_t seed)
53  : db_(db),
54  user_comparator_(cmp),
55  iter_(iter),
56  sequence_(s),
57  direction_(kForward),
58  valid_(false),
59  rnd_(seed),
60  bytes_counter_(RandomPeriod()) {
61  }
62  virtual ~DBIter() {
63  delete iter_;
64  }
65  virtual bool Valid() const { return valid_; }
66  virtual Slice key() const {
67  assert(valid_);
68  return (direction_ == kForward) ? ExtractUserKey(iter_->key()) : saved_key_;
69  }
70  virtual Slice value() const {
71  assert(valid_);
72  return (direction_ == kForward) ? iter_->value() : saved_value_;
73  }
74  virtual Status status() const {
75  if (status_.ok()) {
76  return iter_->status();
77  } else {
78  return status_;
79  }
80  }
81 
82  virtual void Next();
83  virtual void Prev();
84  virtual void Seek(const Slice& target);
85  virtual void SeekToFirst();
86  virtual void SeekToLast();
87 
88  private:
89  void FindNextUserEntry(bool skipping, std::string* skip);
90  void FindPrevUserEntry();
91  bool ParseKey(ParsedInternalKey* key);
92 
93  inline void SaveKey(const Slice& k, std::string* dst) {
94  dst->assign(k.data(), k.size());
95  }
96 
97  inline void ClearSavedValue() {
98  if (saved_value_.capacity() > 1048576) {
99  std::string empty;
100  swap(empty, saved_value_);
101  } else {
102  saved_value_.clear();
103  }
104  }
105 
106  // Pick next gap with average value of config::kReadBytesPeriod.
107  ssize_t RandomPeriod() {
108  return rnd_.Uniform(2*config::kReadBytesPeriod);
109  }
110 
113  Iterator* const iter_;
115 
117  std::string saved_key_; // == current key when direction_==kReverse
118  std::string saved_value_; // == current raw value when direction_==kReverse
120  bool valid_;
121 
123  ssize_t bytes_counter_;
124 
125  // No copying allowed
126  DBIter(const DBIter&);
127  void operator=(const DBIter&);
128 };
129 
130 inline bool DBIter::ParseKey(ParsedInternalKey* ikey) {
131  Slice k = iter_->key();
132  ssize_t n = k.size() + iter_->value().size();
133  bytes_counter_ -= n;
134  while (bytes_counter_ < 0) {
135  bytes_counter_ += RandomPeriod();
136  db_->RecordReadSample(k);
137  }
138  if (!ParseInternalKey(k, ikey)) {
139  status_ = Status::Corruption("corrupted internal key in DBIter");
140  return false;
141  } else {
142  return true;
143  }
144 }
145 
146 void DBIter::Next() {
147  assert(valid_);
148 
149  if (direction_ == kReverse) { // Switch directions?
150  direction_ = kForward;
151  // iter_ is pointing just before the entries for this->key(),
152  // so advance into the range of entries for this->key() and then
153  // use the normal skipping code below.
154  if (!iter_->Valid()) {
155  iter_->SeekToFirst();
156  } else {
157  iter_->Next();
158  }
159  if (!iter_->Valid()) {
160  valid_ = false;
161  saved_key_.clear();
162  return;
163  }
164  // saved_key_ already contains the key to skip past.
165  } else {
166  // Store in saved_key_ the current key so we skip it below.
167  SaveKey(ExtractUserKey(iter_->key()), &saved_key_);
168  }
169 
170  FindNextUserEntry(true, &saved_key_);
171 }
172 
173 void DBIter::FindNextUserEntry(bool skipping, std::string* skip) {
174  // Loop until we hit an acceptable entry to yield
175  assert(iter_->Valid());
176  assert(direction_ == kForward);
177  do {
178  ParsedInternalKey ikey;
179  if (ParseKey(&ikey) && ikey.sequence <= sequence_) {
180  switch (ikey.type) {
181  case kTypeDeletion:
182  // Arrange to skip all upcoming entries for this key since
183  // they are hidden by this deletion.
184  SaveKey(ikey.user_key, skip);
185  skipping = true;
186  break;
187  case kTypeValue:
188  if (skipping &&
189  user_comparator_->Compare(ikey.user_key, *skip) <= 0) {
190  // Entry hidden
191  } else {
192  valid_ = true;
193  saved_key_.clear();
194  return;
195  }
196  break;
197  }
198  }
199  iter_->Next();
200  } while (iter_->Valid());
201  saved_key_.clear();
202  valid_ = false;
203 }
204 
205 void DBIter::Prev() {
206  assert(valid_);
207 
208  if (direction_ == kForward) { // Switch directions?
209  // iter_ is pointing at the current entry. Scan backwards until
210  // the key changes so we can use the normal reverse scanning code.
211  assert(iter_->Valid()); // Otherwise valid_ would have been false
212  SaveKey(ExtractUserKey(iter_->key()), &saved_key_);
213  while (true) {
214  iter_->Prev();
215  if (!iter_->Valid()) {
216  valid_ = false;
217  saved_key_.clear();
218  ClearSavedValue();
219  return;
220  }
221  if (user_comparator_->Compare(ExtractUserKey(iter_->key()),
222  saved_key_) < 0) {
223  break;
224  }
225  }
226  direction_ = kReverse;
227  }
228 
229  FindPrevUserEntry();
230 }
231 
232 void DBIter::FindPrevUserEntry() {
233  assert(direction_ == kReverse);
234 
235  ValueType value_type = kTypeDeletion;
236  if (iter_->Valid()) {
237  do {
238  ParsedInternalKey ikey;
239  if (ParseKey(&ikey) && ikey.sequence <= sequence_) {
240  if ((value_type != kTypeDeletion) &&
241  user_comparator_->Compare(ikey.user_key, saved_key_) < 0) {
242  // We encountered a non-deleted value in entries for previous keys,
243  break;
244  }
245  value_type = ikey.type;
246  if (value_type == kTypeDeletion) {
247  saved_key_.clear();
248  ClearSavedValue();
249  } else {
250  Slice raw_value = iter_->value();
251  if (saved_value_.capacity() > raw_value.size() + 1048576) {
252  std::string empty;
253  swap(empty, saved_value_);
254  }
255  SaveKey(ExtractUserKey(iter_->key()), &saved_key_);
256  saved_value_.assign(raw_value.data(), raw_value.size());
257  }
258  }
259  iter_->Prev();
260  } while (iter_->Valid());
261  }
262 
263  if (value_type == kTypeDeletion) {
264  // End
265  valid_ = false;
266  saved_key_.clear();
267  ClearSavedValue();
268  direction_ = kForward;
269  } else {
270  valid_ = true;
271  }
272 }
273 
274 void DBIter::Seek(const Slice& target) {
275  direction_ = kForward;
276  ClearSavedValue();
277  saved_key_.clear();
279  &saved_key_, ParsedInternalKey(target, sequence_, kValueTypeForSeek));
280  iter_->Seek(saved_key_);
281  if (iter_->Valid()) {
282  FindNextUserEntry(false, &saved_key_ /* temporary storage */);
283  } else {
284  valid_ = false;
285  }
286 }
287 
288 void DBIter::SeekToFirst() {
289  direction_ = kForward;
290  ClearSavedValue();
291  iter_->SeekToFirst();
292  if (iter_->Valid()) {
293  FindNextUserEntry(false, &saved_key_ /* temporary storage */);
294  } else {
295  valid_ = false;
296  }
297 }
298 
299 void DBIter::SeekToLast() {
300  direction_ = kReverse;
301  ClearSavedValue();
302  iter_->SeekToLast();
303  FindPrevUserEntry();
304 }
305 
306 } // anonymous namespace
307 
309  DBImpl* db,
310  const Comparator* user_key_comparator,
311  Iterator* internal_iter,
312  SequenceNumber sequence,
313  uint32_t seed) {
314  return new DBIter(db, user_key_comparator, internal_iter, sequence, seed);
315 }
316 
317 } // namespace leveldb
DBIter(DBImpl *db, const Comparator *cmp, Iterator *iter, SequenceNumber s, uint32_t seed)
Definition: db_iter.cc:51
SequenceNumber sequence
Definition: dbformat.h:72
ValueType
Definition: dbformat.h:51
Iterator * NewDBIterator(DBImpl *db, const Comparator *user_key_comparator, Iterator *internal_iter, SequenceNumber sequence, uint32_t seed)
Definition: db_iter.cc:308
bool ParseInternalKey(const Slice &internal_key, ParsedInternalKey *result)
Definition: dbformat.h:176
void AppendInternalKey(std::string *result, const ParsedInternalKey &key)
Definition: dbformat.cc:18
uint64_t SequenceNumber
Definition: dbformat.h:63
static Status Corruption(const Slice &msg, const Slice &msg2=Slice())
Definition: status.h:38
static const int kReadBytesPeriod
Definition: dbformat.h:42
static const ValueType kValueTypeForSeek
Definition: dbformat.h:61
std::string EscapeString(const Slice &value)
Definition: logging.cc:42
void SaveKey(const Slice &k, std::string *dst)
Definition: db_iter.cc:93
Slice ExtractUserKey(const Slice &internal_key)
Definition: dbformat.h:98
const char * data() const
Definition: slice.h:40
size_t size() const
Definition: slice.h:43