1package networkdb
2
3import (
4	"net"
5
6	"github.com/docker/go-events"
7)
8
9type opType uint8
10
11const (
12	opCreate opType = 1 + iota
13	opUpdate
14	opDelete
15)
16
17type 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
25const NodeTable = "NodeTable"
26
27// NodeAddr represents the value carried for node event in NodeTable
28type NodeAddr struct {
29	Addr net.IP
30}
31
32// CreateEvent generates a table entry create event to the watchers
33type CreateEvent event
34
35// UpdateEvent generates a table entry update event to the watchers
36type UpdateEvent event
37
38// DeleteEvent generates a table entry delete event to the watchers
39type 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.
46func (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
92func 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}
111