github.com/cockroachdb/pebble@v1.1.1-0.20240513155919-3622ade60459/internal/keyspan/iter.go (about) 1 // Copyright 2018 The LevelDB-Go and Pebble Authors. All rights reserved. Use 2 // of this source code is governed by a BSD-style license that can be found in 3 // the LICENSE file. 4 5 package keyspan 6 7 import ( 8 "github.com/cockroachdb/pebble/internal/base" 9 "github.com/cockroachdb/pebble/internal/manifest" 10 ) 11 12 // FragmentIterator defines an iterator interface over spans. The spans 13 // surfaced by a FragmentIterator must be non-overlapping. This is achieved by 14 // fragmenting spans at overlap points (see Fragmenter). 15 // 16 // A Span returned by a FragmentIterator is only valid until the next 17 // positioning method. Some implementations (eg, keyspan.Iter) may provide 18 // longer lifetimes but implementations need only guarantee stability until the 19 // next positioning method. 20 type FragmentIterator interface { 21 // SeekGE moves the iterator to the first span covering a key greater than 22 // or equal to the given key. This is equivalent to seeking to the first 23 // span with an end key greater than the given key. 24 SeekGE(key []byte) *Span 25 26 // SeekLT moves the iterator to the last span covering a key less than the 27 // given key. This is equivalent to seeking to the last span with a start 28 // key less than the given key. 29 SeekLT(key []byte) *Span 30 31 // First moves the iterator to the first span. 32 First() *Span 33 34 // Last moves the iterator to the last span. 35 Last() *Span 36 37 // Next moves the iterator to the next span. 38 // 39 // It is valid to call Next when the iterator is positioned before the first 40 // key/value pair due to either a prior call to SeekLT or Prev which 41 // returned an invalid span. It is not allowed to call Next when the 42 // previous call to SeekGE, SeekPrefixGE or Next returned an invalid span. 43 Next() *Span 44 45 // Prev moves the iterator to the previous span. 46 // 47 // It is valid to call Prev when the iterator is positioned after the last 48 // key/value pair due to either a prior call to SeekGE or Next which 49 // returned an invalid span. It is not allowed to call Prev when the 50 // previous call to SeekLT or Prev returned an invalid span. 51 Prev() *Span 52 53 // Error returns any accumulated error. 54 // 55 // TODO(jackson): Lift errors into return values on the positioning methods. 56 Error() error 57 58 // Close closes the iterator and returns any accumulated error. Exhausting 59 // the iterator is not considered to be an error. It is valid to call Close 60 // multiple times. Other methods should not be called after the iterator has 61 // been closed. 62 Close() error 63 } 64 65 // TableNewSpanIter creates a new iterator for range key spans for the given 66 // file. 67 type TableNewSpanIter func(file *manifest.FileMetadata, iterOptions SpanIterOptions) (FragmentIterator, error) 68 69 // SpanIterOptions is a subset of IterOptions that are necessary to instantiate 70 // per-sstable span iterators. 71 type SpanIterOptions struct { 72 // RangeKeyFilters can be used to avoid scanning tables and blocks in tables 73 // when iterating over range keys. 74 RangeKeyFilters []base.BlockPropertyFilter 75 } 76 77 // Iter is an iterator over a set of fragmented spans. 78 type Iter struct { 79 cmp base.Compare 80 spans []Span 81 index int 82 } 83 84 // Iter implements the FragmentIterator interface. 85 var _ FragmentIterator = (*Iter)(nil) 86 87 // NewIter returns a new iterator over a set of fragmented spans. 88 func NewIter(cmp base.Compare, spans []Span) *Iter { 89 i := &Iter{} 90 i.Init(cmp, spans) 91 return i 92 } 93 94 // Count returns the number of spans contained by Iter. 95 func (i *Iter) Count() int { 96 return len(i.spans) 97 } 98 99 // Init initializes an Iter with the provided spans. 100 func (i *Iter) Init(cmp base.Compare, spans []Span) { 101 *i = Iter{ 102 cmp: cmp, 103 spans: spans, 104 index: -1, 105 } 106 } 107 108 // SeekGE implements FragmentIterator.SeekGE. 109 func (i *Iter) SeekGE(key []byte) *Span { 110 // NB: manually inlined sort.Search is ~5% faster. 111 // 112 // Define f(j) = false iff the span i.spans[j] is strictly before `key` 113 // (equivalently, i.spans[j].End ≤ key.) 114 // 115 // Define f(-1) == false and f(n) == true. 116 // Invariant: f(index-1) == false, f(upper) == true. 117 i.index = 0 118 upper := len(i.spans) 119 for i.index < upper { 120 h := int(uint(i.index+upper) >> 1) // avoid overflow when computing h 121 // i.index ≤ h < upper 122 if i.cmp(key, i.spans[h].End) >= 0 { 123 i.index = h + 1 // preserves f(i-1) == false 124 } else { 125 upper = h // preserves f(j) == true 126 } 127 } 128 129 // i.index == upper, f(i.index-1) == false, and f(upper) (= f(i.index)) == 130 // true => answer is i.index. 131 if i.index >= len(i.spans) { 132 return nil 133 } 134 return &i.spans[i.index] 135 } 136 137 // SeekLT implements FragmentIterator.SeekLT. 138 func (i *Iter) SeekLT(key []byte) *Span { 139 // NB: manually inlined sort.Search is ~5% faster. 140 // 141 // Define f(-1) == false and f(n) == true. 142 // Invariant: f(index-1) == false, f(upper) == true. 143 i.index = 0 144 upper := len(i.spans) 145 for i.index < upper { 146 h := int(uint(i.index+upper) >> 1) // avoid overflow when computing h 147 // i.index ≤ h < upper 148 if i.cmp(key, i.spans[h].Start) > 0 { 149 i.index = h + 1 // preserves f(i-1) == false 150 } else { 151 upper = h // preserves f(j) == true 152 } 153 } 154 // i.index == upper, f(i.index-1) == false, and f(upper) (= f(i.index)) == 155 // true => answer is i.index. 156 157 // Since keys are strictly increasing, if i.index > 0 then i.index-1 will be 158 // the largest whose key is < the key sought. 159 i.index-- 160 if i.index < 0 { 161 return nil 162 } 163 return &i.spans[i.index] 164 } 165 166 // First implements FragmentIterator.First. 167 func (i *Iter) First() *Span { 168 if len(i.spans) == 0 { 169 return nil 170 } 171 i.index = 0 172 return &i.spans[i.index] 173 } 174 175 // Last implements FragmentIterator.Last. 176 func (i *Iter) Last() *Span { 177 if len(i.spans) == 0 { 178 return nil 179 } 180 i.index = len(i.spans) - 1 181 return &i.spans[i.index] 182 } 183 184 // Next implements FragmentIterator.Next. 185 func (i *Iter) Next() *Span { 186 if i.index >= len(i.spans) { 187 return nil 188 } 189 i.index++ 190 if i.index >= len(i.spans) { 191 return nil 192 } 193 return &i.spans[i.index] 194 } 195 196 // Prev implements FragmentIterator.Prev. 197 func (i *Iter) Prev() *Span { 198 if i.index < 0 { 199 return nil 200 } 201 i.index-- 202 if i.index < 0 { 203 return nil 204 } 205 return &i.spans[i.index] 206 } 207 208 // Error implements FragmentIterator.Error. 209 func (i *Iter) Error() error { 210 return nil 211 } 212 213 // Close implements FragmentIterator.Close. 214 func (i *Iter) Close() error { 215 return nil 216 } 217 218 func (i *Iter) String() string { 219 return "fragmented-spans" 220 }