github.com/Prakhar-Agarwal-byte/moby@v0.0.0-20231027092010-a14e3e8ab87e/libnetwork/networkdb/nodemgmt.go (about)

     1  package networkdb
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  
     7  	"github.com/containerd/log"
     8  	"github.com/hashicorp/memberlist"
     9  )
    10  
    11  type nodeState int
    12  
    13  const (
    14  	nodeNotFound    nodeState = -1
    15  	nodeActiveState nodeState = 0
    16  	nodeLeftState   nodeState = 1
    17  	nodeFailedState nodeState = 2
    18  )
    19  
    20  var nodeStateName = map[nodeState]string{
    21  	-1: "NodeNotFound",
    22  	0:  "NodeActive",
    23  	1:  "NodeLeft",
    24  	2:  "NodeFailed",
    25  }
    26  
    27  // findNode search the node into the 3 node lists and returns the node pointer and the list
    28  // where it got found
    29  func (nDB *NetworkDB) findNode(nodeName string) (*node, nodeState, map[string]*node) {
    30  	for i, nodes := range []map[string]*node{
    31  		nDB.nodes,
    32  		nDB.leftNodes,
    33  		nDB.failedNodes,
    34  	} {
    35  		if n, ok := nodes[nodeName]; ok {
    36  			return n, nodeState(i), nodes
    37  		}
    38  	}
    39  	return nil, nodeNotFound, nil
    40  }
    41  
    42  // changeNodeState changes the state of the node specified, returns true if the node was moved,
    43  // false if there was no need to change the node state. Error will be returned if the node does not
    44  // exists
    45  func (nDB *NetworkDB) changeNodeState(nodeName string, newState nodeState) (bool, error) {
    46  	n, currState, m := nDB.findNode(nodeName)
    47  	if n == nil {
    48  		return false, fmt.Errorf("node %s not found", nodeName)
    49  	}
    50  
    51  	switch newState {
    52  	case nodeActiveState:
    53  		if currState == nodeActiveState {
    54  			return false, nil
    55  		}
    56  
    57  		delete(m, nodeName)
    58  		// reset the node reap time
    59  		n.reapTime = 0
    60  		nDB.nodes[nodeName] = n
    61  	case nodeLeftState:
    62  		if currState == nodeLeftState {
    63  			return false, nil
    64  		}
    65  
    66  		delete(m, nodeName)
    67  		nDB.leftNodes[nodeName] = n
    68  	case nodeFailedState:
    69  		if currState == nodeFailedState {
    70  			return false, nil
    71  		}
    72  
    73  		delete(m, nodeName)
    74  		nDB.failedNodes[nodeName] = n
    75  	}
    76  
    77  	log.G(context.TODO()).Infof("Node %s change state %s --> %s", nodeName, nodeStateName[currState], nodeStateName[newState])
    78  
    79  	if newState == nodeLeftState || newState == nodeFailedState {
    80  		// set the node reap time, if not already set
    81  		// It is possible that a node passes from failed to left and the reaptime was already set so keep that value
    82  		if n.reapTime == 0 {
    83  			n.reapTime = nodeReapInterval
    84  		}
    85  		// The node leave or fails, delete all the entries created by it.
    86  		// If the node was temporary down, deleting the entries will guarantee that the CREATE events will be accepted
    87  		// If the node instead left because was going down, then it makes sense to just delete all its state
    88  		nDB.deleteNodeFromNetworks(n.Name)
    89  		nDB.deleteNodeTableEntries(n.Name)
    90  	}
    91  
    92  	return true, nil
    93  }
    94  
    95  func (nDB *NetworkDB) purgeReincarnation(mn *memberlist.Node) bool {
    96  	for name, node := range nDB.nodes {
    97  		if node.Addr.Equal(mn.Addr) && node.Port == mn.Port && mn.Name != name {
    98  			log.G(context.TODO()).Infof("Node %s/%s, is the new incarnation of the active node %s/%s", mn.Name, mn.Addr, name, node.Addr)
    99  			nDB.changeNodeState(name, nodeLeftState)
   100  			return true
   101  		}
   102  	}
   103  
   104  	for name, node := range nDB.failedNodes {
   105  		if node.Addr.Equal(mn.Addr) && node.Port == mn.Port && mn.Name != name {
   106  			log.G(context.TODO()).Infof("Node %s/%s, is the new incarnation of the failed node %s/%s", mn.Name, mn.Addr, name, node.Addr)
   107  			nDB.changeNodeState(name, nodeLeftState)
   108  			return true
   109  		}
   110  	}
   111  
   112  	for name, node := range nDB.leftNodes {
   113  		if node.Addr.Equal(mn.Addr) && node.Port == mn.Port && mn.Name != name {
   114  			log.G(context.TODO()).Infof("Node %s/%s, is the new incarnation of the shutdown node %s/%s", mn.Name, mn.Addr, name, node.Addr)
   115  			nDB.changeNodeState(name, nodeLeftState)
   116  			return true
   117  		}
   118  	}
   119  
   120  	return false
   121  }