github.com/cockroachdb/pebble@v0.0.0-20231214172447-ab4952c5f87b/sstable/block_property_test_utils.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 sstable
     6  
     7  import (
     8  	"math"
     9  
    10  	"github.com/cockroachdb/pebble/internal/base"
    11  	"github.com/cockroachdb/pebble/internal/testkeys"
    12  )
    13  
    14  // Code in this file contains utils for testing. It implements interval block
    15  // property collectors and filters on the suffixes of keys in the format used
    16  // by the testkeys package (eg, 'key@5').
    17  
    18  const testKeysBlockPropertyName = `pebble.internal.testkeys.suffixes`
    19  
    20  // NewTestKeysBlockPropertyCollector constructs a sstable property collector
    21  // over testkey suffixes.
    22  func NewTestKeysBlockPropertyCollector() BlockPropertyCollector {
    23  	return NewBlockIntervalCollector(
    24  		testKeysBlockPropertyName,
    25  		&testKeysSuffixIntervalCollector{},
    26  		nil)
    27  }
    28  
    29  // NewTestKeysBlockPropertyFilter 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 NewTestKeysBlockPropertyFilter(filterMin, filterMax uint64) *BlockIntervalFilter {
    38  	return NewBlockIntervalFilter(testKeysBlockPropertyName, filterMin, filterMax)
    39  }
    40  
    41  // NewTestKeysMaskingFilter constructs a TestKeysMaskingFilter that implements
    42  // pebble.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 NewTestKeysMaskingFilter() TestKeysMaskingFilter {
    46  	return TestKeysMaskingFilter{BlockIntervalFilter: NewTestKeysBlockPropertyFilter(0, math.MaxUint64)}
    47  }
    48  
    49  // TestKeysMaskingFilter 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 TestKeysMaskingFilter struct {
    53  	*BlockIntervalFilter
    54  }
    55  
    56  // SetSuffix implements pebble.BlockPropertyFilterMask.
    57  func (f TestKeysMaskingFilter) 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 TestKeysMaskingFilter) Intersects(prop []byte) (bool, error) {
    68  	return f.BlockIntervalFilter.Intersects(prop)
    69  }
    70  
    71  var _ DataBlockIntervalCollector = (*testKeysSuffixIntervalCollector)(nil)
    72  
    73  // testKeysSuffixIntervalCollector maintains an interval over the timestamps in
    74  // MVCC-like suffixes for keys (e.g. foo@123).
    75  type testKeysSuffixIntervalCollector 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 *testKeysSuffixIntervalCollector) 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 *testKeysSuffixIntervalCollector) 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  }