150 lines
4.1 KiB
Go
150 lines
4.1 KiB
Go
// Copyright 2023 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"
|
|
|
|
// 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
|
|
}
|
|
|
|
// 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) Transformer {
|
|
return TransformerFunc(func(_ base.Compare, s Span, dst *Span) error {
|
|
dst.Start, dst.End = s.Start, s.End
|
|
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
|
|
})
|
|
}
|
|
|
|
// TransformerIter is a FragmentIterator that applies a Transformer on all
|
|
// returned keys. Used for when a caller needs to apply a transformer on an
|
|
// iterator but does not otherwise need the mergingiter's merging ability.
|
|
type TransformerIter struct {
|
|
FragmentIterator
|
|
|
|
// Transformer is applied on every Span returned by this iterator.
|
|
Transformer Transformer
|
|
// Comparer in use for this keyspace.
|
|
Compare base.Compare
|
|
|
|
span Span
|
|
err error
|
|
}
|
|
|
|
func (t *TransformerIter) applyTransform(span *Span) *Span {
|
|
t.span = Span{
|
|
Start: t.span.Start[:0],
|
|
End: t.span.End[:0],
|
|
Keys: t.span.Keys[:0],
|
|
}
|
|
if err := t.Transformer.Transform(t.Compare, *span, &t.span); err != nil {
|
|
t.err = err
|
|
return nil
|
|
}
|
|
return &t.span
|
|
}
|
|
|
|
// SeekGE implements the FragmentIterator interface.
|
|
func (t *TransformerIter) SeekGE(key []byte) *Span {
|
|
span := t.FragmentIterator.SeekGE(key)
|
|
if span == nil {
|
|
return nil
|
|
}
|
|
return t.applyTransform(span)
|
|
}
|
|
|
|
// SeekLT implements the FragmentIterator interface.
|
|
func (t *TransformerIter) SeekLT(key []byte) *Span {
|
|
span := t.FragmentIterator.SeekLT(key)
|
|
if span == nil {
|
|
return nil
|
|
}
|
|
return t.applyTransform(span)
|
|
}
|
|
|
|
// First implements the FragmentIterator interface.
|
|
func (t *TransformerIter) First() *Span {
|
|
span := t.FragmentIterator.First()
|
|
if span == nil {
|
|
return nil
|
|
}
|
|
return t.applyTransform(span)
|
|
}
|
|
|
|
// Last implements the FragmentIterator interface.
|
|
func (t *TransformerIter) Last() *Span {
|
|
span := t.FragmentIterator.Last()
|
|
if span == nil {
|
|
return nil
|
|
}
|
|
return t.applyTransform(span)
|
|
}
|
|
|
|
// Next implements the FragmentIterator interface.
|
|
func (t *TransformerIter) Next() *Span {
|
|
span := t.FragmentIterator.Next()
|
|
if span == nil {
|
|
return nil
|
|
}
|
|
return t.applyTransform(span)
|
|
}
|
|
|
|
// Prev implements the FragmentIterator interface.
|
|
func (t *TransformerIter) Prev() *Span {
|
|
span := t.FragmentIterator.Prev()
|
|
if span == nil {
|
|
return nil
|
|
}
|
|
return t.applyTransform(span)
|
|
}
|
|
|
|
// Error implements the FragmentIterator interface.
|
|
func (t *TransformerIter) Error() error {
|
|
if t.err != nil {
|
|
return t.err
|
|
}
|
|
return t.FragmentIterator.Error()
|
|
}
|
|
|
|
// Close implements the FragmentIterator interface.
|
|
func (t *TransformerIter) Close() error {
|
|
err := t.FragmentIterator.Close()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return t.err
|
|
}
|