LCOV - code coverage report
Current view: top level - pebble/internal/invalidating - iter.go (source / functions) Hit Total Coverage
Test: 2024-04-19 08:16Z 36521833 - tests only.lcov Lines: 91 100 91.0 %
Date: 2024-04-19 08:16:35 Functions: 0 0 -

          Line data    Source code
       1             : // Copyright 2023 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 invalidating
       6             : 
       7             : import (
       8             :         "context"
       9             : 
      10             :         "github.com/cockroachdb/pebble/internal/base"
      11             :         "github.com/cockroachdb/pebble/internal/fastrand"
      12             :         "github.com/cockroachdb/pebble/internal/invariants"
      13             : )
      14             : 
      15             : // MaybeWrapIfInvariants wraps some iterators with an invalidating iterator.
      16             : // MaybeWrapIfInvariants does nothing in non-invariant builds.
      17           1 : func MaybeWrapIfInvariants(iter base.InternalIterator) base.InternalIterator {
      18           1 :         if invariants.Enabled {
      19           1 :                 if fastrand.Uint32n(10) == 1 {
      20           1 :                         return NewIter(iter)
      21           1 :                 }
      22             :         }
      23           1 :         return iter
      24             : }
      25             : 
      26             : // iter tests unsafe key/value slice reuse by modifying the last
      27             : // returned key/value to all 1s.
      28             : type iter struct {
      29             :         iter        base.InternalIterator
      30             :         lastKV      *base.InternalKV
      31             :         ignoreKinds [base.InternalKeyKindMax + 1]bool
      32             :         err         error
      33             : }
      34             : 
      35             : // Option configures the behavior of an invalidating iterator.
      36             : type Option interface {
      37             :         apply(*iter)
      38             : }
      39             : 
      40             : type funcOpt func(*iter)
      41             : 
      42           1 : func (f funcOpt) apply(i *iter) { f(i) }
      43             : 
      44             : // IgnoreKinds constructs an Option that configures an invalidating iterator to
      45             : // skip trashing k/v pairs with the provided key kinds. Some iterators provided
      46             : // key stability guarantees for specific key kinds.
      47           1 : func IgnoreKinds(kinds ...base.InternalKeyKind) Option {
      48           1 :         return funcOpt(func(i *iter) {
      49           1 :                 for _, kind := range kinds {
      50           1 :                         i.ignoreKinds[kind] = true
      51           1 :                 }
      52             :         })
      53             : }
      54             : 
      55             : // NewIter constructs a new invalidating iterator that wraps the provided
      56             : // iterator, trashing buffers for previously returned keys.
      57           1 : func NewIter(originalIterator base.InternalIterator, opts ...Option) base.TopLevelIterator {
      58           1 :         i := &iter{iter: originalIterator}
      59           1 :         for _, opt := range opts {
      60           1 :                 opt.apply(i)
      61           1 :         }
      62           1 :         return i
      63             : }
      64             : 
      65           1 : func (i *iter) update(kv *base.InternalKV) *base.InternalKV {
      66           1 :         i.trashLastKV()
      67           1 :         if kv == nil {
      68           1 :                 i.lastKV = nil
      69           1 :                 return nil
      70           1 :         }
      71             : 
      72           1 :         i.lastKV = &base.InternalKV{
      73           1 :                 K: kv.K.Clone(),
      74           1 :                 V: base.LazyValue{
      75           1 :                         ValueOrHandle: append(make([]byte, 0, len(kv.V.ValueOrHandle)), kv.V.ValueOrHandle...),
      76           1 :                 },
      77           1 :         }
      78           1 :         if kv.V.Fetcher != nil {
      79           1 :                 fetcher := new(base.LazyFetcher)
      80           1 :                 *fetcher = *kv.V.Fetcher
      81           1 :                 i.lastKV.V.Fetcher = fetcher
      82           1 :         }
      83           1 :         return i.lastKV
      84             : }
      85             : 
      86           1 : func (i *iter) trashLastKV() {
      87           1 :         if i.lastKV == nil {
      88           1 :                 return
      89           1 :         }
      90           1 :         if i.ignoreKinds[i.lastKV.Kind()] {
      91           1 :                 return
      92           1 :         }
      93             : 
      94           1 :         if i.lastKV != nil {
      95           1 :                 for j := range i.lastKV.K.UserKey {
      96           1 :                         i.lastKV.K.UserKey[j] = 0xff
      97           1 :                 }
      98           1 :                 i.lastKV.K.Trailer = 0xffffffffffffffff
      99             :         }
     100           1 :         for j := range i.lastKV.V.ValueOrHandle {
     101           1 :                 i.lastKV.V.ValueOrHandle[j] = 0xff
     102           1 :         }
     103           1 :         if i.lastKV.V.Fetcher != nil {
     104           1 :                 // Not all the LazyFetcher fields are visible, so we zero out the last
     105           1 :                 // value's Fetcher struct entirely.
     106           1 :                 *i.lastKV.V.Fetcher = base.LazyFetcher{}
     107           1 :         }
     108             : }
     109             : 
     110           1 : func (i *iter) SeekGE(key []byte, flags base.SeekGEFlags) *base.InternalKV {
     111           1 :         return i.update(i.iter.SeekGE(key, flags))
     112           1 : }
     113             : 
     114           1 : func (i *iter) SeekPrefixGE(prefix, key []byte, flags base.SeekGEFlags) *base.InternalKV {
     115           1 :         return i.update(i.iter.SeekPrefixGE(prefix, key, flags))
     116           1 : }
     117             : 
     118           0 : func (i *iter) SeekPrefixGEStrict(prefix, key []byte, flags base.SeekGEFlags) *base.InternalKV {
     119           0 :         return i.update(i.iter.SeekPrefixGE(prefix, key, flags))
     120           0 : }
     121             : 
     122           1 : func (i *iter) SeekLT(key []byte, flags base.SeekLTFlags) *base.InternalKV {
     123           1 :         return i.update(i.iter.SeekLT(key, flags))
     124           1 : }
     125             : 
     126           1 : func (i *iter) First() *base.InternalKV {
     127           1 :         return i.update(i.iter.First())
     128           1 : }
     129             : 
     130           1 : func (i *iter) Last() *base.InternalKV {
     131           1 :         return i.update(i.iter.Last())
     132           1 : }
     133             : 
     134           1 : func (i *iter) Next() *base.InternalKV {
     135           1 :         return i.update(i.iter.Next())
     136           1 : }
     137             : 
     138           1 : func (i *iter) Prev() *base.InternalKV {
     139           1 :         return i.update(i.iter.Prev())
     140           1 : }
     141             : 
     142           1 : func (i *iter) NextPrefix(succKey []byte) *base.InternalKV {
     143           1 :         return i.update(i.iter.NextPrefix(succKey))
     144           1 : }
     145             : 
     146           1 : func (i *iter) Error() error {
     147           1 :         if err := i.iter.Error(); err != nil {
     148           1 :                 return err
     149           1 :         }
     150           1 :         return i.err
     151             : }
     152             : 
     153           1 : func (i *iter) Close() error {
     154           1 :         return i.iter.Close()
     155           1 : }
     156             : 
     157           1 : func (i *iter) SetBounds(lower, upper []byte) {
     158           1 :         i.iter.SetBounds(lower, upper)
     159           1 : }
     160             : 
     161           0 : func (i *iter) SetContext(ctx context.Context) {
     162           0 :         i.iter.SetContext(ctx)
     163           0 : }
     164             : 
     165           0 : func (i *iter) String() string {
     166           0 :         return i.iter.String()
     167           0 : }

Generated by: LCOV version 1.14