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

     1  package networkdb
     2  
     3  import (
     4  	"net"
     5  
     6  	"github.com/docker/go-events"
     7  )
     8  
     9  type opType uint8
    10  
    11  const (
    12  	opCreate opType = 1 + iota
    13  	opUpdate
    14  	opDelete
    15  )
    16  
    17  type event struct {
    18  	Table     string
    19  	NetworkID string
    20  	Key       string
    21  	Value     []byte
    22  }
    23  
    24  // NodeTable represents table event for node join and leave
    25  const NodeTable = "NodeTable"
    26  
    27  // NodeAddr represents the value carried for node event in NodeTable
    28  type NodeAddr struct {
    29  	Addr net.IP
    30  }
    31  
    32  // CreateEvent generates a table entry create event to the watchers
    33  type CreateEvent event
    34  
    35  // UpdateEvent generates a table entry update event to the watchers
    36  type UpdateEvent event
    37  
    38  // DeleteEvent generates a table entry delete event to the watchers
    39  type DeleteEvent event
    40  
    41  // Watch creates a watcher with filters for a particular table or
    42  // network or key or any combination of the tuple. If any of the
    43  // filter is an empty string it acts as a wildcard for that
    44  // field. Watch returns a channel of events, where the events will be
    45  // sent.
    46  func (nDB *NetworkDB) Watch(tname, nid, key string) (*events.Channel, func()) {
    47  	var matcher events.Matcher
    48  
    49  	if tname != "" || nid != "" || key != "" {
    50  		matcher = events.MatcherFunc(func(ev events.Event) bool {
    51  			var evt event
    52  			switch ev := ev.(type) {
    53  			case CreateEvent:
    54  				evt = event(ev)
    55  			case UpdateEvent:
    56  				evt = event(ev)
    57  			case DeleteEvent:
    58  				evt = event(ev)
    59  			}
    60  
    61  			if tname != "" && evt.Table != tname {
    62  				return false
    63  			}
    64  
    65  			if nid != "" && evt.NetworkID != nid {
    66  				return false
    67  			}
    68  
    69  			if key != "" && evt.Key != key {
    70  				return false
    71  			}
    72  
    73  			return true
    74  		})
    75  	}
    76  
    77  	ch := events.NewChannel(0)
    78  	sink := events.Sink(events.NewQueue(ch))
    79  
    80  	if matcher != nil {
    81  		sink = events.NewFilter(sink, matcher)
    82  	}
    83  
    84  	nDB.broadcaster.Add(sink)
    85  	return ch, func() {
    86  		nDB.broadcaster.Remove(sink)
    87  		ch.Close()
    88  		sink.Close()
    89  	}
    90  }
    91  
    92  func makeEvent(op opType, tname, nid, key string, value []byte) events.Event {
    93  	ev := event{
    94  		Table:     tname,
    95  		NetworkID: nid,
    96  		Key:       key,
    97  		Value:     value,
    98  	}
    99  
   100  	switch op {
   101  	case opCreate:
   102  		return CreateEvent(ev)
   103  	case opUpdate:
   104  		return UpdateEvent(ev)
   105  	case opDelete:
   106  		return DeleteEvent(ev)
   107  	}
   108  
   109  	return nil
   110  }