LCOV - code coverage report
Current view: top level - pebble/metamorphic - retryable.go (source / functions) Hit Total Coverage
Test: 2023-12-11 08:16Z f16e0f48 - tests only.lcov Lines: 107 113 94.7 %
Date: 2023-12-11 08:16:34 Functions: 0 0 -

          Line data    Source code
       1             : // Copyright 2020 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 metamorphic
       6             : 
       7             : import (
       8             :         "github.com/cockroachdb/errors"
       9             :         "github.com/cockroachdb/pebble"
      10             :         "github.com/cockroachdb/pebble/vfs/errorfs"
      11             : )
      12             : 
      13             : // withRetries executes fn, retrying it whenever an errorfs.ErrInjected error
      14             : // is returned.  It returns the first nil or non-errorfs.ErrInjected error
      15             : // returned by fn.
      16           1 : func withRetries(fn func() error) error {
      17           1 :         for {
      18           1 :                 if err := fn(); !errors.Is(err, errorfs.ErrInjected) {
      19           1 :                         return err
      20           1 :                 }
      21             :         }
      22             : }
      23             : 
      24             : // retryableIter holds an iterator and the state necessary to reset it to its
      25             : // state after the last successful operation. This allows us to retry failed
      26             : // iterator operations by running them again on a non-error iterator with the
      27             : // same pre-operation state.
      28             : type retryableIter struct {
      29             :         iter    *pebble.Iterator
      30             :         lastKey []byte
      31             : }
      32             : 
      33           1 : func (i *retryableIter) needRetry() bool {
      34           1 :         return errors.Is(i.iter.Error(), errorfs.ErrInjected)
      35           1 : }
      36             : 
      37           1 : func (i *retryableIter) withRetry(fn func()) {
      38           1 :         for {
      39           1 :                 fn()
      40           1 :                 if !i.needRetry() {
      41           1 :                         break
      42             :                 }
      43           0 :                 for i.needRetry() {
      44           0 :                         i.iter.SeekGE(i.lastKey)
      45           0 :                 }
      46             :         }
      47             : 
      48           1 :         i.lastKey = i.lastKey[:0]
      49           1 :         if i.iter.Valid() {
      50           1 :                 i.lastKey = append(i.lastKey, i.iter.Key()...)
      51           1 :         }
      52             : }
      53             : 
      54           1 : func (i *retryableIter) Close() error {
      55           1 :         return i.iter.Close()
      56           1 : }
      57             : 
      58           1 : func (i *retryableIter) Error() error {
      59           1 :         return i.iter.Error()
      60           1 : }
      61             : 
      62           1 : func (i *retryableIter) First() bool {
      63           1 :         var valid bool
      64           1 :         i.withRetry(func() {
      65           1 :                 valid = i.iter.First()
      66           1 :         })
      67           1 :         return valid
      68             : }
      69             : 
      70           1 : func (i *retryableIter) Key() []byte {
      71           1 :         return i.iter.Key()
      72           1 : }
      73             : 
      74           1 : func (i *retryableIter) RangeKeyChanged() bool {
      75           1 :         return i.iter.RangeKeyChanged()
      76           1 : }
      77             : 
      78           1 : func (i *retryableIter) HasPointAndRange() (bool, bool) {
      79           1 :         return i.iter.HasPointAndRange()
      80           1 : }
      81             : 
      82           1 : func (i *retryableIter) RangeBounds() ([]byte, []byte) {
      83           1 :         return i.iter.RangeBounds()
      84           1 : }
      85             : 
      86           1 : func (i *retryableIter) RangeKeys() []pebble.RangeKeyData {
      87           1 :         return i.iter.RangeKeys()
      88           1 : }
      89             : 
      90           1 : func (i *retryableIter) Last() bool {
      91           1 :         var valid bool
      92           1 :         i.withRetry(func() { valid = i.iter.Last() })
      93           1 :         return valid
      94             : }
      95             : 
      96           1 : func (i *retryableIter) Next() bool {
      97           1 :         var valid bool
      98           1 :         i.withRetry(func() {
      99           1 :                 valid = i.iter.Next()
     100           1 :         })
     101           1 :         return valid
     102             : }
     103             : 
     104           1 : func (i *retryableIter) NextWithLimit(limit []byte) pebble.IterValidityState {
     105           1 :         var validity pebble.IterValidityState
     106           1 :         i.withRetry(func() {
     107           1 :                 validity = i.iter.NextWithLimit(limit)
     108           1 :         })
     109           1 :         return validity
     110             : 
     111             : }
     112             : 
     113           1 : func (i *retryableIter) NextPrefix() bool {
     114           1 :         var valid bool
     115           1 :         i.withRetry(func() {
     116           1 :                 valid = i.iter.NextPrefix()
     117           1 :         })
     118           1 :         return valid
     119             : }
     120             : 
     121           1 : func (i *retryableIter) Prev() bool {
     122           1 :         var valid bool
     123           1 :         i.withRetry(func() {
     124           1 :                 valid = i.iter.Prev()
     125           1 :         })
     126           1 :         return valid
     127             : }
     128             : 
     129           1 : func (i *retryableIter) PrevWithLimit(limit []byte) pebble.IterValidityState {
     130           1 :         var validity pebble.IterValidityState
     131           1 :         i.withRetry(func() {
     132           1 :                 validity = i.iter.PrevWithLimit(limit)
     133           1 :         })
     134           1 :         return validity
     135             : }
     136             : 
     137           1 : func (i *retryableIter) SeekGE(key []byte) bool {
     138           1 :         var valid bool
     139           1 :         i.withRetry(func() { valid = i.iter.SeekGE(key) })
     140           1 :         return valid
     141             : }
     142             : 
     143           1 : func (i *retryableIter) SeekGEWithLimit(key []byte, limit []byte) pebble.IterValidityState {
     144           1 :         var validity pebble.IterValidityState
     145           1 :         i.withRetry(func() { validity = i.iter.SeekGEWithLimit(key, limit) })
     146           1 :         return validity
     147             : }
     148             : 
     149           1 : func (i *retryableIter) SeekLT(key []byte) bool {
     150           1 :         var valid bool
     151           1 :         i.withRetry(func() { valid = i.iter.SeekLT(key) })
     152           1 :         return valid
     153             : }
     154             : 
     155           1 : func (i *retryableIter) SeekLTWithLimit(key []byte, limit []byte) pebble.IterValidityState {
     156           1 :         var validity pebble.IterValidityState
     157           1 :         i.withRetry(func() { validity = i.iter.SeekLTWithLimit(key, limit) })
     158           1 :         return validity
     159             : }
     160             : 
     161           1 : func (i *retryableIter) SeekPrefixGE(key []byte) bool {
     162           1 :         var valid bool
     163           1 :         i.withRetry(func() { valid = i.iter.SeekPrefixGE(key) })
     164           1 :         return valid
     165             : }
     166             : 
     167           1 : func (i *retryableIter) SetBounds(lower, upper []byte) {
     168           1 :         i.iter.SetBounds(lower, upper)
     169           1 : }
     170             : 
     171           1 : func (i *retryableIter) SetOptions(opts *pebble.IterOptions) {
     172           1 :         i.iter.SetOptions(opts)
     173           1 : }
     174             : 
     175           0 : func (i *retryableIter) Valid() bool {
     176           0 :         return i.iter.Valid()
     177           0 : }
     178             : 
     179           1 : func (i *retryableIter) Value() []byte {
     180           1 :         return i.iter.Value()
     181           1 : }

Generated by: LCOV version 1.14