File: monitor.go

package info (click to toggle)
golang-github-ovn-org-libovsdb 0.8.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,536 kB
  • sloc: makefile: 51; sh: 27
file content (136 lines) | stat: -rw-r--r-- 3,689 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
package client

import (
	"fmt"
	"reflect"

	"github.com/google/uuid"
	"github.com/ovn-kubernetes/libovsdb/model"
	"github.com/ovn-kubernetes/libovsdb/ovsdb"
)

const emptyUUID = "00000000-0000-0000-0000-000000000000"

// Monitor represents a monitor
type Monitor struct {
	Method            string
	Tables            []TableMonitor
	Errors            []error
	LastTransactionID string
}

// newMonitor creates a new *Monitor with default values
func newMonitor() *Monitor {
	return &Monitor{
		Method:            ovsdb.ConditionalMonitorSinceRPC,
		Errors:            make([]error, 0),
		LastTransactionID: emptyUUID,
	}
}

// NewMonitor creates a new Monitor with the provided options
func (o *ovsdbClient) NewMonitor(opts ...MonitorOption) *Monitor {
	m := newMonitor()
	for _, opt := range opts {
		err := opt(o, m)
		if err != nil {
			m.Errors = append(m.Errors, err)
		}
	}
	return m
}

// MonitorOption adds Tables to a Monitor
type MonitorOption func(o *ovsdbClient, m *Monitor) error

// MonitorCookie is the struct we pass to correlate from updates back to their
// originating Monitor request.
type MonitorCookie struct {
	DatabaseName string `json:"databaseName"`
	ID           string `json:"id"`
}

func newMonitorCookie(dbName string) MonitorCookie {
	return MonitorCookie{
		DatabaseName: dbName,
		ID:           uuid.NewString(),
	}
}

// TableMonitor is a table to be monitored
type TableMonitor struct {
	// Table is the table to be monitored
	Table string
	// Conditions are the conditions under which the table should be monitored
	Conditions []ovsdb.Condition
	// Fields are the fields in the model to monitor
	// If none are supplied, all fields will be used
	Fields []string
}

func newTableMonitor(o *ovsdbClient, m model.Model, conditions []model.Condition, fields []any) (*TableMonitor, error) {
	dbModel := o.primaryDB().model
	tableName := dbModel.FindTable(reflect.TypeOf(m))
	if tableName == "" {
		return nil, fmt.Errorf("object of type %s is not part of the ClientDBModel", reflect.TypeOf(m))
	}

	var columns []string
	var ovsdbConds []ovsdb.Condition

	if len(fields) == 0 && len(conditions) == 0 {
		return &TableMonitor{
			Table:      tableName,
			Conditions: ovsdbConds,
			Fields:     columns,
		}, nil
	}

	data, err := dbModel.NewModelInfo(m)
	if err != nil {
		return nil, fmt.Errorf("unable to obtain info from model %v: %v", m, err)
	}
	for _, f := range fields {
		column, err := data.ColumnByPtr(f)
		if err != nil {
			return nil, fmt.Errorf("unable to obtain column from model %v: %v", data, err)
		}
		columns = append(columns, column)
	}
	db := o.databases[o.primaryDBName]
	mmapper := db.model.Mapper
	for _, modelCond := range conditions {
		ovsdbCond, err := mmapper.NewCondition(data, modelCond.Field, modelCond.Function, modelCond.Value)
		if err != nil {
			return nil, fmt.Errorf("unable to convert condition %v: %v", modelCond, err)
		}
		ovsdbConds = append(ovsdbConds, *ovsdbCond)
	}
	return &TableMonitor{
		Table:      tableName,
		Conditions: ovsdbConds,
		Fields:     columns,
	}, nil
}

func WithTable(m model.Model, fields ...any) MonitorOption {
	return func(o *ovsdbClient, monitor *Monitor) error {
		tableMonitor, err := newTableMonitor(o, m, []model.Condition{}, fields)
		if err != nil {
			return err
		}
		monitor.Tables = append(monitor.Tables, *tableMonitor)
		return nil
	}
}

func WithConditionalTable(m model.Model, conditions []model.Condition, fields ...any) MonitorOption {
	return func(o *ovsdbClient, monitor *Monitor) error {
		tableMonitor, err := newTableMonitor(o, m, conditions, fields)
		if err != nil {
			return err
		}
		monitor.Tables = append(monitor.Tables, *tableMonitor)
		return nil
	}
}