github.com/cockroachdb/pebble@v1.1.1-0.20240513155919-3622ade60459/internal/keyspan/interleaving_iter.go (about) 1 // Copyright 2021 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 "fmt" 9 10 "github.com/cockroachdb/errors" 11 "github.com/cockroachdb/pebble/internal/base" 12 "github.com/cockroachdb/pebble/internal/invariants" 13 ) 14 15 // A SpanMask may be used to configure an interleaving iterator to skip point 16 // keys that fall within the bounds of some spans. 17 type SpanMask interface { 18 // SpanChanged is invoked by an interleaving iterator whenever the current 19 // span changes. As the iterator passes into or out of a Span, it invokes 20 // SpanChanged, passing the new Span. When the iterator passes out of a 21 // span's boundaries and is no longer covered by any span, SpanChanged is 22 // invoked with a nil span. 23 // 24 // SpanChanged is invoked before SkipPoint, and callers may use SpanChanged 25 // to recalculate state used by SkipPoint for masking. 26 // 27 // SpanChanged may be invoked consecutively with identical spans under some 28 // circumstances, such as repeatedly absolutely positioning an iterator to 29 // positions covered by the same span, or while changing directions. 30 SpanChanged(*Span) 31 // SkipPoint is invoked by the interleaving iterator whenever the iterator 32 // encounters a point key covered by a Span. If SkipPoint returns true, the 33 // interleaving iterator skips the point key and all larger keys with the 34 // same prefix. This is used during range key iteration to skip over point 35 // keys 'masked' by range keys. 36 SkipPoint(userKey []byte) bool 37 } 38 39 // InterleavingIter combines an iterator over point keys with an iterator over 40 // key spans. 41 // 42 // Throughout Pebble, some keys apply at single discrete points within the user 43 // keyspace. Other keys apply over continuous spans of the user key space. 44 // Internally, iterators over point keys adhere to the base.InternalIterator 45 // interface, and iterators over spans adhere to the keyspan.FragmentIterator 46 // interface. The InterleavingIterator wraps a point iterator and span iterator, 47 // providing access to all the elements of both iterators. 48 // 49 // The InterleavingIterator implements the point base.InternalIterator 50 // interface. After any of the iterator's methods return a key, a caller may 51 // call Span to retrieve the span covering the returned key, if any. A span is 52 // considered to 'cover' a returned key if the span's [start, end) bounds 53 // include the key's user key. 54 // 55 // In addition to tracking the current covering span, InterleavingIter returns a 56 // special InternalKey at span start boundaries. Start boundaries are surfaced 57 // as a synthetic span marker: an InternalKey with the boundary as the user key, 58 // the infinite sequence number and a key kind selected from an arbitrary key 59 // the infinite sequence number and an arbitrary contained key's kind. Since 60 // which of the Span's key's kind is surfaced is undefined, the caller should 61 // not use the InternalKey's kind. The caller should only rely on the `Span` 62 // method for retrieving information about spanning keys. The interleaved 63 // synthetic keys have the infinite sequence number so that they're interleaved 64 // before any point keys with the same user key when iterating forward and after 65 // when iterating backward. 66 // 67 // Interleaving the synthetic start key boundaries at the maximum sequence 68 // number provides an opportunity for the higher-level, public Iterator to 69 // observe the Span, even if no live points keys exist within the boudns of the 70 // Span. 71 // 72 // When returning a synthetic marker key for a start boundary, InterleavingIter 73 // will truncate the span's start bound to the SeekGE or SeekPrefixGE search 74 // key. For example, a SeekGE("d") that finds a span [a, z) may return a 75 // synthetic span marker key `d#72057594037927935,21`. 76 // 77 // If bounds have been applied to the iterator through SetBounds, 78 // InterleavingIter will truncate the bounds of spans returned through Span to 79 // the set bounds. The bounds returned through Span are not truncated by a 80 // SeekGE or SeekPrefixGE search key. Consider, for example SetBounds('c', 'e'), 81 // with an iterator containing the Span [a,z): 82 // 83 // First() = `c#72057594037927935,21` Span() = [c,e) 84 // SeekGE('d') = `d#72057594037927935,21` Span() = [c,e) 85 // 86 // InterleavedIter does not interleave synthetic markers for spans that do not 87 // contain any keys. 88 // 89 // # SpanMask 90 // 91 // InterelavingIter takes a SpanMask parameter that may be used to configure the 92 // behavior of the iterator. See the documentation on the SpanMask type. 93 // 94 // All spans containing keys are exposed during iteration. 95 type InterleavingIter struct { 96 cmp base.Compare 97 comparer *base.Comparer 98 pointIter base.InternalIterator 99 keyspanIter FragmentIterator 100 mask SpanMask 101 102 // lower and upper hold the iteration bounds set through SetBounds. 103 lower, upper []byte 104 // keyBuf is used to copy SeekGE or SeekPrefixGE arguments when they're used 105 // to truncate a span. The byte slices backing a SeekGE/SeekPrefixGE search 106 // keys can come directly from the end user, so they're copied into keyBuf 107 // to ensure key stability. 108 keyBuf []byte 109 // nextPrefixBuf is used during SeekPrefixGE calls to store the truncated 110 // upper bound of the returned spans. SeekPrefixGE truncates the returned 111 // spans to an upper bound of the seeked prefix's immediate successor. 112 nextPrefixBuf []byte 113 pointKey *base.InternalKey 114 pointVal base.LazyValue 115 // err holds an iterator error from either pointIter or keyspanIter. It's 116 // reset to nil on seeks. An overview of error-handling mechanics: 117 // 118 // Whenever either pointIter or keyspanIter is respositioned and a nil 119 // key/span is returned, the code performing the positioning is responsible 120 // for checking the iterator's Error() value. This happens in savePoint and 121 // saveSpan[Forward,Backward]. 122 // 123 // Once i.err is non-nil, the computation of i.pos must set i.pos = 124 // posExhausted. This happens in compute[Smallest|Largest]Pos and 125 // [next|prev]Pos. Setting i.pos to posExhausted ensures we'll yield nil to 126 // the caller, which they'll interpret as a signal they must check Error(). 127 // 128 // INVARIANTS: 129 // i.err != nil => i.pos = posExhausted 130 err error 131 // prefix records the iterator's current prefix if the iterator is in prefix 132 // mode. During prefix mode, Pebble will truncate spans to the next prefix. 133 // If the iterator subsequently leaves prefix mode, the existing span cached 134 // in i.span must be invalidated because its bounds do not reflect the 135 // original span's true bounds. 136 prefix []byte 137 // span holds the span at the keyspanIter's current position. If the span is 138 // wholly contained within the iterator bounds, this span is directly 139 // returned to the iterator consumer through Span(). If either bound needed 140 // to be truncated to the iterator bounds, then truncated is set to true and 141 // Span() must return a pointer to truncatedSpan. 142 span *Span 143 // spanMarker holds the synthetic key that is returned when the iterator 144 // passes over a key span's start bound. 145 spanMarker base.InternalKey 146 // truncated indicates whether or not the span at the current position 147 // needed to be truncated. If it did, truncatedSpan holds the truncated 148 // span that should be returned. 149 truncatedSpan Span 150 truncated bool 151 152 // Keeping all of the bools/uint8s together reduces the sizeof the struct. 153 154 // pos encodes the current position of the iterator: exhausted, on the point 155 // key, on a keyspan start, or on a keyspan end. 156 pos interleavePos 157 // withinSpan indicates whether the iterator is currently positioned within 158 // the bounds of the current span (i.span). withinSpan must be updated 159 // whenever the interleaving iterator's position enters or exits the bounds 160 // of a span. 161 withinSpan bool 162 // spanMarkerTruncated is set by SeekGE/SeekPrefixGE calls that truncate a 163 // span's start bound marker to the search key. It's returned to false on 164 // the next repositioning of the keyspan iterator. 165 spanMarkerTruncated bool 166 // maskSpanChangedCalled records whether or not the last call to 167 // SpanMask.SpanChanged provided the current span (i.span) or not. 168 maskSpanChangedCalled bool 169 // dir indicates the direction of iteration: forward (+1) or backward (-1) 170 dir int8 171 } 172 173 // interleavePos indicates the iterator's current position. Note that both 174 // keyspanStart and keyspanEnd positions correspond to their user key boundaries 175 // with maximal sequence numbers. This means in the forward direction 176 // posKeyspanStart and posKeyspanEnd are always interleaved before a posPointKey 177 // with the same user key. 178 type interleavePos int8 179 180 const ( 181 posUninitialized interleavePos = iota 182 posExhausted 183 posPointKey 184 posKeyspanStart 185 posKeyspanEnd 186 ) 187 188 // Assert that *InterleavingIter implements the InternalIterator interface. 189 var _ base.InternalIterator = &InterleavingIter{} 190 191 // InterleavingIterOpts holds options configuring the behavior of a 192 // InterleavingIter. 193 type InterleavingIterOpts struct { 194 Mask SpanMask 195 LowerBound, UpperBound []byte 196 } 197 198 // Init initializes the InterleavingIter to interleave point keys from pointIter 199 // with key spans from keyspanIter. 200 // 201 // The point iterator must already have the bounds provided on opts. Init does 202 // not propagate the bounds down the iterator stack. 203 func (i *InterleavingIter) Init( 204 comparer *base.Comparer, 205 pointIter base.InternalIterator, 206 keyspanIter FragmentIterator, 207 opts InterleavingIterOpts, 208 ) { 209 *i = InterleavingIter{ 210 cmp: comparer.Compare, 211 comparer: comparer, 212 pointIter: pointIter, 213 keyspanIter: keyspanIter, 214 mask: opts.Mask, 215 lower: opts.LowerBound, 216 upper: opts.UpperBound, 217 } 218 } 219 220 // InitSeekGE may be called after Init but before any positioning method. 221 // InitSeekGE initializes the current position of the point iterator and then 222 // performs a SeekGE on the keyspan iterator using the provided key. InitSeekGE 223 // returns whichever point or keyspan key is smaller. After InitSeekGE, the 224 // iterator is positioned and may be repositioned using relative positioning 225 // methods. 226 // 227 // This method is used specifically for lazily constructing combined iterators. 228 // It allows for seeding the iterator with the current position of the point 229 // iterator. 230 func (i *InterleavingIter) InitSeekGE( 231 prefix, key []byte, pointKey *base.InternalKey, pointValue base.LazyValue, 232 ) (*base.InternalKey, base.LazyValue) { 233 i.dir = +1 234 i.clearMask() 235 i.prefix = prefix 236 i.savePoint(pointKey, pointValue) 237 // NB: This keyspanSeekGE call will truncate the span to the seek key if 238 // necessary. This truncation is important for cases where a switch to 239 // combined iteration is made during a user-initiated SeekGE. 240 i.keyspanSeekGE(key, prefix) 241 i.computeSmallestPos() 242 return i.yieldPosition(key, i.nextPos) 243 } 244 245 // InitSeekLT may be called after Init but before any positioning method. 246 // InitSeekLT initializes the current position of the point iterator and then 247 // performs a SeekLT on the keyspan iterator using the provided key. InitSeekLT 248 // returns whichever point or keyspan key is larger. After InitSeekLT, the 249 // iterator is positioned and may be repositioned using relative positioning 250 // methods. 251 // 252 // This method is used specifically for lazily constructing combined iterators. 253 // It allows for seeding the iterator with the current position of the point 254 // iterator. 255 func (i *InterleavingIter) InitSeekLT( 256 key []byte, pointKey *base.InternalKey, pointValue base.LazyValue, 257 ) (*base.InternalKey, base.LazyValue) { 258 i.dir = -1 259 i.clearMask() 260 i.savePoint(pointKey, pointValue) 261 i.keyspanSeekLT(key) 262 i.computeLargestPos() 263 return i.yieldPosition(i.lower, i.prevPos) 264 } 265 266 // SeekGE implements (base.InternalIterator).SeekGE. 267 // 268 // If there exists a span with a start key ≤ the first matching point key, 269 // SeekGE will return a synthetic span marker key for the span. If this span's 270 // start key is less than key, the returned marker will be truncated to key. 271 // Note that this search-key truncation of the marker's key is not applied to 272 // the span returned by Span. 273 // 274 // NB: In accordance with the base.InternalIterator contract: 275 // 276 // i.lower ≤ key 277 func (i *InterleavingIter) SeekGE( 278 key []byte, flags base.SeekGEFlags, 279 ) (*base.InternalKey, base.LazyValue) { 280 i.err = nil 281 i.clearMask() 282 i.disablePrefixMode() 283 i.savePoint(i.pointIter.SeekGE(key, flags)) 284 285 // We need to seek the keyspan iterator too. If the keyspan iterator was 286 // already positioned at a span, we might be able to avoid the seek if the 287 // seek key falls within the existing span's bounds. 288 if i.span != nil && i.cmp(key, i.span.End) < 0 && i.cmp(key, i.span.Start) >= 0 { 289 // We're seeking within the existing span's bounds. We still might need 290 // truncate the span to the iterator's bounds. 291 i.saveSpanForward(i.span) 292 i.savedKeyspan() 293 } else { 294 i.keyspanSeekGE(key, nil /* prefix */) 295 } 296 297 i.dir = +1 298 i.computeSmallestPos() 299 return i.yieldPosition(key, i.nextPos) 300 } 301 302 // SeekPrefixGE implements (base.InternalIterator).SeekPrefixGE. 303 // 304 // If there exists a span with a start key ≤ the first matching point key, 305 // SeekPrefixGE will return a synthetic span marker key for the span. If this 306 // span's start key is less than key, the returned marker will be truncated to 307 // key. Note that this search-key truncation of the marker's key is not applied 308 // to the span returned by Span. 309 // 310 // NB: In accordance with the base.InternalIterator contract: 311 // 312 // i.lower ≤ key 313 func (i *InterleavingIter) SeekPrefixGE( 314 prefix, key []byte, flags base.SeekGEFlags, 315 ) (*base.InternalKey, base.LazyValue) { 316 i.err = nil 317 i.clearMask() 318 i.prefix = prefix 319 i.savePoint(i.pointIter.SeekPrefixGE(prefix, key, flags)) 320 321 // We need to seek the keyspan iterator too. If the keyspan iterator was 322 // already positioned at a span, we might be able to avoid the seek if the 323 // entire seek prefix key falls within the existing span's bounds. 324 // 325 // During a SeekPrefixGE, Pebble defragments range keys within the bounds of 326 // the prefix. For example, a SeekPrefixGE('c', 'c@8') must defragment the 327 // any overlapping range keys within the bounds of [c,c\00). 328 // 329 // If range keys are fragmented within a prefix (eg, because a version 330 // within a prefix was chosen as an sstable boundary), then it's possible 331 // the seek key falls into the current i.span, but the current i.span does 332 // not wholly cover the seek prefix. 333 // 334 // For example, a SeekPrefixGE('d@5') may only defragment a range key to 335 // the bounds of [c@2,e). A subsequent SeekPrefixGE('c@0') must re-seek the 336 // keyspan iterator, because although 'c@0' is contained within [c@2,e), the 337 // full span of the prefix is not. 338 // 339 // Similarly, a SeekPrefixGE('a@3') may only defragment a range key to the 340 // bounds [a,c@8). A subsequent SeekPrefixGE('c@10') must re-seek the 341 // keyspan iterator, because although 'c@10' is contained within [a,c@8), 342 // the full span of the prefix is not. 343 seekKeyspanIter := true 344 if i.span != nil && i.cmp(prefix, i.span.Start) >= 0 { 345 if ei := i.comparer.Split(i.span.End); i.cmp(prefix, i.span.End[:ei]) < 0 { 346 // We're seeking within the existing span's bounds. We still might need 347 // truncate the span to the iterator's bounds. 348 i.saveSpanForward(i.span) 349 i.savedKeyspan() 350 seekKeyspanIter = false 351 } 352 } 353 if seekKeyspanIter { 354 i.keyspanSeekGE(key, prefix) 355 } 356 357 i.dir = +1 358 i.computeSmallestPos() 359 return i.yieldPosition(key, i.nextPos) 360 } 361 362 // SeekLT implements (base.InternalIterator).SeekLT. 363 func (i *InterleavingIter) SeekLT( 364 key []byte, flags base.SeekLTFlags, 365 ) (*base.InternalKey, base.LazyValue) { 366 i.err = nil 367 i.clearMask() 368 i.disablePrefixMode() 369 i.savePoint(i.pointIter.SeekLT(key, flags)) 370 371 // We need to seek the keyspan iterator too. If the keyspan iterator was 372 // already positioned at a span, we might be able to avoid the seek if the 373 // seek key falls within the existing span's bounds. 374 if i.span != nil && i.cmp(key, i.span.Start) > 0 && i.cmp(key, i.span.End) < 0 { 375 // We're seeking within the existing span's bounds. We still might need 376 // truncate the span to the iterator's bounds. 377 i.saveSpanBackward(i.span) 378 // The span's start key is still not guaranteed to be less than key, 379 // because of the bounds enforcement. Consider the following example: 380 // 381 // Bounds are set to [d,e). The user performs a SeekLT(d). The 382 // FragmentIterator.SeekLT lands on a span [b,f). This span has a start 383 // key less than d, as expected. Above, saveSpanBackward truncates the 384 // span to match the iterator's current bounds, modifying the span to 385 // [d,e), which does not overlap the search space of [-∞, d). 386 // 387 // This problem is a consequence of the SeekLT's exclusive search key 388 // and the fact that we don't perform bounds truncation at every leaf 389 // iterator. 390 if i.span != nil && i.truncated && i.cmp(i.truncatedSpan.Start, key) >= 0 { 391 i.span = nil 392 } 393 i.savedKeyspan() 394 } else { 395 i.keyspanSeekLT(key) 396 } 397 398 i.dir = -1 399 i.computeLargestPos() 400 return i.yieldPosition(i.lower, i.prevPos) 401 } 402 403 // First implements (base.InternalIterator).First. 404 func (i *InterleavingIter) First() (*base.InternalKey, base.LazyValue) { 405 i.err = nil 406 i.clearMask() 407 i.disablePrefixMode() 408 i.savePoint(i.pointIter.First()) 409 i.saveSpanForward(i.keyspanIter.First()) 410 i.savedKeyspan() 411 i.dir = +1 412 i.computeSmallestPos() 413 return i.yieldPosition(i.lower, i.nextPos) 414 } 415 416 // Last implements (base.InternalIterator).Last. 417 func (i *InterleavingIter) Last() (*base.InternalKey, base.LazyValue) { 418 i.err = nil 419 i.clearMask() 420 i.disablePrefixMode() 421 i.savePoint(i.pointIter.Last()) 422 i.saveSpanBackward(i.keyspanIter.Last()) 423 i.savedKeyspan() 424 i.dir = -1 425 i.computeLargestPos() 426 return i.yieldPosition(i.lower, i.prevPos) 427 } 428 429 // Next implements (base.InternalIterator).Next. 430 func (i *InterleavingIter) Next() (*base.InternalKey, base.LazyValue) { 431 if i.dir == -1 { 432 // Switching directions. 433 i.dir = +1 434 435 if i.mask != nil { 436 // Clear the mask while we reposition the point iterator. While 437 // switching directions, we may move the point iterator outside of 438 // i.span's bounds. 439 i.clearMask() 440 } 441 442 // When switching directions, iterator state corresponding to the 443 // current iterator position (as indicated by i.pos) is already correct. 444 // However any state that has yet to be interleaved describes a position 445 // behind the current iterator position and needs to be updated to 446 // describe the position ahead of the current iterator position. 447 switch i.pos { 448 case posExhausted: 449 // Nothing to do. The below nextPos call will move both the point 450 // key and span to their next positions and return 451 // MIN(point,s.Start). 452 case posPointKey: 453 // If we're currently on a point key, the below nextPos will 454 // correctly Next the point key iterator to the next point key. 455 // Do we need to move the span forwards? If the current span lies 456 // entirely behind the current key (!i.withinSpan), then we 457 // need to move it to the first span in the forward direction. 458 if !i.withinSpan { 459 i.saveSpanForward(i.keyspanIter.Next()) 460 i.savedKeyspan() 461 } 462 case posKeyspanStart: 463 i.withinSpan = true 464 // Since we're positioned on a Span, the pointIter is positioned 465 // entirely behind the current iterator position. Reposition it 466 // ahead of the current iterator position. 467 i.savePoint(i.pointIter.Next()) 468 case posKeyspanEnd: 469 // Since we're positioned on a Span, the pointIter is positioned 470 // entirely behind of the current iterator position. Reposition it 471 // ahead the current iterator position. 472 i.savePoint(i.pointIter.Next()) 473 } 474 // Fallthrough to calling i.nextPos. 475 } 476 i.nextPos() 477 return i.yieldPosition(i.lower, i.nextPos) 478 } 479 480 // NextPrefix implements (base.InternalIterator).NextPrefix. 481 func (i *InterleavingIter) NextPrefix(succKey []byte) (*base.InternalKey, base.LazyValue) { 482 if i.dir == -1 { 483 panic("pebble: cannot switch directions with NextPrefix") 484 } 485 486 switch i.pos { 487 case posExhausted: 488 return nil, base.LazyValue{} 489 case posPointKey: 490 i.savePoint(i.pointIter.NextPrefix(succKey)) 491 if i.withinSpan { 492 if i.pointKey == nil || i.cmp(i.span.End, i.pointKey.UserKey) <= 0 { 493 i.pos = posKeyspanEnd 494 } else { 495 i.pos = posPointKey 496 } 497 } else { 498 i.computeSmallestPos() 499 } 500 case posKeyspanStart, posKeyspanEnd: 501 i.nextPos() 502 } 503 return i.yieldPosition(i.lower, i.nextPos) 504 } 505 506 // Prev implements (base.InternalIterator).Prev. 507 func (i *InterleavingIter) Prev() (*base.InternalKey, base.LazyValue) { 508 if i.dir == +1 { 509 // Switching directions. 510 i.dir = -1 511 512 if i.mask != nil { 513 // Clear the mask while we reposition the point iterator. While 514 // switching directions, we may move the point iterator outside of 515 // i.span's bounds. 516 i.clearMask() 517 } 518 519 // When switching directions, iterator state corresponding to the 520 // current iterator position (as indicated by i.pos) is already correct. 521 // However any state that has yet to be interleaved describes a position 522 // ahead of the current iterator position and needs to be updated to 523 // describe the position behind the current iterator position. 524 switch i.pos { 525 case posExhausted: 526 // Nothing to do. The below prevPos call will move both the point 527 // key and span to previous positions and return MAX(point, s.End). 528 case posPointKey: 529 // If we're currently on a point key, the point iterator is in the 530 // right place and the call to prevPos will correctly Prev the point 531 // key iterator to the previous point key. Do we need to move the 532 // span backwards? If the current span lies entirely ahead of the 533 // current key (!i.withinSpan), then we need to move it to the first 534 // span in the reverse direction. 535 if !i.withinSpan { 536 i.saveSpanBackward(i.keyspanIter.Prev()) 537 i.savedKeyspan() 538 } 539 case posKeyspanStart: 540 // Since we're positioned on a Span, the pointIter is positioned 541 // entirely ahead of the current iterator position. Reposition it 542 // behind the current iterator position. 543 i.savePoint(i.pointIter.Prev()) 544 // Without considering truncation of spans to seek keys, the keyspan 545 // iterator is already in the right place. But consider span [a, z) 546 // and this sequence of iterator calls: 547 // 548 // SeekGE('c') = c.RANGEKEYSET#72057594037927935 549 // Prev() = a.RANGEKEYSET#72057594037927935 550 // 551 // If the current span's start key was last surfaced truncated due 552 // to a SeekGE or SeekPrefixGE call, then it's still relevant in the 553 // reverse direction with an untruncated start key. 554 if i.spanMarkerTruncated { 555 // When we fallthrough to calling prevPos, we want to move to 556 // MAX(point, span.Start). We cheat here by claiming we're 557 // currently on the end boundary, so that we'll move on to the 558 // untruncated start key if necessary. 559 i.pos = posKeyspanEnd 560 } 561 case posKeyspanEnd: 562 // Since we're positioned on a Span, the pointIter is positioned 563 // entirely ahead of the current iterator position. Reposition it 564 // behind the current iterator position. 565 i.savePoint(i.pointIter.Prev()) 566 } 567 568 if i.spanMarkerTruncated { 569 // Save the keyspan again to clear truncation. 570 i.savedKeyspan() 571 } 572 // Fallthrough to calling i.prevPos. 573 } 574 i.prevPos() 575 return i.yieldPosition(i.lower, i.prevPos) 576 } 577 578 // computeSmallestPos sets i.{pos,withinSpan} to: 579 // 580 // MIN(i.pointKey, i.span.Start) 581 func (i *InterleavingIter) computeSmallestPos() { 582 if i.err == nil { 583 if i.span != nil && (i.pointKey == nil || i.cmp(i.startKey(), i.pointKey.UserKey) <= 0) { 584 i.withinSpan = true 585 i.pos = posKeyspanStart 586 return 587 } 588 i.withinSpan = false 589 if i.pointKey != nil { 590 i.pos = posPointKey 591 return 592 } 593 } 594 i.pos = posExhausted 595 } 596 597 // computeLargestPos sets i.{pos,withinSpan} to: 598 // 599 // MAX(i.pointKey, i.span.End) 600 func (i *InterleavingIter) computeLargestPos() { 601 if i.err == nil { 602 if i.span != nil && (i.pointKey == nil || i.cmp(i.span.End, i.pointKey.UserKey) > 0) { 603 i.withinSpan = true 604 i.pos = posKeyspanEnd 605 return 606 } 607 i.withinSpan = false 608 if i.pointKey != nil { 609 i.pos = posPointKey 610 return 611 } 612 } 613 i.pos = posExhausted 614 } 615 616 // nextPos advances the iterator one position in the forward direction. 617 func (i *InterleavingIter) nextPos() { 618 if invariants.Enabled { 619 defer func() { 620 if i.err != nil && i.pos != posExhausted { 621 panic(errors.AssertionFailedf("iterator has accumulated error but i.pos = %d", i.pos)) 622 } 623 }() 624 } 625 // NB: If i.err != nil or any of the positioning methods performed in this 626 // function result in i.err != nil, we must set i.pos = posExhausted. We 627 // perform this check explicitly here, but if any of the branches below 628 // advance either iterator, they must also check i.err and set posExhausted 629 // if necessary. 630 if i.err != nil { 631 i.pos = posExhausted 632 return 633 } 634 635 switch i.pos { 636 case posExhausted: 637 i.savePoint(i.pointIter.Next()) 638 i.saveSpanForward(i.keyspanIter.Next()) 639 i.savedKeyspan() 640 i.computeSmallestPos() 641 case posPointKey: 642 i.savePoint(i.pointIter.Next()) 643 if i.err != nil { 644 i.pos = posExhausted 645 return 646 } 647 // If we're not currently within the span, we want to chose the 648 // MIN(pointKey,span.Start), which is exactly the calculation performed 649 // by computeSmallestPos. 650 if !i.withinSpan { 651 i.computeSmallestPos() 652 return 653 } 654 // i.withinSpan=true 655 // Since we previously were within the span, we want to choose the 656 // MIN(pointKey,span.End). 657 switch { 658 case i.span == nil: 659 panic("i.withinSpan=true and i.span=nil") 660 case i.pointKey == nil: 661 // Since i.withinSpan=true, we step onto the end boundary of the 662 // keyspan. 663 i.pos = posKeyspanEnd 664 default: 665 // i.withinSpan && i.pointKey != nil && i.span != nil 666 if i.cmp(i.span.End, i.pointKey.UserKey) <= 0 { 667 i.pos = posKeyspanEnd 668 } else { 669 i.pos = posPointKey 670 } 671 } 672 case posKeyspanStart: 673 // Either a point key or the span's end key comes next. 674 if i.pointKey != nil && i.cmp(i.pointKey.UserKey, i.span.End) < 0 { 675 i.pos = posPointKey 676 } else { 677 i.pos = posKeyspanEnd 678 } 679 case posKeyspanEnd: 680 i.saveSpanForward(i.keyspanIter.Next()) 681 i.savedKeyspan() 682 i.computeSmallestPos() 683 default: 684 panic(fmt.Sprintf("unexpected pos=%d", i.pos)) 685 } 686 } 687 688 // prevPos advances the iterator one position in the reverse direction. 689 func (i *InterleavingIter) prevPos() { 690 if invariants.Enabled { 691 defer func() { 692 if i.err != nil && i.pos != posExhausted { 693 panic(errors.AssertionFailedf("iterator has accumulated error but i.pos = %d", i.pos)) 694 } 695 }() 696 } 697 // NB: If i.err != nil or any of the positioning methods performed in this 698 // function result in i.err != nil, we must set i.pos = posExhausted. We 699 // perform this check explicitly here, but if any of the branches below 700 // advance either iterator, they must also check i.err and set posExhausted 701 // if necessary. 702 if i.err != nil { 703 i.pos = posExhausted 704 return 705 } 706 707 switch i.pos { 708 case posExhausted: 709 i.savePoint(i.pointIter.Prev()) 710 i.saveSpanBackward(i.keyspanIter.Prev()) 711 i.savedKeyspan() 712 i.computeLargestPos() 713 case posPointKey: 714 i.savePoint(i.pointIter.Prev()) 715 if i.err != nil { 716 i.pos = posExhausted 717 return 718 } 719 // If we're not currently covered by the span, we want to chose the 720 // MAX(pointKey,span.End), which is exactly the calculation performed 721 // by computeLargestPos. 722 if !i.withinSpan { 723 i.computeLargestPos() 724 return 725 } 726 switch { 727 case i.span == nil: 728 panic("withinSpan=true, but i.span == nil") 729 case i.pointKey == nil: 730 i.pos = posKeyspanEnd 731 default: 732 // i.withinSpan && i.pointKey != nil && i.span != nil 733 if i.cmp(i.span.Start, i.pointKey.UserKey) > 0 { 734 i.pos = posKeyspanStart 735 } else { 736 i.pos = posPointKey 737 } 738 } 739 case posKeyspanStart: 740 i.saveSpanBackward(i.keyspanIter.Prev()) 741 i.savedKeyspan() 742 i.computeLargestPos() 743 case posKeyspanEnd: 744 // Either a point key or the span's start key is previous. 745 if i.pointKey != nil && i.cmp(i.pointKey.UserKey, i.span.Start) >= 0 { 746 i.pos = posPointKey 747 } else { 748 i.pos = posKeyspanStart 749 } 750 default: 751 panic(fmt.Sprintf("unexpected pos=%d", i.pos)) 752 } 753 } 754 755 func (i *InterleavingIter) yieldPosition( 756 lowerBound []byte, advance func(), 757 ) (*base.InternalKey, base.LazyValue) { 758 // This loop returns the first visible position in the current iteration 759 // direction. Some positions are not visible and skipped. For example, if 760 // masking is enabled and the iterator is positioned over a masked point 761 // key, this loop skips the position. If a span's start key should be 762 // interleaved next, but the span is empty, the loop continues to the next 763 // key. Currently, span end keys are also always skipped, and are used only 764 // for maintaining internal state. 765 for { 766 switch i.pos { 767 case posExhausted: 768 return i.yieldNil() 769 case posPointKey: 770 if i.pointKey == nil { 771 panic("i.pointKey is nil") 772 } 773 774 if i.mask != nil { 775 i.maybeUpdateMask() 776 if i.withinSpan && i.mask.SkipPoint(i.pointKey.UserKey) { 777 // The span covers the point key. If a SkipPoint hook is 778 // configured, ask it if we should skip this point key. 779 if i.prefix != nil { 780 // During prefix-iteration node, once a point is masked, 781 // all subsequent keys with the same prefix must also be 782 // masked according to the key ordering. We can stop and 783 // return nil. 784 // 785 // NB: The above is not just an optimization. During 786 // prefix-iteration mode, the internal iterator contract 787 // prohibits us from Next-ing beyond the first key 788 // beyond the iteration prefix. If we didn't already 789 // stop early, we would need to check if this masked 790 // point is already beyond the prefix. 791 return i.yieldNil() 792 } 793 // TODO(jackson): If we thread a base.Comparer through to 794 // InterleavingIter so that we have access to 795 // ImmediateSuccessor, we could use NextPrefix. We'd need to 796 // tweak the SpanMask interface slightly. 797 798 // Advance beyond the masked point key. 799 advance() 800 continue 801 } 802 } 803 return i.yieldPointKey() 804 case posKeyspanEnd: 805 // Don't interleave end keys; just advance. 806 advance() 807 continue 808 case posKeyspanStart: 809 // Don't interleave an empty span. 810 if i.span.Empty() { 811 advance() 812 continue 813 } 814 return i.yieldSyntheticSpanMarker(lowerBound) 815 default: 816 panic(fmt.Sprintf("unexpected interleavePos=%d", i.pos)) 817 } 818 } 819 } 820 821 // keyspanSeekGE seeks the keyspan iterator to the first span covering a key ≥ k. 822 func (i *InterleavingIter) keyspanSeekGE(k []byte, prefix []byte) { 823 i.saveSpanForward(i.keyspanIter.SeekGE(k)) 824 i.savedKeyspan() 825 } 826 827 // keyspanSeekLT seeks the keyspan iterator to the last span covering a key < k. 828 func (i *InterleavingIter) keyspanSeekLT(k []byte) { 829 i.saveSpanBackward(i.keyspanIter.SeekLT(k)) 830 // The current span's start key is not guaranteed to be less than key, 831 // because of the bounds enforcement. Consider the following example: 832 // 833 // Bounds are set to [d,e). The user performs a SeekLT(d). The 834 // FragmentIterator.SeekLT lands on a span [b,f). This span has a start key 835 // less than d, as expected. Above, saveSpanBackward truncates the span to 836 // match the iterator's current bounds, modifying the span to [d,e), which 837 // does not overlap the search space of [-∞, d). 838 // 839 // This problem is a consequence of the SeekLT's exclusive search key and 840 // the fact that we don't perform bounds truncation at every leaf iterator. 841 if i.span != nil && i.truncated && i.cmp(i.truncatedSpan.Start, k) >= 0 { 842 i.span = nil 843 } 844 i.savedKeyspan() 845 } 846 847 func (i *InterleavingIter) saveSpanForward(span *Span) { 848 i.span = span 849 i.truncated = false 850 i.truncatedSpan = Span{} 851 if i.span == nil { 852 i.err = firstError(i.err, i.keyspanIter.Error()) 853 return 854 } 855 if invariants.Enabled { 856 if err := i.keyspanIter.Error(); err != nil { 857 panic(errors.WithSecondaryError( 858 errors.AssertionFailedf("pebble: %T keyspan iterator returned non-nil span %s while iter has error", i.keyspanIter, i.span), 859 err)) 860 } 861 } 862 // Check the upper bound if we have one. 863 if i.upper != nil && i.cmp(i.span.Start, i.upper) >= 0 { 864 i.span = nil 865 return 866 } 867 868 // TODO(jackson): The key comparisons below truncate bounds whenever the 869 // keyspan iterator is repositioned. We could perform this lazily, and do it 870 // the first time the user actually asks for this span's bounds in 871 // SpanBounds. This would reduce work in the case where there's no span 872 // covering the point and the keyspan iterator is non-empty. 873 874 // NB: These truncations don't require setting `keyspanMarkerTruncated`: 875 // That flag only applies to truncated span marker keys. 876 if i.lower != nil && i.cmp(i.span.Start, i.lower) < 0 { 877 i.truncated = true 878 i.truncatedSpan = *i.span 879 i.truncatedSpan.Start = i.lower 880 } 881 if i.upper != nil && i.cmp(i.upper, i.span.End) < 0 { 882 if !i.truncated { 883 i.truncated = true 884 i.truncatedSpan = *i.span 885 } 886 i.truncatedSpan.End = i.upper 887 } 888 // If this is a part of a SeekPrefixGE call, we may also need to truncate to 889 // the prefix's bounds. 890 if i.prefix != nil { 891 if !i.truncated { 892 i.truncated = true 893 i.truncatedSpan = *i.span 894 } 895 if i.cmp(i.prefix, i.truncatedSpan.Start) > 0 { 896 i.truncatedSpan.Start = i.prefix 897 } 898 i.nextPrefixBuf = i.comparer.ImmediateSuccessor(i.nextPrefixBuf[:0], i.prefix) 899 if i.truncated && i.cmp(i.nextPrefixBuf, i.truncatedSpan.End) < 0 { 900 i.truncatedSpan.End = i.nextPrefixBuf 901 } 902 } 903 904 if i.truncated && i.comparer.Equal(i.truncatedSpan.Start, i.truncatedSpan.End) { 905 i.span = nil 906 } 907 } 908 909 func (i *InterleavingIter) saveSpanBackward(span *Span) { 910 i.span = span 911 i.truncated = false 912 i.truncatedSpan = Span{} 913 if i.span == nil { 914 i.err = firstError(i.err, i.keyspanIter.Error()) 915 return 916 } 917 if invariants.Enabled { 918 if err := i.keyspanIter.Error(); err != nil { 919 panic(errors.WithSecondaryError( 920 errors.AssertionFailedf("pebble: %T keyspan iterator returned non-nil span %s while iter has error", i.keyspanIter, i.span), 921 err)) 922 } 923 } 924 925 // Check the lower bound if we have one. 926 if i.lower != nil && i.cmp(i.span.End, i.lower) <= 0 { 927 i.span = nil 928 return 929 } 930 931 // TODO(jackson): The key comparisons below truncate bounds whenever the 932 // keyspan iterator is repositioned. We could perform this lazily, and do it 933 // the first time the user actually asks for this span's bounds in 934 // SpanBounds. This would reduce work in the case where there's no span 935 // covering the point and the keyspan iterator is non-empty. 936 937 // NB: These truncations don't require setting `keyspanMarkerTruncated`: 938 // That flag only applies to truncated span marker keys. 939 if i.lower != nil && i.cmp(i.span.Start, i.lower) < 0 { 940 i.truncated = true 941 i.truncatedSpan = *i.span 942 i.truncatedSpan.Start = i.lower 943 } 944 if i.upper != nil && i.cmp(i.upper, i.span.End) < 0 { 945 if !i.truncated { 946 i.truncated = true 947 i.truncatedSpan = *i.span 948 } 949 i.truncatedSpan.End = i.upper 950 } 951 if i.truncated && i.comparer.Equal(i.truncatedSpan.Start, i.truncatedSpan.End) { 952 i.span = nil 953 } 954 } 955 956 func (i *InterleavingIter) yieldNil() (*base.InternalKey, base.LazyValue) { 957 i.withinSpan = false 958 i.clearMask() 959 return i.verify(nil, base.LazyValue{}) 960 } 961 962 func (i *InterleavingIter) yieldPointKey() (*base.InternalKey, base.LazyValue) { 963 return i.verify(i.pointKey, i.pointVal) 964 } 965 966 func (i *InterleavingIter) yieldSyntheticSpanMarker( 967 lowerBound []byte, 968 ) (*base.InternalKey, base.LazyValue) { 969 i.spanMarker.UserKey = i.startKey() 970 i.spanMarker.Trailer = base.MakeTrailer(base.InternalKeySeqNumMax, i.span.Keys[0].Kind()) 971 972 // Truncate the key we return to our lower bound if we have one. Note that 973 // we use the lowerBound function parameter, not i.lower. The lowerBound 974 // argument is guaranteed to be ≥ i.lower. It may be equal to the SetBounds 975 // lower bound, or it could come from a SeekGE or SeekPrefixGE search key. 976 if lowerBound != nil && i.cmp(lowerBound, i.startKey()) > 0 { 977 // Truncating to the lower bound may violate the upper bound if 978 // lowerBound == i.upper. For example, a SeekGE(k) uses k as a lower 979 // bound for truncating a span. The span a-z will be truncated to [k, 980 // z). If i.upper == k, we'd mistakenly try to return a span [k, k), an 981 // invariant violation. 982 if i.comparer.Equal(lowerBound, i.upper) { 983 return i.yieldNil() 984 } 985 986 // If the lowerBound argument came from a SeekGE or SeekPrefixGE 987 // call, and it may be backed by a user-provided byte slice that is not 988 // guaranteed to be stable. 989 // 990 // If the lowerBound argument is the lower bound set by SetBounds, 991 // Pebble owns the slice's memory. However, consider two successive 992 // calls to SetBounds(). The second may overwrite the lower bound. 993 // Although the external contract requires a seek after a SetBounds, 994 // Pebble's tests don't always. For this reason and to simplify 995 // reasoning around lifetimes, always copy the bound into keyBuf when 996 // truncating. 997 i.keyBuf = append(i.keyBuf[:0], lowerBound...) 998 i.spanMarker.UserKey = i.keyBuf 999 i.spanMarkerTruncated = true 1000 } 1001 i.maybeUpdateMask() 1002 return i.verify(&i.spanMarker, base.LazyValue{}) 1003 } 1004 1005 func (i *InterleavingIter) disablePrefixMode() { 1006 if i.prefix != nil { 1007 i.prefix = nil 1008 // Clear the existing span. It may not hold the true end bound of the 1009 // underlying span. 1010 i.span = nil 1011 } 1012 } 1013 1014 func (i *InterleavingIter) verify( 1015 k *base.InternalKey, v base.LazyValue, 1016 ) (*base.InternalKey, base.LazyValue) { 1017 // Wrap the entire function body in the invariants build tag, so that 1018 // production builds elide this entire function. 1019 if invariants.Enabled { 1020 switch { 1021 case i.dir == -1 && i.spanMarkerTruncated: 1022 panic("pebble: invariant violation: truncated span key in reverse iteration") 1023 case k != nil && i.lower != nil && i.cmp(k.UserKey, i.lower) < 0: 1024 panic("pebble: invariant violation: key < lower bound") 1025 case k != nil && i.upper != nil && i.cmp(k.UserKey, i.upper) >= 0: 1026 panic("pebble: invariant violation: key ≥ upper bound") 1027 case i.err != nil && k != nil: 1028 panic("pebble: invariant violation: accumulated error swallowed") 1029 case i.err == nil && i.pointIter.Error() != nil: 1030 panic("pebble: invariant violation: pointIter swallowed") 1031 case i.err == nil && i.keyspanIter.Error() != nil: 1032 panic("pebble: invariant violation: keyspanIter error swallowed") 1033 } 1034 } 1035 return k, v 1036 } 1037 1038 func (i *InterleavingIter) savedKeyspan() { 1039 i.spanMarkerTruncated = false 1040 i.maskSpanChangedCalled = false 1041 } 1042 1043 // updateMask updates the current mask, if a mask is configured and the mask 1044 // hasn't been updated with the current keyspan yet. 1045 func (i *InterleavingIter) maybeUpdateMask() { 1046 switch { 1047 case i.mask == nil, i.maskSpanChangedCalled: 1048 return 1049 case !i.withinSpan || i.span.Empty(): 1050 i.clearMask() 1051 case i.truncated: 1052 i.mask.SpanChanged(&i.truncatedSpan) 1053 i.maskSpanChangedCalled = true 1054 default: 1055 i.mask.SpanChanged(i.span) 1056 i.maskSpanChangedCalled = true 1057 } 1058 } 1059 1060 // clearMask clears the current mask, if a mask is configured and no mask should 1061 // be active. 1062 func (i *InterleavingIter) clearMask() { 1063 if i.mask != nil { 1064 i.maskSpanChangedCalled = false 1065 i.mask.SpanChanged(nil) 1066 } 1067 } 1068 1069 func (i *InterleavingIter) startKey() []byte { 1070 if i.truncated { 1071 return i.truncatedSpan.Start 1072 } 1073 return i.span.Start 1074 } 1075 1076 func (i *InterleavingIter) savePoint(key *base.InternalKey, value base.LazyValue) { 1077 i.pointKey, i.pointVal = key, value 1078 if key == nil { 1079 i.err = firstError(i.err, i.pointIter.Error()) 1080 } 1081 if invariants.Enabled { 1082 if err := i.pointIter.Error(); key != nil && err != nil { 1083 panic(errors.WithSecondaryError( 1084 errors.AssertionFailedf("pebble: %T point iterator returned non-nil key %q while iter has error", i.pointIter, key), 1085 err)) 1086 } 1087 } 1088 } 1089 1090 // Span returns the span covering the last key returned, if any. A span key is 1091 // considered to 'cover' a key if the key falls within the span's user key 1092 // bounds. The returned span is owned by the InterleavingIter. The caller is 1093 // responsible for copying if stability is required. 1094 // 1095 // Span will never return an invalid or empty span. 1096 func (i *InterleavingIter) Span() *Span { 1097 if !i.withinSpan || len(i.span.Keys) == 0 { 1098 return nil 1099 } else if i.truncated { 1100 return &i.truncatedSpan 1101 } 1102 return i.span 1103 } 1104 1105 // SetBounds implements (base.InternalIterator).SetBounds. 1106 func (i *InterleavingIter) SetBounds(lower, upper []byte) { 1107 i.lower, i.upper = lower, upper 1108 i.pointIter.SetBounds(lower, upper) 1109 i.Invalidate() 1110 } 1111 1112 // Invalidate invalidates the interleaving iterator's current position, clearing 1113 // its state. This prevents optimizations such as reusing the current span on 1114 // seek. 1115 func (i *InterleavingIter) Invalidate() { 1116 i.span = nil 1117 i.pointKey = nil 1118 i.pointVal = base.LazyValue{} 1119 } 1120 1121 // Error implements (base.InternalIterator).Error. 1122 func (i *InterleavingIter) Error() error { 1123 return i.err 1124 } 1125 1126 // Close implements (base.InternalIterator).Close. 1127 func (i *InterleavingIter) Close() error { 1128 perr := i.pointIter.Close() 1129 rerr := i.keyspanIter.Close() 1130 return firstError(perr, rerr) 1131 } 1132 1133 // String implements (base.InternalIterator).String. 1134 func (i *InterleavingIter) String() string { 1135 return fmt.Sprintf("keyspan-interleaving(%q)", i.pointIter.String()) 1136 } 1137 1138 func firstError(err0, err1 error) error { 1139 if err0 != nil { 1140 return err0 1141 } 1142 return err1 1143 }