github.com/zuoyebang/bitalostable@v1.0.1-0.20240229032404-e3b99a834294/internal/testkeys/blockprop/blockprop.go (about) 1 // Copyright 2022 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 blockprop implements interval block property collectors and filters 6 // on the suffixes of keys in the format used by the testkeys package (eg, 7 // 'key@5'). 8 package blockprop 9 10 import ( 11 "math" 12 13 "github.com/zuoyebang/bitalostable/internal/base" 14 "github.com/zuoyebang/bitalostable/internal/testkeys" 15 "github.com/zuoyebang/bitalostable/sstable" 16 ) 17 18 const blockPropertyName = `bitalostable.internal.testkeys.suffixes` 19 20 // NewBlockPropertyCollector constructs a sstable property collector over 21 // testkey suffixes. 22 func NewBlockPropertyCollector() sstable.BlockPropertyCollector { 23 return sstable.NewBlockIntervalCollector( 24 blockPropertyName, 25 &suffixIntervalCollector{}, 26 nil) 27 } 28 29 // NewBlockPropertyFilter constructs a new block-property filter that excludes 30 // blocks containing exclusively suffixed keys where all the suffixes fall 31 // outside of the range [filterMin, filterMax). 32 // 33 // The filter only filters based on data derived from the key. The iteration 34 // results of this block property filter are deterministic for unsuffixed keys 35 // and keys with suffixes within the range [filterMin, filterMax). For keys with 36 // suffixes outside the range, iteration is nondeterministic. 37 func NewBlockPropertyFilter(filterMin, filterMax uint64) *sstable.BlockIntervalFilter { 38 return sstable.NewBlockIntervalFilter(blockPropertyName, filterMin, filterMax) 39 } 40 41 // NewMaskingFilter constructs a MaskingFilter that implements 42 // bitalostable.BlockPropertyFilterMask for efficient range-key masking using the 43 // testkeys block property filter. The masking filter wraps a block interval 44 // filter, and modifies the configured interval when Pebble requests it. 45 func NewMaskingFilter() MaskingFilter { 46 return MaskingFilter{BlockIntervalFilter: NewBlockPropertyFilter(0, math.MaxUint64)} 47 } 48 49 // MaskingFilter implements BlockPropertyFilterMask and may be used to mask 50 // point keys with the testkeys-style suffixes (eg, @4) that are masked by range 51 // keys with testkeys-style suffixes. 52 type MaskingFilter struct { 53 *sstable.BlockIntervalFilter 54 } 55 56 // SetSuffix implements bitalostable.BlockPropertyFilterMask. 57 func (f MaskingFilter) SetSuffix(suffix []byte) error { 58 ts, err := testkeys.ParseSuffix(suffix) 59 if err != nil { 60 return err 61 } 62 f.BlockIntervalFilter.SetInterval(uint64(ts), math.MaxUint64) 63 return nil 64 } 65 66 // Intersects implements the BlockPropertyFilter interface. 67 func (f MaskingFilter) Intersects(prop []byte) (bool, error) { 68 return f.BlockIntervalFilter.Intersects(prop) 69 } 70 71 var _ sstable.DataBlockIntervalCollector = (*suffixIntervalCollector)(nil) 72 73 // suffixIntervalCollector maintains an interval over the timestamps in 74 // MVCC-like suffixes for keys (e.g. foo@123). 75 type suffixIntervalCollector struct { 76 initialized bool 77 lower, upper uint64 78 } 79 80 // Add implements DataBlockIntervalCollector by adding the timestamp(s) in the 81 // suffix(es) of this record to the current interval. 82 // 83 // Note that range sets and unsets may have multiple suffixes. Range key deletes 84 // do not have a suffix. All other point keys have a single suffix. 85 func (c *suffixIntervalCollector) Add(key base.InternalKey, value []byte) error { 86 i := testkeys.Comparer.Split(key.UserKey) 87 if i == len(key.UserKey) { 88 c.initialized = true 89 c.lower, c.upper = 0, math.MaxUint64 90 return nil 91 } 92 ts, err := testkeys.ParseSuffix(key.UserKey[i:]) 93 if err != nil { 94 return err 95 } 96 uts := uint64(ts) 97 if !c.initialized { 98 c.lower, c.upper = uts, uts+1 99 c.initialized = true 100 return nil 101 } 102 if uts < c.lower { 103 c.lower = uts 104 } 105 if uts >= c.upper { 106 c.upper = uts + 1 107 } 108 return nil 109 } 110 111 // FinishDataBlock implements DataBlockIntervalCollector. 112 func (c *suffixIntervalCollector) FinishDataBlock() (lower, upper uint64, err error) { 113 l, u := c.lower, c.upper 114 c.lower, c.upper = 0, 0 115 c.initialized = false 116 return l, u, nil 117 }