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  }