-/* Allocates an array of 'mt->n_columns' ovsdb_datums and initializes them as
- * copies of the data in 'row' drawn from the columns represented by
- * mt->columns[]. Returns the array.
- *
- * If 'row' is NULL, returns NULL. */
-static struct ovsdb_datum *
-clone_monitor_row_data(const struct ovsdb_monitor_table *mt,
- const struct ovsdb_row *row)
-{
- struct ovsdb_datum *data;
- size_t i;
-
- if (!row) {
- return NULL;
- }
-
- data = xmalloc(mt->n_columns * sizeof *data);
- for (i = 0; i < mt->n_columns; i++) {
- const struct ovsdb_column *c = mt->columns[i].column;
- const struct ovsdb_datum *src = &row->fields[c->index];
- struct ovsdb_datum *dst = &data[i];
- const struct ovsdb_type *type = &c->type;
-
- ovsdb_datum_clone(dst, src, type);
- }
- return data;
-}
-
-/* Replaces the mt->n_columns ovsdb_datums in row[] by copies of the data from
- * in 'row' drawn from the columns represented by mt->columns[]. */
-static void
-update_monitor_row_data(const struct ovsdb_monitor_table *mt,
- const struct ovsdb_row *row,
- struct ovsdb_datum *data)
-{
- size_t i;
-
- for (i = 0; i < mt->n_columns; i++) {
- const struct ovsdb_column *c = mt->columns[i].column;
- const struct ovsdb_datum *src = &row->fields[c->index];
- struct ovsdb_datum *dst = &data[i];
- const struct ovsdb_type *type = &c->type;
-
- if (!ovsdb_datum_equals(src, dst, type)) {
- ovsdb_datum_destroy(dst, type);
- ovsdb_datum_clone(dst, src, type);
- }
- }
-}
-
-/* Frees all of the mt->n_columns ovsdb_datums in data[], using the types taken
- * from mt->columns[], plus 'data' itself. */
-static void
-free_monitor_row_data(const struct ovsdb_monitor_table *mt,
- struct ovsdb_datum *data)
-{
- if (data) {
- size_t i;
-
- for (i = 0; i < mt->n_columns; i++) {
- const struct ovsdb_column *c = mt->columns[i].column;
-
- ovsdb_datum_destroy(&data[i], &c->type);
- }
- free(data);
- }
-}
-
-/* Frees 'row', which must have been created from 'mt'. */
-static void
-ovsdb_monitor_row_destroy(const struct ovsdb_monitor_table *mt,
- struct ovsdb_monitor_row *row)
-{
- if (row) {
- free_monitor_row_data(mt, row->old);
- free_monitor_row_data(mt, row->new);
- free(row);
- }
-}
-
-static bool
-ovsdb_monitor_change_cb(const struct ovsdb_row *old,
- const struct ovsdb_row *new,
- const unsigned long int *changed OVS_UNUSED,
- void *aux_)
-{
- struct ovsdb_monitor_aux *aux = aux_;
- const struct ovsdb_monitor *m = aux->monitor;
- struct ovsdb_table *table = new ? new->table : old->table;
- const struct uuid *uuid = ovsdb_row_get_uuid(new ? new : old);
- struct ovsdb_monitor_row *change;
- struct ovsdb_monitor_table *mt;
-
- if (!aux->mt || table != aux->mt->table) {
- aux->mt = shash_find_data(&m->tables, table->schema->name);
- if (!aux->mt) {
- /* We don't care about rows in this table at all. Tell the caller
- * to skip it. */
- return false;
- }
- }
- mt = aux->mt;
-
- change = ovsdb_monitor_row_find(mt, uuid);
- if (!change) {
- change = xmalloc(sizeof *change);
- hmap_insert(&mt->changes, &change->hmap_node, uuid_hash(uuid));
- change->uuid = *uuid;
- change->old = clone_monitor_row_data(mt, old);
- change->new = clone_monitor_row_data(mt, new);
- } else {
- if (new) {
- update_monitor_row_data(mt, new, change->new);
- } else {
- free_monitor_row_data(mt, change->new);
- change->new = NULL;
-
- if (!change->old) {
- /* This row was added then deleted. Forget about it. */
- hmap_remove(&mt->changes, &change->hmap_node);
- free(change);
- }
- }
- }
- return true;
-}
-
-/* Returns JSON for a <row-update> (as described in RFC 7047) for 'row' within
- * 'mt', or NULL if no row update should be sent.
- *
- * The caller should specify 'initial' as true if the returned JSON is going to
- * be used as part of the initial reply to a "monitor" request, false if it is
- * going to be used as part of an "update" notification.
- *
- * 'changed' must be a scratch buffer for internal use that is at least
- * bitmap_n_bytes(mt->n_columns) bytes long. */