github.com/cockroachdb/pebble@v0.0.0-20231214172447-ab4952c5f87b/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 }