LCOV - code coverage report
Current view: top level - pebble/sstable/rowblk - rowblk_fragment_iter.go (source / functions) Hit Total Coverage
Test: 2024-12-08 08:16Z 0f9bf63d - tests + meta.lcov Lines: 203 235 86.4 %
Date: 2024-12-08 08:17:55 Functions: 0 0 -

          Line data    Source code
       1             : // Copyright 2018 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 rowblk
       6             : 
       7             : import (
       8             :         "bytes"
       9             :         "context"
      10             :         "fmt"
      11             :         "os"
      12             :         "sync"
      13             : 
      14             :         "github.com/cockroachdb/pebble/internal/base"
      15             :         "github.com/cockroachdb/pebble/internal/invariants"
      16             :         "github.com/cockroachdb/pebble/internal/keyspan"
      17             :         "github.com/cockroachdb/pebble/internal/rangedel"
      18             :         "github.com/cockroachdb/pebble/internal/rangekey"
      19             :         "github.com/cockroachdb/pebble/internal/treeprinter"
      20             :         "github.com/cockroachdb/pebble/sstable/block"
      21             : )
      22             : 
      23             : // fragmentIter wraps an Iter, implementing the keyspan.FragmentIterator
      24             : // interface. It's used for reading range deletion and range key blocks.
      25             : //
      26             : // Range deletions and range keys are fragmented before they're persisted to the
      27             : // block. Overlapping fragments have identical bounds.  The fragmentIter gathers
      28             : // all the fragments with identical bounds within a block and returns a single
      29             : // keyspan.Span describing all the keys defined over the span.
      30             : //
      31             : // # Memory lifetime
      32             : //
      33             : // A Span returned by fragmentIter is only guaranteed to be stable until the
      34             : // next fragmentIter iteration positioning method. A Span's Keys slice may be
      35             : // reused, so the user must not assume it's stable.
      36             : //
      37             : // Blocks holding range deletions and range keys are configured to use a restart
      38             : // interval of 1. This provides key stability. The caller may treat the various
      39             : // byte slices (start, end, suffix, value) as stable for the lifetime of the
      40             : // iterator.
      41             : type fragmentIter struct {
      42             :         suffixCmp base.CompareRangeSuffixes
      43             :         blockIter Iter
      44             :         keyBuf    [2]keyspan.Key
      45             :         span      keyspan.Span
      46             :         dir       int8
      47             : 
      48             :         // fileNum is used for logging/debugging.
      49             :         fileNum base.DiskFileNum
      50             : 
      51             :         syntheticPrefixAndSuffix block.SyntheticPrefixAndSuffix
      52             :         // startKeyBuf is a buffer that is reused to store the start key of the span
      53             :         // when a synthetic prefix is used.
      54             :         startKeyBuf []byte
      55             :         // endKeyBuf is a buffer that is reused to generate the end key of the span
      56             :         // when a synthetic prefix is set. It always starts with syntheticPrefix.
      57             :         endKeyBuf []byte
      58             : 
      59             :         closeCheck invariants.CloseChecker
      60             : }
      61             : 
      62             : var _ keyspan.FragmentIterator = (*fragmentIter)(nil)
      63             : 
      64             : var fragmentBlockIterPool = sync.Pool{
      65           2 :         New: func() interface{} {
      66           2 :                 i := &fragmentIter{}
      67           2 :                 // Note: this is a no-op if invariants are disabled or race is enabled.
      68           2 :                 invariants.SetFinalizer(i, checkFragmentBlockIterator)
      69           2 :                 return i
      70           2 :         },
      71             : }
      72             : 
      73             : // NewFragmentIter returns a new keyspan iterator that iterates over a block's
      74             : // spans.
      75             : func NewFragmentIter(
      76             :         fileNum base.DiskFileNum,
      77             :         comparer *base.Comparer,
      78             :         blockHandle block.BufferHandle,
      79             :         transforms block.FragmentIterTransforms,
      80           2 : ) (keyspan.FragmentIterator, error) {
      81           2 :         i := fragmentBlockIterPool.Get().(*fragmentIter)
      82           2 : 
      83           2 :         i.suffixCmp = comparer.CompareRangeSuffixes
      84           2 :         // Use the i.keyBuf array to back the Keys slice to prevent an allocation
      85           2 :         // when the spans contain few keys.
      86           2 :         i.span.Keys = i.keyBuf[:0]
      87           2 :         i.fileNum = fileNum
      88           2 :         i.syntheticPrefixAndSuffix = transforms.SyntheticPrefixAndSuffix
      89           2 :         if transforms.HasSyntheticPrefix() {
      90           2 :                 i.endKeyBuf = append(i.endKeyBuf[:0], transforms.SyntheticPrefix()...)
      91           2 :         }
      92           2 :         i.closeCheck = invariants.CloseChecker{}
      93           2 : 
      94           2 :         if err := i.blockIter.InitHandle(comparer, blockHandle, block.IterTransforms{
      95           2 :                 SyntheticSeqNum: transforms.SyntheticSeqNum,
      96           2 :                 // We let the blockIter prepend the prefix to span start keys; the fragment
      97           2 :                 // iterator will prepend it for end keys. We could do everything in the
      98           2 :                 // fragment iterator, but we'd have to duplicate the logic for adjusting the
      99           2 :                 // seek key for SeekGE/SeekLT.
     100           2 :                 SyntheticPrefixAndSuffix: transforms.SyntheticPrefixAndSuffix.RemoveSuffix(),
     101           2 :                 // It's okay for HideObsoletePoints to be false here, even for shared
     102           2 :                 // ingested sstables. This is because rangedels do not apply to points in
     103           2 :                 // the same sstable at the same sequence number anyway, so exposing obsolete
     104           2 :                 // rangedels is harmless.
     105           2 :                 HideObsoletePoints: false,
     106           2 :         }); err != nil {
     107           0 :                 i.Close()
     108           0 :                 return nil, err
     109           0 :         }
     110           2 :         return i, nil
     111             : }
     112             : 
     113             : // initSpan initializes the span with a single fragment.
     114             : //
     115             : // Note that the span start and end keys and range key contents are aliased to
     116             : // the key or value when we don't have a synthetic prefix. This is ok because
     117             : // the range del/key block doesn't use prefix compression, so the key/value will
     118             : // be pointing directly into the buffer data.
     119           2 : func (i *fragmentIter) initSpan(ik base.InternalKey, internalValue []byte) error {
     120           2 :         if ik.Kind() == base.InternalKeyKindRangeDelete {
     121           2 :                 i.span = rangedel.Decode(ik, internalValue, i.span.Keys[:0])
     122           2 :         } else {
     123           2 :                 var err error
     124           2 :                 i.span, err = rangekey.Decode(ik, internalValue, i.span.Keys[:0])
     125           2 :                 if err != nil {
     126           0 :                         return err
     127           0 :                 }
     128             :         }
     129             :         // When synthetic prefix is used in the blockIter, the keys cannot be used
     130             :         // across multiple blockIter operations; we have to make a copy in this case.
     131           2 :         if i.syntheticPrefixAndSuffix.HasPrefix() || invariants.Sometimes(10) {
     132           2 :                 i.startKeyBuf = append(i.startKeyBuf[:0], i.span.Start...)
     133           2 :                 i.span.Start = i.startKeyBuf
     134           2 :         }
     135           2 :         return nil
     136             : }
     137             : 
     138             : // addToSpan adds a fragment to the existing span. The fragment must be for the
     139             : // same start/end keys.
     140             : func (i *fragmentIter) addToSpan(
     141             :         cmp base.Compare, ik base.InternalKey, internalValue []byte,
     142           2 : ) error {
     143           2 :         var err error
     144           2 :         if ik.Kind() == base.InternalKeyKindRangeDelete {
     145           2 :                 err = rangedel.DecodeIntoSpan(cmp, ik, internalValue, &i.span)
     146           2 :         } else {
     147           2 :                 err = rangekey.DecodeIntoSpan(cmp, ik, internalValue, &i.span)
     148           2 :         }
     149           2 :         return err
     150             : }
     151             : 
     152             : // applySpanTransforms applies changes to the span that we decoded, if
     153             : // appropriate.
     154           2 : func (i *fragmentIter) applySpanTransforms() error {
     155           2 :         if i.syntheticPrefixAndSuffix.HasPrefix() || invariants.Sometimes(10) {
     156           2 :                 syntheticPrefix := i.syntheticPrefixAndSuffix.Prefix()
     157           2 :                 // We have to make a copy of the start key because it will not stay valid
     158           2 :                 // across multiple blockIter operations.
     159           2 :                 i.startKeyBuf = append(i.startKeyBuf[:0], i.span.Start...)
     160           2 :                 i.span.Start = i.startKeyBuf
     161           2 :                 if invariants.Enabled && !bytes.Equal(syntheticPrefix, i.endKeyBuf[:len(syntheticPrefix)]) {
     162           0 :                         panic("pebble: invariant violation: synthetic prefix mismatch")
     163             :                 }
     164           2 :                 i.endKeyBuf = append(i.endKeyBuf[:len(syntheticPrefix)], i.span.End...)
     165           2 :                 i.span.End = i.endKeyBuf
     166             :         }
     167             : 
     168           2 :         if i.syntheticPrefixAndSuffix.HasSuffix() {
     169           1 :                 syntheticSuffix := i.syntheticPrefixAndSuffix.Suffix()
     170           1 :                 for keyIdx := range i.span.Keys {
     171           1 :                         k := &i.span.Keys[keyIdx]
     172           1 : 
     173           1 :                         switch k.Kind() {
     174           1 :                         case base.InternalKeyKindRangeKeySet:
     175           1 :                                 if len(k.Suffix) > 0 {
     176           1 :                                         if invariants.Enabled && i.suffixCmp(syntheticSuffix, k.Suffix) >= 0 {
     177           1 :                                                 return base.AssertionFailedf("synthetic suffix %q >= RangeKeySet suffix %q",
     178           1 :                                                         syntheticSuffix, k.Suffix)
     179           1 :                                         }
     180           1 :                                         k.Suffix = syntheticSuffix
     181             :                                 }
     182           1 :                         case base.InternalKeyKindRangeKeyDelete:
     183             :                                 // Nothing to do.
     184           1 :                         default:
     185           1 :                                 return base.AssertionFailedf("synthetic suffix not supported with key kind %s", k.Kind())
     186             :                         }
     187             :                 }
     188             :         }
     189           2 :         return nil
     190             : }
     191             : 
     192             : // gatherForward gathers internal keys with identical bounds. Keys defined over
     193             : // spans of the keyspace are fragmented such that any overlapping key spans have
     194             : // identical bounds. When these spans are persisted to a range deletion or range
     195             : // key block, they may be persisted as multiple internal keys in order to encode
     196             : // multiple sequence numbers or key kinds.
     197             : //
     198             : // gatherForward iterates forward, re-combining the fragmented internal keys to
     199             : // reconstruct a keyspan.Span that holds all the keys defined over the span.
     200           2 : func (i *fragmentIter) gatherForward(kv *base.InternalKV) (*keyspan.Span, error) {
     201           2 :         i.span = keyspan.Span{}
     202           2 :         if kv == nil || !i.blockIter.Valid() {
     203           2 :                 return nil, nil
     204           2 :         }
     205             :         // Use the i.keyBuf array to back the Keys slice to prevent an allocation
     206             :         // when a span contains few keys.
     207           2 :         i.span.Keys = i.keyBuf[:0]
     208           2 : 
     209           2 :         // Decode the span's end key and individual keys from the value.
     210           2 :         if err := i.initSpan(kv.K, kv.InPlaceValue()); err != nil {
     211           0 :                 return nil, err
     212           0 :         }
     213             : 
     214             :         // There might exist additional internal keys with identical bounds encoded
     215             :         // within the block. Iterate forward, accumulating all the keys with
     216             :         // identical bounds to s.
     217             : 
     218             :         // Overlapping fragments are required to have exactly equal start and
     219             :         // end bounds.
     220           2 :         for kv = i.blockIter.Next(); kv != nil && i.blockIter.cmp(kv.K.UserKey, i.span.Start) == 0; kv = i.blockIter.Next() {
     221           2 :                 if err := i.addToSpan(i.blockIter.cmp, kv.K, kv.InPlaceValue()); err != nil {
     222           0 :                         return nil, err
     223           0 :                 }
     224             :         }
     225           2 :         if err := i.applySpanTransforms(); err != nil {
     226           0 :                 return nil, err
     227           0 :         }
     228             : 
     229             :         // Apply a consistent ordering.
     230           2 :         keyspan.SortKeysByTrailer(i.span.Keys)
     231           2 : 
     232           2 :         // i.blockIter is positioned over the first internal key for the next span.
     233           2 :         return &i.span, nil
     234             : }
     235             : 
     236             : // gatherBackward gathers internal keys with identical bounds. Keys defined over
     237             : // spans of the keyspace are fragmented such that any overlapping key spans have
     238             : // identical bounds. When these spans are persisted to a range deletion or range
     239             : // key block, they may be persisted as multiple internal keys in order to encode
     240             : // multiple sequence numbers or key kinds.
     241             : //
     242             : // gatherBackward iterates backwards, re-combining the fragmented internal keys
     243             : // to reconstruct a keyspan.Span that holds all the keys defined over the span.
     244           2 : func (i *fragmentIter) gatherBackward(kv *base.InternalKV) (*keyspan.Span, error) {
     245           2 :         i.span = keyspan.Span{}
     246           2 :         if kv == nil || !i.blockIter.Valid() {
     247           2 :                 return nil, nil
     248           2 :         }
     249             : 
     250             :         // Decode the span's end key and individual keys from the value.
     251           2 :         if err := i.initSpan(kv.K, kv.InPlaceValue()); err != nil {
     252           0 :                 return nil, err
     253           0 :         }
     254             : 
     255             :         // There might exist additional internal keys with identical bounds encoded
     256             :         // within the block. Iterate backward, accumulating all the keys with
     257             :         // identical bounds to s.
     258             :         //
     259             :         // Overlapping fragments are required to have exactly equal start and
     260             :         // end bounds.
     261           2 :         for kv = i.blockIter.Prev(); kv != nil && i.blockIter.cmp(kv.K.UserKey, i.span.Start) == 0; kv = i.blockIter.Prev() {
     262           2 :                 if err := i.addToSpan(i.blockIter.cmp, kv.K, kv.InPlaceValue()); err != nil {
     263           0 :                         return nil, err
     264           0 :                 }
     265             :         }
     266             :         // i.blockIter is positioned over the last internal key for the previous
     267             :         // span.
     268             : 
     269             :         // Apply a consistent ordering.
     270           2 :         keyspan.SortKeysByTrailer(i.span.Keys)
     271           2 : 
     272           2 :         i.applySpanTransforms()
     273           2 :         return &i.span, nil
     274             : }
     275             : 
     276             : // SetContext is part of the FragmentIterator interface.
     277           0 : func (i *fragmentIter) SetContext(ctx context.Context) {}
     278             : 
     279             : // Close implements (keyspan.FragmentIterator).Close.
     280           2 : func (i *fragmentIter) Close() {
     281           2 :         i.blockIter.Close()
     282           2 :         i.closeCheck.Close()
     283           2 : 
     284           2 :         if invariants.Sometimes(25) {
     285           2 :                 // In invariants mode, sometimes don't add the object to the pool so that we
     286           2 :                 // can check for double closes that take longer than the object stays in the
     287           2 :                 // pool.
     288           2 :                 return
     289           2 :         }
     290           2 :         i.span = keyspan.Span{}
     291           2 :         i.dir = 0
     292           2 :         i.fileNum = 0
     293           2 :         i.syntheticPrefixAndSuffix = block.SyntheticPrefixAndSuffix{}
     294           2 :         i.startKeyBuf = i.startKeyBuf[:0]
     295           2 :         i.endKeyBuf = i.endKeyBuf[:0]
     296           2 :         fragmentBlockIterPool.Put(i)
     297             : }
     298             : 
     299             : // First implements (keyspan.FragmentIterator).First
     300           2 : func (i *fragmentIter) First() (*keyspan.Span, error) {
     301           2 :         i.dir = +1
     302           2 :         return i.gatherForward(i.blockIter.First())
     303           2 : }
     304             : 
     305             : // Last implements (keyspan.FragmentIterator).Last.
     306           2 : func (i *fragmentIter) Last() (*keyspan.Span, error) {
     307           2 :         i.dir = -1
     308           2 :         return i.gatherBackward(i.blockIter.Last())
     309           2 : }
     310             : 
     311             : // Next implements (keyspan.FragmentIterator).Next.
     312           2 : func (i *fragmentIter) Next() (*keyspan.Span, error) {
     313           2 :         switch {
     314           2 :         case i.dir == -1 && !i.span.Valid():
     315           2 :                 // Switching directions.
     316           2 :                 //
     317           2 :                 // i.blockIter is exhausted, before the first key. Move onto the first.
     318           2 :                 i.blockIter.First()
     319           2 :                 i.dir = +1
     320           2 :         case i.dir == -1 && i.span.Valid():
     321           2 :                 // Switching directions.
     322           2 :                 //
     323           2 :                 // i.blockIter is currently positioned over the last internal key for
     324           2 :                 // the previous span. Next it once to move to the first internal key
     325           2 :                 // that makes up the current span, and gatherForwaad to land on the
     326           2 :                 // first internal key making up the next span.
     327           2 :                 //
     328           2 :                 // In the diagram below, if the last span returned to the user during
     329           2 :                 // reverse iteration was [b,c), i.blockIter is currently positioned at
     330           2 :                 // [a,b). The block iter must be positioned over [d,e) to gather the
     331           2 :                 // next span's fragments.
     332           2 :                 //
     333           2 :                 //    ... [a,b) [b,c) [b,c) [b,c) [d,e) ...
     334           2 :                 //          ^                       ^
     335           2 :                 //     i.blockIter                 want
     336           2 :                 if x, err := i.gatherForward(i.blockIter.Next()); err != nil {
     337           0 :                         return nil, err
     338           2 :                 } else if invariants.Enabled && !x.Valid() {
     339           0 :                         panic("pebble: invariant violation: next entry unexpectedly invalid")
     340             :                 }
     341           2 :                 i.dir = +1
     342             :         }
     343             :         // We know that this blockIter has in-place values.
     344           2 :         return i.gatherForward(i.blockIter.KV())
     345             : }
     346             : 
     347             : // Prev implements (keyspan.FragmentIterator).Prev.
     348           2 : func (i *fragmentIter) Prev() (*keyspan.Span, error) {
     349           2 :         switch {
     350           2 :         case i.dir == +1 && !i.span.Valid():
     351           2 :                 // Switching directions.
     352           2 :                 //
     353           2 :                 // i.blockIter is exhausted, after the last key. Move onto the last.
     354           2 :                 i.blockIter.Last()
     355           2 :                 i.dir = -1
     356           2 :         case i.dir == +1 && i.span.Valid():
     357           2 :                 // Switching directions.
     358           2 :                 //
     359           2 :                 // i.blockIter is currently positioned over the first internal key for
     360           2 :                 // the next span. Prev it once to move to the last internal key that
     361           2 :                 // makes up the current span, and gatherBackward to land on the last
     362           2 :                 // internal key making up the previous span.
     363           2 :                 //
     364           2 :                 // In the diagram below, if the last span returned to the user during
     365           2 :                 // forward iteration was [b,c), i.blockIter is currently positioned at
     366           2 :                 // [d,e). The block iter must be positioned over [a,b) to gather the
     367           2 :                 // previous span's fragments.
     368           2 :                 //
     369           2 :                 //    ... [a,b) [b,c) [b,c) [b,c) [d,e) ...
     370           2 :                 //          ^                       ^
     371           2 :                 //        want                  i.blockIter
     372           2 :                 if x, err := i.gatherBackward(i.blockIter.Prev()); err != nil {
     373           0 :                         return nil, err
     374           2 :                 } else if invariants.Enabled && !x.Valid() {
     375           0 :                         panic("pebble: invariant violation: previous entry unexpectedly invalid")
     376             :                 }
     377           2 :                 i.dir = -1
     378             :         }
     379             :         // We know that this blockIter has in-place values.
     380           2 :         return i.gatherBackward(i.blockIter.KV())
     381             : }
     382             : 
     383             : // SeekGE implements (keyspan.FragmentIterator).SeekGE.
     384           2 : func (i *fragmentIter) SeekGE(k []byte) (*keyspan.Span, error) {
     385           2 :         if s, err := i.SeekLT(k); err != nil {
     386           0 :                 return nil, err
     387           2 :         } else if s != nil && i.blockIter.cmp(k, s.End) < 0 {
     388           2 :                 return s, nil
     389           2 :         }
     390             :         // TODO(jackson): If the above i.SeekLT(k) discovers a span but the span
     391             :         // doesn't meet the k < s.End comparison, then there's no need for the
     392             :         // SeekLT to gatherBackward.
     393           2 :         return i.Next()
     394             : }
     395             : 
     396             : // SeekLT implements (keyspan.FragmentIterator).SeekLT.
     397           2 : func (i *fragmentIter) SeekLT(k []byte) (*keyspan.Span, error) {
     398           2 :         i.dir = -1
     399           2 :         return i.gatherBackward(i.blockIter.SeekLT(k, base.SeekLTFlagsNone))
     400           2 : }
     401             : 
     402             : // String implements fmt.Stringer.
     403           0 : func (i *fragmentIter) String() string {
     404           0 :         return "fragment-block-iter"
     405           0 : }
     406             : 
     407             : // WrapChildren implements FragmentIterator.
     408           0 : func (i *fragmentIter) WrapChildren(wrap keyspan.WrapFn) {}
     409             : 
     410             : // DebugTree is part of the FragmentIterator interface.
     411           0 : func (i *fragmentIter) DebugTree(tp treeprinter.Node) {
     412           0 :         tp.Childf("%T(%p) fileNum=%s", i, i, i.fileNum)
     413           0 : }
     414             : 
     415           2 : func checkFragmentBlockIterator(obj interface{}) {
     416           2 :         i := obj.(*fragmentIter)
     417           2 :         if h := i.blockIter.Handle(); h.Valid() {
     418           0 :                 fmt.Fprintf(os.Stderr, "fragmentBlockIter.blockIter.handle is not nil: %#v\n", h)
     419           0 :                 os.Exit(1)
     420           0 :         }
     421             : }

Generated by: LCOV version 1.14