github.com/cockroachdb/pebble@v1.1.1-0.20240513155919-3622ade60459/sstable/filter.go (about)

     1  // Copyright 2011 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 "sync/atomic"
     8  
     9  // FilterMetrics holds metrics for the filter policy.
    10  type FilterMetrics struct {
    11  	// The number of hits for the filter policy. This is the
    12  	// number of times the filter policy was successfully used to avoid access
    13  	// of a data block.
    14  	Hits int64
    15  	// The number of misses for the filter policy. This is the number of times
    16  	// the filter policy was checked but was unable to filter an access of a data
    17  	// block.
    18  	Misses int64
    19  }
    20  
    21  // FilterMetricsTracker is used to keep track of filter metrics. It contains the
    22  // same metrics as FilterMetrics, but they can be updated atomically. An
    23  // instance of FilterMetricsTracker can be passed to a Reader as a ReaderOption.
    24  type FilterMetricsTracker struct {
    25  	// See FilterMetrics.Hits.
    26  	hits atomic.Int64
    27  	// See FilterMetrics.Misses.
    28  	misses atomic.Int64
    29  }
    30  
    31  var _ ReaderOption = (*FilterMetricsTracker)(nil)
    32  
    33  func (m *FilterMetricsTracker) readerApply(r *Reader) {
    34  	if r.tableFilter != nil {
    35  		r.tableFilter.metrics = m
    36  	}
    37  }
    38  
    39  // Load returns the current values as FilterMetrics.
    40  func (m *FilterMetricsTracker) Load() FilterMetrics {
    41  	return FilterMetrics{
    42  		Hits:   m.hits.Load(),
    43  		Misses: m.misses.Load(),
    44  	}
    45  }
    46  
    47  // BlockHandle is the file offset and length of a block.
    48  type BlockHandle struct {
    49  	Offset, Length uint64
    50  }
    51  
    52  // BlockHandleWithProperties is used for data blocks and first/lower level
    53  // index blocks, since they can be annotated using BlockPropertyCollectors.
    54  type BlockHandleWithProperties struct {
    55  	BlockHandle
    56  	Props []byte
    57  }
    58  
    59  type filterWriter interface {
    60  	addKey(key []byte)
    61  	finish() ([]byte, error)
    62  	metaName() string
    63  	policyName() string
    64  }
    65  
    66  type tableFilterReader struct {
    67  	policy  FilterPolicy
    68  	metrics *FilterMetricsTracker
    69  }
    70  
    71  func newTableFilterReader(policy FilterPolicy) *tableFilterReader {
    72  	return &tableFilterReader{
    73  		policy:  policy,
    74  		metrics: nil,
    75  	}
    76  }
    77  
    78  func (f *tableFilterReader) mayContain(data, key []byte) bool {
    79  	mayContain := f.policy.MayContain(TableFilter, data, key)
    80  	if f.metrics != nil {
    81  		if mayContain {
    82  			f.metrics.misses.Add(1)
    83  		} else {
    84  			f.metrics.hits.Add(1)
    85  		}
    86  	}
    87  	return mayContain
    88  }
    89  
    90  type tableFilterWriter struct {
    91  	policy FilterPolicy
    92  	writer FilterWriter
    93  	// count is the count of the number of keys added to the filter.
    94  	count int
    95  }
    96  
    97  func newTableFilterWriter(policy FilterPolicy) *tableFilterWriter {
    98  	return &tableFilterWriter{
    99  		policy: policy,
   100  		writer: policy.NewWriter(TableFilter),
   101  	}
   102  }
   103  
   104  func (f *tableFilterWriter) addKey(key []byte) {
   105  	f.count++
   106  	f.writer.AddKey(key)
   107  }
   108  
   109  func (f *tableFilterWriter) finish() ([]byte, error) {
   110  	if f.count == 0 {
   111  		return nil, nil
   112  	}
   113  	return f.writer.Finish(nil), nil
   114  }
   115  
   116  func (f *tableFilterWriter) metaName() string {
   117  	return "fullfilter." + f.policy.Name()
   118  }
   119  
   120  func (f *tableFilterWriter) policyName() string {
   121  	return f.policy.Name()
   122  }