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