LCOV - code coverage report
Current view: top level - pebble/sstable/rowblk - rowblk_fragment_iter.go (source / functions) Hit Total Coverage
Test: 2024-07-02 08:16Z 4981bd0e - tests + meta.lcov Lines: 173 197 87.8 %
Date: 2024-07-02 08:17:10 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             :         "fmt"
       9             :         "os"
      10             :         "sync"
      11             : 
      12             :         "github.com/cockroachdb/pebble/internal/base"
      13             :         "github.com/cockroachdb/pebble/internal/invariants"
      14             :         "github.com/cockroachdb/pebble/internal/keyspan"
      15             :         "github.com/cockroachdb/pebble/internal/rangedel"
      16             :         "github.com/cockroachdb/pebble/internal/rangekey"
      17             :         "github.com/cockroachdb/pebble/sstable/block"
      18             : )
      19             : 
      20             : // fragmentIter wraps an Iter, implementing the keyspan.FragmentIterator
      21             : // interface. It's used for reading range deletion and range key blocks.
      22             : //
      23             : // Range deletions and range keys are fragmented before they're persisted to the
      24             : // block. Overlapping fragments have identical bounds.  The fragmentIter gathers
      25             : // all the fragments with identical bounds within a block and returns a single
      26             : // keyspan.Span describing all the keys defined over the span.
      27             : //
      28             : // # Memory lifetime
      29             : //
      30             : // A Span returned by fragmentIter is only guaranteed to be stable until the
      31             : // next fragmentIter iteration positioning method. A Span's Keys slice may be
      32             : // reused, so the user must not assume it's stable.
      33             : //
      34             : // Blocks holding range deletions and range keys are configured to use a restart
      35             : // interval of 1. This provides key stability. The caller may treat the various
      36             : // byte slices (start, end, suffix, value) as stable for the lifetime of the
      37             : // iterator.
      38             : type fragmentIter struct {
      39             :         blockIter Iter
      40             :         keyBuf    [2]keyspan.Key
      41             :         span      keyspan.Span
      42             :         dir       int8
      43             : 
      44             :         // elideSameSeqnum, if true, returns only the first-occurring (in forward
      45             :         // order) Key for each sequence number.
      46             :         elideSameSeqnum bool
      47             :         closeCheck      invariants.CloseChecker
      48             : }
      49             : 
      50             : var _ keyspan.FragmentIterator = (*fragmentIter)(nil)
      51             : 
      52             : var fragmentBlockIterPool = sync.Pool{
      53           2 :         New: func() interface{} {
      54           2 :                 i := &fragmentIter{}
      55           2 :                 // Note: this is a no-op if invariants are disabled or race is enabled.
      56           2 :                 invariants.SetFinalizer(i, checkFragmentBlockIterator)
      57           2 :                 return i
      58           2 :         },
      59             : }
      60             : 
      61             : // NewFragmentIter returns a new keyspan iterator that iterates over a block's
      62             : // spans.
      63             : func NewFragmentIter(
      64             :         cmp base.Compare,
      65             :         split base.Split,
      66             :         blockHandle block.BufferHandle,
      67             :         transforms block.FragmentIterTransforms,
      68           2 : ) (keyspan.FragmentIterator, error) {
      69           2 :         i := fragmentBlockIterPool.Get().(*fragmentIter)
      70           2 : 
      71           2 :         // Use the i.keyBuf array to back the Keys slice to prevent an allocation
      72           2 :         // when the spans contain few keys.
      73           2 :         i.span.Keys = i.keyBuf[:0]
      74           2 :         i.elideSameSeqnum = transforms.ElideSameSeqNum
      75           2 :         i.closeCheck = invariants.CloseChecker{}
      76           2 : 
      77           2 :         if err := i.blockIter.InitHandle(cmp, split, blockHandle, block.IterTransforms{
      78           2 :                 SyntheticSeqNum: transforms.SyntheticSeqNum,
      79           2 :                 // It's okay for HideObsoletePoints to be false here, even for shared
      80           2 :                 // ingested sstables. This is because rangedels do not apply to points in
      81           2 :                 // the same sstable at the same sequence number anyway, so exposing obsolete
      82           2 :                 // rangedels is harmless.
      83           2 :                 HideObsoletePoints: false,
      84           2 :         }); err != nil {
      85           0 :                 i.Close()
      86           0 :                 return nil, err
      87           0 :         }
      88           2 :         return i, nil
      89             : }
      90             : 
      91             : // initSpan initializes the span with a single fragment.
      92             : // Note that the span start and end keys and range key contents are aliased to
      93             : // the key or value. This is ok because the range del/key block doesn't use
      94             : // prefix compression (and we don't perform any transforms), so the key/value
      95             : // will be pointing directly into the buffer data.
      96           2 : func (i *fragmentIter) initSpan(ik base.InternalKey, internalValue []byte) error {
      97           2 :         var err error
      98           2 :         if ik.Kind() == base.InternalKeyKindRangeDelete {
      99           2 :                 i.span = rangedel.Decode(ik, internalValue, i.span.Keys[:0])
     100           2 :         } else {
     101           2 :                 i.span, err = rangekey.Decode(ik, internalValue, i.span.Keys[:0])
     102           2 :         }
     103           2 :         return err
     104             : }
     105             : 
     106             : // addToSpan adds a fragment to the existing span. The fragment must be for the
     107             : // same start/end keys.
     108             : func (i *fragmentIter) addToSpan(
     109             :         cmp base.Compare, ik base.InternalKey, internalValue []byte,
     110           2 : ) error {
     111           2 :         var err error
     112           2 :         if ik.Kind() == base.InternalKeyKindRangeDelete {
     113           2 :                 err = rangedel.DecodeIntoSpan(cmp, ik, internalValue, &i.span)
     114           2 :         } else {
     115           2 :                 err = rangekey.DecodeIntoSpan(cmp, ik, internalValue, &i.span)
     116           2 :         }
     117           2 :         return err
     118             : }
     119             : 
     120           2 : func (i *fragmentIter) elideKeysOfSameSeqNum() {
     121           2 :         if invariants.Enabled {
     122           2 :                 if !i.elideSameSeqnum || len(i.span.Keys) == 0 {
     123           0 :                         panic("elideKeysOfSameSeqNum called when it should not be")
     124             :                 }
     125             :         }
     126           2 :         lastSeqNum := i.span.Keys[0].SeqNum()
     127           2 :         k := 1
     128           2 :         for j := 1; j < len(i.span.Keys); j++ {
     129           2 :                 if lastSeqNum != i.span.Keys[j].SeqNum() {
     130           2 :                         lastSeqNum = i.span.Keys[j].SeqNum()
     131           2 :                         i.span.Keys[k] = i.span.Keys[j]
     132           2 :                         k++
     133           2 :                 }
     134             :         }
     135           2 :         i.span.Keys = i.span.Keys[:k]
     136             : }
     137             : 
     138             : // gatherForward gathers internal keys with identical bounds. Keys defined over
     139             : // spans of the keyspace are fragmented such that any overlapping key spans have
     140             : // identical bounds. When these spans are persisted to a range deletion or range
     141             : // key block, they may be persisted as multiple internal keys in order to encode
     142             : // multiple sequence numbers or key kinds.
     143             : //
     144             : // gatherForward iterates forward, re-combining the fragmented internal keys to
     145             : // reconstruct a keyspan.Span that holds all the keys defined over the span.
     146           2 : func (i *fragmentIter) gatherForward(kv *base.InternalKV) (*keyspan.Span, error) {
     147           2 :         i.span = keyspan.Span{}
     148           2 :         if kv == nil || !i.blockIter.Valid() {
     149           2 :                 return nil, nil
     150           2 :         }
     151             :         // Use the i.keyBuf array to back the Keys slice to prevent an allocation
     152             :         // when a span contains few keys.
     153           2 :         i.span.Keys = i.keyBuf[:0]
     154           2 : 
     155           2 :         // Decode the span's end key and individual keys from the value.
     156           2 :         if err := i.initSpan(kv.K, kv.InPlaceValue()); err != nil {
     157           0 :                 return nil, err
     158           0 :         }
     159             : 
     160             :         // There might exist additional internal keys with identical bounds encoded
     161             :         // within the block. Iterate forward, accumulating all the keys with
     162             :         // identical bounds to s.
     163             : 
     164             :         // Overlapping fragments are required to have exactly equal start and
     165             :         // end bounds.
     166           2 :         for kv = i.blockIter.Next(); kv != nil && i.blockIter.cmp(kv.K.UserKey, i.span.Start) == 0; kv = i.blockIter.Next() {
     167           2 :                 if err := i.addToSpan(i.blockIter.cmp, kv.K, kv.InPlaceValue()); err != nil {
     168           0 :                         return nil, err
     169           0 :                 }
     170             :         }
     171           2 :         if i.elideSameSeqnum && len(i.span.Keys) > 0 {
     172           2 :                 i.elideKeysOfSameSeqNum()
     173           2 :         }
     174             :         // i.blockIter is positioned over the first internal key for the next span.
     175           2 :         return &i.span, nil
     176             : }
     177             : 
     178             : // gatherBackward gathers internal keys with identical bounds. Keys defined over
     179             : // spans of the keyspace are fragmented such that any overlapping key spans have
     180             : // identical bounds. When these spans are persisted to a range deletion or range
     181             : // key block, they may be persisted as multiple internal keys in order to encode
     182             : // multiple sequence numbers or key kinds.
     183             : //
     184             : // gatherBackward iterates backwards, re-combining the fragmented internal keys
     185             : // to reconstruct a keyspan.Span that holds all the keys defined over the span.
     186           2 : func (i *fragmentIter) gatherBackward(kv *base.InternalKV) (*keyspan.Span, error) {
     187           2 :         i.span = keyspan.Span{}
     188           2 :         if kv == nil || !i.blockIter.Valid() {
     189           2 :                 return nil, nil
     190           2 :         }
     191             : 
     192             :         // Decode the span's end key and individual keys from the value.
     193           2 :         if err := i.initSpan(kv.K, kv.InPlaceValue()); err != nil {
     194           0 :                 return nil, err
     195           0 :         }
     196             : 
     197             :         // There might exist additional internal keys with identical bounds encoded
     198             :         // within the block. Iterate backward, accumulating all the keys with
     199             :         // identical bounds to s.
     200             :         //
     201             :         // Overlapping fragments are required to have exactly equal start and
     202             :         // end bounds.
     203           2 :         for kv = i.blockIter.Prev(); kv != nil && i.blockIter.cmp(kv.K.UserKey, i.span.Start) == 0; kv = i.blockIter.Prev() {
     204           2 :                 if err := i.addToSpan(i.blockIter.cmp, kv.K, kv.InPlaceValue()); err != nil {
     205           0 :                         return nil, err
     206           0 :                 }
     207             :         }
     208             :         // i.blockIter is positioned over the last internal key for the previous
     209             :         // span.
     210             : 
     211             :         // Backwards iteration encounters internal keys in the wrong order.
     212           2 :         keyspan.SortKeysByTrailer(&i.span.Keys)
     213           2 : 
     214           2 :         if i.elideSameSeqnum && len(i.span.Keys) > 0 {
     215           2 :                 i.elideKeysOfSameSeqNum()
     216           2 :         }
     217           2 :         return &i.span, nil
     218             : }
     219             : 
     220             : // Close implements (keyspan.FragmentIterator).Close.
     221           2 : func (i *fragmentIter) Close() {
     222           2 :         i.blockIter.Close()
     223           2 :         i.closeCheck.Close()
     224           2 : 
     225           2 :         if invariants.Sometimes(25) {
     226           2 :                 // In invariants mode, sometimes don't add the object to the pool so that we
     227           2 :                 // can check for double closes that take longer than the object stays in the
     228           2 :                 // pool.
     229           2 :                 return
     230           2 :         }
     231             : 
     232           2 :         *i = fragmentIter{
     233           2 :                 blockIter:  i.blockIter.ResetForReuse(),
     234           2 :                 closeCheck: i.closeCheck,
     235           2 :         }
     236           2 :         fragmentBlockIterPool.Put(i)
     237             : }
     238             : 
     239             : // First implements (keyspan.FragmentIterator).First
     240           2 : func (i *fragmentIter) First() (*keyspan.Span, error) {
     241           2 :         i.dir = +1
     242           2 :         return i.gatherForward(i.blockIter.First())
     243           2 : }
     244             : 
     245             : // Last implements (keyspan.FragmentIterator).Last.
     246           2 : func (i *fragmentIter) Last() (*keyspan.Span, error) {
     247           2 :         i.dir = -1
     248           2 :         return i.gatherBackward(i.blockIter.Last())
     249           2 : }
     250             : 
     251             : // Next implements (keyspan.FragmentIterator).Next.
     252           2 : func (i *fragmentIter) Next() (*keyspan.Span, error) {
     253           2 :         switch {
     254           2 :         case i.dir == -1 && !i.span.Valid():
     255           2 :                 // Switching directions.
     256           2 :                 //
     257           2 :                 // i.blockIter is exhausted, before the first key. Move onto the first.
     258           2 :                 i.blockIter.First()
     259           2 :                 i.dir = +1
     260           2 :         case i.dir == -1 && i.span.Valid():
     261           2 :                 // Switching directions.
     262           2 :                 //
     263           2 :                 // i.blockIter is currently positioned over the last internal key for
     264           2 :                 // the previous span. Next it once to move to the first internal key
     265           2 :                 // that makes up the current span, and gatherForwaad to land on the
     266           2 :                 // first internal key making up the next span.
     267           2 :                 //
     268           2 :                 // In the diagram below, if the last span returned to the user during
     269           2 :                 // reverse iteration was [b,c), i.blockIter is currently positioned at
     270           2 :                 // [a,b). The block iter must be positioned over [d,e) to gather the
     271           2 :                 // next span's fragments.
     272           2 :                 //
     273           2 :                 //    ... [a,b) [b,c) [b,c) [b,c) [d,e) ...
     274           2 :                 //          ^                       ^
     275           2 :                 //     i.blockIter                 want
     276           2 :                 if x, err := i.gatherForward(i.blockIter.Next()); err != nil {
     277           0 :                         return nil, err
     278           2 :                 } else if invariants.Enabled && !x.Valid() {
     279           0 :                         panic("pebble: invariant violation: next entry unexpectedly invalid")
     280             :                 }
     281           2 :                 i.dir = +1
     282             :         }
     283             :         // We know that this blockIter has in-place values.
     284           2 :         return i.gatherForward(i.blockIter.KV())
     285             : }
     286             : 
     287             : // Prev implements (keyspan.FragmentIterator).Prev.
     288           2 : func (i *fragmentIter) Prev() (*keyspan.Span, error) {
     289           2 :         switch {
     290           2 :         case i.dir == +1 && !i.span.Valid():
     291           2 :                 // Switching directions.
     292           2 :                 //
     293           2 :                 // i.blockIter is exhausted, after the last key. Move onto the last.
     294           2 :                 i.blockIter.Last()
     295           2 :                 i.dir = -1
     296           2 :         case i.dir == +1 && i.span.Valid():
     297           2 :                 // Switching directions.
     298           2 :                 //
     299           2 :                 // i.blockIter is currently positioned over the first internal key for
     300           2 :                 // the next span. Prev it once to move to the last internal key that
     301           2 :                 // makes up the current span, and gatherBackward to land on the last
     302           2 :                 // internal key making up the previous span.
     303           2 :                 //
     304           2 :                 // In the diagram below, if the last span returned to the user during
     305           2 :                 // forward iteration was [b,c), i.blockIter is currently positioned at
     306           2 :                 // [d,e). The block iter must be positioned over [a,b) to gather the
     307           2 :                 // previous span's fragments.
     308           2 :                 //
     309           2 :                 //    ... [a,b) [b,c) [b,c) [b,c) [d,e) ...
     310           2 :                 //          ^                       ^
     311           2 :                 //        want                  i.blockIter
     312           2 :                 if x, err := i.gatherBackward(i.blockIter.Prev()); err != nil {
     313           0 :                         return nil, err
     314           2 :                 } else if invariants.Enabled && !x.Valid() {
     315           0 :                         panic("pebble: invariant violation: previous entry unexpectedly invalid")
     316             :                 }
     317           2 :                 i.dir = -1
     318             :         }
     319             :         // We know that this blockIter has in-place values.
     320           2 :         return i.gatherBackward(i.blockIter.KV())
     321             : }
     322             : 
     323             : // SeekGE implements (keyspan.FragmentIterator).SeekGE.
     324           2 : func (i *fragmentIter) SeekGE(k []byte) (*keyspan.Span, error) {
     325           2 :         if s, err := i.SeekLT(k); err != nil {
     326           0 :                 return nil, err
     327           2 :         } else if s != nil && i.blockIter.cmp(k, s.End) < 0 {
     328           2 :                 return s, nil
     329           2 :         }
     330             :         // TODO(jackson): If the above i.SeekLT(k) discovers a span but the span
     331             :         // doesn't meet the k < s.End comparison, then there's no need for the
     332             :         // SeekLT to gatherBackward.
     333           2 :         return i.Next()
     334             : }
     335             : 
     336             : // SeekLT implements (keyspan.FragmentIterator).SeekLT.
     337           2 : func (i *fragmentIter) SeekLT(k []byte) (*keyspan.Span, error) {
     338           2 :         i.dir = -1
     339           2 :         return i.gatherBackward(i.blockIter.SeekLT(k, base.SeekLTFlagsNone))
     340           2 : }
     341             : 
     342             : // String implements fmt.Stringer.
     343           0 : func (i *fragmentIter) String() string {
     344           0 :         return "fragment-block-iter"
     345           0 : }
     346             : 
     347             : // WrapChildren implements FragmentIterator.
     348           0 : func (i *fragmentIter) WrapChildren(wrap keyspan.WrapFn) {}
     349             : 
     350           2 : func checkFragmentBlockIterator(obj interface{}) {
     351           2 :         i := obj.(*fragmentIter)
     352           2 :         if p := i.blockIter.Handle().Get(); p != nil {
     353           0 :                 fmt.Fprintf(os.Stderr, "fragmentBlockIter.blockIter.handle is not nil: %p\n", p)
     354           0 :                 os.Exit(1)
     355           0 :         }
     356             : }

Generated by: LCOV version 1.14