github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/iavl/nodedb_fnc.go (about)

     1  package iavl
     2  
     3  import (
     4  	"sync"
     5  
     6  	"github.com/tendermint/go-amino"
     7  )
     8  
     9  type fastNodeChanges struct {
    10  	additions map[string]*FastNode
    11  	removals  map[string]interface{}
    12  	mtx       sync.RWMutex
    13  }
    14  
    15  func newFastNodeChanges() *fastNodeChanges {
    16  	return &fastNodeChanges{
    17  		additions: make(map[string]*FastNode),
    18  		removals:  make(map[string]interface{}),
    19  	}
    20  }
    21  
    22  func (fnc *fastNodeChanges) get(key []byte) (*FastNode, bool) {
    23  	fnc.mtx.RLock()
    24  	defer fnc.mtx.RUnlock()
    25  	if node, ok := fnc.additions[string(key)]; ok {
    26  		return node, true
    27  	}
    28  	if _, ok := fnc.removals[string(key)]; ok {
    29  		return nil, true
    30  	}
    31  
    32  	return nil, false
    33  }
    34  
    35  func (fnc *fastNodeChanges) add(key []byte, fastNode *FastNode) {
    36  	fnc.mtx.Lock()
    37  	fnc.additions[string(key)] = fastNode
    38  	delete(fnc.removals, string(key))
    39  	fnc.mtx.Unlock()
    40  }
    41  
    42  func (fnc *fastNodeChanges) addAdditions(key []byte, fastNode *FastNode) {
    43  	fnc.mtx.Lock()
    44  	fnc.additions[string(key)] = fastNode
    45  	fnc.mtx.Unlock()
    46  }
    47  
    48  func (fnc *fastNodeChanges) remove(key []byte, value interface{}) {
    49  	fnc.mtx.Lock()
    50  	fnc.removals[string(key)] = value
    51  	delete(fnc.additions, string(key))
    52  	fnc.mtx.Unlock()
    53  }
    54  
    55  func (fnc *fastNodeChanges) addRemovals(key []byte) {
    56  	fnc.mtx.Lock()
    57  	fnc.removals[string(key)] = true
    58  	fnc.mtx.Unlock()
    59  }
    60  
    61  func (fnc *fastNodeChanges) checkRemovals(key []byte) bool {
    62  	fnc.mtx.RLock()
    63  	defer fnc.mtx.RUnlock()
    64  
    65  	if _, ok := fnc.removals[string(key)]; ok {
    66  		return true
    67  	}
    68  	return false
    69  }
    70  
    71  func (fnc *fastNodeChanges) checkAdditions(key []byte) bool {
    72  	fnc.mtx.RLock()
    73  	defer fnc.mtx.RUnlock()
    74  	if _, ok := fnc.additions[string(key)]; ok {
    75  		return true
    76  	}
    77  
    78  	return false
    79  }
    80  
    81  func (fnc *fastNodeChanges) getAdditions() map[string]*FastNode {
    82  	return fnc.additions
    83  }
    84  
    85  func (fnc *fastNodeChanges) getRemovals() map[string]interface{} {
    86  	return fnc.removals
    87  }
    88  
    89  func (fnc *fastNodeChanges) clone() *fastNodeChanges {
    90  	if fnc == nil {
    91  		return nil
    92  	}
    93  	fnc.mtx.RLock()
    94  	defer fnc.mtx.RUnlock()
    95  	var additions map[string]*FastNode
    96  	if fnc.additions != nil {
    97  		additions = make(map[string]*FastNode, len(fnc.additions))
    98  		for k, v := range fnc.additions {
    99  			additions[k] = v
   100  		}
   101  	}
   102  
   103  	var removals map[string]interface{}
   104  	if fnc.removals != nil {
   105  		removals = make(map[string]interface{}, len(fnc.removals))
   106  		for k, v := range fnc.removals {
   107  			removals[k] = v
   108  		}
   109  	}
   110  	return &fastNodeChanges{
   111  		additions: additions,
   112  		removals:  removals,
   113  	}
   114  }
   115  
   116  // mergePrev merge previous to fnc, prev is old than fnc
   117  func (fnc *fastNodeChanges) mergePrev(prev *fastNodeChanges) *fastNodeChanges {
   118  	if fnc == nil {
   119  		return prev
   120  	}
   121  	if prev == nil {
   122  		return fnc
   123  	}
   124  
   125  	for k, v := range prev.additions {
   126  		if !fnc.checkAdditions(amino.StrToBytes(k)) && !fnc.checkRemovals(amino.StrToBytes(k)) {
   127  			fnc.add(amino.StrToBytes(k), v)
   128  		}
   129  	}
   130  	for k, v := range prev.removals {
   131  		if !fnc.checkAdditions(amino.StrToBytes(k)) && !fnc.checkRemovals(amino.StrToBytes(k)) {
   132  			fnc.remove(amino.StrToBytes(k), v)
   133  		}
   134  	}
   135  	return fnc
   136  }
   137  
   138  // mergeLater merge later to fnc, later is new than fnc
   139  func (fnc *fastNodeChanges) mergeLater(later *fastNodeChanges) {
   140  	for k, v := range later.additions {
   141  		fnc.add(amino.StrToBytes(k), v)
   142  	}
   143  	for k, v := range later.removals {
   144  		fnc.remove(amino.StrToBytes(k), v)
   145  	}
   146  }
   147  
   148  func (fnc *fastNodeChanges) reset() {
   149  	fnc.mtx.Lock()
   150  	for k := range fnc.additions {
   151  		delete(fnc.additions, k)
   152  	}
   153  	for k := range fnc.removals {
   154  		delete(fnc.removals, k)
   155  	}
   156  	fnc.mtx.Unlock()
   157  }
   158  
   159  type fastNodeChangesWithVersion struct {
   160  	mtx      sync.RWMutex
   161  	versions []int64
   162  	fncMap   map[int64]*fastNodeChanges
   163  }
   164  
   165  func newFastNodeChangesWithVersion() *fastNodeChangesWithVersion {
   166  	return &fastNodeChangesWithVersion{
   167  		fncMap: make(map[int64]*fastNodeChanges),
   168  	}
   169  }
   170  
   171  func (fncv *fastNodeChangesWithVersion) add(version int64, fnc *fastNodeChanges) {
   172  	fncv.mtx.Lock()
   173  	defer fncv.mtx.Unlock()
   174  	fncv.versions = append(fncv.versions, version)
   175  	fncv.fncMap[version] = fnc
   176  }
   177  
   178  func (fncv *fastNodeChangesWithVersion) remove(version int64) {
   179  	if len(fncv.versions) < 1 || version != fncv.versions[0] {
   180  		return
   181  	}
   182  	fncv.mtx.Lock()
   183  	defer fncv.mtx.Unlock()
   184  	fncv.versions = fncv.versions[1:]
   185  	delete(fncv.fncMap, version)
   186  }
   187  
   188  func (fncv *fastNodeChangesWithVersion) get(key []byte) (*FastNode, bool) {
   189  	fncv.mtx.RLock()
   190  	defer fncv.mtx.RUnlock()
   191  	for i := len(fncv.versions) - 1; i >= 0; i-- {
   192  		if fn, ok := fncv.fncMap[fncv.versions[i]].get(key); ok {
   193  			return fn, ok
   194  		}
   195  	}
   196  	return nil, false
   197  }
   198  
   199  func (fncv *fastNodeChangesWithVersion) expand(changes *fastNodeChanges) *fastNodeChanges {
   200  	fncv.mtx.RLock()
   201  	defer fncv.mtx.RUnlock()
   202  	ret := changes.clone()
   203  	if ret == nil {
   204  		ret = newFastNodeChanges()
   205  	}
   206  	for i := len(fncv.versions) - 1; i >= 0; i-- {
   207  		for k, v := range fncv.fncMap[fncv.versions[i]].additions {
   208  			if !ret.checkAdditions(amino.StrToBytes(k)) && !ret.checkRemovals(amino.StrToBytes(k)) {
   209  				ret.add(amino.StrToBytes(k), v)
   210  			}
   211  		}
   212  		for k, v := range fncv.fncMap[fncv.versions[i]].removals {
   213  			if !ret.checkAdditions(amino.StrToBytes(k)) && !ret.checkRemovals(amino.StrToBytes(k)) {
   214  				ret.remove(amino.StrToBytes(k), v)
   215  			}
   216  		}
   217  	}
   218  
   219  	return ret
   220  }