github.com/vescale/zgraph@v0.0.0-20230410094002-959c02d50f95/storage/snapshot_iterator.go (about)

     1  // Copyright 2022 zGraph Authors. All rights reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package storage
    16  
    17  import (
    18  	"bytes"
    19  	"sync"
    20  
    21  	"github.com/cenkalti/backoff"
    22  	"github.com/cockroachdb/pebble"
    23  	"github.com/vescale/zgraph/storage/kv"
    24  	"github.com/vescale/zgraph/storage/mvcc"
    25  	"github.com/vescale/zgraph/storage/resolver"
    26  )
    27  
    28  // SnapshotIter represents a iterator which provides a consistent view of key/value store.
    29  type SnapshotIter struct {
    30  	db       *pebble.DB
    31  	vp       kv.VersionProvider
    32  	ver      kv.Version
    33  	inner    *pebble.Iterator
    34  	resolver *resolver.Scheduler
    35  	mu       struct {
    36  		sync.RWMutex
    37  		resolved []kv.Version
    38  	}
    39  
    40  	// Iterator states
    41  	valid   bool
    42  	reverse bool
    43  	key     kv.Key
    44  	val     []byte
    45  	nextKey kv.Key
    46  
    47  	// Only for reverse iterator
    48  	entry mvcc.Entry
    49  }
    50  
    51  // Valid implements the Iterator interface.
    52  func (i *SnapshotIter) Valid() bool {
    53  	return i.valid
    54  }
    55  
    56  // Key implements the Iterator interface.
    57  func (i *SnapshotIter) Key() kv.Key {
    58  	return i.key
    59  }
    60  
    61  // Value implements the Iterator interface.
    62  func (i *SnapshotIter) Value() []byte {
    63  	return i.val
    64  }
    65  
    66  // Next implements the Iterator interface.
    67  func (i *SnapshotIter) Next() error {
    68  	err := backoff.RetryNotify(func() error {
    69  		i.valid = i.inner.Valid()
    70  		if !i.valid {
    71  			return nil
    72  		}
    73  
    74  		var err error
    75  		if i.reverse {
    76  			err = i.reverseNext()
    77  		} else {
    78  			err = i.next()
    79  		}
    80  
    81  		if err != nil {
    82  			lockedErr, ok := err.(*mvcc.LockedError)
    83  			if !ok {
    84  				return err
    85  			}
    86  			// Try to resolve lock
    87  			status, err := resolver.CheckTxnStatus(i.db, i.vp, lockedErr.Primary, lockedErr.StartVer)
    88  			if err != nil {
    89  				return &backoff.PermanentError{Err: err}
    90  			}
    91  			switch status.Action {
    92  			case resolver.TxnActionNone:
    93  				// Transaction is still alive and try it letter.
    94  				err = resolver.ErrRetryable("txn still alive")
    95  
    96  			case resolver.TxnActionTTLExpireRollback,
    97  				resolver.TxnActionLockNotExistRollback:
    98  				// Resolve the current key.
    99  				i.resolver.Resolve([]kv.Key{lockedErr.Key}, lockedErr.StartVer, 0, nil)
   100  				// Put the resolve transaction into the resolved list to make the
   101  				// subsequent request bypass them.
   102  				i.mu.Lock()
   103  				i.mu.resolved = append(i.mu.resolved, lockedErr.StartVer)
   104  				i.mu.Unlock()
   105  				err = resolver.ErrRetryable("bypass rollback transaction")
   106  
   107  			default:
   108  				// TxnActionLockNotExistDoNothing
   109  				// Transaction committed: we try to resolve the current key and backoff.
   110  				i.resolver.Resolve([]kv.Key{lockedErr.Key}, lockedErr.StartVer, status.CommitVer, nil)
   111  				err = resolver.ErrRetryable("resolving committed transaction")
   112  			}
   113  
   114  			// We must make the iterator point to the correct key.
   115  			i.resetIter()
   116  			return err
   117  		}
   118  
   119  		return nil
   120  	}, expoBackoff(), BackoffErrReporter("SnapshotIter.Next"))
   121  
   122  	return err
   123  }
   124  
   125  func (i *SnapshotIter) resetIter() {
   126  	lowerBound, upperBound := i.inner.RangeBounds()
   127  	if i.reverse {
   128  		iter := i.db.NewIter(&pebble.IterOptions{
   129  			LowerBound: lowerBound,
   130  			UpperBound: i.nextKey.PrefixNext(),
   131  		})
   132  		iter.Last()
   133  		i.inner = iter
   134  	} else {
   135  		iter := i.db.NewIter(&pebble.IterOptions{
   136  			LowerBound: mvcc.LockKey(i.nextKey),
   137  			UpperBound: upperBound,
   138  		})
   139  		iter.First()
   140  		i.inner = iter
   141  	}
   142  }
   143  
   144  // Close implements the Iterator interface.
   145  func (i *SnapshotIter) Close() {
   146  	_ = i.inner.Close()
   147  }
   148  
   149  func (i *SnapshotIter) next() error {
   150  	for hasNext := true; hasNext; {
   151  		i.mu.RLock()
   152  		resolved := i.mu.resolved
   153  		i.mu.RUnlock()
   154  		val, err := getValue(i.inner, i.nextKey, i.ver, resolved)
   155  		if err != nil {
   156  			return err
   157  		}
   158  
   159  		// We cannot early return here because we must skip the remained
   160  		// versions and set the next key properly.
   161  		if val != nil {
   162  			i.key = i.nextKey
   163  			i.val = val
   164  		}
   165  
   166  		// Skip the remained multiple versions if we found a valid value.
   167  		// Or seek to the next valid key.
   168  		skip := mvcc.SkipDecoder{CurrKey: i.nextKey}
   169  		hasNext, err = skip.Decode(i.inner)
   170  		if err != nil {
   171  			return err
   172  		}
   173  		i.nextKey = skip.CurrKey
   174  
   175  		// Early return if we found a valid value.
   176  		if val != nil {
   177  			return nil
   178  		}
   179  	}
   180  
   181  	// This position means we didn't find a valid value in the above loop.
   182  	// We should set the valid flag into false to avoid the caller read
   183  	// previous key/value.
   184  	i.valid = false
   185  
   186  	return nil
   187  }
   188  
   189  func (i *SnapshotIter) reverseNext() error {
   190  	for hasPrev := true; hasPrev; {
   191  		key, ver, err := mvcc.Decode(i.inner.Key())
   192  		if err != nil {
   193  			return err
   194  		}
   195  		if !bytes.Equal(key, i.nextKey) {
   196  			err := i.finishEntry()
   197  			if err != nil {
   198  				return err
   199  			}
   200  			i.key = i.nextKey
   201  			i.nextKey = key
   202  
   203  			// Early return if we found a valid value. The SnapshotReverseIter will
   204  			// continue to decode the next different key because the inner iterator
   205  			// had pointed to next different key.
   206  			if len(i.val) > 0 {
   207  				return nil
   208  			}
   209  		}
   210  		val, err := i.inner.ValueAndErr()
   211  		if err != nil {
   212  			return err
   213  		}
   214  		if ver == mvcc.LockVer {
   215  			var lock mvcc.Lock
   216  			err = lock.UnmarshalBinary(val)
   217  		} else {
   218  			var value mvcc.Value
   219  			err = value.UnmarshalBinary(val)
   220  			i.entry.Values = append(i.entry.Values, value)
   221  		}
   222  		if err != nil {
   223  			return err
   224  		}
   225  		hasPrev = i.inner.Prev()
   226  
   227  		// Set the key/value to properly value if there is no previous key/value.
   228  		if !hasPrev {
   229  			err := i.finishEntry()
   230  			if err != nil {
   231  				return err
   232  			}
   233  			i.key = i.nextKey
   234  		}
   235  	}
   236  
   237  	// This position means there is no previous key in the specified range of iterator.
   238  	// The `finishEntry` method always was called even there is no previous key remained
   239  	// because there maybe some old versions are stored in `entry.values`.
   240  	// The i.val nil means we didn't find any valid data for the current key. So, we
   241  	// should set the valid flag into false to avoid the caller read previous key/value.
   242  	if len(i.val) == 0 {
   243  		i.valid = false
   244  	}
   245  
   246  	return nil
   247  }
   248  
   249  func reverse(values []mvcc.Value) {
   250  	i, j := 0, len(values)-1
   251  	for i < j {
   252  		values[i], values[j] = values[j], values[i]
   253  		i++
   254  		j--
   255  	}
   256  }
   257  
   258  func (i *SnapshotIter) finishEntry() error {
   259  	if i.entry.Lock != nil {
   260  		return i.entry.Lock.LockErr(i.nextKey)
   261  	}
   262  
   263  	reverse(i.entry.Values)
   264  	i.entry.Key = mvcc.NewKey(i.nextKey)
   265  	val, err := i.entry.Get(i.ver, nil)
   266  	if err != nil {
   267  		return err
   268  	}
   269  	i.val = val
   270  	i.entry = mvcc.Entry{}
   271  	return nil
   272  }