LCOV - code coverage report
Current view: top level - pebble/sstable - block_property_test_utils.go (source / functions) Hit Total Coverage
Test: 2024-04-10 08:16Z 6cdb88d4 - tests only.lcov Lines: 48 69 69.6 %
Date: 2024-04-10 08:16:32 Functions: 0 0 -

          Line data    Source code
       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             :         "fmt"
       9             :         "math"
      10             : 
      11             :         "github.com/cockroachdb/errors"
      12             :         "github.com/cockroachdb/pebble/internal/base"
      13             :         "github.com/cockroachdb/pebble/internal/testkeys"
      14             : )
      15             : 
      16             : // Code in this file contains utils for testing. It implements interval block
      17             : // property collectors and filters on the suffixes of keys in the format used
      18             : // by the testkeys package (eg, 'key@5').
      19             : 
      20             : const testKeysBlockPropertyName = `pebble.internal.testkeys.suffixes`
      21             : 
      22             : // NewTestKeysBlockPropertyCollector constructs a sstable property collector
      23             : // over testkey suffixes.
      24           1 : func NewTestKeysBlockPropertyCollector() BlockPropertyCollector {
      25           1 :         return NewBlockIntervalCollector(
      26           1 :                 testKeysBlockPropertyName,
      27           1 :                 &testKeysSuffixIntervalCollector{},
      28           1 :                 nil)
      29           1 : }
      30             : 
      31             : // NewTestKeysBlockPropertyFilter constructs a new block-property filter that excludes
      32             : // blocks containing exclusively suffixed keys where all the suffixes fall
      33             : // outside of the range [filterMin, filterMax).
      34             : //
      35             : // The filter only filters based on data derived from the key. The iteration
      36             : // results of this block property filter are deterministic for unsuffixed keys
      37             : // and keys with suffixes within the range [filterMin, filterMax). For keys with
      38             : // suffixes outside the range, iteration is nondeterministic.
      39           1 : func NewTestKeysBlockPropertyFilter(filterMin, filterMax uint64) *BlockIntervalFilter {
      40           1 :         return NewBlockIntervalFilter(testKeysBlockPropertyName, filterMin, filterMax, testKeysBlockIntervalSyntheticReplacer{})
      41           1 : }
      42             : 
      43             : var _ BlockIntervalSyntheticReplacer = testKeysBlockIntervalSyntheticReplacer{}
      44             : 
      45             : type testKeysBlockIntervalSyntheticReplacer struct{}
      46             : 
      47             : // AdjustIntervalWithSyntheticSuffix implements BlockIntervalSyntheticReplacer.
      48             : func (sr testKeysBlockIntervalSyntheticReplacer) AdjustIntervalWithSyntheticSuffix(
      49             :         lower uint64, upper uint64, suffix []byte,
      50           0 : ) (adjustedLower uint64, adjustedUpper uint64, err error) {
      51           0 :         decoded, err := testkeys.ParseSuffix(suffix)
      52           0 :         if err != nil {
      53           0 :                 return 0, 0, err
      54           0 :         }
      55             :         // The testKeysSuffixIntervalCollector below maps keys with no suffix to MaxUint64; ignore it.
      56           0 :         if upper != math.MaxUint64 && uint64(decoded) < upper {
      57           0 :                 panic(fmt.Sprintf("the synthetic suffix %d is less than the property upper bound %d", decoded, upper))
      58             :         }
      59           0 :         return uint64(decoded), uint64(decoded) + 1, nil
      60             : }
      61             : 
      62             : // NewTestKeysMaskingFilter constructs a TestKeysMaskingFilter that implements
      63             : // pebble.BlockPropertyFilterMask for efficient range-key masking using the
      64             : // testkeys block property filter. The masking filter wraps a block interval
      65             : // filter, and modifies the configured interval when Pebble requests it.
      66           1 : func NewTestKeysMaskingFilter() TestKeysMaskingFilter {
      67           1 :         return TestKeysMaskingFilter{BlockIntervalFilter: NewTestKeysBlockPropertyFilter(0, math.MaxUint64)}
      68           1 : }
      69             : 
      70             : // TestKeysMaskingFilter implements BlockPropertyFilterMask and may be used to mask
      71             : // point keys with the testkeys-style suffixes (eg, @4) that are masked by range
      72             : // keys with testkeys-style suffixes.
      73             : type TestKeysMaskingFilter struct {
      74             :         *BlockIntervalFilter
      75             : }
      76             : 
      77             : // SetSuffix implements pebble.BlockPropertyFilterMask.
      78           1 : func (f TestKeysMaskingFilter) SetSuffix(suffix []byte) error {
      79           1 :         ts, err := testkeys.ParseSuffix(suffix)
      80           1 :         if err != nil {
      81           0 :                 return err
      82           0 :         }
      83           1 :         f.BlockIntervalFilter.SetInterval(uint64(ts), math.MaxUint64)
      84           1 :         return nil
      85             : }
      86             : 
      87             : // Intersects implements the BlockPropertyFilter interface.
      88           1 : func (f TestKeysMaskingFilter) Intersects(prop []byte) (bool, error) {
      89           1 :         return f.BlockIntervalFilter.Intersects(prop)
      90           1 : }
      91             : 
      92             : // SyntheticSuffixIntersects implements the BlockPropertyFilter interface.
      93           0 : func (f TestKeysMaskingFilter) SyntheticSuffixIntersects(prop []byte, suffix []byte) (bool, error) {
      94           0 :         return f.BlockIntervalFilter.SyntheticSuffixIntersects(prop, suffix)
      95           0 : }
      96             : 
      97             : var _ DataBlockIntervalCollector = (*testKeysSuffixIntervalCollector)(nil)
      98             : 
      99             : // testKeysSuffixIntervalCollector maintains an interval over the timestamps in
     100             : // MVCC-like suffixes for keys (e.g. foo@123).
     101             : type testKeysSuffixIntervalCollector struct {
     102             :         initialized  bool
     103             :         lower, upper uint64
     104             : }
     105             : 
     106             : // Add implements DataBlockIntervalCollector by adding the timestamp(s) in the
     107             : // suffix(es) of this record to the current interval.
     108             : //
     109             : // Note that range sets and unsets may have multiple suffixes. Range key deletes
     110             : // do not have a suffix. All other point keys have a single suffix.
     111           1 : func (c *testKeysSuffixIntervalCollector) Add(key base.InternalKey, value []byte) error {
     112           1 :         i := testkeys.Comparer.Split(key.UserKey)
     113           1 :         if i == len(key.UserKey) {
     114           1 :                 c.initialized = true
     115           1 :                 c.lower, c.upper = 0, math.MaxUint64
     116           1 :                 return nil
     117           1 :         }
     118           1 :         ts, err := testkeys.ParseSuffix(key.UserKey[i:])
     119           1 :         if err != nil {
     120           0 :                 return err
     121           0 :         }
     122           1 :         uts := uint64(ts)
     123           1 :         if !c.initialized {
     124           1 :                 c.lower, c.upper = uts, uts+1
     125           1 :                 c.initialized = true
     126           1 :                 return nil
     127           1 :         }
     128           1 :         if uts < c.lower {
     129           1 :                 c.lower = uts
     130           1 :         }
     131           1 :         if uts >= c.upper {
     132           1 :                 c.upper = uts + 1
     133           1 :         }
     134           1 :         return nil
     135             : }
     136             : 
     137             : // FinishDataBlock implements DataBlockIntervalCollector.
     138           1 : func (c *testKeysSuffixIntervalCollector) FinishDataBlock() (lower, upper uint64, err error) {
     139           1 :         l, u := c.lower, c.upper
     140           1 :         c.lower, c.upper = 0, 0
     141           1 :         c.initialized = false
     142           1 :         return l, u, nil
     143           1 : }
     144             : 
     145             : // AddCollectedWithSuffixReplacement is part of the DataBlockIntervalCollector interface.
     146             : func (c *testKeysSuffixIntervalCollector) AddCollectedWithSuffixReplacement(
     147             :         oldLower, oldUpper uint64, oldSuffix, newSuffix []byte,
     148           0 : ) error {
     149           0 :         return errors.Errorf("not implemented")
     150           0 : }
     151             : 
     152             : // SupportsSuffixReplacement part of the DataBlockIntervalCollector interface.
     153           0 : func (c *testKeysSuffixIntervalCollector) SupportsSuffixReplacement() bool {
     154           0 :         return false
     155           0 : }

Generated by: LCOV version 1.14