github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/iavl/nodedb_update_branch.go (about) 1 package iavl 2 3 import "sync" 4 5 func (ndb *nodeDB) updateBranch(node *Node, savedNodes map[string]*Node) []byte { 6 if node.persisted || node.prePersisted { 7 return node.hash 8 } 9 10 if node.leftNode != nil { 11 node.leftHash = ndb.updateBranch(node.leftNode, savedNodes) 12 } 13 if node.rightNode != nil { 14 node.rightHash = ndb.updateBranch(node.rightNode, savedNodes) 15 } 16 17 node._hash() 18 ndb.saveNodeToPrePersistCache(node) 19 20 node.leftNode = nil 21 node.rightNode = nil 22 23 // TODO: handle magic number 24 savedNodes[string(node.hash)] = node 25 26 return node.hash 27 } 28 29 func (ndb *nodeDB) updateBranchConcurrency(node *Node, savedNodes map[string]*Node) []byte { 30 if node.persisted || node.prePersisted { 31 return node.hash 32 } 33 34 nodeCh := make(chan *Node, 1024) 35 wg := &sync.WaitGroup{} 36 37 var needNilNodeNum = 0 38 if node.leftNode != nil { 39 needNilNodeNum += 1 40 wg.Add(1) 41 go func(node *Node, wg *sync.WaitGroup, nodeCh chan *Node) { 42 node.leftHash = updateBranchRoutine(node.leftNode, nodeCh) 43 wg.Done() 44 }(node, wg, nodeCh) 45 } 46 if node.rightNode != nil { 47 needNilNodeNum += 1 48 wg.Add(1) 49 go func(node *Node, wg *sync.WaitGroup, nodeCh chan *Node) { 50 node.rightHash = updateBranchRoutine(node.rightNode, nodeCh) 51 wg.Done() 52 }(node, wg, nodeCh) 53 } 54 55 if needNilNodeNum > 0 { 56 getNodeNil := 0 57 for n := range nodeCh { 58 if n == nil { 59 getNodeNil += 1 60 if getNodeNil == needNilNodeNum { 61 break 62 } 63 } else { 64 ndb.saveNodeToPrePersistCache(n) 65 n.leftNode = nil 66 n.rightNode = nil 67 if savedNodes != nil { 68 savedNodes[string(n.hash)] = n 69 } 70 } 71 } 72 } 73 74 close(nodeCh) 75 wg.Wait() 76 77 node._hash() 78 79 ndb.saveNodeToPrePersistCache(node) 80 81 node.leftNode = nil 82 node.rightNode = nil 83 84 // TODO: handle magic number 85 if savedNodes != nil { 86 savedNodes[string(node.hash)] = node 87 } 88 89 return node.hash 90 } 91 92 func updateBranchRoutine(node *Node, saveNodesCh chan<- *Node) []byte { 93 if node.persisted || node.prePersisted { 94 saveNodesCh <- nil 95 return node.hash 96 } 97 98 if node.leftNode != nil { 99 node.leftHash = updateBranchAndSaveNodeToChan(node.leftNode, saveNodesCh) 100 } 101 if node.rightNode != nil { 102 node.rightHash = updateBranchAndSaveNodeToChan(node.rightNode, saveNodesCh) 103 } 104 105 node._hash() 106 107 saveNodesCh <- node 108 saveNodesCh <- nil 109 110 return node.hash 111 } 112 113 func updateBranchAndSaveNodeToChan(node *Node, saveNodesCh chan<- *Node) []byte { 114 if node.persisted || node.prePersisted { 115 return node.hash 116 } 117 118 if node.leftNode != nil { 119 node.leftHash = updateBranchAndSaveNodeToChan(node.leftNode, saveNodesCh) 120 } 121 if node.rightNode != nil { 122 node.rightHash = updateBranchAndSaveNodeToChan(node.rightNode, saveNodesCh) 123 } 124 125 node._hash() 126 127 saveNodesCh <- node 128 129 return node.hash 130 } 131 132 func (ndb *nodeDB) updateBranchForFastNode(fnc *fastNodeChanges) { 133 ndb.mtx.Lock() 134 ndb.prePersistFastNode.mergeLater(fnc) 135 ndb.mtx.Unlock() 136 } 137 138 func (ndb *nodeDB) updateBranchMoreConcurrency(node *Node) []byte { 139 if node.persisted || node.prePersisted { 140 return node.hash 141 } 142 143 wg := &sync.WaitGroup{} 144 145 if node.leftNode != nil { 146 wg.Add(1) 147 go func(node *Node, wg *sync.WaitGroup) { 148 node.leftHash = ndb.updateBranchConcurrency(node.leftNode, nil) 149 wg.Done() 150 }(node, wg) 151 } 152 if node.rightNode != nil { 153 wg.Add(1) 154 go func(node *Node, wg *sync.WaitGroup) { 155 node.rightHash = ndb.updateBranchConcurrency(node.rightNode, nil) 156 wg.Done() 157 }(node, wg) 158 } 159 160 wg.Wait() 161 162 node._hash() 163 ndb.saveNodeToPrePersistCache(node) 164 165 node.leftNode = nil 166 node.rightNode = nil 167 168 return node.hash 169 }