Coverage Report

Created: 2026-08-14 08:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/rocksdb/table/two_level_iterator.cc
Line
Count
Source
1
//  Copyright (c) 2011-present, Facebook, Inc.  All rights reserved.
2
//  This source code is licensed under both the GPLv2 (found in the
3
//  COPYING file in the root directory) and Apache 2.0 License
4
//  (found in the LICENSE.Apache file in the root directory).
5
//
6
// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
7
// Use of this source code is governed by a BSD-style license that can be
8
// found in the LICENSE file. See the AUTHORS file for names of contributors.
9
10
#include "table/two_level_iterator.h"
11
12
#include "db/pinned_iterators_manager.h"
13
#include "memory/arena.h"
14
#include "rocksdb/options.h"
15
#include "rocksdb/table.h"
16
#include "table/block_based/block.h"
17
#include "table/format.h"
18
19
namespace ROCKSDB_NAMESPACE {
20
21
namespace {
22
23
class TwoLevelIndexIterator : public InternalIteratorBase<IndexValue> {
24
 public:
25
  explicit TwoLevelIndexIterator(
26
      TwoLevelIteratorState* state,
27
      InternalIteratorBase<IndexValue>* first_level_iter);
28
29
0
  ~TwoLevelIndexIterator() override {
30
0
    first_level_iter_.DeleteIter(false /* is_arena_mode */);
31
0
    second_level_iter_.DeleteIter(false /* is_arena_mode */);
32
0
    delete state_;
33
0
  }
34
35
  void Seek(const Slice& target) override;
36
  void SeekForPrev(const Slice& target) override;
37
  void SeekToFirst() override;
38
  void SeekToLast() override;
39
  void Next() override;
40
  void Prev() override;
41
42
0
  bool Valid() const override { return second_level_iter_.Valid(); }
43
0
  Slice key() const override {
44
0
    assert(Valid());
45
0
    return second_level_iter_.key();
46
0
  }
47
0
  Slice user_key() const override {
48
0
    assert(Valid());
49
0
    return second_level_iter_.user_key();
50
0
  }
51
0
  IndexValue value() const override {
52
0
    assert(Valid());
53
0
    return second_level_iter_.value();
54
0
  }
55
0
  Status status() const override {
56
0
    if (!first_level_iter_.status().ok()) {
57
0
      assert(second_level_iter_.iter() == nullptr);
58
0
      return first_level_iter_.status();
59
0
    } else if (second_level_iter_.iter() != nullptr &&
60
0
               !second_level_iter_.status().ok()) {
61
0
      return second_level_iter_.status();
62
0
    } else {
63
0
      return status_;
64
0
    }
65
0
  }
66
  void SetPinnedItersMgr(
67
0
      PinnedIteratorsManager* /*pinned_iters_mgr*/) override {}
68
0
  bool IsKeyPinned() const override { return false; }
69
0
  bool IsValuePinned() const override { return false; }
70
71
 private:
72
0
  void SaveError(const Status& s) {
73
0
    if (status_.ok() && !s.ok()) {
74
0
      status_ = s;
75
0
    }
76
0
  }
77
  void SkipEmptyDataBlocksForward();
78
  void SkipEmptyDataBlocksBackward();
79
  void SetSecondLevelIterator(InternalIteratorBase<IndexValue>* iter);
80
  void InitDataBlock();
81
82
  TwoLevelIteratorState* state_;
83
  IteratorWrapperBase<IndexValue> first_level_iter_;
84
  IteratorWrapperBase<IndexValue> second_level_iter_;  // May be nullptr
85
  Status status_;
86
  // If second_level_iter is non-nullptr, then "data_block_handle_" holds the
87
  // "index_value" passed to block_function_ to create the second_level_iter.
88
  BlockHandle data_block_handle_;
89
};
90
91
TwoLevelIndexIterator::TwoLevelIndexIterator(
92
    TwoLevelIteratorState* state,
93
    InternalIteratorBase<IndexValue>* first_level_iter)
94
0
    : state_(state), first_level_iter_(first_level_iter) {}
95
96
0
void TwoLevelIndexIterator::Seek(const Slice& target) {
97
0
  first_level_iter_.Seek(target);
98
99
0
  InitDataBlock();
100
0
  if (second_level_iter_.iter() != nullptr) {
101
0
    second_level_iter_.Seek(target);
102
0
  }
103
0
  SkipEmptyDataBlocksForward();
104
0
}
105
106
0
void TwoLevelIndexIterator::SeekForPrev(const Slice& target) {
107
0
  first_level_iter_.Seek(target);
108
0
  InitDataBlock();
109
0
  if (second_level_iter_.iter() != nullptr) {
110
0
    second_level_iter_.SeekForPrev(target);
111
0
  }
112
0
  if (!Valid()) {
113
0
    if (!first_level_iter_.Valid() && first_level_iter_.status().ok()) {
114
0
      first_level_iter_.SeekToLast();
115
0
      InitDataBlock();
116
0
      if (second_level_iter_.iter() != nullptr) {
117
0
        second_level_iter_.SeekForPrev(target);
118
0
      }
119
0
    }
120
0
    SkipEmptyDataBlocksBackward();
121
0
  }
122
0
}
123
124
0
void TwoLevelIndexIterator::SeekToFirst() {
125
0
  first_level_iter_.SeekToFirst();
126
0
  InitDataBlock();
127
0
  if (second_level_iter_.iter() != nullptr) {
128
0
    second_level_iter_.SeekToFirst();
129
0
  }
130
0
  SkipEmptyDataBlocksForward();
131
0
}
132
133
0
void TwoLevelIndexIterator::SeekToLast() {
134
0
  first_level_iter_.SeekToLast();
135
0
  InitDataBlock();
136
0
  if (second_level_iter_.iter() != nullptr) {
137
0
    second_level_iter_.SeekToLast();
138
0
  }
139
0
  SkipEmptyDataBlocksBackward();
140
0
}
141
142
0
void TwoLevelIndexIterator::Next() {
143
0
  assert(Valid());
144
0
  second_level_iter_.Next();
145
0
  SkipEmptyDataBlocksForward();
146
0
}
147
148
0
void TwoLevelIndexIterator::Prev() {
149
0
  assert(Valid());
150
0
  second_level_iter_.Prev();
151
0
  SkipEmptyDataBlocksBackward();
152
0
}
153
154
0
void TwoLevelIndexIterator::SkipEmptyDataBlocksForward() {
155
0
  while (second_level_iter_.iter() == nullptr ||
156
0
         (!second_level_iter_.Valid() && second_level_iter_.status().ok())) {
157
    // Move to next block
158
0
    if (!first_level_iter_.Valid()) {
159
0
      SetSecondLevelIterator(nullptr);
160
0
      return;
161
0
    }
162
0
    first_level_iter_.Next();
163
0
    InitDataBlock();
164
0
    if (second_level_iter_.iter() != nullptr) {
165
0
      second_level_iter_.SeekToFirst();
166
0
    }
167
0
  }
168
0
}
169
170
0
void TwoLevelIndexIterator::SkipEmptyDataBlocksBackward() {
171
0
  while (second_level_iter_.iter() == nullptr ||
172
0
         (!second_level_iter_.Valid() && second_level_iter_.status().ok())) {
173
    // Move to next block
174
0
    if (!first_level_iter_.Valid()) {
175
0
      SetSecondLevelIterator(nullptr);
176
0
      return;
177
0
    }
178
0
    first_level_iter_.Prev();
179
0
    InitDataBlock();
180
0
    if (second_level_iter_.iter() != nullptr) {
181
0
      second_level_iter_.SeekToLast();
182
0
    }
183
0
  }
184
0
}
185
186
void TwoLevelIndexIterator::SetSecondLevelIterator(
187
0
    InternalIteratorBase<IndexValue>* iter) {
188
0
  InternalIteratorBase<IndexValue>* old_iter = second_level_iter_.Set(iter);
189
0
  delete old_iter;
190
0
}
191
192
0
void TwoLevelIndexIterator::InitDataBlock() {
193
0
  if (!first_level_iter_.Valid()) {
194
0
    SetSecondLevelIterator(nullptr);
195
0
  } else {
196
0
    BlockHandle handle = first_level_iter_.value().handle;
197
0
    if (second_level_iter_.iter() != nullptr &&
198
0
        !second_level_iter_.status().IsIncomplete() &&
199
0
        handle.offset() == data_block_handle_.offset()) {
200
      // second_level_iter is already constructed with this iterator, so
201
      // no need to change anything
202
0
    } else {
203
0
      InternalIteratorBase<IndexValue>* iter =
204
0
          state_->NewSecondaryIterator(handle);
205
0
      data_block_handle_ = handle;
206
0
      SetSecondLevelIterator(iter);
207
0
      if (iter == nullptr) {
208
0
        status_ = Status::Corruption("Missing block for partition " +
209
0
                                     handle.ToString());
210
0
      }
211
0
    }
212
0
  }
213
0
}
214
215
}  // namespace
216
217
InternalIteratorBase<IndexValue>* NewTwoLevelIterator(
218
    TwoLevelIteratorState* state,
219
0
    InternalIteratorBase<IndexValue>* first_level_iter) {
220
0
  return new TwoLevelIndexIterator(state, first_level_iter);
221
0
}
222
}  // namespace ROCKSDB_NAMESPACE