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

     1  package iavl
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/tendermint/go-amino"
     7  )
     8  
     9  type OrphanInfo struct {
    10  	ndb             *nodeDB
    11  	orphanNodeCache map[string]*Node
    12  	orphanItemMap   map[int64]*orphanItem
    13  	itemSize        int
    14  
    15  	orphanTaskChan chan func()
    16  	resultChan     chan int64
    17  }
    18  
    19  type orphanItem struct {
    20  	rootHash []byte
    21  	orphans  []*Node
    22  }
    23  
    24  func newOrphanInfo(ndb *nodeDB) *OrphanInfo {
    25  	oi := &OrphanInfo{
    26  		ndb:             ndb,
    27  		orphanNodeCache: make(map[string]*Node),
    28  		orphanItemMap:   make(map[int64]*orphanItem),
    29  		itemSize:        HeightOrphansCacheSize,
    30  		orphanTaskChan:  make(chan func(), 1),
    31  		resultChan:      make(chan int64, 1),
    32  	}
    33  
    34  	oi.enqueueResult(0)
    35  	go oi.handleOrphansRoutine()
    36  	return oi
    37  }
    38  
    39  func (oi *OrphanInfo) enqueueResult(res int64) {
    40  	oi.resultChan <- res
    41  }
    42  
    43  func (oi *OrphanInfo) enqueueTask(t func()) {
    44  	oi.orphanTaskChan <- t
    45  }
    46  
    47  func (oi *OrphanInfo) handleOrphansRoutine() {
    48  	for task := range oi.orphanTaskChan {
    49  		task()
    50  	}
    51  }
    52  
    53  func (oi *OrphanInfo) wait4Result(version int64) {
    54  
    55  	version--
    56  	for versionCompleted := range oi.resultChan {
    57  		if versionCompleted == version {
    58  			break
    59  		} else if versionCompleted == 0 {
    60  			break
    61  		}
    62  	}
    63  }
    64  
    65  func (oi *OrphanInfo) addOrphanItem(version int64, rootHash []byte) {
    66  	if rootHash == nil {
    67  		rootHash = []byte{}
    68  	}
    69  	orphanObj := &orphanItem{
    70  		rootHash: rootHash,
    71  	}
    72  	_, ok := oi.orphanItemMap[version]
    73  	if ok {
    74  		panic(fmt.Sprintf("unexpected orphanItemMap, version: %d", version))
    75  	}
    76  	oi.orphanItemMap[version] = orphanObj
    77  }
    78  
    79  func (oi *OrphanInfo) removeOldOrphans(version int64) {
    80  	expiredVersion := version - int64(oi.itemSize)
    81  	expiredItem, ok := oi.orphanItemMap[expiredVersion]
    82  	if !ok {
    83  		return
    84  	}
    85  	for _, node := range expiredItem.orphans {
    86  		delete(oi.orphanNodeCache, amino.BytesToStr(node.hash))
    87  	}
    88  	delete(oi.orphanItemMap, expiredVersion)
    89  }
    90  
    91  func (oi *OrphanInfo) feedOrphansMap(version int64, orphans []*Node) {
    92  	v, ok := oi.orphanItemMap[version]
    93  	if !ok {
    94  		return
    95  	}
    96  	v.orphans = orphans
    97  }
    98  
    99  func (oi *OrphanInfo) feedOrphanNodeCache(node *Node) {
   100  	oi.orphanNodeCache[string(node.hash)] = node
   101  }
   102  
   103  func (oi *OrphanInfo) getNodeFromOrphanCache(hash []byte) *Node {
   104  	elem, ok := oi.orphanNodeCache[string(hash)]
   105  	if ok {
   106  		return elem
   107  	}
   108  	return nil
   109  }
   110  
   111  func (oi *OrphanInfo) orphanNodeCacheLen() int {
   112  	return len(oi.orphanNodeCache)
   113  }
   114  
   115  func (oi *OrphanInfo) findRootHash(version int64) (res []byte, found bool) {
   116  	v, ok := oi.orphanItemMap[version]
   117  	if ok {
   118  		res = v.rootHash
   119  		found = true
   120  	}
   121  	return
   122  }