Coverage Report

Created: 2025-07-11 07:01

/src/leveldb/db/db_iter.cc
Line
Count
Source (jump to first uncovered line)
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/db_impl.h"
8
#include "db/dbformat.h"
9
#include "db/filename.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
      std::fprintf(stderr, "Corrupt '%s'\n", EscapeString(iter->key()).c_str());
25
    } else {
26
      std::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 { kForward, kReverse };
47
48
  DBIter(DBImpl* db, const Comparator* cmp, Iterator* iter, SequenceNumber s,
49
         uint32_t seed)
50
143k
      : db_(db),
51
143k
        user_comparator_(cmp),
52
143k
        iter_(iter),
53
143k
        sequence_(s),
54
143k
        direction_(kForward),
55
143k
        valid_(false),
56
143k
        rnd_(seed),
57
143k
        bytes_until_read_sampling_(RandomCompactionPeriod()) {}
58
59
  DBIter(const DBIter&) = delete;
60
  DBIter& operator=(const DBIter&) = delete;
61
62
143k
  ~DBIter() override { delete iter_; }
63
384k
  bool Valid() const override { return valid_; }
64
0
  Slice key() const override {
65
0
    assert(valid_);
66
0
    return (direction_ == kForward) ? ExtractUserKey(iter_->key()) : saved_key_;
67
0
  }
68
0
  Slice value() const override {
69
0
    assert(valid_);
70
0
    return (direction_ == kForward) ? iter_->value() : saved_value_;
71
0
  }
72
0
  Status status() const override {
73
0
    if (status_.ok()) {
74
0
      return iter_->status();
75
0
    } else {
76
0
      return status_;
77
0
    }
78
0
  }
79
80
  void Next() override;
81
  void Prev() override;
82
  void Seek(const Slice& target) override;
83
  void SeekToFirst() override;
84
  void SeekToLast() override;
85
86
 private:
87
  void FindNextUserEntry(bool skipping, std::string* skip);
88
  void FindPrevUserEntry();
89
  bool ParseKey(ParsedInternalKey* key);
90
91
6.12M
  inline void SaveKey(const Slice& k, std::string* dst) {
92
6.12M
    dst->assign(k.data(), k.size());
93
6.12M
  }
94
95
62.7k
  inline void ClearSavedValue() {
96
62.7k
    if (saved_value_.capacity() > 1048576) {
97
0
      std::string empty;
98
0
      swap(empty, saved_value_);
99
62.7k
    } else {
100
62.7k
      saved_value_.clear();
101
62.7k
    }
102
62.7k
  }
103
104
  // Picks the number of bytes that can be read until a compaction is scheduled.
105
149k
  size_t RandomCompactionPeriod() {
106
149k
    return rnd_.Uniform(2 * config::kReadBytesPeriod);
107
149k
  }
108
109
  DBImpl* db_;
110
  const Comparator* const user_comparator_;
111
  Iterator* const iter_;
112
  SequenceNumber const sequence_;
113
  Status status_;
114
  std::string saved_key_;    // == current key when direction_==kReverse
115
  std::string saved_value_;  // == current raw value when direction_==kReverse
116
  Direction direction_;
117
  bool valid_;
118
  Random rnd_;
119
  size_t bytes_until_read_sampling_;
120
};
121
122
6.16M
inline bool DBIter::ParseKey(ParsedInternalKey* ikey) {
123
6.16M
  Slice k = iter_->key();
124
125
6.16M
  size_t bytes_read = k.size() + iter_->value().size();
126
6.17M
  while (bytes_until_read_sampling_ < bytes_read) {
127
5.61k
    bytes_until_read_sampling_ += RandomCompactionPeriod();
128
5.61k
    db_->RecordReadSample(k);
129
5.61k
  }
130
6.16M
  assert(bytes_until_read_sampling_ >= bytes_read);
131
6.16M
  bytes_until_read_sampling_ -= bytes_read;
132
133
6.16M
  if (!ParseInternalKey(k, ikey)) {
134
0
    status_ = Status::Corruption("corrupted internal key in DBIter");
135
0
    return false;
136
6.16M
  } else {
137
6.16M
    return true;
138
6.16M
  }
139
6.16M
}
140
141
321k
void DBIter::Next() {
142
321k
  assert(valid_);
143
144
321k
  if (direction_ == kReverse) {  // Switch directions?
145
0
    direction_ = kForward;
146
    // iter_ is pointing just before the entries for this->key(),
147
    // so advance into the range of entries for this->key() and then
148
    // use the normal skipping code below.
149
0
    if (!iter_->Valid()) {
150
0
      iter_->SeekToFirst();
151
0
    } else {
152
0
      iter_->Next();
153
0
    }
154
0
    if (!iter_->Valid()) {
155
0
      valid_ = false;
156
0
      saved_key_.clear();
157
0
      return;
158
0
    }
159
    // saved_key_ already contains the key to skip past.
160
321k
  } else {
161
    // Store in saved_key_ the current key so we skip it below.
162
321k
    SaveKey(ExtractUserKey(iter_->key()), &saved_key_);
163
164
    // iter_ is pointing to current key. We can now safely move to the next to
165
    // avoid checking current key.
166
321k
    iter_->Next();
167
321k
    if (!iter_->Valid()) {
168
18.7k
      valid_ = false;
169
18.7k
      saved_key_.clear();
170
18.7k
      return;
171
18.7k
    }
172
321k
  }
173
174
302k
  FindNextUserEntry(true, &saved_key_);
175
302k
}
176
177
359k
void DBIter::FindNextUserEntry(bool skipping, std::string* skip) {
178
  // Loop until we hit an acceptable entry to yield
179
359k
  assert(iter_->Valid());
180
359k
  assert(direction_ == kForward);
181
6.16M
  do {
182
6.16M
    ParsedInternalKey ikey;
183
6.16M
    if (ParseKey(&ikey) && ikey.sequence <= sequence_) {
184
6.16M
      switch (ikey.type) {
185
5.80M
        case kTypeDeletion:
186
          // Arrange to skip all upcoming entries for this key since
187
          // they are hidden by this deletion.
188
5.80M
          SaveKey(ikey.user_key, skip);
189
5.80M
          skipping = true;
190
5.80M
          break;
191
369k
        case kTypeValue:
192
369k
          if (skipping &&
193
369k
              user_comparator_->Compare(ikey.user_key, *skip) <= 0) {
194
            // Entry hidden
195
321k
          } else {
196
321k
            valid_ = true;
197
321k
            saved_key_.clear();
198
321k
            return;
199
321k
          }
200
48.1k
          break;
201
6.16M
      }
202
6.16M
    }
203
5.84M
    iter_->Next();
204
5.84M
  } while (iter_->Valid());
205
37.8k
  saved_key_.clear();
206
37.8k
  valid_ = false;
207
37.8k
}
208
209
0
void DBIter::Prev() {
210
0
  assert(valid_);
211
212
0
  if (direction_ == kForward) {  // Switch directions?
213
    // iter_ is pointing at the current entry.  Scan backwards until
214
    // the key changes so we can use the normal reverse scanning code.
215
0
    assert(iter_->Valid());  // Otherwise valid_ would have been false
216
0
    SaveKey(ExtractUserKey(iter_->key()), &saved_key_);
217
0
    while (true) {
218
0
      iter_->Prev();
219
0
      if (!iter_->Valid()) {
220
0
        valid_ = false;
221
0
        saved_key_.clear();
222
0
        ClearSavedValue();
223
0
        return;
224
0
      }
225
0
      if (user_comparator_->Compare(ExtractUserKey(iter_->key()), saved_key_) <
226
0
          0) {
227
0
        break;
228
0
      }
229
0
    }
230
0
    direction_ = kReverse;
231
0
  }
232
233
0
  FindPrevUserEntry();
234
0
}
235
236
0
void DBIter::FindPrevUserEntry() {
237
0
  assert(direction_ == kReverse);
238
239
0
  ValueType value_type = kTypeDeletion;
240
0
  if (iter_->Valid()) {
241
0
    do {
242
0
      ParsedInternalKey ikey;
243
0
      if (ParseKey(&ikey) && ikey.sequence <= sequence_) {
244
0
        if ((value_type != kTypeDeletion) &&
245
0
            user_comparator_->Compare(ikey.user_key, saved_key_) < 0) {
246
          // We encountered a non-deleted value in entries for previous keys,
247
0
          break;
248
0
        }
249
0
        value_type = ikey.type;
250
0
        if (value_type == kTypeDeletion) {
251
0
          saved_key_.clear();
252
0
          ClearSavedValue();
253
0
        } else {
254
0
          Slice raw_value = iter_->value();
255
0
          if (saved_value_.capacity() > raw_value.size() + 1048576) {
256
0
            std::string empty;
257
0
            swap(empty, saved_value_);
258
0
          }
259
0
          SaveKey(ExtractUserKey(iter_->key()), &saved_key_);
260
0
          saved_value_.assign(raw_value.data(), raw_value.size());
261
0
        }
262
0
      }
263
0
      iter_->Prev();
264
0
    } while (iter_->Valid());
265
0
  }
266
267
0
  if (value_type == kTypeDeletion) {
268
    // End
269
0
    valid_ = false;
270
0
    saved_key_.clear();
271
0
    ClearSavedValue();
272
0
    direction_ = kForward;
273
0
  } else {
274
0
    valid_ = true;
275
0
  }
276
0
}
277
278
0
void DBIter::Seek(const Slice& target) {
279
0
  direction_ = kForward;
280
0
  ClearSavedValue();
281
0
  saved_key_.clear();
282
0
  AppendInternalKey(&saved_key_,
283
0
                    ParsedInternalKey(target, sequence_, kValueTypeForSeek));
284
0
  iter_->Seek(saved_key_);
285
0
  if (iter_->Valid()) {
286
0
    FindNextUserEntry(false, &saved_key_ /* temporary storage */);
287
0
  } else {
288
0
    valid_ = false;
289
0
  }
290
0
}
291
292
62.7k
void DBIter::SeekToFirst() {
293
62.7k
  direction_ = kForward;
294
62.7k
  ClearSavedValue();
295
62.7k
  iter_->SeekToFirst();
296
62.7k
  if (iter_->Valid()) {
297
56.6k
    FindNextUserEntry(false, &saved_key_ /* temporary storage */);
298
56.6k
  } else {
299
6.16k
    valid_ = false;
300
6.16k
  }
301
62.7k
}
302
303
0
void DBIter::SeekToLast() {
304
0
  direction_ = kReverse;
305
0
  ClearSavedValue();
306
0
  iter_->SeekToLast();
307
0
  FindPrevUserEntry();
308
0
}
309
310
}  // anonymous namespace
311
312
Iterator* NewDBIterator(DBImpl* db, const Comparator* user_key_comparator,
313
                        Iterator* internal_iter, SequenceNumber sequence,
314
143k
                        uint32_t seed) {
315
143k
  return new DBIter(db, user_key_comparator, internal_iter, sequence, seed);
316
143k
}
317
318
}  // namespace leveldb