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