Upgrade versions of vendored libs
This commit is contained in:
265
vendor/github.com/cockroachdb/pebble/internal/keyspan/bounded.go
generated
vendored
Normal file
265
vendor/github.com/cockroachdb/pebble/internal/keyspan/bounded.go
generated
vendored
Normal file
@@ -0,0 +1,265 @@
|
||||
// Copyright 2022 The LevelDB-Go and Pebble Authors. All rights reserved. Use
|
||||
// of this source code is governed by a BSD-style license that can be found in
|
||||
// the LICENSE file.
|
||||
|
||||
package keyspan
|
||||
|
||||
import "github.com/cockroachdb/pebble/internal/base"
|
||||
|
||||
// TODO(jackson): Consider removing this type and adding bounds enforcement
|
||||
// directly to the MergingIter. This type is probably too lightweight to warrant
|
||||
// its own type, but for now we implement it separately for expediency.
|
||||
|
||||
// boundedIterPos records the position of the BoundedIter relative to the
|
||||
// underlying iterator's position. It's used to avoid Next/Prev-ing the iterator
|
||||
// if there can't possibly be another span within bounds, because the current
|
||||
// span overlaps the bound.
|
||||
//
|
||||
// Imagine bounds [a,c) and an iterator that seeks to a span [b,d). The span
|
||||
// [b,d) overlaps some portion of the iterator bounds, so the iterator must
|
||||
// return it. If the iterator is subsequently Nexted, Next can tell that the
|
||||
// iterator is exhausted without advancing the underlying iterator because the
|
||||
// current span's end bound of d is ≥ the upper bound of c. In this case, the
|
||||
// bounded iterator returns nil and records i.pos as posAtUpperLimit to remember
|
||||
// that the underlying iterator position does not match the current BoundedIter
|
||||
// position.
|
||||
type boundedIterPos int8
|
||||
|
||||
const (
|
||||
posAtLowerLimit boundedIterPos = -1
|
||||
posAtIterSpan boundedIterPos = 0
|
||||
posAtUpperLimit boundedIterPos = +1
|
||||
)
|
||||
|
||||
// BoundedIter implements FragmentIterator and enforces bounds.
|
||||
//
|
||||
// Like the point InternalIterator interface, the bounded iterator's forward
|
||||
// positioning routines (SeekGE, First, and Next) only check the upper bound.
|
||||
// The reverse positioning routines (SeekLT, Last, and Prev) only check the
|
||||
// lower bound. It is up to the caller to ensure that the forward positioning
|
||||
// routines respect the lower bound and the reverse positioning routines respect
|
||||
// the upper bound (i.e. calling SeekGE instead of First if there is a lower
|
||||
// bound, and SeekLT instead of Last if there is an upper bound).
|
||||
//
|
||||
// When the hasPrefix parameter indicates that the iterator is in prefix
|
||||
// iteration mode, BoundedIter elides any spans that do not overlap with the
|
||||
// prefix's keyspace. In prefix iteration mode, reverse iteration is disallowed,
|
||||
// except for an initial SeekLT with a seek key greater than or equal to the
|
||||
// prefix. In prefix iteration mode, the first seek must position the iterator
|
||||
// at or immediately before the first fragment covering a key greater than or
|
||||
// equal to the prefix.
|
||||
type BoundedIter struct {
|
||||
iter FragmentIterator
|
||||
iterSpan *Span
|
||||
cmp base.Compare
|
||||
split base.Split
|
||||
lower []byte
|
||||
upper []byte
|
||||
hasPrefix *bool
|
||||
prefix *[]byte
|
||||
pos boundedIterPos
|
||||
}
|
||||
|
||||
// Init initializes the bounded iterator.
|
||||
//
|
||||
// In addition to the iterator bounds, Init takes pointers to a boolean
|
||||
// indicating whether the iterator is in prefix iteration mode and the prefix
|
||||
// key if it is. This is used to exclude spans that are outside the iteration
|
||||
// prefix.
|
||||
func (i *BoundedIter) Init(
|
||||
cmp base.Compare,
|
||||
split base.Split,
|
||||
iter FragmentIterator,
|
||||
lower, upper []byte,
|
||||
hasPrefix *bool,
|
||||
prefix *[]byte,
|
||||
) {
|
||||
*i = BoundedIter{
|
||||
iter: iter,
|
||||
cmp: cmp,
|
||||
split: split,
|
||||
lower: lower,
|
||||
upper: upper,
|
||||
hasPrefix: hasPrefix,
|
||||
prefix: prefix,
|
||||
}
|
||||
}
|
||||
|
||||
var _ FragmentIterator = (*BoundedIter)(nil)
|
||||
|
||||
// Seek calls.
|
||||
//
|
||||
// Seek calls check iterator bounds in the direction of the seek. Additionally,
|
||||
// if the iterator is in prefix iteration mode, seek calls check both start and
|
||||
// end bounds against the prefix's bounds. We check both bounds for defense in
|
||||
// depth. This optimization has been a source of various bugs due to various
|
||||
// other prefix iteration optimizations that can result in seek keys that don't
|
||||
// respect the prefix bounds.
|
||||
|
||||
// SeekGE implements FragmentIterator.
|
||||
func (i *BoundedIter) SeekGE(key []byte) *Span {
|
||||
s := i.iter.SeekGE(key)
|
||||
s = i.checkPrefixSpanStart(s)
|
||||
s = i.checkPrefixSpanEnd(s)
|
||||
return i.checkForwardBound(s)
|
||||
}
|
||||
|
||||
// SeekLT implements FragmentIterator.
|
||||
func (i *BoundedIter) SeekLT(key []byte) *Span {
|
||||
s := i.iter.SeekLT(key)
|
||||
s = i.checkPrefixSpanStart(s)
|
||||
s = i.checkPrefixSpanEnd(s)
|
||||
return i.checkBackwardBound(s)
|
||||
}
|
||||
|
||||
// First implements FragmentIterator.
|
||||
func (i *BoundedIter) First() *Span {
|
||||
s := i.iter.First()
|
||||
s = i.checkPrefixSpanStart(s)
|
||||
return i.checkForwardBound(s)
|
||||
}
|
||||
|
||||
// Last implements FragmentIterator.
|
||||
func (i *BoundedIter) Last() *Span {
|
||||
s := i.iter.Last()
|
||||
s = i.checkPrefixSpanEnd(s)
|
||||
return i.checkBackwardBound(s)
|
||||
}
|
||||
|
||||
// Next implements FragmentIterator.
|
||||
func (i *BoundedIter) Next() *Span {
|
||||
switch i.pos {
|
||||
case posAtLowerLimit:
|
||||
// The BoundedIter had previously returned nil, because it knew from
|
||||
// i.iterSpan's bounds that there was no previous span. To Next, we only
|
||||
// need to return the current iter span and reset i.pos to reflect that
|
||||
// we're no longer positioned at the limit.
|
||||
i.pos = posAtIterSpan
|
||||
return i.iterSpan
|
||||
case posAtIterSpan:
|
||||
// If the span at the underlying iterator position extends to or beyond the
|
||||
// upper bound, we can avoid advancing because the next span is necessarily
|
||||
// out of bounds.
|
||||
if i.iterSpan != nil && i.upper != nil && i.cmp(i.iterSpan.End, i.upper) >= 0 {
|
||||
i.pos = posAtUpperLimit
|
||||
return nil
|
||||
}
|
||||
// Similarly, if the span extends to the next prefix and we're in prefix
|
||||
// iteration mode, we can avoid advancing.
|
||||
if i.iterSpan != nil && *i.hasPrefix {
|
||||
ei := i.split(i.iterSpan.End)
|
||||
if i.cmp(i.iterSpan.End[:ei], *i.prefix) > 0 {
|
||||
i.pos = posAtUpperLimit
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return i.checkForwardBound(i.checkPrefixSpanStart(i.iter.Next()))
|
||||
case posAtUpperLimit:
|
||||
// Already exhausted.
|
||||
return nil
|
||||
default:
|
||||
panic("unreachable")
|
||||
}
|
||||
}
|
||||
|
||||
// Prev implements FragmentIterator.
|
||||
func (i *BoundedIter) Prev() *Span {
|
||||
switch i.pos {
|
||||
case posAtLowerLimit:
|
||||
// Already exhausted.
|
||||
return nil
|
||||
case posAtIterSpan:
|
||||
// If the span at the underlying iterator position extends to or beyond
|
||||
// the lower bound, we can avoid advancing because the previous span is
|
||||
// necessarily out of bounds.
|
||||
if i.iterSpan != nil && i.lower != nil && i.cmp(i.iterSpan.Start, i.lower) <= 0 {
|
||||
i.pos = posAtLowerLimit
|
||||
return nil
|
||||
}
|
||||
// Similarly, if the span extends to or beyond the current prefix and
|
||||
// we're in prefix iteration mode, we can avoid advancing.
|
||||
if i.iterSpan != nil && *i.hasPrefix {
|
||||
si := i.split(i.iterSpan.Start)
|
||||
if i.cmp(i.iterSpan.Start[:si], *i.prefix) < 0 {
|
||||
i.pos = posAtLowerLimit
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return i.checkBackwardBound(i.checkPrefixSpanEnd(i.iter.Prev()))
|
||||
case posAtUpperLimit:
|
||||
// The BoundedIter had previously returned nil, because it knew from
|
||||
// i.iterSpan's bounds that there was no next span. To Prev, we only
|
||||
// need to return the current iter span and reset i.pos to reflect that
|
||||
// we're no longer positioned at the limit.
|
||||
i.pos = posAtIterSpan
|
||||
return i.iterSpan
|
||||
default:
|
||||
panic("unreachable")
|
||||
}
|
||||
}
|
||||
|
||||
// Error implements FragmentIterator.
|
||||
func (i *BoundedIter) Error() error {
|
||||
return i.iter.Error()
|
||||
}
|
||||
|
||||
// Close implements FragmentIterator.
|
||||
func (i *BoundedIter) Close() error {
|
||||
return i.iter.Close()
|
||||
}
|
||||
|
||||
// SetBounds modifies the FragmentIterator's bounds.
|
||||
func (i *BoundedIter) SetBounds(lower, upper []byte) {
|
||||
i.lower, i.upper = lower, upper
|
||||
}
|
||||
|
||||
func (i *BoundedIter) checkPrefixSpanStart(span *Span) *Span {
|
||||
// Compare to the prefix's bounds, if in prefix iteration mode.
|
||||
if span != nil && *i.hasPrefix {
|
||||
si := i.split(span.Start)
|
||||
if i.cmp(span.Start[:si], *i.prefix) > 0 {
|
||||
// This span starts at a prefix that sorts after our current prefix.
|
||||
span = nil
|
||||
}
|
||||
}
|
||||
return span
|
||||
}
|
||||
|
||||
// checkForwardBound enforces the upper bound, returning nil if the provided
|
||||
// span is wholly outside the upper bound. It also updates i.pos and i.iterSpan
|
||||
// to reflect the new iterator position.
|
||||
func (i *BoundedIter) checkForwardBound(span *Span) *Span {
|
||||
// Compare to the upper bound.
|
||||
if span != nil && i.upper != nil && i.cmp(span.Start, i.upper) >= 0 {
|
||||
span = nil
|
||||
}
|
||||
i.iterSpan = span
|
||||
if i.pos != posAtIterSpan {
|
||||
i.pos = posAtIterSpan
|
||||
}
|
||||
return span
|
||||
}
|
||||
|
||||
func (i *BoundedIter) checkPrefixSpanEnd(span *Span) *Span {
|
||||
// Compare to the prefix's bounds, if in prefix iteration mode.
|
||||
if span != nil && *i.hasPrefix && i.cmp(span.End, *i.prefix) <= 0 {
|
||||
// This span ends before the current prefix.
|
||||
span = nil
|
||||
}
|
||||
return span
|
||||
}
|
||||
|
||||
// checkBackward enforces the lower bound, returning nil if the provided span is
|
||||
// wholly outside the lower bound. It also updates i.pos and i.iterSpan to
|
||||
// reflect the new iterator position.
|
||||
func (i *BoundedIter) checkBackwardBound(span *Span) *Span {
|
||||
// Compare to the lower bound.
|
||||
if span != nil && i.lower != nil && i.cmp(span.End, i.lower) <= 0 {
|
||||
span = nil
|
||||
}
|
||||
i.iterSpan = span
|
||||
if i.pos != posAtIterSpan {
|
||||
i.pos = posAtIterSpan
|
||||
}
|
||||
return span
|
||||
}
|
||||
53
vendor/github.com/cockroachdb/pebble/internal/keyspan/defragment.go
generated
vendored
53
vendor/github.com/cockroachdb/pebble/internal/keyspan/defragment.go
generated
vendored
@@ -21,26 +21,30 @@ const bufferReuseMaxCapacity = 10 << 10 // 10 KB
|
||||
type DefragmentMethod interface {
|
||||
// ShouldDefragment takes two abutting spans and returns whether the two
|
||||
// spans should be combined into a single, defragmented Span.
|
||||
ShouldDefragment(cmp base.Compare, left, right *Span) bool
|
||||
ShouldDefragment(equal base.Equal, left, right *Span) bool
|
||||
}
|
||||
|
||||
// The DefragmentMethodFunc type is an adapter to allow the use of ordinary
|
||||
// functions as DefragmentMethods. If f is a function with the appropriate
|
||||
// signature, DefragmentMethodFunc(f) is a DefragmentMethod that calls f.
|
||||
type DefragmentMethodFunc func(cmp base.Compare, left, right *Span) bool
|
||||
type DefragmentMethodFunc func(equal base.Equal, left, right *Span) bool
|
||||
|
||||
// ShouldDefragment calls f(cmp, left, right).
|
||||
func (f DefragmentMethodFunc) ShouldDefragment(cmp base.Compare, left, right *Span) bool {
|
||||
return f(cmp, left, right)
|
||||
// ShouldDefragment calls f(equal, left, right).
|
||||
func (f DefragmentMethodFunc) ShouldDefragment(equal base.Equal, left, right *Span) bool {
|
||||
return f(equal, left, right)
|
||||
}
|
||||
|
||||
// DefragmentInternal configures a DefragmentingIter to defragment spans
|
||||
// only if they have identical keys.
|
||||
// only if they have identical keys. It requires spans' keys to be sorted in
|
||||
// trailer descending order.
|
||||
//
|
||||
// This defragmenting method is intended for use in compactions that may see
|
||||
// internal range keys fragments that may now be joined, because the state that
|
||||
// required their fragmentation has been dropped.
|
||||
var DefragmentInternal DefragmentMethod = DefragmentMethodFunc(func(cmp base.Compare, a, b *Span) bool {
|
||||
var DefragmentInternal DefragmentMethod = DefragmentMethodFunc(func(equal base.Equal, a, b *Span) bool {
|
||||
if a.KeysOrder != ByTrailerDesc || b.KeysOrder != ByTrailerDesc {
|
||||
panic("pebble: span keys unexpectedly not in trailer descending order")
|
||||
}
|
||||
if len(a.Keys) != len(b.Keys) {
|
||||
return false
|
||||
}
|
||||
@@ -48,7 +52,7 @@ var DefragmentInternal DefragmentMethod = DefragmentMethodFunc(func(cmp base.Com
|
||||
if a.Keys[i].Trailer != b.Keys[i].Trailer {
|
||||
return false
|
||||
}
|
||||
if cmp(a.Keys[i].Suffix, b.Keys[i].Suffix) != 0 {
|
||||
if !equal(a.Keys[i].Suffix, b.Keys[i].Suffix) {
|
||||
return false
|
||||
}
|
||||
if !bytes.Equal(a.Keys[i].Value, b.Keys[i].Value) {
|
||||
@@ -114,7 +118,8 @@ const (
|
||||
// defragments in the iteration direction, ensuring it's found a whole
|
||||
// defragmented span.
|
||||
type DefragmentingIter struct {
|
||||
cmp base.Compare
|
||||
comparer *base.Comparer
|
||||
equal base.Equal
|
||||
iter FragmentIterator
|
||||
iterSpan *Span
|
||||
iterPos iterPos
|
||||
@@ -149,13 +154,14 @@ var _ FragmentIterator = (*DefragmentingIter)(nil)
|
||||
// Init initializes the defragmenting iter using the provided defragment
|
||||
// method.
|
||||
func (i *DefragmentingIter) Init(
|
||||
cmp base.Compare, iter FragmentIterator, equal DefragmentMethod, reducer DefragmentReducer,
|
||||
comparer *base.Comparer, iter FragmentIterator, equal DefragmentMethod, reducer DefragmentReducer,
|
||||
) {
|
||||
*i = DefragmentingIter{
|
||||
cmp: cmp,
|
||||
iter: iter,
|
||||
method: equal,
|
||||
reduce: reducer,
|
||||
comparer: comparer,
|
||||
equal: comparer.Equal,
|
||||
iter: iter,
|
||||
method: equal,
|
||||
reduce: reducer,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,11 +182,14 @@ func (i *DefragmentingIter) SeekGE(key []byte) *Span {
|
||||
if i.iterSpan == nil {
|
||||
i.iterPos = iterPosCurr
|
||||
return nil
|
||||
} else if i.iterSpan.Empty() {
|
||||
i.iterPos = iterPosCurr
|
||||
return i.iterSpan
|
||||
}
|
||||
// Save the current span and peek backwards.
|
||||
i.saveCurrent()
|
||||
i.iterSpan = i.iter.Prev()
|
||||
if i.iterSpan != nil && i.cmp(i.curr.Start, i.iterSpan.End) == 0 && i.checkEqual(i.iterSpan, &i.curr) {
|
||||
if i.iterSpan != nil && i.equal(i.curr.Start, i.iterSpan.End) && i.checkEqual(i.iterSpan, &i.curr) {
|
||||
// A continuation. The span we originally landed on and defragmented
|
||||
// backwards has a true Start key < key. To obey the FragmentIterator
|
||||
// contract, we must not return this defragmented span. Defragment
|
||||
@@ -206,6 +215,9 @@ func (i *DefragmentingIter) SeekLT(key []byte) *Span {
|
||||
if i.iterSpan == nil {
|
||||
i.iterPos = iterPosCurr
|
||||
return nil
|
||||
} else if i.iterSpan.Empty() {
|
||||
i.iterPos = iterPosCurr
|
||||
return i.iterSpan
|
||||
}
|
||||
// Defragment forward to find the end of the defragmented span.
|
||||
i.defragmentForward()
|
||||
@@ -355,7 +367,7 @@ func (i *DefragmentingIter) Prev() *Span {
|
||||
// DefragmentMethod and ensures both spans are NOT empty; not defragmenting empty
|
||||
// spans is an optimization that lets us load fewer sstable blocks.
|
||||
func (i *DefragmentingIter) checkEqual(left, right *Span) bool {
|
||||
return (!left.Empty() && !right.Empty()) && i.method.ShouldDefragment(i.cmp, i.iterSpan, &i.curr)
|
||||
return (!left.Empty() && !right.Empty()) && i.method.ShouldDefragment(i.equal, i.iterSpan, &i.curr)
|
||||
}
|
||||
|
||||
// defragmentForward defragments spans in the forward direction, starting from
|
||||
@@ -374,7 +386,7 @@ func (i *DefragmentingIter) defragmentForward() *Span {
|
||||
i.iterPos = iterPosNext
|
||||
i.iterSpan = i.iter.Next()
|
||||
for i.iterSpan != nil {
|
||||
if i.cmp(i.curr.End, i.iterSpan.Start) != 0 {
|
||||
if !i.equal(i.curr.End, i.iterSpan.Start) {
|
||||
// Not a continuation.
|
||||
break
|
||||
}
|
||||
@@ -407,7 +419,7 @@ func (i *DefragmentingIter) defragmentBackward() *Span {
|
||||
i.iterPos = iterPosPrev
|
||||
i.iterSpan = i.iter.Prev()
|
||||
for i.iterSpan != nil {
|
||||
if i.cmp(i.curr.Start, i.iterSpan.End) != 0 {
|
||||
if !i.equal(i.curr.Start, i.iterSpan.End) {
|
||||
// Not a continuation.
|
||||
break
|
||||
}
|
||||
@@ -438,8 +450,9 @@ func (i *DefragmentingIter) saveCurrent() {
|
||||
return
|
||||
}
|
||||
i.curr = Span{
|
||||
Start: i.saveBytes(i.iterSpan.Start),
|
||||
End: i.saveBytes(i.iterSpan.End),
|
||||
Start: i.saveBytes(i.iterSpan.Start),
|
||||
End: i.saveBytes(i.iterSpan.End),
|
||||
KeysOrder: i.iterSpan.KeysOrder,
|
||||
}
|
||||
for j := range i.iterSpan.Keys {
|
||||
i.keysBuf = append(i.keysBuf, Key{
|
||||
|
||||
4
vendor/github.com/cockroachdb/pebble/internal/keyspan/fragmenter.go
generated
vendored
4
vendor/github.com/cockroachdb/pebble/internal/keyspan/fragmenter.go
generated
vendored
@@ -183,9 +183,13 @@ func (f *Fragmenter) checkInvariants(buf []Span) {
|
||||
// deletion and range key blocks, so these keys are stable. Because of this key
|
||||
// stability, typically callers only need to perform a shallow clone of the Span
|
||||
// before Add-ing it to the fragmenter.
|
||||
//
|
||||
// Add requires the provided span's keys are sorted in Trailer descending order.
|
||||
func (f *Fragmenter) Add(s Span) {
|
||||
if f.finished {
|
||||
panic("pebble: span fragmenter already finished")
|
||||
} else if s.KeysOrder != ByTrailerDesc {
|
||||
panic("pebble: span keys unexpectedly not in trailer descending order")
|
||||
}
|
||||
if f.flushedKey != nil {
|
||||
switch c := f.Cmp(s.Start, f.flushedKey); {
|
||||
|
||||
357
vendor/github.com/cockroachdb/pebble/internal/keyspan/interleaving_iter.go
generated
vendored
357
vendor/github.com/cockroachdb/pebble/internal/keyspan/interleaving_iter.go
generated
vendored
@@ -35,14 +35,6 @@ type SpanMask interface {
|
||||
SkipPoint(userKey []byte) bool
|
||||
}
|
||||
|
||||
type maskState int8
|
||||
|
||||
const (
|
||||
maskStale maskState = iota
|
||||
maskCleared
|
||||
maskCurrent
|
||||
)
|
||||
|
||||
// InterleavingIter combines an iterator over point keys with an iterator over
|
||||
// key spans.
|
||||
//
|
||||
@@ -101,7 +93,8 @@ const (
|
||||
// All spans containing keys are exposed during iteration.
|
||||
type InterleavingIter struct {
|
||||
cmp base.Compare
|
||||
pointIter base.InternalIteratorWithStats
|
||||
comparer *base.Comparer
|
||||
pointIter base.InternalIterator
|
||||
keyspanIter FragmentIterator
|
||||
mask SpanMask
|
||||
|
||||
@@ -111,9 +104,13 @@ type InterleavingIter struct {
|
||||
// to truncate a span. The byte slices backing a SeekGE/SeekPrefixGE search
|
||||
// keys can come directly from the end user, so they're copied into keyBuf
|
||||
// to ensure key stability.
|
||||
keyBuf []byte
|
||||
pointKey *base.InternalKey
|
||||
pointVal []byte
|
||||
keyBuf []byte
|
||||
// nextPrefixBuf is used during SeekPrefixGE calls to store the truncated
|
||||
// upper bound of the returned spans. SeekPrefixGE truncates the returned
|
||||
// spans to an upper bound of the seeked prefix's immediate successor.
|
||||
nextPrefixBuf []byte
|
||||
pointKey *base.InternalKey
|
||||
pointVal base.LazyValue
|
||||
// span holds the span at the keyspanIter's current position. If the span is
|
||||
// wholly contained within the iterator bounds, this span is directly
|
||||
// returned to the iterator consumer through Span(). If either bound needed
|
||||
@@ -158,32 +155,15 @@ type InterleavingIter struct {
|
||||
// span's start bound marker to the search key. It's returned to false on
|
||||
// the next repositioning of the keyspan iterator.
|
||||
spanMarkerTruncated bool
|
||||
// maskState holds a tri-state enum describing the state of the state
|
||||
// machine managing invocations to i.mask.SpanChanged. When i.span is
|
||||
// updated, `maskState` is set to the starting state `maskStale` to reflect
|
||||
// that the mask has not been informed of the new span. From `maskStale`,
|
||||
// the state transitions to `maskCleared` if the next returned key does not
|
||||
// fall within i.span's bounds. The state transitions to `maskCurrent` if
|
||||
// the next returned key does fall within i.span's bounds.
|
||||
//
|
||||
// return key outside [s,e)
|
||||
// keyspan.Iter.{Next,Prev}
|
||||
// _________________________________
|
||||
// \/ |
|
||||
// _____________ |
|
||||
// | maskStale | |
|
||||
// |_____________| |
|
||||
// return key / \ return key |
|
||||
// outside [s,e) / \ within [s,e) |
|
||||
// \/ \/ |
|
||||
// ________________________ __________________________ |
|
||||
// | SpanChanged(nil) | | SpanChanged(i.span) | __|
|
||||
// | maskState = maskCleared| | maskState = maskCurrent |
|
||||
// |________________________| |__________________________|
|
||||
// |__________________________^
|
||||
// return key within [s,e)
|
||||
//
|
||||
maskState maskState
|
||||
// maskSpanChangedCalled records whether or not the last call to
|
||||
// SpanMask.SpanChanged provided the current span (i.span) or not.
|
||||
maskSpanChangedCalled bool
|
||||
// prefix records whether the iteator is in prefix mode. During prefix mode,
|
||||
// Pebble will truncate spans to the next prefix. If the iterator
|
||||
// subsequently leaves prefix mode, the existing span cached in i.span must
|
||||
// be invalidated because its bounds do not reflect the original span's true
|
||||
// bounds.
|
||||
prefix bool
|
||||
// dir indicates the direction of iteration: forward (+1) or backward (-1)
|
||||
dir int8
|
||||
}
|
||||
@@ -197,14 +177,15 @@ var _ base.InternalIterator = &InterleavingIter{}
|
||||
// The point iterator must already have the provided bounds. Init does not
|
||||
// propagate the bounds down the iterator stack.
|
||||
func (i *InterleavingIter) Init(
|
||||
cmp base.Compare,
|
||||
pointIter base.InternalIteratorWithStats,
|
||||
comparer *base.Comparer,
|
||||
pointIter base.InternalIterator,
|
||||
keyspanIter FragmentIterator,
|
||||
mask SpanMask,
|
||||
lowerBound, upperBound []byte,
|
||||
) {
|
||||
*i = InterleavingIter{
|
||||
cmp: cmp,
|
||||
cmp: comparer.Compare,
|
||||
comparer: comparer,
|
||||
pointIter: pointIter,
|
||||
keyspanIter: keyspanIter,
|
||||
mask: mask,
|
||||
@@ -224,16 +205,18 @@ func (i *InterleavingIter) Init(
|
||||
// It allows for seeding the iterator with the current position of the point
|
||||
// iterator.
|
||||
func (i *InterleavingIter) InitSeekGE(
|
||||
key []byte, pointKey *base.InternalKey, pointValue []byte,
|
||||
) (*base.InternalKey, []byte) {
|
||||
prefix, key []byte, pointKey *base.InternalKey, pointValue base.LazyValue,
|
||||
) (*base.InternalKey, base.LazyValue) {
|
||||
i.dir = +1
|
||||
i.clearMask()
|
||||
i.prefix = prefix != nil
|
||||
i.pointKey, i.pointVal = pointKey, pointValue
|
||||
i.pointKeyInterleaved = false
|
||||
// NB: This keyspanSeekGE call will truncate the span to the seek key if
|
||||
// necessary. This truncation is important for cases where a switch to
|
||||
// combined iteration is made during a user-initiated SeekGE.
|
||||
i.keyspanSeekGE(key)
|
||||
return i.interleaveForward(key)
|
||||
i.keyspanSeekGE(key, prefix)
|
||||
return i.interleaveForward(key, prefix)
|
||||
}
|
||||
|
||||
// InitSeekLT may be called after Init but before any positioning method.
|
||||
@@ -247,9 +230,10 @@ func (i *InterleavingIter) InitSeekGE(
|
||||
// It allows for seeding the iterator with the current position of the point
|
||||
// iterator.
|
||||
func (i *InterleavingIter) InitSeekLT(
|
||||
key []byte, pointKey *base.InternalKey, pointValue []byte,
|
||||
) (*base.InternalKey, []byte) {
|
||||
key []byte, pointKey *base.InternalKey, pointValue base.LazyValue,
|
||||
) (*base.InternalKey, base.LazyValue) {
|
||||
i.dir = -1
|
||||
i.clearMask()
|
||||
i.pointKey, i.pointVal = pointKey, pointValue
|
||||
i.pointKeyInterleaved = false
|
||||
i.keyspanSeekLT(key)
|
||||
@@ -265,14 +249,30 @@ func (i *InterleavingIter) InitSeekLT(
|
||||
// the span returned by Span.
|
||||
//
|
||||
// NB: In accordance with the base.InternalIterator contract:
|
||||
// i.lower ≤ key
|
||||
func (i *InterleavingIter) SeekGE(key []byte, flags base.SeekGEFlags) (*base.InternalKey, []byte) {
|
||||
i.maybeUpdateMask(false /* covered */)
|
||||
//
|
||||
// i.lower ≤ key
|
||||
func (i *InterleavingIter) SeekGE(
|
||||
key []byte, flags base.SeekGEFlags,
|
||||
) (*base.InternalKey, base.LazyValue) {
|
||||
i.clearMask()
|
||||
i.disablePrefixMode()
|
||||
i.pointKey, i.pointVal = i.pointIter.SeekGE(key, flags)
|
||||
i.pointKeyInterleaved = false
|
||||
i.keyspanSeekGE(key)
|
||||
|
||||
// We need to seek the keyspan iterator too. If the keyspan iterator was
|
||||
// already positioned at a span, we might be able to avoid the seek if the
|
||||
// seek key falls within the existing span's bounds.
|
||||
if i.span != nil && i.cmp(key, i.span.End) < 0 && i.cmp(key, i.span.Start) >= 0 {
|
||||
// We're seeking within the existing span's bounds. We still might need
|
||||
// truncate the span to the iterator's bounds.
|
||||
i.checkForwardBound(nil /* prefix */)
|
||||
i.savedKeyspan()
|
||||
} else {
|
||||
i.keyspanSeekGE(key, nil /* prefix */)
|
||||
}
|
||||
|
||||
i.dir = +1
|
||||
return i.interleaveForward(key)
|
||||
return i.interleaveForward(key, nil /* prefix */)
|
||||
}
|
||||
|
||||
// SeekPrefixGE implements (base.InternalIterator).SeekPrefixGE.
|
||||
@@ -284,43 +284,113 @@ func (i *InterleavingIter) SeekGE(key []byte, flags base.SeekGEFlags) (*base.Int
|
||||
// to the span returned by Span.
|
||||
//
|
||||
// NB: In accordance with the base.InternalIterator contract:
|
||||
// i.lower ≤ key
|
||||
//
|
||||
// i.lower ≤ key
|
||||
func (i *InterleavingIter) SeekPrefixGE(
|
||||
prefix, key []byte, flags base.SeekGEFlags,
|
||||
) (*base.InternalKey, []byte) {
|
||||
i.maybeUpdateMask(false /* covered */)
|
||||
) (*base.InternalKey, base.LazyValue) {
|
||||
i.clearMask()
|
||||
i.pointKey, i.pointVal = i.pointIter.SeekPrefixGE(prefix, key, flags)
|
||||
i.pointKeyInterleaved = false
|
||||
i.keyspanSeekGE(key)
|
||||
i.prefix = true
|
||||
|
||||
// We need to seek the keyspan iterator too. If the keyspan iterator was
|
||||
// already positioned at a span, we might be able to avoid the seek if the
|
||||
// entire seek prefix key falls within the existing span's bounds.
|
||||
//
|
||||
// During a SeekPrefixGE, Pebble defragments range keys within the bounds of
|
||||
// the prefix. For example, a SeekPrefixGE('c', 'c@8') must defragment the
|
||||
// any overlapping range keys within the bounds of [c,c\00).
|
||||
//
|
||||
// If range keys are fragmented within a prefix (eg, because a version
|
||||
// within a prefix was chosen as an sstable boundary), then it's possible
|
||||
// the seek key falls into the current i.span, but the current i.span does
|
||||
// not wholly cover the seek prefix.
|
||||
//
|
||||
// For example, a SeekPrefixGE('d@5') may only defragment a range key to
|
||||
// the bounds of [c@2,e). A subsequent SeekPrefixGE('c@0') must re-seek the
|
||||
// keyspan iterator, because although 'c@0' is contained within [c@2,e), the
|
||||
// full span of the prefix is not.
|
||||
//
|
||||
// Similarly, a SeekPrefixGE('a@3') may only defragment a range key to the
|
||||
// bounds [a,c@8). A subsequent SeekPrefixGE('c@10') must re-seek the
|
||||
// keyspan iterator, because although 'c@10' is contained within [a,c@8),
|
||||
// the full span of the prefix is not.
|
||||
seekKeyspanIter := true
|
||||
if i.span != nil && i.cmp(prefix, i.span.Start) >= 0 {
|
||||
if ei := i.comparer.Split(i.span.End); i.cmp(prefix, i.span.End[:ei]) < 0 {
|
||||
// We're seeking within the existing span's bounds. We still might need
|
||||
// truncate the span to the iterator's bounds.
|
||||
i.checkForwardBound(prefix)
|
||||
i.savedKeyspan()
|
||||
seekKeyspanIter = false
|
||||
}
|
||||
}
|
||||
if seekKeyspanIter {
|
||||
i.keyspanSeekGE(key, prefix)
|
||||
}
|
||||
|
||||
i.dir = +1
|
||||
return i.interleaveForward(key)
|
||||
return i.interleaveForward(key, prefix)
|
||||
}
|
||||
|
||||
// SeekLT implements (base.InternalIterator).SeekLT.
|
||||
func (i *InterleavingIter) SeekLT(key []byte, flags base.SeekLTFlags) (*base.InternalKey, []byte) {
|
||||
i.maybeUpdateMask(false /* covered */)
|
||||
func (i *InterleavingIter) SeekLT(
|
||||
key []byte, flags base.SeekLTFlags,
|
||||
) (*base.InternalKey, base.LazyValue) {
|
||||
i.clearMask()
|
||||
i.disablePrefixMode()
|
||||
i.pointKey, i.pointVal = i.pointIter.SeekLT(key, flags)
|
||||
i.pointKeyInterleaved = false
|
||||
i.keyspanSeekLT(key)
|
||||
|
||||
// We need to seek the keyspan iterator too. If the keyspan iterator was
|
||||
// already positioned at a span, we might be able to avoid the seek if the
|
||||
// seek key falls within the existing span's bounds.
|
||||
if i.span != nil && i.cmp(key, i.span.Start) > 0 && i.cmp(key, i.span.End) < 0 {
|
||||
// We're seeking within the existing span's bounds. We still might need
|
||||
// truncate the span to the iterator's bounds.
|
||||
i.checkBackwardBound()
|
||||
// The span's start key is still not guaranteed to be less than key,
|
||||
// because of the bounds enforcement. Consider the following example:
|
||||
//
|
||||
// Bounds are set to [d,e). The user performs a SeekLT(d). The
|
||||
// FragmentIterator.SeekLT lands on a span [b,f). This span has a start
|
||||
// key less than d, as expected. Above, checkBackwardBound truncates the
|
||||
// span to match the iterator's current bounds, modifying the span to
|
||||
// [d,e), which does not overlap the search space of [-∞, d).
|
||||
//
|
||||
// This problem is a consequence of the SeekLT's exclusive search key
|
||||
// and the fact that we don't perform bounds truncation at every leaf
|
||||
// iterator.
|
||||
if i.span != nil && i.truncated && i.cmp(i.truncatedSpan.Start, key) >= 0 {
|
||||
i.span = nil
|
||||
}
|
||||
i.savedKeyspan()
|
||||
} else {
|
||||
i.keyspanSeekLT(key)
|
||||
}
|
||||
|
||||
i.dir = -1
|
||||
return i.interleaveBackward()
|
||||
}
|
||||
|
||||
// First implements (base.InternalIterator).First.
|
||||
func (i *InterleavingIter) First() (*base.InternalKey, []byte) {
|
||||
i.maybeUpdateMask(false /* covered */)
|
||||
func (i *InterleavingIter) First() (*base.InternalKey, base.LazyValue) {
|
||||
i.clearMask()
|
||||
i.disablePrefixMode()
|
||||
i.pointKey, i.pointVal = i.pointIter.First()
|
||||
i.pointKeyInterleaved = false
|
||||
i.span = i.keyspanIter.First()
|
||||
i.checkForwardBound()
|
||||
i.checkForwardBound(nil /* prefix */)
|
||||
i.savedKeyspan()
|
||||
i.dir = +1
|
||||
return i.interleaveForward(i.lower)
|
||||
return i.interleaveForward(i.lower, nil /* prefix */)
|
||||
}
|
||||
|
||||
// Last implements (base.InternalIterator).Last.
|
||||
func (i *InterleavingIter) Last() (*base.InternalKey, []byte) {
|
||||
i.maybeUpdateMask(false /* covered */)
|
||||
func (i *InterleavingIter) Last() (*base.InternalKey, base.LazyValue) {
|
||||
i.clearMask()
|
||||
i.disablePrefixMode()
|
||||
i.pointKey, i.pointVal = i.pointIter.Last()
|
||||
i.pointKeyInterleaved = false
|
||||
i.span = i.keyspanIter.Last()
|
||||
@@ -331,11 +401,18 @@ func (i *InterleavingIter) Last() (*base.InternalKey, []byte) {
|
||||
}
|
||||
|
||||
// Next implements (base.InternalIterator).Next.
|
||||
func (i *InterleavingIter) Next() (*base.InternalKey, []byte) {
|
||||
func (i *InterleavingIter) Next() (*base.InternalKey, base.LazyValue) {
|
||||
if i.dir == -1 {
|
||||
// Switching directions.
|
||||
i.dir = +1
|
||||
|
||||
if i.mask != nil {
|
||||
// Clear the mask while we reposition the point iterator. While
|
||||
// switching directions, we may move the point iterator outside of
|
||||
// i.span's bounds.
|
||||
i.clearMask()
|
||||
}
|
||||
|
||||
// The existing point key (denoted below with *) is either the last
|
||||
// key we returned (the current iterator position):
|
||||
// points: x (y*) z
|
||||
@@ -358,7 +435,7 @@ func (i *InterleavingIter) Next() (*base.InternalKey, []byte) {
|
||||
// There was no span in the reverse direction, but there may be
|
||||
// a span in the forward direction.
|
||||
i.span = i.keyspanIter.Next()
|
||||
i.checkForwardBound()
|
||||
i.checkForwardBound(nil /* prefix */)
|
||||
i.savedKeyspan()
|
||||
} else {
|
||||
// Regardless of the current iterator state, we mark any existing
|
||||
@@ -396,18 +473,25 @@ func (i *InterleavingIter) Next() (*base.InternalKey, []byte) {
|
||||
if i.keyspanInterleaved && i.pointKey != nil && i.span != nil &&
|
||||
i.cmp(i.pointKey.UserKey, i.span.End) >= 0 {
|
||||
i.span = i.keyspanIter.Next()
|
||||
i.checkForwardBound()
|
||||
i.checkForwardBound(nil /* prefix */)
|
||||
i.savedKeyspan()
|
||||
}
|
||||
return i.interleaveForward(i.lower)
|
||||
return i.interleaveForward(i.lower, nil /* prefix */)
|
||||
}
|
||||
|
||||
// Prev implements (base.InternalIterator).Prev.
|
||||
func (i *InterleavingIter) Prev() (*base.InternalKey, []byte) {
|
||||
func (i *InterleavingIter) Prev() (*base.InternalKey, base.LazyValue) {
|
||||
if i.dir == +1 {
|
||||
// Switching directions.
|
||||
i.dir = -1
|
||||
|
||||
if i.mask != nil {
|
||||
// Clear the mask while we reposition the point iterator. While
|
||||
// switching directions, we may move the point iterator outside of
|
||||
// i.span's bounds.
|
||||
i.clearMask()
|
||||
}
|
||||
|
||||
if i.keyspanInterleaved {
|
||||
// The current span's start key has already been interleaved in the
|
||||
// forward direction. The start key may have been interleaved a
|
||||
@@ -490,7 +574,9 @@ func (i *InterleavingIter) Prev() (*base.InternalKey, []byte) {
|
||||
return i.interleaveBackward()
|
||||
}
|
||||
|
||||
func (i *InterleavingIter) interleaveForward(lowerBound []byte) (*base.InternalKey, []byte) {
|
||||
func (i *InterleavingIter) interleaveForward(
|
||||
lowerBound []byte, prefix []byte,
|
||||
) (*base.InternalKey, base.LazyValue) {
|
||||
// This loop determines whether a point key or a span marker key should be
|
||||
// interleaved on each iteration. If masking is disabled and the span is
|
||||
// nonempty, this loop executes for exactly one iteration. If masking is
|
||||
@@ -536,7 +622,7 @@ func (i *InterleavingIter) interleaveForward(lowerBound []byte) (*base.InternalK
|
||||
// advancing past the current point key.
|
||||
if i.keyspanInterleaved {
|
||||
i.span = i.keyspanIter.Next()
|
||||
i.checkForwardBound()
|
||||
i.checkForwardBound(prefix)
|
||||
i.savedKeyspan()
|
||||
if i.span == nil {
|
||||
return i.yieldNil()
|
||||
@@ -558,7 +644,7 @@ func (i *InterleavingIter) interleaveForward(lowerBound []byte) (*base.InternalK
|
||||
// keyspanInterleaved would likely trip up the invariant check
|
||||
// above.
|
||||
i.span = i.keyspanIter.Next()
|
||||
i.checkForwardBound()
|
||||
i.checkForwardBound(prefix)
|
||||
i.savedKeyspan()
|
||||
} else {
|
||||
i.keyspanInterleaved = true
|
||||
@@ -600,7 +686,7 @@ func (i *InterleavingIter) interleaveForward(lowerBound []byte) (*base.InternalK
|
||||
// reestablish it before the next iteration.
|
||||
if i.pointKey != nil && i.cmp(i.pointKey.UserKey, i.span.End) >= 0 {
|
||||
i.span = i.keyspanIter.Next()
|
||||
i.checkForwardBound()
|
||||
i.checkForwardBound(prefix)
|
||||
i.savedKeyspan()
|
||||
}
|
||||
continue
|
||||
@@ -614,7 +700,7 @@ func (i *InterleavingIter) interleaveForward(lowerBound []byte) (*base.InternalK
|
||||
}
|
||||
}
|
||||
|
||||
func (i *InterleavingIter) interleaveBackward() (*base.InternalKey, []byte) {
|
||||
func (i *InterleavingIter) interleaveBackward() (*base.InternalKey, base.LazyValue) {
|
||||
// This loop determines whether a point key or a span's start key should be
|
||||
// interleaved on each iteration. If masking is disabled and the span is
|
||||
// nonempty, this loop executes for exactly one iteration. If masking is
|
||||
@@ -697,7 +783,7 @@ func (i *InterleavingIter) interleaveBackward() (*base.InternalKey, []byte) {
|
||||
// keyspanSeekGE seeks the keyspan iterator to the first span covering k ≥ key.
|
||||
// Note that this differs from the FragmentIterator.SeekGE semantics, which
|
||||
// seek to the first span with a start key ≥ key.
|
||||
func (i *InterleavingIter) keyspanSeekGE(key []byte) {
|
||||
func (i *InterleavingIter) keyspanSeekGE(key []byte, prefix []byte) {
|
||||
// Seek using SeekLT to look for a span that starts before key, with an end
|
||||
// boundary extending beyond key.
|
||||
i.span = i.keyspanIter.SeekLT(key)
|
||||
@@ -706,7 +792,7 @@ func (i *InterleavingIter) keyspanSeekGE(key []byte) {
|
||||
// found ends before key. Next to the first key with a start ≥ key.
|
||||
i.span = i.keyspanIter.Next()
|
||||
}
|
||||
i.checkForwardBound()
|
||||
i.checkForwardBound(prefix)
|
||||
i.savedKeyspan()
|
||||
}
|
||||
|
||||
@@ -733,7 +819,7 @@ func (i *InterleavingIter) keyspanSeekLT(key []byte) {
|
||||
i.savedKeyspan()
|
||||
}
|
||||
|
||||
func (i *InterleavingIter) checkForwardBound() {
|
||||
func (i *InterleavingIter) checkForwardBound(prefix []byte) {
|
||||
i.truncated = false
|
||||
i.truncatedSpan = Span{}
|
||||
if i.span == nil {
|
||||
@@ -765,7 +851,23 @@ func (i *InterleavingIter) checkForwardBound() {
|
||||
}
|
||||
i.truncatedSpan.End = i.upper
|
||||
}
|
||||
if i.truncated && i.cmp(i.truncatedSpan.Start, i.truncatedSpan.End) == 0 {
|
||||
// If this is a part of a SeekPrefixGE call, we may also need to truncate to
|
||||
// the prefix's bounds.
|
||||
if prefix != nil {
|
||||
if !i.truncated {
|
||||
i.truncated = true
|
||||
i.truncatedSpan = *i.span
|
||||
}
|
||||
if i.cmp(prefix, i.truncatedSpan.Start) > 0 {
|
||||
i.truncatedSpan.Start = prefix
|
||||
}
|
||||
i.nextPrefixBuf = i.comparer.ImmediateSuccessor(i.nextPrefixBuf[:0], prefix)
|
||||
if i.truncated && i.cmp(i.nextPrefixBuf, i.truncatedSpan.End) < 0 {
|
||||
i.truncatedSpan.End = i.nextPrefixBuf
|
||||
}
|
||||
}
|
||||
|
||||
if i.truncated && i.comparer.Equal(i.truncatedSpan.Start, i.truncatedSpan.End) {
|
||||
i.span = nil
|
||||
}
|
||||
}
|
||||
@@ -802,25 +904,27 @@ func (i *InterleavingIter) checkBackwardBound() {
|
||||
}
|
||||
i.truncatedSpan.End = i.upper
|
||||
}
|
||||
if i.truncated && i.cmp(i.truncatedSpan.Start, i.truncatedSpan.End) == 0 {
|
||||
if i.truncated && i.comparer.Equal(i.truncatedSpan.Start, i.truncatedSpan.End) {
|
||||
i.span = nil
|
||||
}
|
||||
}
|
||||
|
||||
func (i *InterleavingIter) yieldNil() (*base.InternalKey, []byte) {
|
||||
func (i *InterleavingIter) yieldNil() (*base.InternalKey, base.LazyValue) {
|
||||
i.spanCoversKey = false
|
||||
i.maybeUpdateMask(false /* covered */)
|
||||
return i.verify(nil, nil)
|
||||
i.clearMask()
|
||||
return i.verify(nil, base.LazyValue{})
|
||||
}
|
||||
|
||||
func (i *InterleavingIter) yieldPointKey(covered bool) (*base.InternalKey, []byte) {
|
||||
func (i *InterleavingIter) yieldPointKey(covered bool) (*base.InternalKey, base.LazyValue) {
|
||||
i.pointKeyInterleaved = true
|
||||
i.spanCoversKey = covered
|
||||
i.maybeUpdateMask(covered)
|
||||
return i.verify(i.pointKey, i.pointVal)
|
||||
}
|
||||
|
||||
func (i *InterleavingIter) yieldSyntheticSpanMarker(lowerBound []byte) (*base.InternalKey, []byte) {
|
||||
func (i *InterleavingIter) yieldSyntheticSpanMarker(
|
||||
lowerBound []byte,
|
||||
) (*base.InternalKey, base.LazyValue) {
|
||||
i.spanMarker.UserKey = i.startKey()
|
||||
i.spanMarker.Trailer = base.MakeTrailer(base.InternalKeySeqNumMax, i.span.Keys[0].Kind())
|
||||
i.keyspanInterleaved = true
|
||||
@@ -836,7 +940,7 @@ func (i *InterleavingIter) yieldSyntheticSpanMarker(lowerBound []byte) (*base.In
|
||||
// bound for truncating a span. The span a-z will be truncated to [k,
|
||||
// z). If i.upper == k, we'd mistakenly try to return a span [k, k), an
|
||||
// invariant violation.
|
||||
if i.cmp(lowerBound, i.upper) == 0 {
|
||||
if i.comparer.Equal(lowerBound, i.upper) {
|
||||
return i.yieldNil()
|
||||
}
|
||||
|
||||
@@ -856,10 +960,21 @@ func (i *InterleavingIter) yieldSyntheticSpanMarker(lowerBound []byte) (*base.In
|
||||
i.spanMarkerTruncated = true
|
||||
}
|
||||
i.maybeUpdateMask(true /* covered */)
|
||||
return i.verify(&i.spanMarker, nil)
|
||||
return i.verify(&i.spanMarker, base.LazyValue{})
|
||||
}
|
||||
|
||||
func (i *InterleavingIter) verify(k *base.InternalKey, v []byte) (*base.InternalKey, []byte) {
|
||||
func (i *InterleavingIter) disablePrefixMode() {
|
||||
if i.prefix {
|
||||
i.prefix = false
|
||||
// Clear the existing span. It may not hold the true end bound of the
|
||||
// underlying span.
|
||||
i.span = nil
|
||||
}
|
||||
}
|
||||
|
||||
func (i *InterleavingIter) verify(
|
||||
k *base.InternalKey, v base.LazyValue,
|
||||
) (*base.InternalKey, base.LazyValue) {
|
||||
// Wrap the entire function body in the invariants build tag, so that
|
||||
// production builds elide this entire function.
|
||||
if invariants.Enabled {
|
||||
@@ -893,38 +1008,32 @@ func (i *InterleavingIter) verify(k *base.InternalKey, v []byte) (*base.Internal
|
||||
func (i *InterleavingIter) savedKeyspan() {
|
||||
i.keyspanInterleaved = false
|
||||
i.spanMarkerTruncated = false
|
||||
if i.maskState == maskCurrent {
|
||||
// There's a span set as current. If the keyspan iterator was
|
||||
// exhausted or moved to an empty keyspan, the current mask will need to be
|
||||
// cleared. If the keyspan iterator was moved to a new keyspan, then we'll need
|
||||
// to set the new mask once we step into the new keyspan's bounds.
|
||||
//
|
||||
// Either way, we need to reset to to `maskStale`.
|
||||
i.maskState = maskStale
|
||||
}
|
||||
i.maskSpanChangedCalled = false
|
||||
}
|
||||
|
||||
// maybeUpdateMask updates the current mask, if a mask is configured and
|
||||
// the mask hasn't been updated with the current keyspan yet.
|
||||
func (i *InterleavingIter) maybeUpdateMask(covered bool) {
|
||||
if i.mask == nil {
|
||||
return
|
||||
if i.mask != nil {
|
||||
if !covered || i.span.Empty() {
|
||||
i.clearMask()
|
||||
} else if !i.maskSpanChangedCalled {
|
||||
if i.truncated {
|
||||
i.mask.SpanChanged(&i.truncatedSpan)
|
||||
} else {
|
||||
i.mask.SpanChanged(i.span)
|
||||
}
|
||||
i.maskSpanChangedCalled = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Although covered=true, the covering span might be empty. Empty span's
|
||||
// don't mask.
|
||||
covered = covered && !i.span.Empty()
|
||||
|
||||
if covered && i.maskState != maskCurrent {
|
||||
// We're currently positioned within the bounds of i.span, and we
|
||||
// haven't updated the mask to this span yet. Update it now.
|
||||
i.mask.SpanChanged(i.span)
|
||||
i.maskState = maskCurrent
|
||||
} else if !covered && i.maskState != maskCleared {
|
||||
// We're not positioned beneath i.span, so we shouldn't set the mask to
|
||||
// i.span. However, we've never cleared the previous mask.
|
||||
// clearMask clears the current mask, if a mask is configured and no mask should
|
||||
// be active.
|
||||
func (i *InterleavingIter) clearMask() {
|
||||
if i.mask != nil {
|
||||
i.maskSpanChangedCalled = false
|
||||
i.mask.SpanChanged(nil)
|
||||
i.maskState = maskCleared
|
||||
}
|
||||
}
|
||||
|
||||
@@ -955,6 +1064,16 @@ func (i *InterleavingIter) Span() *Span {
|
||||
func (i *InterleavingIter) SetBounds(lower, upper []byte) {
|
||||
i.lower, i.upper = lower, upper
|
||||
i.pointIter.SetBounds(lower, upper)
|
||||
i.Invalidate()
|
||||
}
|
||||
|
||||
// Invalidate invalidates the interleaving iterator's current position, clearing
|
||||
// its state. This prevents optimizations such as reusing the current span on
|
||||
// seek.
|
||||
func (i *InterleavingIter) Invalidate() {
|
||||
i.span = nil
|
||||
i.pointKey = nil
|
||||
i.pointVal = base.LazyValue{}
|
||||
}
|
||||
|
||||
// Error implements (base.InternalIterator).Error.
|
||||
@@ -974,18 +1093,6 @@ func (i *InterleavingIter) String() string {
|
||||
return fmt.Sprintf("keyspan-interleaving(%q)", i.pointIter.String())
|
||||
}
|
||||
|
||||
var _ base.InternalIteratorWithStats = &InterleavingIter{}
|
||||
|
||||
// Stats implements InternalIteratorWithStats.
|
||||
func (i *InterleavingIter) Stats() base.InternalIteratorStats {
|
||||
return i.pointIter.Stats()
|
||||
}
|
||||
|
||||
// ResetStats implements InternalIteratorWithStats.
|
||||
func (i *InterleavingIter) ResetStats() {
|
||||
i.pointIter.ResetStats()
|
||||
}
|
||||
|
||||
func firstError(err0, err1 error) error {
|
||||
if err0 != nil {
|
||||
return err0
|
||||
|
||||
22
vendor/github.com/cockroachdb/pebble/internal/keyspan/internal_iter_shim.go
generated
vendored
22
vendor/github.com/cockroachdb/pebble/internal/keyspan/internal_iter_shim.go
generated
vendored
@@ -38,57 +38,57 @@ func (i *InternalIteratorShim) Span() *Span {
|
||||
// SeekGE implements (base.InternalIterator).SeekGE.
|
||||
func (i *InternalIteratorShim) SeekGE(
|
||||
key []byte, flags base.SeekGEFlags,
|
||||
) (*base.InternalKey, []byte) {
|
||||
) (*base.InternalKey, base.LazyValue) {
|
||||
panic("unimplemented")
|
||||
}
|
||||
|
||||
// SeekPrefixGE implements (base.InternalIterator).SeekPrefixGE.
|
||||
func (i *InternalIteratorShim) SeekPrefixGE(
|
||||
prefix, key []byte, flags base.SeekGEFlags,
|
||||
) (*base.InternalKey, []byte) {
|
||||
) (*base.InternalKey, base.LazyValue) {
|
||||
panic("unimplemented")
|
||||
}
|
||||
|
||||
// SeekLT implements (base.InternalIterator).SeekLT.
|
||||
func (i *InternalIteratorShim) SeekLT(
|
||||
key []byte, flags base.SeekLTFlags,
|
||||
) (*base.InternalKey, []byte) {
|
||||
) (*base.InternalKey, base.LazyValue) {
|
||||
panic("unimplemented")
|
||||
}
|
||||
|
||||
// First implements (base.InternalIterator).First.
|
||||
func (i *InternalIteratorShim) First() (*base.InternalKey, []byte) {
|
||||
func (i *InternalIteratorShim) First() (*base.InternalKey, base.LazyValue) {
|
||||
i.span = i.miter.First()
|
||||
for i.span != nil && i.span.Empty() {
|
||||
i.span = i.miter.Next()
|
||||
}
|
||||
if i.span == nil {
|
||||
return nil, nil
|
||||
return nil, base.LazyValue{}
|
||||
}
|
||||
i.iterKey = base.InternalKey{UserKey: i.span.Start, Trailer: i.span.Keys[0].Trailer}
|
||||
return &i.iterKey, i.span.End
|
||||
return &i.iterKey, base.MakeInPlaceValue(i.span.End)
|
||||
}
|
||||
|
||||
// Last implements (base.InternalIterator).Last.
|
||||
func (i *InternalIteratorShim) Last() (*base.InternalKey, []byte) {
|
||||
func (i *InternalIteratorShim) Last() (*base.InternalKey, base.LazyValue) {
|
||||
panic("unimplemented")
|
||||
}
|
||||
|
||||
// Next implements (base.InternalIterator).Next.
|
||||
func (i *InternalIteratorShim) Next() (*base.InternalKey, []byte) {
|
||||
func (i *InternalIteratorShim) Next() (*base.InternalKey, base.LazyValue) {
|
||||
i.span = i.miter.Next()
|
||||
for i.span != nil && i.span.Empty() {
|
||||
i.span = i.miter.Next()
|
||||
}
|
||||
if i.span == nil {
|
||||
return nil, nil
|
||||
return nil, base.LazyValue{}
|
||||
}
|
||||
i.iterKey = base.InternalKey{UserKey: i.span.Start, Trailer: i.span.Keys[0].Trailer}
|
||||
return &i.iterKey, i.span.End
|
||||
return &i.iterKey, base.MakeInPlaceValue(i.span.End)
|
||||
}
|
||||
|
||||
// Prev implements (base.InternalIterator).Prev.
|
||||
func (i *InternalIteratorShim) Prev() (*base.InternalKey, []byte) {
|
||||
func (i *InternalIteratorShim) Prev() (*base.InternalKey, base.LazyValue) {
|
||||
panic("unimplemented")
|
||||
}
|
||||
|
||||
|
||||
31
vendor/github.com/cockroachdb/pebble/internal/keyspan/merging_iter.go
generated
vendored
31
vendor/github.com/cockroachdb/pebble/internal/keyspan/merging_iter.go
generated
vendored
@@ -52,7 +52,11 @@ func visibleTransform(snapshot uint64) Transformer {
|
||||
dst.Start, dst.End = s.Start, s.End
|
||||
dst.Keys = dst.Keys[:0]
|
||||
for _, k := range s.Keys {
|
||||
if base.Visible(k.SeqNum(), snapshot) {
|
||||
// NB: The InternalKeySeqNumMax value is used for the batch snapshot
|
||||
// because a batch's visible span keys are filtered when they're
|
||||
// fragmented. There's no requirement to enforce visibility at
|
||||
// iteration time.
|
||||
if base.Visible(k.SeqNum(), snapshot, base.InternalKeySeqNumMax) {
|
||||
dst.Keys = append(dst.Keys, k)
|
||||
}
|
||||
}
|
||||
@@ -68,6 +72,10 @@ func visibleTransform(snapshot uint64) Transformer {
|
||||
// overlapping keys are surfaced in a single Span. Key spans from one child
|
||||
// iterator may overlap key spans from another child iterator arbitrarily.
|
||||
//
|
||||
// The spans combined by MergingIter will return spans with keys sorted by
|
||||
// trailer descending. If the MergingIter is configured with a Transformer, it's
|
||||
// permitted to modify the ordering of the spans' keys returned by MergingIter.
|
||||
//
|
||||
// Algorithm
|
||||
//
|
||||
// The merging iterator wraps child iterators, merging and fragmenting spans
|
||||
@@ -210,9 +218,9 @@ type MergingIter struct {
|
||||
// buf is a buffer used to save [start, end) boundary keys.
|
||||
buf []byte
|
||||
// keys holds all of the keys across all levels that overlap the key span
|
||||
// [start, end), sorted by sequence number and kind descending. This slice
|
||||
// is reconstituted in synthesizeKeys from each mergingIterLevel's keys
|
||||
// every time the [start, end) bounds change.
|
||||
// [start, end), sorted by Trailer descending. This slice is reconstituted
|
||||
// in synthesizeKeys from each mergingIterLevel's keys every time the
|
||||
// [start, end) bounds change.
|
||||
//
|
||||
// Each element points into a child iterator's memory, so the keys may not
|
||||
// be directly modified.
|
||||
@@ -809,15 +817,22 @@ func (m *MergingIter) synthesizeKeys(dir int8) (bool, *Span) {
|
||||
found = true
|
||||
}
|
||||
}
|
||||
// TODO(jackson): We should be able to remove this sort and instead
|
||||
// guarantee that we'll return keys in the order of the levels they're from.
|
||||
// With careful iterator construction, this would guarantee that they're
|
||||
// sorted by trailer descending for the range key iteration use case.
|
||||
sort.Sort(&m.keys)
|
||||
|
||||
// Apply the configured transform. See visibleTransform.
|
||||
s := Span{
|
||||
Start: m.start,
|
||||
End: m.end,
|
||||
Keys: m.keys,
|
||||
Start: m.start,
|
||||
End: m.end,
|
||||
Keys: m.keys,
|
||||
KeysOrder: ByTrailerDesc,
|
||||
}
|
||||
if err := m.transformer.Transform(m.cmp, s, &m.span); err != nil {
|
||||
// NB: m.heap.cmp is a base.Compare, whereas m.cmp is a method on
|
||||
// MergingIter.
|
||||
if err := m.transformer.Transform(m.heap.cmp, s, &m.span); err != nil {
|
||||
m.err = err
|
||||
return false, nil
|
||||
}
|
||||
|
||||
90
vendor/github.com/cockroachdb/pebble/internal/keyspan/span.go
generated
vendored
90
vendor/github.com/cockroachdb/pebble/internal/keyspan/span.go
generated
vendored
@@ -31,16 +31,30 @@ type Span struct {
|
||||
// non-nil, or both nil if representing an invalid Span.
|
||||
Start, End []byte
|
||||
// Keys holds the set of keys applied over the [Start, End) user key range.
|
||||
// Keys is sorted by (SeqNum, Kind) descending. If SeqNum and Kind are
|
||||
// equal, the order of Keys is undefined. Keys may be empty, even if Start
|
||||
// and End are non-nil.
|
||||
// Keys is sorted by (SeqNum, Kind) descending, unless otherwise specified
|
||||
// by the context. If SeqNum and Kind are equal, the order of Keys is
|
||||
// undefined. Keys may be empty, even if Start and End are non-nil.
|
||||
//
|
||||
// Keys are a decoded representation of the internal keys stored in batches
|
||||
// or sstable blocks. A single internal key in a range key block may produce
|
||||
// several decoded Keys.
|
||||
Keys []Key
|
||||
Keys []Key
|
||||
KeysOrder KeysOrder
|
||||
}
|
||||
|
||||
// KeysOrder describes the ordering of Keys within a Span.
|
||||
type KeysOrder int8
|
||||
|
||||
const (
|
||||
// ByTrailerDesc indicates a Span's keys are sorted by Trailer descending.
|
||||
// This is the default ordering, and the ordering used during physical
|
||||
// storage.
|
||||
ByTrailerDesc KeysOrder = iota
|
||||
// BySuffixAsc indicates a Span's keys are sorted by Suffix ascending. This
|
||||
// ordering is used during user iteration of range keys.
|
||||
BySuffixAsc
|
||||
)
|
||||
|
||||
// Key represents a single key applied over a span of user keys. A Key is
|
||||
// contained by a Span which specifies the span of user keys over which the Key
|
||||
// is applied.
|
||||
@@ -69,9 +83,9 @@ func (k Key) Kind() base.InternalKeyKind {
|
||||
// Equal returns true if this Key is equal to the given key. Two keys are said
|
||||
// to be equal if the two Keys have equal trailers, suffix and value. Suffix
|
||||
// comparison uses the provided base.Compare func. Value comparison is bytewise.
|
||||
func (k Key) Equal(cmp base.Compare, b Key) bool {
|
||||
func (k Key) Equal(equal base.Equal, b Key) bool {
|
||||
return k.Trailer == b.Trailer &&
|
||||
cmp(k.Suffix, b.Suffix) == 0 &&
|
||||
equal(k.Suffix, b.Suffix) &&
|
||||
bytes.Equal(k.Value, b.Value)
|
||||
}
|
||||
|
||||
@@ -90,10 +104,13 @@ func (s *Span) Empty() bool {
|
||||
}
|
||||
|
||||
// SmallestKey returns the smallest internal key defined by the span's keys.
|
||||
// It panics if the span contains no keys.
|
||||
// It requires the Span's keys be in ByTrailerDesc order. It panics if the span
|
||||
// contains no keys or its keys are sorted in a different order.
|
||||
func (s *Span) SmallestKey() base.InternalKey {
|
||||
if len(s.Keys) == 0 {
|
||||
panic("pebble: Span contains no keys")
|
||||
} else if s.KeysOrder != ByTrailerDesc {
|
||||
panic("pebble: span's keys unexpectedly not in trailer order")
|
||||
}
|
||||
// The first key has the highest (sequence number,kind) tuple.
|
||||
return base.InternalKey{
|
||||
@@ -108,10 +125,13 @@ func (s *Span) SmallestKey() base.InternalKey {
|
||||
// with the maximal sequence number, ensuring all InternalKeys with the same
|
||||
// user key sort after the sentinel key.
|
||||
//
|
||||
// It panics if the span contains no keys.
|
||||
// It requires the Span's keys be in ByTrailerDesc order. It panics if the span
|
||||
// contains no keys or its keys are sorted in a different order.
|
||||
func (s *Span) LargestKey() base.InternalKey {
|
||||
if len(s.Keys) == 0 {
|
||||
panic("pebble: Span contains no keys")
|
||||
} else if s.KeysOrder != ByTrailerDesc {
|
||||
panic("pebble: span's keys unexpectedly not in trailer order")
|
||||
}
|
||||
// The last key has the lowest (sequence number,kind) tuple.
|
||||
kind := s.Keys[len(s.Keys)-1].Kind()
|
||||
@@ -119,19 +139,26 @@ func (s *Span) LargestKey() base.InternalKey {
|
||||
}
|
||||
|
||||
// SmallestSeqNum returns the smallest sequence number of a key contained within
|
||||
// the span. It panics if the span contains no keys.
|
||||
// the span. It requires the Span's keys be in ByTrailerDesc order. It panics if
|
||||
// the span contains no keys or its keys are sorted in a different order.
|
||||
func (s *Span) SmallestSeqNum() uint64 {
|
||||
if len(s.Keys) == 0 {
|
||||
panic("pebble: Span contains no keys")
|
||||
} else if s.KeysOrder != ByTrailerDesc {
|
||||
panic("pebble: span's keys unexpectedly not in trailer order")
|
||||
}
|
||||
|
||||
return s.Keys[len(s.Keys)-1].SeqNum()
|
||||
}
|
||||
|
||||
// LargestSeqNum returns the largest sequence number of a key contained within
|
||||
// the span. It panics if the span contains no keys.
|
||||
// the span. It requires the Span's keys be in ByTrailerDesc order. It panics if
|
||||
// the span contains no keys or its keys are sorted in a different order.
|
||||
func (s *Span) LargestSeqNum() uint64 {
|
||||
if len(s.Keys) == 0 {
|
||||
panic("pebble: Span contains no keys")
|
||||
} else if s.KeysOrder != ByTrailerDesc {
|
||||
panic("pebble: span's keys unexpectedly not in trailer order")
|
||||
}
|
||||
return s.Keys[0].SeqNum()
|
||||
}
|
||||
@@ -140,11 +167,16 @@ func (s *Span) LargestSeqNum() uint64 {
|
||||
// that avoid the need to construct a new Span.
|
||||
|
||||
// Visible returns a span with the subset of keys visible at the provided
|
||||
// sequence number.
|
||||
// sequence number. It requires the Span's keys be in ByTrailerDesc order. It
|
||||
// panics if the span's keys are sorted in a different order.
|
||||
//
|
||||
// Visible may incur an allocation, so callers should prefer targeted,
|
||||
// non-allocating methods when possible.
|
||||
func (s Span) Visible(snapshot uint64) Span {
|
||||
if s.KeysOrder != ByTrailerDesc {
|
||||
panic("pebble: span's keys unexpectedly not in trailer order")
|
||||
}
|
||||
|
||||
ret := Span{Start: s.Start, End: s.End}
|
||||
if len(s.Keys) == 0 {
|
||||
return ret
|
||||
@@ -214,7 +246,13 @@ func (s Span) Visible(snapshot uint64) Span {
|
||||
// VisibleAt returns true if the span contains a key visible at the provided
|
||||
// snapshot. Keys with sequence numbers with the batch bit set are treated as
|
||||
// always visible.
|
||||
//
|
||||
// VisibleAt requires the Span's keys be in ByTrailerDesc order. It panics if
|
||||
// the span's keys are sorted in a different order.
|
||||
func (s *Span) VisibleAt(snapshot uint64) bool {
|
||||
if s.KeysOrder != ByTrailerDesc {
|
||||
panic("pebble: span's keys unexpectedly not in trailer order")
|
||||
}
|
||||
if len(s.Keys) == 0 {
|
||||
return false
|
||||
} else if first := s.Keys[0].SeqNum(); first&base.InternalKeySeqNumBatch != 0 {
|
||||
@@ -235,9 +273,10 @@ func (s *Span) VisibleAt(snapshot uint64) bool {
|
||||
// None of the key byte slices are cloned (see Span.DeepClone).
|
||||
func (s *Span) ShallowClone() Span {
|
||||
c := Span{
|
||||
Start: s.Start,
|
||||
End: s.End,
|
||||
Keys: make([]Key, len(s.Keys)),
|
||||
Start: s.Start,
|
||||
End: s.End,
|
||||
Keys: make([]Key, len(s.Keys)),
|
||||
KeysOrder: s.KeysOrder,
|
||||
}
|
||||
copy(c.Keys, s.Keys)
|
||||
return c
|
||||
@@ -248,9 +287,10 @@ func (s *Span) ShallowClone() Span {
|
||||
// because it is allocation heavy.
|
||||
func (s *Span) DeepClone() Span {
|
||||
c := Span{
|
||||
Start: make([]byte, len(s.Start)),
|
||||
End: make([]byte, len(s.End)),
|
||||
Keys: make([]Key, len(s.Keys)),
|
||||
Start: make([]byte, len(s.Start)),
|
||||
End: make([]byte, len(s.End)),
|
||||
Keys: make([]Key, len(s.Keys)),
|
||||
KeysOrder: s.KeysOrder,
|
||||
}
|
||||
copy(c.Start, s.Start)
|
||||
copy(c.End, s.End)
|
||||
@@ -274,7 +314,13 @@ func (s *Span) Contains(cmp base.Compare, key []byte) bool {
|
||||
}
|
||||
|
||||
// Covers returns true if the span covers keys at seqNum.
|
||||
//
|
||||
// Covers requires the Span's keys be in ByTrailerDesc order. It panics if the
|
||||
// span's keys are sorted in a different order.
|
||||
func (s Span) Covers(seqNum uint64) bool {
|
||||
if s.KeysOrder != ByTrailerDesc {
|
||||
panic("pebble: span's keys unexpectedly not in trailer order")
|
||||
}
|
||||
return !s.Empty() && s.Keys[0].SeqNum() > seqNum
|
||||
}
|
||||
|
||||
@@ -284,7 +330,13 @@ func (s Span) Covers(seqNum uint64) bool {
|
||||
//
|
||||
// Keys with sequence numbers with the batch bit set are treated as always
|
||||
// visible.
|
||||
//
|
||||
// CoversAt requires the Span's keys be in ByTrailerDesc order. It panics if the
|
||||
// span's keys are sorted in a different order.
|
||||
func (s *Span) CoversAt(snapshot, seqNum uint64) bool {
|
||||
if s.KeysOrder != ByTrailerDesc {
|
||||
panic("pebble: span's keys unexpectedly not in trailer order")
|
||||
}
|
||||
// NB: A key is visible at `snapshot` if its sequence number is strictly
|
||||
// less than `snapshot`. See base.Visible.
|
||||
for i := range s.Keys {
|
||||
@@ -336,8 +388,8 @@ func (s prettySpan) Format(fs fmt.State, c rune) {
|
||||
fmt.Fprintf(fs, "}")
|
||||
}
|
||||
|
||||
// SortKeys sorts a keys slice by trailer.
|
||||
func SortKeys(keys *[]Key) {
|
||||
// SortKeysByTrailer sorts a keys slice by trailer.
|
||||
func SortKeysByTrailer(keys *[]Key) {
|
||||
// NB: keys is a pointer to a slice instead of a slice to avoid `sorted`
|
||||
// escaping to the heap.
|
||||
sorted := (*keysBySeqNumKind)(keys)
|
||||
|
||||
Reference in New Issue
Block a user