github.com/docker/engine@v22.0.0-20211208180946-d456264580cf+incompatible/libnetwork/networkdb/broadcast.go (about)

     1  package networkdb
     2  
     3  import (
     4  	"errors"
     5  	"time"
     6  
     7  	"github.com/hashicorp/memberlist"
     8  	"github.com/hashicorp/serf/serf"
     9  )
    10  
    11  const broadcastTimeout = 5 * time.Second
    12  
    13  type networkEventMessage struct {
    14  	id   string
    15  	node string
    16  	msg  []byte
    17  }
    18  
    19  func (m *networkEventMessage) Invalidates(other memberlist.Broadcast) bool {
    20  	otherm := other.(*networkEventMessage)
    21  	return m.id == otherm.id && m.node == otherm.node
    22  }
    23  
    24  func (m *networkEventMessage) Message() []byte {
    25  	return m.msg
    26  }
    27  
    28  func (m *networkEventMessage) Finished() {
    29  }
    30  
    31  func (nDB *NetworkDB) sendNetworkEvent(nid string, event NetworkEvent_Type, ltime serf.LamportTime) error {
    32  	nEvent := NetworkEvent{
    33  		Type:      event,
    34  		LTime:     ltime,
    35  		NodeName:  nDB.config.NodeID,
    36  		NetworkID: nid,
    37  	}
    38  
    39  	raw, err := encodeMessage(MessageTypeNetworkEvent, &nEvent)
    40  	if err != nil {
    41  		return err
    42  	}
    43  
    44  	nDB.networkBroadcasts.QueueBroadcast(&networkEventMessage{
    45  		msg:  raw,
    46  		id:   nid,
    47  		node: nDB.config.NodeID,
    48  	})
    49  	return nil
    50  }
    51  
    52  type nodeEventMessage struct {
    53  	msg    []byte
    54  	notify chan<- struct{}
    55  }
    56  
    57  func (m *nodeEventMessage) Invalidates(other memberlist.Broadcast) bool {
    58  	return false
    59  }
    60  
    61  func (m *nodeEventMessage) Message() []byte {
    62  	return m.msg
    63  }
    64  
    65  func (m *nodeEventMessage) Finished() {
    66  	if m.notify != nil {
    67  		close(m.notify)
    68  	}
    69  }
    70  
    71  func (nDB *NetworkDB) sendNodeEvent(event NodeEvent_Type) error {
    72  	nEvent := NodeEvent{
    73  		Type:     event,
    74  		LTime:    nDB.networkClock.Increment(),
    75  		NodeName: nDB.config.NodeID,
    76  	}
    77  
    78  	raw, err := encodeMessage(MessageTypeNodeEvent, &nEvent)
    79  	if err != nil {
    80  		return err
    81  	}
    82  
    83  	notifyCh := make(chan struct{})
    84  	nDB.nodeBroadcasts.QueueBroadcast(&nodeEventMessage{
    85  		msg:    raw,
    86  		notify: notifyCh,
    87  	})
    88  
    89  	nDB.RLock()
    90  	noPeers := len(nDB.nodes) <= 1
    91  	nDB.RUnlock()
    92  
    93  	// Message enqueued, do not wait for a send if no peer is present
    94  	if noPeers {
    95  		return nil
    96  	}
    97  
    98  	// Wait for the broadcast
    99  	select {
   100  	case <-notifyCh:
   101  	case <-time.After(broadcastTimeout):
   102  		return errors.New("timed out broadcasting node event")
   103  	}
   104  
   105  	return nil
   106  }
   107  
   108  type tableEventMessage struct {
   109  	id    string
   110  	tname string
   111  	key   string
   112  	msg   []byte
   113  }
   114  
   115  func (m *tableEventMessage) Invalidates(other memberlist.Broadcast) bool {
   116  	otherm := other.(*tableEventMessage)
   117  	return m.tname == otherm.tname && m.id == otherm.id && m.key == otherm.key
   118  }
   119  
   120  func (m *tableEventMessage) Message() []byte {
   121  	return m.msg
   122  }
   123  
   124  func (m *tableEventMessage) Finished() {
   125  }
   126  
   127  func (nDB *NetworkDB) sendTableEvent(event TableEvent_Type, nid string, tname string, key string, entry *entry) error {
   128  	tEvent := TableEvent{
   129  		Type:      event,
   130  		LTime:     entry.ltime,
   131  		NodeName:  nDB.config.NodeID,
   132  		NetworkID: nid,
   133  		TableName: tname,
   134  		Key:       key,
   135  		Value:     entry.value,
   136  		// The duration in second is a float that below would be truncated
   137  		ResidualReapTime: int32(entry.reapTime.Seconds()),
   138  	}
   139  
   140  	raw, err := encodeMessage(MessageTypeTableEvent, &tEvent)
   141  	if err != nil {
   142  		return err
   143  	}
   144  
   145  	var broadcastQ *memberlist.TransmitLimitedQueue
   146  	nDB.RLock()
   147  	thisNodeNetworks, ok := nDB.networks[nDB.config.NodeID]
   148  	if ok {
   149  		// The network may have been removed
   150  		network, networkOk := thisNodeNetworks[nid]
   151  		if !networkOk {
   152  			nDB.RUnlock()
   153  			return nil
   154  		}
   155  
   156  		broadcastQ = network.tableBroadcasts
   157  	}
   158  	nDB.RUnlock()
   159  
   160  	// The network may have been removed
   161  	if broadcastQ == nil {
   162  		return nil
   163  	}
   164  
   165  	broadcastQ.QueueBroadcast(&tableEventMessage{
   166  		msg:   raw,
   167  		id:    nid,
   168  		tname: tname,
   169  		key:   key,
   170  	})
   171  	return nil
   172  }