LCOV - code coverage report
Current view: top level - pebble/sstable - block_property_obsolete.go (source / functions) Hit Total Coverage
Test: 2024-08-22 08:16Z 99abcf76 - meta test only.lcov Lines: 53 72 73.6 %
Date: 2024-08-22 08:16:55 Functions: 0 0 -

          Line data    Source code
       1             : // Copyright 2024 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             :         "github.com/cockroachdb/errors"
       9             :         "github.com/cockroachdb/pebble/internal/base"
      10             : )
      11             : 
      12             : // obsoleteKeyBlockPropertyCollector is a block property collector used to
      13             : // implement obsoleteKeyBlockPropertyFilter - a filter that excludes blocks
      14             : // which contain only obsolete keys.
      15             : //
      16             : // For an explanation of obsolete keys, see the comment for TableFormatPebblev4
      17             : // which explains obsolete keys.
      18             : type obsoleteKeyBlockPropertyCollector struct {
      19             :         blockIsNonObsolete bool
      20             :         indexIsNonObsolete bool
      21             :         tableIsNonObsolete bool
      22             : }
      23             : 
      24             : var _ BlockPropertyCollector = (*obsoleteKeyBlockPropertyCollector)(nil)
      25             : 
      26             : // Name is part of the BlockPropertyCollector interface.
      27           1 : func (o *obsoleteKeyBlockPropertyCollector) Name() string {
      28           1 :         return "obsolete-key"
      29           1 : }
      30             : 
      31             : // AddPointKey is part of the BlockPropertyCollector interface.
      32           1 : func (o *obsoleteKeyBlockPropertyCollector) AddPointKey(key InternalKey, value []byte) error {
      33           1 :         // Ignore.
      34           1 :         return nil
      35           1 : }
      36             : 
      37             : // AddRangeKeys is part of the BlockPropertyCollector interface.
      38           1 : func (o *obsoleteKeyBlockPropertyCollector) AddRangeKeys(span Span) error {
      39           1 :         // Ignore.
      40           1 :         return nil
      41           1 : }
      42             : 
      43             : // AddPoint is an out-of-band method that is specific to this collector.
      44           1 : func (o *obsoleteKeyBlockPropertyCollector) AddPoint(isObsolete bool) {
      45           1 :         o.blockIsNonObsolete = o.blockIsNonObsolete || !isObsolete
      46           1 : }
      47             : 
      48             : // FinishDataBlock is part of the BlockPropertyCollector interface.
      49           1 : func (o *obsoleteKeyBlockPropertyCollector) FinishDataBlock(buf []byte) ([]byte, error) {
      50           1 :         o.tableIsNonObsolete = o.tableIsNonObsolete || o.blockIsNonObsolete
      51           1 :         return obsoleteKeyBlockPropertyEncode(!o.blockIsNonObsolete, buf), nil
      52           1 : }
      53             : 
      54             : // AddPrevDataBlockToIndexBlock is part of the BlockPropertyCollector interface.
      55           1 : func (o *obsoleteKeyBlockPropertyCollector) AddPrevDataBlockToIndexBlock() {
      56           1 :         o.indexIsNonObsolete = o.indexIsNonObsolete || o.blockIsNonObsolete
      57           1 :         o.blockIsNonObsolete = false
      58           1 : }
      59             : 
      60             : // FinishIndexBlock is part of the BlockPropertyCollector interface.
      61           1 : func (o *obsoleteKeyBlockPropertyCollector) FinishIndexBlock(buf []byte) ([]byte, error) {
      62           1 :         buf = obsoleteKeyBlockPropertyEncode(!o.indexIsNonObsolete, buf)
      63           1 :         o.indexIsNonObsolete = false
      64           1 :         return buf, nil
      65           1 : }
      66             : 
      67             : // FinishTable is part of the BlockPropertyCollector interface.
      68           1 : func (o *obsoleteKeyBlockPropertyCollector) FinishTable(buf []byte) ([]byte, error) {
      69           1 :         return obsoleteKeyBlockPropertyEncode(!o.tableIsNonObsolete, buf), nil
      70           1 : }
      71             : 
      72             : // AddCollectedWithSuffixReplacement is part of the BlockPropertyCollector interface.
      73             : func (o *obsoleteKeyBlockPropertyCollector) AddCollectedWithSuffixReplacement(
      74             :         oldProp []byte, oldSuffix, newSuffix []byte,
      75           0 : ) error {
      76           0 :         // Verify the property is valid.
      77           0 :         _, err := obsoleteKeyBlockPropertyDecode(oldProp)
      78           0 :         if err != nil {
      79           0 :                 return err
      80           0 :         }
      81             :         // Suffix rewriting currently loses the obsolete bit.
      82           0 :         o.blockIsNonObsolete = true
      83           0 :         return nil
      84             : }
      85             : 
      86             : // SupportsSuffixReplacement is part of the BlockPropertyCollector interface.
      87           0 : func (o *obsoleteKeyBlockPropertyCollector) SupportsSuffixReplacement() bool {
      88           0 :         return true
      89           0 : }
      90             : 
      91             : // obsoleteKeyBlockPropertyFilter implements the filter that excludes blocks
      92             : // that only contain obsolete keys. It pairs with
      93             : // obsoleteKeyBlockPropertyCollector.
      94             : //
      95             : // Note that we filter data blocks as well as first-level index blocks.
      96             : //
      97             : // For an explanation of obsolete keys, see the comment for TableFormatPebblev4
      98             : // which explains obsolete keys.
      99             : //
     100             : // NB: obsoleteKeyBlockPropertyFilter is stateless. This aspect of the filter
     101             : // is used in table_cache.go for in-place modification of a filters slice.
     102             : type obsoleteKeyBlockPropertyFilter struct{}
     103             : 
     104             : var _ BlockPropertyFilter = obsoleteKeyBlockPropertyFilter{}
     105             : 
     106             : // Name is part of the BlockPropertyFilter interface. It must match
     107             : // obsoleteKeyBlockPropertyCollector.Name.
     108           1 : func (o obsoleteKeyBlockPropertyFilter) Name() string {
     109           1 :         return "obsolete-key"
     110           1 : }
     111             : 
     112             : // Intersects is part of the BlockPropertyFilter interface. It returns true
     113             : // if the block may contain non-obsolete keys.
     114           1 : func (o obsoleteKeyBlockPropertyFilter) Intersects(prop []byte) (bool, error) {
     115           1 :         isObsolete, err := obsoleteKeyBlockPropertyDecode(prop)
     116           1 :         if err != nil {
     117           0 :                 return false, err
     118           0 :         }
     119           1 :         return !isObsolete, nil
     120             : }
     121             : 
     122             : // SyntheticSuffixIntersects is part of the BlockPropertyFilter interface. It
     123             : // expects that synthetic suffix is never used with tables that contain obsolete
     124             : // keys.
     125             : func (o obsoleteKeyBlockPropertyFilter) SyntheticSuffixIntersects(
     126             :         prop []byte, suffix []byte,
     127           1 : ) (bool, error) {
     128           1 :         isObsolete, err := obsoleteKeyBlockPropertyDecode(prop)
     129           1 :         if err != nil {
     130           0 :                 return false, err
     131           0 :         }
     132             :         // A block with suffix replacement should never be obsolete.
     133           1 :         if isObsolete {
     134           0 :                 return false, base.AssertionFailedf("block with synthetic suffix is obsolete")
     135           0 :         }
     136           1 :         return true, nil
     137             : }
     138             : 
     139             : // Encodes the information of whether the block contains only obsolete keys. We
     140             : // use the empty encoding for the common case of a block not being obsolete.
     141           1 : func obsoleteKeyBlockPropertyEncode(isObsolete bool, buf []byte) []byte {
     142           1 :         if isObsolete {
     143           1 :                 return append(buf, 't')
     144           1 :         }
     145           1 :         return buf
     146             : }
     147             : 
     148             : // Decodes the information of whether the block contains only obsolete keys (the
     149             : // inverse of obsoleteKeyBlockPropertyEncode).
     150           1 : func obsoleteKeyBlockPropertyDecode(prop []byte) (isObsolete bool, _ error) {
     151           1 :         switch {
     152           1 :         case len(prop) == 0:
     153           1 :                 return false, nil
     154           1 :         case len(prop) == 1 && prop[0] == 't':
     155           1 :                 return true, nil
     156           0 :         default:
     157           0 :                 return false, errors.Errorf("invalid obsolete block property %x", prop)
     158             :         }
     159             : }

Generated by: LCOV version 1.14