Upgrade versions of vendored libs

This commit is contained in:
eleksir
2022-11-04 16:29:14 +03:00
parent fba732cc24
commit a7ae372459
941 changed files with 219674 additions and 23611 deletions

View File

@@ -11,6 +11,7 @@ import (
"github.com/cockroachdb/pebble/internal/base"
"github.com/cockroachdb/pebble/internal/invariants"
"github.com/cockroachdb/pebble/internal/manifest"
)
// TODO(jackson): Consider implementing an optimization to seek lower levels
@@ -20,27 +21,47 @@ import (
// seeks would require introducing key comparisons to switchTo{Min,Max}Heap
// where there currently are none.
// Transform defines a transform function to be applied to a Span. A Transform
// takes a Span as input and writes the transformed Span to the provided output
// *Span pointer. The output Span's Keys slice may be reused by Transform to
// reduce allocations.
type Transform func(cmp base.Compare, in Span, out *Span) error
// Transformer defines a transformation to be applied to a Span.
type Transformer interface {
// Transform takes a Span as input and writes the transformed Span to the
// provided output *Span pointer. The output Span's Keys slice may be reused
// by Transform to reduce allocations.
Transform(cmp base.Compare, in Span, out *Span) error
}
func noopTransform(_ base.Compare, s Span, dst *Span) error {
// The TransformerFunc type is an adapter to allow the use of ordinary functions
// as Transformers. If f is a function with the appropriate signature,
// TransformerFunc(f) is a Transformer that calls f.
type TransformerFunc func(base.Compare, Span, *Span) error
// Transform calls f(cmp, in, out).
func (tf TransformerFunc) Transform(cmp base.Compare, in Span, out *Span) error {
return tf(cmp, in, out)
}
var noopTransform Transformer = TransformerFunc(func(_ base.Compare, s Span, dst *Span) error {
dst.Start, dst.End = s.Start, s.End
dst.Keys = append(dst.Keys[:0], s.Keys...)
return nil
}
})
// visibleTransform filters keys that are invisible at the provided snapshot
// sequence number.
func visibleTransform(snapshot uint64) Transform {
return func(_ base.Compare, s Span, dst *Span) error {
s = s.Visible(snapshot)
func visibleTransform(snapshot uint64) Transformer {
return TransformerFunc(func(_ base.Compare, s Span, dst *Span) error {
dst.Start, dst.End = s.Start, s.End
dst.Keys = append(dst.Keys[:0], s.Keys...)
dst.Keys = dst.Keys[:0]
for _, k := range s.Keys {
// 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)
}
}
return nil
}
})
}
// MergingIter merges spans across levels of the LSM, exposing an iterator over
@@ -51,6 +72,10 @@ func visibleTransform(snapshot uint64) Transform {
// 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
@@ -193,17 +218,17 @@ 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.
keys keysBySeqNumKind
// transform defines a function to be applied to a span before it's yielded
// to the user. A transform may filter individual keys contained within the
// span.
transform Transform
// transformer defines a transformation to be applied to a span before it's
// yielded to the user. Transforming may filter individual keys contained
// within the span.
transformer Transformer
// span holds the iterator's current span. This span is used as the
// destination for transforms. Every tranformed span overwrites the
// previous.
@@ -211,6 +236,17 @@ type MergingIter struct {
err error
dir int8
// alloc preallocates mergingIterLevel and mergingIterItems for use by the
// merging iterator. As long as the merging iterator is used with
// manifest.NumLevels+3 and fewer fragment iterators, the merging iterator
// will not need to allocate upon initialization. The value NumLevels+3
// mirrors the preallocated levels in iterAlloc used for point iterators.
// Invariant: cap(levels) == cap(items)
alloc struct {
levels [manifest.NumLevels + 3]mergingIterLevel
items [manifest.NumLevels + 3]mergingIterItem
}
}
// MergingIter implements the FragmentIterator interface.
@@ -225,45 +261,82 @@ type mergingIterLevel struct {
func (l *mergingIterLevel) next() {
if l.heapKey.kind == boundKindFragmentStart {
l.heapKey = endBound(l.heapKey.span)
l.heapKey = boundKey{
kind: boundKindFragmentEnd,
key: l.heapKey.span.End,
span: l.heapKey.span,
}
return
}
l.heapKey = startBound(l.iter.Next())
if s := l.iter.Next(); s == nil {
l.heapKey = boundKey{kind: boundKindInvalid}
} else {
l.heapKey = boundKey{
kind: boundKindFragmentStart,
key: s.Start,
span: s,
}
}
}
func (l *mergingIterLevel) prev() {
if l.heapKey.kind == boundKindFragmentEnd {
l.heapKey = startBound(l.heapKey.span)
l.heapKey = boundKey{
kind: boundKindFragmentStart,
key: l.heapKey.span.Start,
span: l.heapKey.span,
}
return
}
l.heapKey = endBound(l.iter.Prev())
if s := l.iter.Prev(); s == nil {
l.heapKey = boundKey{kind: boundKindInvalid}
} else {
l.heapKey = boundKey{
kind: boundKindFragmentEnd,
key: s.End,
span: s,
}
}
}
// Init initializes the merging iterator with the provided fragment iterators.
func (m *MergingIter) Init(cmp base.Compare, transform Transform, iters ...FragmentIterator) {
func (m *MergingIter) Init(cmp base.Compare, transformer Transformer, iters ...FragmentIterator) {
levels, items := m.levels, m.heap.items
*m = MergingIter{
heap: mergingIterHeap{cmp: cmp},
transform: transform,
heap: mergingIterHeap{cmp: cmp},
transformer: transformer,
}
// Invariant: cap(levels) == cap(items)
if cap(levels) < len(iters) {
m.levels = make([]mergingIterLevel, len(iters))
m.heap.items = make([]mergingIterItem, 0, len(iters))
} else {
// Invariant: cap(levels) >= cap(items)
// Invariant: cap(alloc.levels) == cap(alloc.items)
if len(iters) <= len(m.alloc.levels) {
// The slices allocated on the MergingIter struct are large enough.
m.levels = m.alloc.levels[:len(iters)]
m.heap.items = m.alloc.items[:0]
} else if len(iters) <= cap(levels) {
// The existing heap-allocated slices are large enough, so reuse them.
m.levels = levels[:len(iters)]
m.heap.items = items[:0]
} else {
// Heap allocate new slices.
m.levels = make([]mergingIterLevel, len(iters))
m.heap.items = make([]mergingIterItem, 0, len(iters))
}
for i := range m.levels {
m.levels[i] = mergingIterLevel{}
m.levels[i].iter = iters[i]
m.levels[i] = mergingIterLevel{iter: iters[i]}
}
}
// AddLevel adds a new level to the bottom of the merging iterator. AddLevel
// must be called after Init and before any other method.
func (m *MergingIter) AddLevel(iter FragmentIterator) {
m.levels = append(m.levels, mergingIterLevel{iter: iter})
}
// SeekGE moves the iterator to the first span with a start key greater than or
// equal to key.
func (m *MergingIter) SeekGE(key []byte) Span {
func (m *MergingIter) SeekGE(key []byte) *Span {
m.invalidate() // clear state about current position
for i := range m.levels {
l := &m.levels[i]
@@ -277,24 +350,35 @@ func (m *MergingIter) SeekGE(key []byte) Span {
// Otherwise we use the start boundary of the next span which
// necessarily has a start ≥ key.
s := l.iter.SeekLT(key)
if s.Valid() && m.cmp(s.End, key) >= 0 {
if s != nil && m.cmp(s.End, key) >= 0 {
// s.End ≥ key
// We need to use this span's end bound.
l.heapKey = endBound(s)
l.heapKey = boundKey{
kind: boundKindFragmentEnd,
key: s.End,
span: s,
}
continue
}
// s.End < key
// The span `s` ends before key. Next to the first span with a Start ≥
// key, and use that.
s = l.iter.Next()
l.heapKey = startBound(s)
if s = l.iter.Next(); s == nil {
l.heapKey = boundKey{kind: boundKindInvalid}
} else {
l.heapKey = boundKey{
kind: boundKindFragmentStart,
key: s.Start,
span: s,
}
}
}
m.initMinHeap()
return m.findNextFragmentSet()
}
// SeekLT moves the iterator to the last span with a start key less than key.
func (m *MergingIter) SeekLT(key []byte) Span {
func (m *MergingIter) SeekLT(key []byte) *Span {
// TODO(jackson): Evaluate whether there's an implementation of SeekLT
// independent of SeekGE that is more efficient. It's tricky, because the
// span we should return might straddle `key` itself.
@@ -314,42 +398,56 @@ func (m *MergingIter) SeekLT(key []byte) Span {
// Start user key < key: [b,l)#1. This requires examining bounds both < 'c'
// (the 'b' of [b,m)#1's start key) and bounds ≥ 'c' (the 'l' of ([a,l)#2's
// end key).
if s := m.SeekGE(key); !s.Valid() && m.err != nil {
return Span{}
if s := m.SeekGE(key); s == nil && m.err != nil {
return nil
}
// Prev to the previous span.
return m.Prev()
}
// First seeks the iterator to the first span.
func (m *MergingIter) First() Span {
func (m *MergingIter) First() *Span {
m.invalidate() // clear state about current position
for i := range m.levels {
l := &m.levels[i]
l.heapKey = startBound(l.iter.First())
if s := m.levels[i].iter.First(); s == nil {
m.levels[i].heapKey = boundKey{kind: boundKindInvalid}
} else {
m.levels[i].heapKey = boundKey{
kind: boundKindFragmentStart,
key: s.Start,
span: s,
}
}
}
m.initMinHeap()
return m.findNextFragmentSet()
}
// Last seeks the iterator to the last span.
func (m *MergingIter) Last() Span {
func (m *MergingIter) Last() *Span {
m.invalidate() // clear state about current position
for i := range m.levels {
l := &m.levels[i]
l.heapKey = endBound(l.iter.Last())
if s := m.levels[i].iter.Last(); s == nil {
m.levels[i].heapKey = boundKey{kind: boundKindInvalid}
} else {
m.levels[i].heapKey = boundKey{
kind: boundKindFragmentEnd,
key: s.End,
span: s,
}
}
}
m.initMaxHeap()
return m.findPrevFragmentSet()
}
// Next advances the iterator to the next span.
func (m *MergingIter) Next() Span {
func (m *MergingIter) Next() *Span {
if m.err != nil {
return Span{}
return nil
}
if m.dir == +1 && (m.end == nil || m.start == nil) {
return Span{}
return nil
}
if m.dir != +1 {
m.switchToMinHeap()
@@ -358,12 +456,12 @@ func (m *MergingIter) Next() Span {
}
// Prev advances the iterator to the previous span.
func (m *MergingIter) Prev() Span {
func (m *MergingIter) Prev() *Span {
if m.err != nil {
return Span{}
return nil
}
if m.dir == -1 && (m.end == nil || m.start == nil) {
return Span{}
return nil
}
if m.dir != -1 {
m.switchToMaxHeap()
@@ -533,7 +631,7 @@ func (m *MergingIter) cmp(a, b []byte) int {
return m.heap.cmp(a, b)
}
func (m *MergingIter) findNextFragmentSet() Span {
func (m *MergingIter) findNextFragmentSet() *Span {
// Each iteration of this loop considers a new merged span between unique
// user keys. An iteration may find that there exists no overlap for a given
// span, (eg, if the spans [a,b), [d, e) exist within level iterators, the
@@ -601,16 +699,16 @@ func (m *MergingIter) findNextFragmentSet() Span {
// we elide empty spans created by the mergingIter itself that don't overlap
// with any child iterator returned spans (i.e. empty spans that bridge two
// distinct child-iterator-defined spans).
if found, s := m.synthesizeKeys(+1); found && s.Valid() {
if found, s := m.synthesizeKeys(+1); found && s != nil {
return s
}
}
// Exhausted.
m.clear()
return Span{}
return nil
}
func (m *MergingIter) findPrevFragmentSet() Span {
func (m *MergingIter) findPrevFragmentSet() *Span {
// Each iteration of this loop considers a new merged span between unique
// user keys. An iteration may find that there exists no overlap for a given
// span, (eg, if the spans [a,b), [d, e) exist within level iterators, the
@@ -677,13 +775,13 @@ func (m *MergingIter) findPrevFragmentSet() Span {
// we elide empty spans created by the mergingIter itself that don't overlap
// with any child iterator returned spans (i.e. empty spans that bridge two
// distinct child-iterator-defined spans).
if found, s := m.synthesizeKeys(-1); found && s.Valid() {
if found, s := m.synthesizeKeys(-1); found && s != nil {
return s
}
}
// Exhausted.
m.clear()
return Span{}
return nil
}
func (m *MergingIter) heapRoot() []byte {
@@ -703,7 +801,7 @@ func (m *MergingIter) heapRoot() []byte {
//
// The boolean return value, `found`, is true if the returned span overlaps
// with a span returned by a child iterator.
func (m *MergingIter) synthesizeKeys(dir int8) (bool, Span) {
func (m *MergingIter) synthesizeKeys(dir int8) (bool, *Span) {
if invariants.Enabled {
if m.cmp(m.start, m.end) >= 0 {
panic(fmt.Sprintf("pebble: invariant violation: span start ≥ end: %s >= %s", m.start, m.end))
@@ -719,19 +817,26 @@ 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.
// 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.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, Span{}
return false, nil
}
return found, m.span
return found, &m.span
}
func (m *MergingIter) invalidate() {
@@ -885,28 +990,6 @@ func (h *mergingIterHeap) down(i0, n int) bool {
return i > i0
}
func startBound(s Span) boundKey {
if !s.Valid() {
return boundKey{kind: boundKindInvalid}
}
return boundKey{
kind: boundKindFragmentStart,
key: s.Start,
span: s,
}
}
func endBound(s Span) boundKey {
if !s.Valid() {
return boundKey{kind: boundKindInvalid}
}
return boundKey{
kind: boundKindFragmentEnd,
key: s.End,
span: s,
}
}
type boundKind int8
const (
@@ -922,7 +1005,7 @@ type boundKey struct {
//
// If kind is boundKindFragmentStart, then key is span.Start. If kind is
// boundKindFragmentEnd, then key is span.End.
span Span
span *Span
}
func (k boundKey) valid() bool {