github.com/cockroachdb/pebble@v0.0.0-20231214172447-ab4952c5f87b/get_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 pebble 6 7 import ( 8 "context" 9 "fmt" 10 11 "github.com/cockroachdb/pebble/internal/base" 12 "github.com/cockroachdb/pebble/internal/keyspan" 13 "github.com/cockroachdb/pebble/internal/manifest" 14 "github.com/cockroachdb/pebble/sstable" 15 ) 16 17 // getIter is an internal iterator used to perform gets. It iterates through 18 // the values for a particular key, level by level. It is not a general purpose 19 // internalIterator, but specialized for Get operations so that it loads data 20 // lazily. 21 type getIter struct { 22 logger Logger 23 comparer *Comparer 24 newIters tableNewIters 25 snapshot uint64 26 key []byte 27 iter internalIterator 28 rangeDelIter keyspan.FragmentIterator 29 tombstone *keyspan.Span 30 levelIter levelIter 31 level int 32 batch *Batch 33 mem flushableList 34 l0 []manifest.LevelSlice 35 version *version 36 iterKey *InternalKey 37 iterValue base.LazyValue 38 err error 39 } 40 41 // TODO(sumeer): CockroachDB code doesn't use getIter, but, for completeness, 42 // make this implement InternalIteratorWithStats. 43 44 // getIter implements the base.InternalIterator interface. 45 var _ base.InternalIterator = (*getIter)(nil) 46 47 func (g *getIter) String() string { 48 return fmt.Sprintf("len(l0)=%d, len(mem)=%d, level=%d", len(g.l0), len(g.mem), g.level) 49 } 50 51 func (g *getIter) SeekGE(key []byte, flags base.SeekGEFlags) (*InternalKey, base.LazyValue) { 52 panic("pebble: SeekGE unimplemented") 53 } 54 55 func (g *getIter) SeekPrefixGE( 56 prefix, key []byte, flags base.SeekGEFlags, 57 ) (*base.InternalKey, base.LazyValue) { 58 panic("pebble: SeekPrefixGE unimplemented") 59 } 60 61 func (g *getIter) SeekLT(key []byte, flags base.SeekLTFlags) (*InternalKey, base.LazyValue) { 62 panic("pebble: SeekLT unimplemented") 63 } 64 65 func (g *getIter) First() (*InternalKey, base.LazyValue) { 66 return g.Next() 67 } 68 69 func (g *getIter) Last() (*InternalKey, base.LazyValue) { 70 panic("pebble: Last unimplemented") 71 } 72 73 func (g *getIter) Next() (*InternalKey, base.LazyValue) { 74 if g.iter != nil { 75 g.iterKey, g.iterValue = g.iter.Next() 76 } 77 78 for { 79 if g.iter != nil { 80 // We have to check rangeDelIter on each iteration because a single 81 // user-key can be spread across multiple tables in a level. A range 82 // tombstone will appear in the table corresponding to its start 83 // key. Every call to levelIter.Next() potentially switches to a new 84 // table and thus reinitializes rangeDelIter. 85 if g.rangeDelIter != nil { 86 g.tombstone = keyspan.Get(g.comparer.Compare, g.rangeDelIter, g.key) 87 if g.err = g.rangeDelIter.Close(); g.err != nil { 88 return nil, base.LazyValue{} 89 } 90 g.rangeDelIter = nil 91 } 92 93 if g.iterKey != nil { 94 key := g.iterKey 95 if g.tombstone != nil && g.tombstone.CoversAt(g.snapshot, key.SeqNum()) { 96 // We have a range tombstone covering this key. Rather than return a 97 // point or range deletion here, we return false and close our 98 // internal iterator which will make Valid() return false, 99 // effectively stopping iteration. 100 g.err = g.iter.Close() 101 g.iter = nil 102 return nil, base.LazyValue{} 103 } 104 if g.comparer.Equal(g.key, key.UserKey) { 105 if !key.Visible(g.snapshot, base.InternalKeySeqNumMax) { 106 g.iterKey, g.iterValue = g.iter.Next() 107 continue 108 } 109 return g.iterKey, g.iterValue 110 } 111 } 112 // We've advanced the iterator passed the desired key. Move on to the 113 // next memtable / level. 114 g.err = g.iter.Close() 115 g.iter = nil 116 if g.err != nil { 117 return nil, base.LazyValue{} 118 } 119 } 120 121 // Create an iterator from the batch. 122 if g.batch != nil { 123 if g.batch.index == nil { 124 g.err = ErrNotIndexed 125 g.iterKey, g.iterValue = nil, base.LazyValue{} 126 return nil, base.LazyValue{} 127 } 128 g.iter = g.batch.newInternalIter(nil) 129 g.rangeDelIter = g.batch.newRangeDelIter( 130 nil, 131 // Get always reads the entirety of the batch's history, so no 132 // batch keys should be filtered. 133 base.InternalKeySeqNumMax, 134 ) 135 g.iterKey, g.iterValue = g.iter.SeekGE(g.key, base.SeekGEFlagsNone) 136 g.batch = nil 137 continue 138 } 139 140 // If we have a tombstone from a previous level it is guaranteed to delete 141 // keys in lower levels. 142 if g.tombstone != nil && g.tombstone.VisibleAt(g.snapshot) { 143 return nil, base.LazyValue{} 144 } 145 146 // Create iterators from memtables from newest to oldest. 147 if n := len(g.mem); n > 0 { 148 m := g.mem[n-1] 149 g.iter = m.newIter(nil) 150 g.rangeDelIter = m.newRangeDelIter(nil) 151 g.mem = g.mem[:n-1] 152 g.iterKey, g.iterValue = g.iter.SeekGE(g.key, base.SeekGEFlagsNone) 153 continue 154 } 155 156 if g.level == 0 { 157 // Create iterators from L0 from newest to oldest. 158 if n := len(g.l0); n > 0 { 159 files := g.l0[n-1].Iter() 160 g.l0 = g.l0[:n-1] 161 iterOpts := IterOptions{ 162 // TODO(sumeer): replace with a parameter provided by the caller. 163 CategoryAndQoS: sstable.CategoryAndQoS{ 164 Category: "pebble-get", 165 QoSLevel: sstable.LatencySensitiveQoSLevel, 166 }, 167 logger: g.logger, 168 snapshotForHideObsoletePoints: g.snapshot} 169 g.levelIter.init(context.Background(), iterOpts, g.comparer, g.newIters, 170 files, manifest.L0Sublevel(n), internalIterOpts{}) 171 g.levelIter.initRangeDel(&g.rangeDelIter) 172 bc := levelIterBoundaryContext{} 173 g.levelIter.initBoundaryContext(&bc) 174 g.iter = &g.levelIter 175 176 // Compute the key prefix for bloom filtering if split function is 177 // specified, or use the user key as default. 178 prefix := g.key 179 if g.comparer.Split != nil { 180 prefix = g.key[:g.comparer.Split(g.key)] 181 } 182 g.iterKey, g.iterValue = g.iter.SeekPrefixGE(prefix, g.key, base.SeekGEFlagsNone) 183 if bc.isSyntheticIterBoundsKey || bc.isIgnorableBoundaryKey { 184 g.iterKey = nil 185 g.iterValue = base.LazyValue{} 186 } 187 continue 188 } 189 g.level++ 190 } 191 192 if g.level >= numLevels { 193 return nil, base.LazyValue{} 194 } 195 if g.version.Levels[g.level].Empty() { 196 g.level++ 197 continue 198 } 199 200 iterOpts := IterOptions{ 201 // TODO(sumeer): replace with a parameter provided by the caller. 202 CategoryAndQoS: sstable.CategoryAndQoS{ 203 Category: "pebble-get", 204 QoSLevel: sstable.LatencySensitiveQoSLevel, 205 }, logger: g.logger, snapshotForHideObsoletePoints: g.snapshot} 206 g.levelIter.init(context.Background(), iterOpts, g.comparer, g.newIters, 207 g.version.Levels[g.level].Iter(), manifest.Level(g.level), internalIterOpts{}) 208 g.levelIter.initRangeDel(&g.rangeDelIter) 209 bc := levelIterBoundaryContext{} 210 g.levelIter.initBoundaryContext(&bc) 211 g.level++ 212 g.iter = &g.levelIter 213 214 // Compute the key prefix for bloom filtering if split function is 215 // specified, or use the user key as default. 216 prefix := g.key 217 if g.comparer.Split != nil { 218 prefix = g.key[:g.comparer.Split(g.key)] 219 } 220 g.iterKey, g.iterValue = g.iter.SeekPrefixGE(prefix, g.key, base.SeekGEFlagsNone) 221 if bc.isSyntheticIterBoundsKey || bc.isIgnorableBoundaryKey { 222 g.iterKey = nil 223 g.iterValue = base.LazyValue{} 224 } 225 } 226 } 227 228 func (g *getIter) Prev() (*InternalKey, base.LazyValue) { 229 panic("pebble: Prev unimplemented") 230 } 231 232 func (g *getIter) NextPrefix([]byte) (*InternalKey, base.LazyValue) { 233 panic("pebble: NextPrefix unimplemented") 234 } 235 236 func (g *getIter) Valid() bool { 237 return g.iterKey != nil && g.err == nil 238 } 239 240 func (g *getIter) Error() error { 241 return g.err 242 } 243 244 func (g *getIter) Close() error { 245 if g.iter != nil { 246 if err := g.iter.Close(); err != nil && g.err == nil { 247 g.err = err 248 } 249 g.iter = nil 250 } 251 return g.err 252 } 253 254 func (g *getIter) SetBounds(lower, upper []byte) { 255 panic("pebble: SetBounds unimplemented") 256 } 257 258 func (g *getIter) SetContext(_ context.Context) {}