+/* Finds and returns the ovsdb_jsonrpc_monitor_row in 'mt->changes' for the
+ * given 'uuid', or NULL if there is no such row. */
+static struct ovsdb_jsonrpc_monitor_row *
+ovsdb_jsonrpc_monitor_row_find(const struct ovsdb_jsonrpc_monitor_table *mt,
+ const struct uuid *uuid)
+{
+ struct ovsdb_jsonrpc_monitor_row *row;
+
+ HMAP_FOR_EACH_WITH_HASH (row, hmap_node, uuid_hash(uuid), &mt->changes) {
+ if (uuid_equals(uuid, &row->uuid)) {
+ return row;
+ }
+ }
+ return NULL;
+}
+
+/* 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_jsonrpc_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_jsonrpc_monitor_table *mt,
+ const struct ovsdb_row *row,
+ struct ovsdb_datum *data)