mirror of
https://source.quilibrium.com/quilibrium/ceremonyclient.git
synced 2024-12-27 17:15:18 +00:00
74 lines
2.3 KiB
Go
74 lines
2.3 KiB
Go
|
// Copyright 2019 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"
|
||
|
|
||
|
// Truncate creates a new iterator where every span in the supplied iterator is
|
||
|
// truncated to be contained within the range [lower, upper). If start and end
|
||
|
// are specified, filter out any spans that are completely outside those bounds.
|
||
|
func Truncate(
|
||
|
cmp base.Compare,
|
||
|
iter FragmentIterator,
|
||
|
lower, upper []byte,
|
||
|
start, end *base.InternalKey,
|
||
|
panicOnUpperTruncate bool,
|
||
|
) FragmentIterator {
|
||
|
return Filter(iter, func(in *Span, out *Span) (keep bool) {
|
||
|
out.Start, out.End = in.Start, in.End
|
||
|
out.Keys = append(out.Keys[:0], in.Keys...)
|
||
|
|
||
|
// Ignore this span if it lies completely outside start, end. Note that
|
||
|
// end endInclusive indicated whether end is inclusive.
|
||
|
//
|
||
|
// The comparison between s.End and start is by user key only, as
|
||
|
// the span is exclusive at s.End, so comparing by user keys
|
||
|
// is sufficient.
|
||
|
if start != nil && cmp(in.End, start.UserKey) <= 0 {
|
||
|
return false
|
||
|
}
|
||
|
if end != nil {
|
||
|
v := cmp(in.Start, end.UserKey)
|
||
|
switch {
|
||
|
case v > 0:
|
||
|
// Wholly outside the end bound. Skip it.
|
||
|
return false
|
||
|
case v == 0:
|
||
|
// This span begins at the same user key as `end`. Whether or
|
||
|
// not any of the keys contained within the span are relevant is
|
||
|
// dependent on Trailers. Any keys contained within the span
|
||
|
// with trailers larger than end cover the small sliver of
|
||
|
// keyspace between [k#inf, k#<end-seqnum>]. Since keys are
|
||
|
// sorted descending by Trailer within the span, we need to find
|
||
|
// the prefix of keys with larger trailers.
|
||
|
for i := range in.Keys {
|
||
|
if in.Keys[i].Trailer < end.Trailer {
|
||
|
out.Keys = out.Keys[:i]
|
||
|
break
|
||
|
}
|
||
|
}
|
||
|
default:
|
||
|
// Wholly within the end bound. Keep it.
|
||
|
}
|
||
|
}
|
||
|
|
||
|
var truncated bool
|
||
|
// Truncate the bounds to lower and upper.
|
||
|
if cmp(in.Start, lower) < 0 {
|
||
|
out.Start = lower
|
||
|
}
|
||
|
if cmp(in.End, upper) > 0 {
|
||
|
truncated = true
|
||
|
out.End = upper
|
||
|
}
|
||
|
|
||
|
if panicOnUpperTruncate && truncated {
|
||
|
panic("pebble: upper bound should not be truncated")
|
||
|
}
|
||
|
|
||
|
return !out.Empty() && cmp(out.Start, out.End) < 0
|
||
|
}, cmp)
|
||
|
}
|