github.com/cockroachdb/pebble@v0.0.0-20231214172447-ab4952c5f87b/internal/keyspan/truncate.go (about) 1 // Copyright 2019 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 // Truncate creates a new iterator where every span in the supplied iterator is 10 // truncated to be contained within the range [lower, upper). If start and end 11 // are specified, filter out any spans that are completely outside those bounds. 12 func Truncate( 13 cmp base.Compare, 14 iter FragmentIterator, 15 lower, upper []byte, 16 start, end *base.InternalKey, 17 panicOnUpperTruncate bool, 18 ) FragmentIterator { 19 return Filter(iter, func(in *Span, out *Span) (keep bool) { 20 out.Start, out.End = in.Start, in.End 21 out.Keys = append(out.Keys[:0], in.Keys...) 22 23 // Ignore this span if it lies completely outside start, end. Note that 24 // end endInclusive indicated whether end is inclusive. 25 // 26 // The comparison between s.End and start is by user key only, as 27 // the span is exclusive at s.End, so comparing by user keys 28 // is sufficient. 29 if start != nil && cmp(in.End, start.UserKey) <= 0 { 30 return false 31 } 32 if end != nil { 33 v := cmp(in.Start, end.UserKey) 34 switch { 35 case v > 0: 36 // Wholly outside the end bound. Skip it. 37 return false 38 case v == 0: 39 // This span begins at the same user key as `end`. Whether or 40 // not any of the keys contained within the span are relevant is 41 // dependent on Trailers. Any keys contained within the span 42 // with trailers larger than end cover the small sliver of 43 // keyspace between [k#inf, k#<end-seqnum>]. Since keys are 44 // sorted descending by Trailer within the span, we need to find 45 // the prefix of keys with larger trailers. 46 for i := range in.Keys { 47 if in.Keys[i].Trailer < end.Trailer { 48 out.Keys = out.Keys[:i] 49 break 50 } 51 } 52 default: 53 // Wholly within the end bound. Keep it. 54 } 55 } 56 57 var truncated bool 58 // Truncate the bounds to lower and upper. 59 if cmp(in.Start, lower) < 0 { 60 out.Start = lower 61 } 62 if cmp(in.End, upper) > 0 { 63 truncated = true 64 out.End = upper 65 } 66 67 if panicOnUpperTruncate && truncated { 68 panic("pebble: upper bound should not be truncated") 69 } 70 71 return !out.Empty() && cmp(out.Start, out.End) < 0 72 }, cmp) 73 }