github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/cosmos-sdk/store/cachekv/mergeiterator.go (about)

     1  package cachekv
     2  
     3  import (
     4  	"bytes"
     5  	"errors"
     6  
     7  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/store/types"
     8  )
     9  
    10  // cacheMergeIterator merges a parent Iterator and a cache Iterator.
    11  // The cache iterator may return nil keys to signal that an item
    12  // had been deleted (but not deleted in the parent).
    13  // If the cache iterator has the same key as the parent, the
    14  // cache shadows (overrides) the parent.
    15  //
    16  // TODO: Optimize by memoizing.
    17  type cacheMergeIterator struct {
    18  	parent    types.Iterator
    19  	cache     types.Iterator
    20  	ascending bool
    21  }
    22  
    23  var _ types.Iterator = (*cacheMergeIterator)(nil)
    24  
    25  func newCacheMergeIterator(parent, cache types.Iterator, ascending bool) *cacheMergeIterator {
    26  	iter := &cacheMergeIterator{
    27  		parent:    parent,
    28  		cache:     cache,
    29  		ascending: ascending,
    30  	}
    31  	return iter
    32  }
    33  
    34  // Domain implements Iterator.
    35  // If the domains are different, returns the union.
    36  func (iter *cacheMergeIterator) Domain() (start, end []byte) {
    37  	startP, endP := iter.parent.Domain()
    38  	startC, endC := iter.cache.Domain()
    39  	if iter.compare(startP, startC) < 0 {
    40  		start = startP
    41  	} else {
    42  		start = startC
    43  	}
    44  	if iter.compare(endP, endC) < 0 {
    45  		end = endC
    46  	} else {
    47  		end = endP
    48  	}
    49  	return start, end
    50  }
    51  
    52  // Valid implements Iterator.
    53  func (iter *cacheMergeIterator) Valid() bool {
    54  	return iter.skipUntilExistsOrInvalid()
    55  }
    56  
    57  // Next implements Iterator
    58  func (iter *cacheMergeIterator) Next() {
    59  	iter.skipUntilExistsOrInvalid()
    60  	iter.assertValid()
    61  
    62  	// If parent is invalid, get the next cache item.
    63  	if !iter.parent.Valid() {
    64  		iter.cache.Next()
    65  		return
    66  	}
    67  
    68  	// If cache is invalid, get the next parent item.
    69  	if !iter.cache.Valid() {
    70  		iter.parent.Next()
    71  		return
    72  	}
    73  
    74  	// Both are valid.  Compare keys.
    75  	keyP, keyC := iter.parent.Key(), iter.cache.Key()
    76  	switch iter.compare(keyP, keyC) {
    77  	case -1: // parent < cache
    78  		iter.parent.Next()
    79  	case 0: // parent == cache
    80  		iter.parent.Next()
    81  		iter.cache.Next()
    82  	case 1: // parent > cache
    83  		iter.cache.Next()
    84  	}
    85  }
    86  
    87  // Key implements Iterator
    88  func (iter *cacheMergeIterator) Key() []byte {
    89  	iter.skipUntilExistsOrInvalid()
    90  	iter.assertValid()
    91  
    92  	// If parent is invalid, get the cache key.
    93  	if !iter.parent.Valid() {
    94  		return iter.cache.Key()
    95  	}
    96  
    97  	// If cache is invalid, get the parent key.
    98  	if !iter.cache.Valid() {
    99  		return iter.parent.Key()
   100  	}
   101  
   102  	// Both are valid.  Compare keys.
   103  	keyP, keyC := iter.parent.Key(), iter.cache.Key()
   104  	cmp := iter.compare(keyP, keyC)
   105  	switch cmp {
   106  	case -1: // parent < cache
   107  		return keyP
   108  	case 0: // parent == cache
   109  		return keyP
   110  	case 1: // parent > cache
   111  		return keyC
   112  	default:
   113  		panic("invalid compare result")
   114  	}
   115  }
   116  
   117  // Value implements Iterator
   118  func (iter *cacheMergeIterator) Value() []byte {
   119  	iter.skipUntilExistsOrInvalid()
   120  	iter.assertValid()
   121  
   122  	// If parent is invalid, get the cache value.
   123  	if !iter.parent.Valid() {
   124  		return iter.cache.Value()
   125  	}
   126  
   127  	// If cache is invalid, get the parent value.
   128  	if !iter.cache.Valid() {
   129  		return iter.parent.Value()
   130  	}
   131  
   132  	// Both are valid.  Compare keys.
   133  	keyP, keyC := iter.parent.Key(), iter.cache.Key()
   134  	cmp := iter.compare(keyP, keyC)
   135  	switch cmp {
   136  	case -1: // parent < cache
   137  		return iter.parent.Value()
   138  	case 0: // parent == cache
   139  		return iter.cache.Value()
   140  	case 1: // parent > cache
   141  		return iter.cache.Value()
   142  	default:
   143  		panic("invalid comparison result")
   144  	}
   145  }
   146  
   147  // Close implements Iterator
   148  func (iter *cacheMergeIterator) Close() {
   149  	iter.parent.Close()
   150  	iter.cache.Close()
   151  }
   152  
   153  // Error returns an error if the cacheMergeIterator is invalid defined by the
   154  // Valid method.
   155  func (iter *cacheMergeIterator) Error() error {
   156  	if !iter.Valid() {
   157  		return errors.New("invalid cacheMergeIterator")
   158  	}
   159  
   160  	return nil
   161  }
   162  
   163  // If not valid, panics.
   164  // NOTE: May have side-effect of iterating over cache.
   165  func (iter *cacheMergeIterator) assertValid() {
   166  	if err := iter.Error(); err != nil {
   167  		panic(err)
   168  	}
   169  }
   170  
   171  // Like bytes.Compare but opposite if not ascending.
   172  func (iter *cacheMergeIterator) compare(a, b []byte) int {
   173  	if iter.ascending {
   174  		return bytes.Compare(a, b)
   175  	}
   176  	return bytes.Compare(a, b) * -1
   177  }
   178  
   179  // Skip all delete-items from the cache w/ `key < until`.  After this function,
   180  // current cache item is a non-delete-item, or `until <= key`.
   181  // If the current cache item is not a delete item, does nothing.
   182  // If `until` is nil, there is no limit, and cache may end up invalid.
   183  // CONTRACT: cache is valid.
   184  func (iter *cacheMergeIterator) skipCacheDeletes(until []byte) {
   185  	for iter.cache.Valid() &&
   186  		iter.cache.Value() == nil &&
   187  		(until == nil || iter.compare(iter.cache.Key(), until) < 0) {
   188  
   189  		iter.cache.Next()
   190  	}
   191  }
   192  
   193  // Fast forwards cache (or parent+cache in case of deleted items) until current
   194  // item exists, or until iterator becomes invalid.
   195  // Returns whether the iterator is valid.
   196  func (iter *cacheMergeIterator) skipUntilExistsOrInvalid() bool {
   197  	for {
   198  		// If parent is invalid, fast-forward cache.
   199  		if !iter.parent.Valid() {
   200  			iter.skipCacheDeletes(nil)
   201  			return iter.cache.Valid()
   202  		}
   203  		// Parent is valid.
   204  
   205  		if !iter.cache.Valid() {
   206  			return true
   207  		}
   208  		// Parent is valid, cache is valid.
   209  
   210  		// Compare parent and cache.
   211  		keyP := iter.parent.Key()
   212  		keyC := iter.cache.Key()
   213  		switch iter.compare(keyP, keyC) {
   214  
   215  		case -1: // parent < cache.
   216  			return true
   217  
   218  		case 0: // parent == cache.
   219  
   220  			// Skip over if cache item is a delete.
   221  			valueC := iter.cache.Value()
   222  			if valueC == nil {
   223  				iter.parent.Next()
   224  				iter.cache.Next()
   225  				continue
   226  			}
   227  			// Cache is not a delete.
   228  
   229  			return true // cache exists.
   230  
   231  		case 1: // cache < parent
   232  
   233  			// Skip over if cache item is a delete.
   234  			valueC := iter.cache.Value()
   235  			if valueC == nil {
   236  				iter.skipCacheDeletes(keyP)
   237  				continue
   238  			}
   239  			// Cache is not a delete.
   240  
   241  			return true // cache exists.
   242  		}
   243  	}
   244  }