YugabyteDB (2.13.1.0-b60, 21121d69985fbf76aa6958d8f04a9bfa936293b5)

Coverage Report

Created: 2022-03-22 16:43

/Users/deen/code/yugabyte-db/src/yb/rocksdb/table/two_level_iterator.cc
Line
Count
Source (jump to first uncovered line)
1
//  Copyright (c) 2011-present, Facebook, Inc.  All rights reserved.
2
//  This source code is licensed under the BSD-style license found in the
3
//  LICENSE file in the root directory of this source tree. An additional grant
4
//  of patent rights can be found in the PATENTS file in the same directory.
5
//
6
// The following only applies to changes made to this file as part of YugaByte development.
7
//
8
// Portions Copyright (c) YugaByte, Inc.
9
//
10
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
11
// in compliance with the License.  You may obtain a copy of the License at
12
//
13
// http://www.apache.org/licenses/LICENSE-2.0
14
//
15
// Unless required by applicable law or agreed to in writing, software distributed under the License
16
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
17
// or implied.  See the License for the specific language governing permissions and limitations
18
// under the License.
19
//
20
// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
21
// Use of this source code is governed by a BSD-style license that can be
22
// found in the LICENSE file. See the AUTHORS file for names of contributors.
23
24
#include "yb/rocksdb/table/two_level_iterator.h"
25
26
#include "yb/rocksdb/table/iterator_wrapper.h"
27
#include "yb/rocksdb/util/arena.h"
28
29
namespace rocksdb {
30
31
namespace {
32
33
class TwoLevelIterator : public InternalIterator {
34
 public:
35
  explicit TwoLevelIterator(TwoLevelIteratorState* state,
36
                            InternalIterator* first_level_iter,
37
                            bool need_free_iter_and_state);
38
39
14.6M
  virtual ~TwoLevelIterator() {
40
14.6M
    first_level_iter_.DeleteIter(!need_free_iter_and_state_);
41
14.6M
    second_level_iter_.DeleteIter(false);
42
14.6M
    if (need_free_iter_and_state_) {
43
14.6M
      delete state_;
44
14.6M
    } else {
45
12.2k
      state_->~TwoLevelIteratorState();
46
12.2k
    }
47
14.6M
  }
48
49
  void Seek(const Slice& target) override;
50
  void SeekToFirst() override;
51
  void SeekToLast() override;
52
  void Next() override;
53
  void Prev() override;
54
55
4.57G
  bool Valid() const override { return second_level_iter_.Valid(); }
56
833M
  Slice key() const override {
57
833M
    assert(Valid());
58
0
    return second_level_iter_.key();
59
833M
  }
60
2.15G
  Slice value() const override {
61
2.15G
    assert(Valid());
62
0
    return second_level_iter_.value();
63
2.15G
  }
64
3.41M
  Status status() const override {
65
    // It'd be nice if status() returned a const Status& instead of a Status
66
3.41M
    if (!first_level_iter_.status().ok()) {
67
0
      return first_level_iter_.status();
68
3.41M
    } else if (second_level_iter_.iter() != nullptr &&
69
3.41M
               
!second_level_iter_.status().ok()3.15M
) {
70
54
      return second_level_iter_.status();
71
3.41M
    } else {
72
3.41M
      return status_;
73
3.41M
    }
74
3.41M
  }
75
116k
  Status PinData() override { return second_level_iter_.PinData(); }
76
0
  Status ReleasePinnedData() override {
77
0
    return second_level_iter_.ReleasePinnedData();
78
0
  }
79
753k
  bool IsKeyPinned() const override {
80
753k
    return second_level_iter_.iter() ? second_level_iter_.IsKeyPinned() : 
false0
;
81
753k
  }
82
83
 private:
84
18.6M
  void SaveError(const Status& s) {
85
18.6M
    if (
status_.ok()18.6M
&& !s.ok())
status_ = s1
;
86
18.6M
  }
87
  void SkipEmptyDataBlocksForward();
88
  void SkipEmptyDataBlocksBackward();
89
  void SetSecondLevelIterator(InternalIterator* iter);
90
  void InitDataBlock();
91
92
  TwoLevelIteratorState* state_;
93
  IteratorWrapper first_level_iter_;
94
  IteratorWrapper second_level_iter_;  // May be nullptr
95
  bool need_free_iter_and_state_;
96
  Status status_;
97
  // If second_level_iter is non-nullptr, then "data_block_handle_" holds the
98
  // "index_value" passed to block_function_ to create the second_level_iter.
99
  std::string data_block_handle_;
100
};
101
102
TwoLevelIterator::TwoLevelIterator(TwoLevelIteratorState* state,
103
                                   InternalIterator* first_level_iter,
104
                                   bool need_free_iter_and_state)
105
    : state_(state),
106
      first_level_iter_(first_level_iter),
107
14.6M
      need_free_iter_and_state_(need_free_iter_and_state) {}
108
109
81.2M
void TwoLevelIterator::Seek(const Slice& target) {
110
81.2M
  if (state_->check_prefix_may_match &&
111
81.2M
      
!state_->PrefixMayMatch(target)15.8k
) {
112
31
    SetSecondLevelIterator(nullptr);
113
31
    return;
114
31
  }
115
81.2M
  first_level_iter_.Seek(target);
116
117
81.2M
  InitDataBlock();
118
81.2M
  if (second_level_iter_.iter() != nullptr) {
119
81.2M
    second_level_iter_.Seek(target);
120
81.2M
  }
121
81.2M
  SkipEmptyDataBlocksForward();
122
81.2M
}
123
124
299k
void TwoLevelIterator::SeekToFirst() {
125
299k
  first_level_iter_.SeekToFirst();
126
299k
  InitDataBlock();
127
299k
  if (second_level_iter_.iter() != nullptr) {
128
297k
    second_level_iter_.SeekToFirst();
129
297k
  }
130
299k
  SkipEmptyDataBlocksForward();
131
299k
}
132
133
1.44M
void TwoLevelIterator::SeekToLast() {
134
1.44M
  first_level_iter_.SeekToLast();
135
1.44M
  InitDataBlock();
136
1.44M
  if (second_level_iter_.iter() != nullptr) {
137
1.44M
    second_level_iter_.SeekToLast();
138
1.44M
  }
139
1.44M
  SkipEmptyDataBlocksBackward();
140
1.44M
}
141
142
746M
void TwoLevelIterator::Next() {
143
746M
  assert(Valid());
144
0
  second_level_iter_.Next();
145
746M
  SkipEmptyDataBlocksForward();
146
746M
}
147
148
6.64M
void TwoLevelIterator::Prev() {
149
6.64M
  assert(Valid());
150
0
  second_level_iter_.Prev();
151
6.64M
  SkipEmptyDataBlocksBackward();
152
6.64M
}
153
154
155
826M
void TwoLevelIterator::SkipEmptyDataBlocksForward() {
156
830M
  while (second_level_iter_.iter() == nullptr ||
157
830M
         
(829M
!second_level_iter_.Valid()829M
&&
158
829M
         
!second_level_iter_.status().IsIncomplete()4.39M
)) {
159
    // Move to next block
160
5.48M
    if (!first_level_iter_.Valid()) {
161
1.09M
      SetSecondLevelIterator(nullptr);
162
1.09M
      return;
163
1.09M
    }
164
4.39M
    first_level_iter_.Next();
165
4.39M
    InitDataBlock();
166
4.39M
    if (second_level_iter_.iter() != nullptr) {
167
3.32M
      second_level_iter_.SeekToFirst();
168
3.32M
    }
169
4.39M
  }
170
826M
}
171
172
8.09M
void TwoLevelIterator::SkipEmptyDataBlocksBackward() {
173
8.37M
  while (second_level_iter_.iter() == nullptr ||
174
8.37M
         
(8.16M
!second_level_iter_.Valid()8.16M
&&
175
8.16M
         
!second_level_iter_.status().IsIncomplete()282k
)) {
176
    // Move to next block
177
488k
    if (!first_level_iter_.Valid()) {
178
206k
      SetSecondLevelIterator(nullptr);
179
206k
      return;
180
206k
    }
181
282k
    first_level_iter_.Prev();
182
282k
    InitDataBlock();
183
282k
    if (second_level_iter_.iter() != nullptr) {
184
77.9k
      second_level_iter_.SeekToLast();
185
77.9k
    }
186
282k
  }
187
8.09M
}
188
189
35.5M
void TwoLevelIterator::SetSecondLevelIterator(InternalIterator* iter) {
190
35.5M
  if (second_level_iter_.iter() != nullptr) {
191
18.6M
    SaveError(second_level_iter_.status());
192
18.6M
  }
193
35.5M
  second_level_iter_.Set(iter);
194
35.5M
}
195
196
87.7M
void TwoLevelIterator::InitDataBlock() {
197
87.7M
  if (!first_level_iter_.Valid()) {
198
1.29M
    SetSecondLevelIterator(nullptr);
199
86.4M
  } else {
200
86.4M
    Slice handle = first_level_iter_.value();
201
86.4M
    if (second_level_iter_.iter() != nullptr &&
202
86.4M
        
!second_level_iter_.status().IsIncomplete()70.8M
&&
203
86.4M
        
handle.compare(data_block_handle_) == 070.8M
) {
204
      // second_level_iter is already constructed with this iterator, so
205
      // no need to change anything
206
53.4M
    } else {
207
32.9M
      InternalIterator* iter = state_->NewSecondaryIterator(handle);
208
32.9M
      data_block_handle_.assign(handle.cdata(), handle.size());
209
32.9M
      SetSecondLevelIterator(iter);
210
32.9M
    }
211
86.4M
  }
212
87.7M
}
213
214
}  // namespace
215
216
InternalIterator* NewTwoLevelIterator(
217
    TwoLevelIteratorState* state, InternalIterator* first_level_iter, Arena* arena,
218
14.6M
    bool need_free_iter_and_state) {
219
14.6M
  if (arena == nullptr) {
220
271k
    return new TwoLevelIterator(state, first_level_iter, need_free_iter_and_state);
221
14.4M
  } else {
222
14.4M
    auto mem = arena->AllocateAligned(sizeof(TwoLevelIterator));
223
14.4M
    return new (mem)
224
14.4M
        TwoLevelIterator(state, first_level_iter, need_free_iter_and_state);
225
14.4M
  }
226
14.6M
}
227
228
}  // namespace rocksdb