Line data Source code
1 : // Copyright 2023 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 "github.com/cockroachdb/pebble/internal/base"
8 :
9 : // Transformer defines a transformation to be applied to a Span.
10 : type Transformer interface {
11 : // Transform takes a Span as input and writes the transformed Span to the
12 : // provided output *Span pointer. The output Span's Keys slice may be reused
13 : // by Transform to reduce allocations.
14 : Transform(cmp base.Compare, in Span, out *Span) error
15 : }
16 :
17 : // The TransformerFunc type is an adapter to allow the use of ordinary functions
18 : // as Transformers. If f is a function with the appropriate signature,
19 : // TransformerFunc(f) is a Transformer that calls f.
20 : type TransformerFunc func(base.Compare, Span, *Span) error
21 :
22 : // Transform calls f(cmp, in, out).
23 2 : func (tf TransformerFunc) Transform(cmp base.Compare, in Span, out *Span) error {
24 2 : return tf(cmp, in, out)
25 2 : }
26 :
27 : // NoopTransform is a Transformer that performs no mutations.
28 2 : var NoopTransform Transformer = TransformerFunc(func(_ base.Compare, s Span, dst *Span) error {
29 2 : dst.Start, dst.End = s.Start, s.End
30 2 : dst.Keys = append(dst.Keys[:0], s.Keys...)
31 2 : return nil
32 2 : })
33 :
34 : // VisibleTransform filters keys that are invisible at the provided snapshot
35 : // sequence number.
36 2 : func VisibleTransform(snapshot uint64) Transformer {
37 2 : return TransformerFunc(func(_ base.Compare, s Span, dst *Span) error {
38 2 : dst.Start, dst.End = s.Start, s.End
39 2 : dst.Keys = dst.Keys[:0]
40 2 : for _, k := range s.Keys {
41 2 : // NB: The InternalKeySeqNumMax value is used for the batch snapshot
42 2 : // because a batch's visible span keys are filtered when they're
43 2 : // fragmented. There's no requirement to enforce visibility at
44 2 : // iteration time.
45 2 : if base.Visible(k.SeqNum(), snapshot, base.InternalKeySeqNumMax) {
46 2 : dst.Keys = append(dst.Keys, k)
47 2 : }
48 : }
49 2 : return nil
50 : })
51 : }
52 :
53 : // TransformerIter is a FragmentIterator that applies a Transformer on all
54 : // returned keys. Used for when a caller needs to apply a transformer on an
55 : // iterator but does not otherwise need the mergingiter's merging ability.
56 : type TransformerIter struct {
57 : FragmentIterator
58 :
59 : // Transformer is applied on every Span returned by this iterator.
60 : Transformer Transformer
61 : // Comparer in use for this keyspace.
62 : Compare base.Compare
63 :
64 : span Span
65 : }
66 :
67 2 : func (t *TransformerIter) applyTransform(span *Span) (*Span, error) {
68 2 : if span == nil {
69 2 : return nil, nil
70 2 : }
71 2 : t.span = Span{
72 2 : Start: t.span.Start[:0],
73 2 : End: t.span.End[:0],
74 2 : Keys: t.span.Keys[:0],
75 2 : }
76 2 : if err := t.Transformer.Transform(t.Compare, *span, &t.span); err != nil {
77 0 : return nil, err
78 0 : }
79 2 : return &t.span, nil
80 : }
81 :
82 : // SeekGE implements the FragmentIterator interface.
83 2 : func (t *TransformerIter) SeekGE(key []byte) (*Span, error) {
84 2 : span, err := t.FragmentIterator.SeekGE(key)
85 2 : if err != nil {
86 0 : return nil, err
87 0 : }
88 2 : return t.applyTransform(span)
89 : }
90 :
91 : // SeekLT implements the FragmentIterator interface.
92 2 : func (t *TransformerIter) SeekLT(key []byte) (*Span, error) {
93 2 : span, err := t.FragmentIterator.SeekLT(key)
94 2 : if err != nil {
95 0 : return nil, err
96 0 : }
97 2 : return t.applyTransform(span)
98 : }
99 :
100 : // First implements the FragmentIterator interface.
101 2 : func (t *TransformerIter) First() (*Span, error) {
102 2 : span, err := t.FragmentIterator.First()
103 2 : if err != nil {
104 0 : return nil, err
105 0 : }
106 2 : return t.applyTransform(span)
107 : }
108 :
109 : // Last implements the FragmentIterator interface.
110 2 : func (t *TransformerIter) Last() (*Span, error) {
111 2 : span, err := t.FragmentIterator.Last()
112 2 : if err != nil {
113 0 : return nil, err
114 0 : }
115 2 : return t.applyTransform(span)
116 : }
117 :
118 : // Next implements the FragmentIterator interface.
119 2 : func (t *TransformerIter) Next() (*Span, error) {
120 2 : span, err := t.FragmentIterator.Next()
121 2 : if err != nil {
122 0 : return nil, err
123 0 : }
124 2 : return t.applyTransform(span)
125 : }
126 :
127 : // Prev implements the FragmentIterator interface.
128 2 : func (t *TransformerIter) Prev() (*Span, error) {
129 2 : span, err := t.FragmentIterator.Prev()
130 2 : if err != nil {
131 0 : return nil, err
132 0 : }
133 2 : return t.applyTransform(span)
134 : }
135 :
136 : // Close implements the FragmentIterator interface.
137 2 : func (t *TransformerIter) Close() error {
138 2 : return t.FragmentIterator.Close()
139 2 : }
|