Skip to content

Commit

Permalink
internal/keyspan: clean up InterleavingIter
Browse files Browse the repository at this point in the history
Remove superfluous Split parameter. Split was required for implementing
masking, but a direct implementation of masking was replaced with generic
Hooks.

Also, don't interleave a synthetic marker for empty spans. The synthetic marker
doesn't serve any purpose if there are no keys defined over the span. This
allows us to return a synthetic marker using an arbitrary Key's kind (rather
than always using RANGEKEYSET, even if the Span contained no RANGEKEYSET keys).
  • Loading branch information
jbowens committed Apr 18, 2022
1 parent b9bcae6 commit 785bb36
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 27 deletions.
2 changes: 1 addition & 1 deletion db.go
Original file line number Diff line number Diff line change
Expand Up @@ -978,7 +978,7 @@ func finishInitializingIter(buf *iterAlloc) *Iterator {
// NB: The interleaving iterator is always reinitialized, even if
// dbi already had an initialized range key iterator, in case the point
// iterator changed or the range key masking suffix changed.
dbi.rangeKey.iter.Init(dbi.cmp, dbi.split, dbi.iter, dbi.rangeKey.rangeKeyIter, keyspan.Hooks{
dbi.rangeKey.iter.Init(dbi.cmp, dbi.iter, dbi.rangeKey.rangeKeyIter, keyspan.Hooks{
SpanChanged: dbi.rangeKeySpanChanged,
SkipPoint: dbi.rangeKeySkipPoint,
})
Expand Down
2 changes: 1 addition & 1 deletion external_iterator.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ func NewExternalIter(
rangeKeyIters...,
)

dbi.rangeKey.iter.Init(dbi.cmp, dbi.split, &buf.merging, dbi.rangeKey.rangeKeyIter, keyspan.Hooks{
dbi.rangeKey.iter.Init(dbi.cmp, &buf.merging, dbi.rangeKey.rangeKeyIter, keyspan.Hooks{
SpanChanged: dbi.rangeKeySpanChanged,
SkipPoint: dbi.rangeKeySkipPoint,
})
Expand Down
42 changes: 29 additions & 13 deletions internal/keyspan/interleaving_iter.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,6 @@ type Hooks struct {
// All spans containing keys are exposed during iteration.
type InterleavingIter struct {
cmp base.Compare
split base.Split
pointIter base.InternalIteratorWithStats
keyspanIter FragmentIterator
hooks Hooks
Expand Down Expand Up @@ -149,14 +148,12 @@ var _ base.InternalIterator = &InterleavingIter{}
// with key spans from keyspanIter.
func (i *InterleavingIter) Init(
cmp base.Compare,
split base.Split,
pointIter base.InternalIteratorWithStats,
keyspanIter FragmentIterator,
hooks Hooks,
) {
*i = InterleavingIter{
cmp: cmp,
split: split,
pointIter: pointIter,
keyspanIter: keyspanIter,
hooks: hooks,
Expand Down Expand Up @@ -381,10 +378,12 @@ func (i *InterleavingIter) Prev() (*base.InternalKey, []byte) {

func (i *InterleavingIter) interleaveForward(lowerBound []byte) (*base.InternalKey, []byte) {
// This loop determines whether a point key or a span marker key should be
// interleaved on each iteration. If masking is disabled, this loop executes
// for exactly one iteration. If masking is enabled and a masked key is
// determined to be interleaved next, this loop continues until the
// interleaved key is unmasked.
// interleaved on each iteration. If masking is disabled and the span is
// nonempty, this loop executes for exactly one iteration. If masking is
// enabled and a masked key is determined to be interleaved next, this loop
// continues until the interleaved key is unmasked. If a span's start key
// should be interleaved next, but the span is empty, the loop continues to
// the next key.
for {
// Check invariants.
// INVARIANT: !pointKeyInterleaved
Expand Down Expand Up @@ -425,12 +424,20 @@ func (i *InterleavingIter) interleaveForward(lowerBound []byte) (*base.InternalK
return i.yieldNil()
}
}
if i.span.Empty() {
i.keyspanInterleaved = true
continue
}
return i.yieldSyntheticSpanMarker(lowerBound)
default:
if i.cmp(i.pointKey.UserKey, i.span.Start) >= 0 {
// The span start key lies before the point key. If we haven't
// interleaved it, we should.
if !i.keyspanInterleaved {
if i.span.Empty() {
i.keyspanInterleaved = true
continue
}
return i.yieldSyntheticSpanMarker(lowerBound)
}

Expand Down Expand Up @@ -473,10 +480,12 @@ func (i *InterleavingIter) interleaveForward(lowerBound []byte) (*base.InternalK

func (i *InterleavingIter) interleaveBackward() (*base.InternalKey, []byte) {
// This loop determines whether a point key or a span's start key should be
// interleaved on each iteration. If masking is disabled, this loop executes
// for exactly one iteration. If masking is enabled and a masked key is
// determined to be interleaved next, this loop continues until the
// interleaved key is unmasked.
// interleaved on each iteration. If masking is disabled and the span is
// nonempty, this loop executes for exactly one iteration. If masking is
// enabled and a masked key is determined to be interleaved next, this loop
// continues until the interleaved key is unmasked. If a span's start key
// should be interleaved next, but the span is empty, the loop continues to
// the next key.
for {
// Check invariants.
// INVARIANT: !pointKeyInterleaved
Expand All @@ -491,11 +500,19 @@ func (i *InterleavingIter) interleaveBackward() (*base.InternalKey, []byte) {
return i.yieldPointKey(false /* covered */)
case i.pointKey == nil:
// If we're out of point keys, we need to return a span marker.
if i.span.Empty() {
i.keyspanInterleaved = true
continue
}
return i.yieldSyntheticSpanMarker(i.lower)
default:
// If the span's start key is greater than the point key, return a
// marker for the span.
if i.cmp(i.span.Start, i.pointKey.UserKey) > 0 {
if i.span.Empty() {
i.keyspanInterleaved = true
continue
}
return i.yieldSyntheticSpanMarker(i.lower)
}
// We have a span but it has not been interleaved and begins at a
Expand Down Expand Up @@ -570,9 +587,8 @@ func (i *InterleavingIter) yieldPointKey(covered bool) (*base.InternalKey, []byt
}

func (i *InterleavingIter) yieldSyntheticSpanMarker(lowerBound []byte) (*base.InternalKey, []byte) {
// TODO(jackson): Elide empty spans.
i.spanMarker.UserKey = i.span.Start
i.spanMarker.Trailer = base.InternalKeyBoundaryRangeKey
i.spanMarker.Trailer = base.MakeTrailer(base.InternalKeySeqNumMax, i.span.Keys[0].Kind())
i.keyspanInterleaved = true
i.spanCoversKey = true

Expand Down
4 changes: 2 additions & 2 deletions internal/keyspan/interleaving_iter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ func runInterleavingIterTest(t *testing.T, filename string) {
}
keyspanIter.Init(cmp, noopTransform, NewIter(cmp, spans))
hooks.maskSuffix = nil
iter.Init(cmp, testkeys.Comparer.Split, base.WrapIterWithStats(&pointIter), &keyspanIter, Hooks{
iter.Init(cmp, base.WrapIterWithStats(&pointIter), &keyspanIter, Hooks{
SpanChanged: hooks.SpanChanged,
SkipPoint: hooks.SkipPoint,
})
Expand All @@ -103,7 +103,7 @@ func runInterleavingIterTest(t *testing.T, filename string) {
}
pointIter = pointIterator{cmp: cmp, keys: points}
hooks.maskSuffix = nil
iter.Init(cmp, testkeys.Comparer.Split, base.WrapIterWithStats(&pointIter), &keyspanIter, Hooks{
iter.Init(cmp, base.WrapIterWithStats(&pointIter), &keyspanIter, Hooks{
SpanChanged: hooks.SpanChanged,
SkipPoint: hooks.SkipPoint,
})
Expand Down
16 changes: 8 additions & 8 deletions internal/keyspan/testdata/interleaving_iter
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,10 @@ Span: c-d:{(#4,RANGEKEYSET,@3,coconut)}
PointKey: e#72057594037927935,21
Span: e-f:{(#20,RANGEKEYSET,@5,pineapple) (#20,RANGEKEYSET,@3,guava)}
-
PointKey: h#72057594037927935,21
PointKey: h#72057594037927935,19
Span: h-j:{(#22,RANGEKEYDEL) (#21,RANGEKEYSET,@5,peaches) (#21,RANGEKEYSET,@3,starfruit)}
-
PointKey: l#72057594037927935,21
PointKey: l#72057594037927935,20
Span: l-m:{(#2,RANGEKEYUNSET,@9) (#2,RANGEKEYUNSET,@5)}
-
PointKey: parsnip#3,1
Expand Down Expand Up @@ -154,7 +154,7 @@ Span: q-z:{(#14,RANGEKEYSET,@9,mangos)}
PointKey: parsnip#3,1
Span: <invalid>
-
PointKey: l#72057594037927935,21
PointKey: l#72057594037927935,20
Span: l-m:{(#2,RANGEKEYUNSET,@9) (#2,RANGEKEYUNSET,@5)}
-
PointKey: parsnip#3,1
Expand Down Expand Up @@ -281,7 +281,7 @@ Span: e-f:{(#20,RANGEKEYSET,@5,pineapple) (#20,RANGEKEYSET,@3,guava)}
PointKey: e#2,1
Span: e-f:{(#20,RANGEKEYSET,@5,pineapple) (#20,RANGEKEYSET,@3,guava)}
-
PointKey: h#72057594037927935,21
PointKey: h#72057594037927935,19
Span: h-j:{(#22,RANGEKEYDEL) (#21,RANGEKEYSET,@5,peaches) (#21,RANGEKEYSET,@3,starfruit)}
-

Expand Down Expand Up @@ -510,13 +510,13 @@ last
seek-ge a
seek-lt d
----
PointKey: b#72057594037927935,21
PointKey: b#72057594037927935,19
Span: b-d:{(#5,RANGEKEYDEL)}
-
PointKey: f#72057594037927935,21
PointKey: f#72057594037927935,19
Span: f-g:{(#6,RANGEKEYDEL)}
-
PointKey: b#72057594037927935,21
PointKey: b#72057594037927935,19
Span: b-d:{(#5,RANGEKEYDEL)}
-
PointKey: c#8,1
Expand Down Expand Up @@ -548,7 +548,7 @@ Span: w-y:{(#5,RANGEKEYSET,@1,v1)}
PointKey: x#8,1
Span: w-y:{(#5,RANGEKEYSET,@1,v1)}
-
PointKey: y#72057594037927935,21
PointKey: y#72057594037927935,19
Span: y-z:{(#5,RANGEKEYDEL)}
-

Expand Down
4 changes: 2 additions & 2 deletions internal/keyspan/testdata/interleaving_iter_masking
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ next
next
next
----
PointKey: a#72057594037927935,21
PointKey: a#72057594037927935,20
Span: a-c:{(#1,RANGEKEYUNSET,@5) (#1,RANGEKEYUNSET,@2)}
-
PointKey: a#1,1
Expand All @@ -332,7 +332,7 @@ Span: a-c:{(#1,RANGEKEYUNSET,@5) (#1,RANGEKEYUNSET,@2)}
PointKey: a#1,1
Span: a-c:{(#1,RANGEKEYUNSET,@5) (#1,RANGEKEYUNSET,@2)}
-
PointKey: a#72057594037927935,21
PointKey: a#72057594037927935,20
Span: a-c:{(#1,RANGEKEYUNSET,@5) (#1,RANGEKEYUNSET,@2)}
-
.
Expand Down

0 comments on commit 785bb36

Please sign in to comment.