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 }