github.com/petermattis/pebble@v0.0.0-20190905164901-ab51a2166067/level_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 "sort" 9 ) 10 11 // tableNewIters creates a new point and range-del iterator for the given file 12 // number. If bytesIterated is specified, it is incremented as the given file is 13 // iterated through. 14 type tableNewIters func( 15 meta *fileMetadata, opts *IterOptions, bytesIterated *uint64, 16 ) (internalIterator, internalIterator, error) 17 18 // levelIter provides a merged view of the sstables in a level. 19 // 20 // levelIter is used during compaction and as part of the Iterator 21 // implementation. When used as part of the Iterator implementation, level 22 // iteration needs to "pause" at sstable boundaries if a range deletion 23 // tombstone is the source of that boundary. We know if a range tombstone is 24 // the smallest or largest key in a file because the kind will be 25 // InternalKeyKindRangeDeletion. If the boundary key is a range deletion 26 // tombstone, we materialize a fake entry to return from levelIter. This 27 // prevents mergingIter from advancing past the sstable until the sstable 28 // contains the smallest (or largest for reverse iteration) key in the merged 29 // heap. Note that Iterator treat a range deletion tombstone as a no-op and 30 // processes range deletions via mergingIter. 31 type levelIter struct { 32 opts *IterOptions 33 tableOpts IterOptions 34 cmp Compare 35 index int 36 // The key to return when iterating past an sstable boundary and that 37 // boundary is a range deletion tombstone. Note that if boundary != nil, then 38 // iter == nil, and if iter != nil, then boundary == nil. 39 boundary *InternalKey 40 iter internalIterator 41 newIters tableNewIters 42 rangeDelIter *internalIterator 43 files []fileMetadata 44 err error 45 // Pointer into this level's entry in `mergingIter::largestUserKeys`. We populate it 46 // with the largest user key for the currently opened file. It is used to limit the optimization 47 // that seeks lower-level iterators past keys shadowed by a range tombstone. Limiting this 48 // seek to the file upper-bound is necessary since range tombstones are stored untruncated, 49 // while they only apply to keys within their containing file's boundaries. For a detailed 50 // example, see comment above `mergingIter`. 51 // 52 // This field differs from the `boundary` field in a few ways: 53 // - `boundary` is only populated when the iterator is positioned exactly on the sentinel key. 54 // - `boundary` can hold either the lower- or upper-bound, depending on the iterator direction. 55 // - `boundary` is not exposed to the next higher-level iterator, i.e., `mergingIter`. 56 largestUserKey *[]byte 57 // bytesIterated keeps track of the number of bytes iterated during compaction. 58 bytesIterated *uint64 59 } 60 61 // levelIter implements the internalIterator interface. 62 var _ internalIterator = (*levelIter)(nil) 63 64 func newLevelIter( 65 opts *IterOptions, 66 cmp Compare, 67 newIters tableNewIters, 68 files []fileMetadata, 69 bytesIterated *uint64, 70 ) *levelIter { 71 l := &levelIter{} 72 l.init(opts, cmp, newIters, files, bytesIterated) 73 return l 74 } 75 76 func (l *levelIter) init( 77 opts *IterOptions, 78 cmp Compare, 79 newIters tableNewIters, 80 files []fileMetadata, 81 bytesIterated *uint64, 82 ) { 83 l.opts = opts 84 if l.opts != nil { 85 l.tableOpts.TableFilter = l.opts.TableFilter 86 } 87 l.cmp = cmp 88 l.index = -1 89 l.newIters = newIters 90 l.files = files 91 l.bytesIterated = bytesIterated 92 } 93 94 func (l *levelIter) initRangeDel(rangeDelIter *internalIterator) { 95 l.rangeDelIter = rangeDelIter 96 } 97 98 func (l *levelIter) initLargestUserKey(largestUserKey *[]byte) { 99 l.largestUserKey = largestUserKey 100 } 101 102 func (l *levelIter) findFileGE(key []byte) int { 103 // Find the earliest file whose largest key is >= ikey. Note that the range 104 // deletion sentinel key is handled specially and a search for K will not 105 // find a table where K<range-del-sentinel> is the largest key. This prevents 106 // loading untruncated range deletions from a table which can't possibly 107 // contain the target key and is required for correctness by DB.Get. 108 // 109 // TODO(peter): inline the binary search. 110 return sort.Search(len(l.files), func(i int) bool { 111 largest := &l.files[i].Largest 112 c := l.cmp(largest.UserKey, key) 113 if c > 0 { 114 return true 115 } 116 return c == 0 && largest.Trailer != InternalKeyRangeDeleteSentinel 117 }) 118 } 119 120 func (l *levelIter) findFileLT(key []byte) int { 121 // Find the last file whose smallest key is < ikey. 122 index := sort.Search(len(l.files), func(i int) bool { 123 return l.cmp(l.files[i].Smallest.UserKey, key) >= 0 124 }) 125 return index - 1 126 } 127 128 func (l *levelIter) loadFile(index, dir int) bool { 129 l.boundary = nil 130 if l.index == index { 131 return l.iter != nil 132 } 133 if l.iter != nil { 134 l.err = l.iter.Close() 135 if l.err != nil { 136 return false 137 } 138 l.iter = nil 139 } 140 if l.rangeDelIter != nil { 141 *l.rangeDelIter = nil 142 } 143 144 for ; ; index += dir { 145 l.index = index 146 if l.index < 0 || l.index >= len(l.files) { 147 return false 148 } 149 150 f := &l.files[l.index] 151 l.tableOpts.LowerBound = l.opts.GetLowerBound() 152 if l.tableOpts.LowerBound != nil { 153 if l.cmp(f.Largest.UserKey, l.tableOpts.LowerBound) < 0 { 154 // The largest key in the sstable is smaller than the lower bound. 155 if dir < 0 { 156 return false 157 } 158 continue 159 } 160 if l.cmp(l.tableOpts.LowerBound, f.Smallest.UserKey) < 0 { 161 // The lower bound is smaller than the smallest key in the 162 // table. Iteration within the table does not need to check the lower 163 // bound. 164 l.tableOpts.LowerBound = nil 165 } 166 } 167 l.tableOpts.UpperBound = l.opts.GetUpperBound() 168 if l.tableOpts.UpperBound != nil { 169 if l.cmp(f.Smallest.UserKey, l.tableOpts.UpperBound) >= 0 { 170 // The smallest key in the sstable is greater than or equal to the 171 // lower bound. 172 if dir > 0 { 173 return false 174 } 175 continue 176 } 177 if l.cmp(l.tableOpts.UpperBound, f.Largest.UserKey) > 0 { 178 // The upper bound is greater than the largest key in the 179 // table. Iteration within the table does not need to check the upper 180 // bound. 181 l.tableOpts.UpperBound = nil 182 } 183 } 184 185 var rangeDelIter internalIterator 186 l.iter, rangeDelIter, l.err = l.newIters(f, &l.tableOpts, l.bytesIterated) 187 if l.err != nil || l.iter == nil { 188 return false 189 } 190 if l.rangeDelIter != nil { 191 *l.rangeDelIter = rangeDelIter 192 } 193 if l.largestUserKey != nil { 194 *l.largestUserKey = f.Largest.UserKey 195 } 196 return true 197 } 198 } 199 200 func (l *levelIter) SeekGE(key []byte) (*InternalKey, []byte) { 201 // NB: the top-level Iterator has already adjusted key based on 202 // IterOptions.LowerBound. 203 if !l.loadFile(l.findFileGE(key), 1) { 204 return nil, nil 205 } 206 if key, val := l.iter.SeekGE(key); key != nil { 207 return key, val 208 } 209 return l.skipEmptyFileForward() 210 } 211 212 func (l *levelIter) SeekPrefixGE(prefix, key []byte) (*InternalKey, []byte) { 213 // NB: the top-level Iterator has already adjusted key based on 214 // IterOptions.LowerBound. 215 if !l.loadFile(l.findFileGE(key), 1) { 216 return nil, nil 217 } 218 if key, val := l.iter.SeekPrefixGE(prefix, key); key != nil { 219 return key, val 220 } 221 return l.skipEmptyFileForward() 222 } 223 224 func (l *levelIter) SeekLT(key []byte) (*InternalKey, []byte) { 225 // NB: the top-level Iterator has already adjusted key based on 226 // IterOptions.UpperBound. 227 if !l.loadFile(l.findFileLT(key), -1) { 228 return nil, nil 229 } 230 if key, val := l.iter.SeekLT(key); key != nil { 231 return key, val 232 } 233 return l.skipEmptyFileBackward() 234 } 235 236 func (l *levelIter) First() (*InternalKey, []byte) { 237 // NB: the top-level Iterator will call SeekGE if IterOptions.LowerBound is 238 // set. 239 if !l.loadFile(0, 1) { 240 return nil, nil 241 } 242 if key, val := l.iter.First(); key != nil { 243 return key, val 244 } 245 return l.skipEmptyFileForward() 246 } 247 248 func (l *levelIter) Last() (*InternalKey, []byte) { 249 // NB: the top-level Iterator will call SeekLT if IterOptions.UpperBound is 250 // set. 251 if !l.loadFile(len(l.files)-1, -1) { 252 return nil, nil 253 } 254 if key, val := l.iter.Last(); key != nil { 255 return key, val 256 } 257 return l.skipEmptyFileBackward() 258 } 259 260 func (l *levelIter) Next() (*InternalKey, []byte) { 261 if l.err != nil { 262 return nil, nil 263 } 264 265 if l.iter == nil { 266 if l.boundary != nil { 267 if l.loadFile(l.index+1, 1) { 268 if key, val := l.iter.First(); key != nil { 269 return key, val 270 } 271 return l.skipEmptyFileForward() 272 } 273 return nil, nil 274 } 275 if l.index == -1 && l.loadFile(0, 1) { 276 // The iterator was positioned off the beginning of the level. Position 277 // at the first entry. 278 if key, val := l.iter.First(); key != nil { 279 return key, val 280 } 281 return l.skipEmptyFileForward() 282 } 283 return nil, nil 284 } 285 286 if key, val := l.iter.Next(); key != nil { 287 return key, val 288 } 289 return l.skipEmptyFileForward() 290 } 291 292 func (l *levelIter) Prev() (*InternalKey, []byte) { 293 if l.err != nil { 294 return nil, nil 295 } 296 297 if l.iter == nil { 298 if l.boundary != nil { 299 if l.loadFile(l.index-1, -1) { 300 if key, val := l.iter.Last(); key != nil { 301 return key, val 302 } 303 return l.skipEmptyFileBackward() 304 } 305 return nil, nil 306 } 307 if n := len(l.files); l.index == n && l.loadFile(n-1, -1) { 308 // The iterator was positioned off the end of the level. Position at the 309 // last entry. 310 if key, val := l.iter.Last(); key != nil { 311 return key, val 312 } 313 return l.skipEmptyFileBackward() 314 } 315 return nil, nil 316 } 317 318 if key, val := l.iter.Prev(); key != nil { 319 return key, val 320 } 321 return l.skipEmptyFileBackward() 322 } 323 324 func (l *levelIter) skipEmptyFileForward() (*InternalKey, []byte) { 325 var key *InternalKey 326 var val []byte 327 for ; key == nil; key, val = l.iter.First() { 328 if l.err = l.iter.Close(); l.err != nil { 329 return nil, nil 330 } 331 l.iter = nil 332 333 if l.rangeDelIter != nil { 334 // We're being used as part of an Iterator and we've reached the end of 335 // the sstable. If the boundary is a range deletion tombstone, return 336 // that key. 337 if f := &l.files[l.index]; f.Largest.Kind() == InternalKeyKindRangeDelete { 338 l.boundary = &f.Largest 339 return l.boundary, nil 340 } 341 *l.rangeDelIter = nil 342 } 343 344 // Current file was exhausted. Move to the next file. 345 if !l.loadFile(l.index+1, 1) { 346 return nil, nil 347 } 348 } 349 return key, val 350 } 351 352 func (l *levelIter) skipEmptyFileBackward() (*InternalKey, []byte) { 353 var key *InternalKey 354 var val []byte 355 for ; key == nil; key, val = l.iter.Last() { 356 if l.err = l.iter.Close(); l.err != nil { 357 return nil, nil 358 } 359 l.iter = nil 360 361 if l.rangeDelIter != nil { 362 // We're being used as part of an Iterator and we've reached the end of 363 // the sstable. If the boundary is a range deletion tombstone, return 364 // that key. 365 if f := &l.files[l.index]; f.Smallest.Kind() == InternalKeyKindRangeDelete { 366 l.boundary = &f.Smallest 367 return l.boundary, nil 368 } 369 *l.rangeDelIter = nil 370 } 371 372 // Current file was exhausted. Move to the previous file. 373 if !l.loadFile(l.index-1, -1) { 374 return nil, nil 375 } 376 } 377 return key, val 378 } 379 380 func (l *levelIter) Key() *InternalKey { 381 if l.iter == nil { 382 if l.boundary != nil { 383 return l.boundary 384 } 385 return nil 386 } 387 return l.iter.Key() 388 } 389 390 func (l *levelIter) Value() []byte { 391 if l.iter == nil { 392 return nil 393 } 394 return l.iter.Value() 395 } 396 397 func (l *levelIter) Valid() bool { 398 if l.iter == nil { 399 return l.boundary != nil 400 } 401 return l.iter.Valid() 402 } 403 404 func (l *levelIter) Error() error { 405 if l.err != nil || l.iter == nil { 406 return l.err 407 } 408 return l.iter.Error() 409 } 410 411 func (l *levelIter) Close() error { 412 if l.iter != nil { 413 l.err = l.iter.Close() 414 l.iter = nil 415 } 416 if l.rangeDelIter != nil { 417 if t := *l.rangeDelIter; t != nil { 418 if err := t.Close(); err != nil && l.err == nil { 419 l.err = err 420 } 421 } 422 *l.rangeDelIter = nil 423 } 424 return l.err 425 } 426 427 func (l *levelIter) SetBounds(lower, upper []byte) { 428 l.opts.LowerBound = lower 429 l.opts.UpperBound = upper 430 if l.iter != nil { 431 l.iter.SetBounds(lower, upper) 432 } 433 }