+ m = xzalloc(sizeof *m);
+ ovsdb_replica_init(&m->replica, &ovsdb_jsonrpc_replica_class);
+ ovsdb_add_replica(s->remote->server->db, &m->replica);
+ m->session = s;
+ hmap_insert(&s->monitors, &m->node, json_hash(monitor_id, 0));
+ m->monitor_id = json_clone(monitor_id);
+ shash_init(&m->tables);
+
+ SHASH_FOR_EACH (node, json_object(monitor_requests)) {
+ const struct ovsdb_table *table;
+ struct ovsdb_jsonrpc_monitor_table *mt;
+ const struct json *columns_json, *select_json;
+ struct ovsdb_parser parser;
+
+ table = ovsdb_get_table(s->remote->server->db, node->name);
+ if (!table) {
+ error = ovsdb_syntax_error(NULL, NULL,
+ "no table named %s", node->name);
+ goto error;
+ }
+
+ mt = xzalloc(sizeof *mt);
+ mt->table = table;
+ mt->select = OJMS_INITIAL | OJMS_INSERT | OJMS_DELETE | OJMS_MODIFY;
+ ovsdb_column_set_init(&mt->columns);
+ shash_add(&m->tables, table->schema->name, mt);
+
+ ovsdb_parser_init(&parser, node->data, "table %s", node->name);
+ columns_json = ovsdb_parser_member(&parser, "columns",
+ OP_ARRAY | OP_OPTIONAL);
+ select_json = ovsdb_parser_member(&parser, "select",
+ OP_OBJECT | OP_OPTIONAL);
+ error = ovsdb_parser_finish(&parser);
+ if (error) {
+ goto error;
+ }
+
+ if (columns_json) {
+ error = ovsdb_column_set_from_json(columns_json, table,
+ &mt->columns);
+ if (error) {
+ goto error;
+ }
+ } else {
+ struct shash_node *node;
+
+ SHASH_FOR_EACH (node, &table->schema->columns) {
+ const struct ovsdb_column *column = node->data;
+ if (column->index != OVSDB_COL_UUID) {
+ ovsdb_column_set_add(&mt->columns, column);
+ }
+ }
+ }
+
+ if (select_json) {
+ mt->select = 0;
+ ovsdb_parser_init(&parser, select_json, "table %s select",
+ table->schema->name);
+ if (parse_bool(&parser, "initial", true)) {
+ mt->select |= OJMS_INITIAL;
+ }
+ if (parse_bool(&parser, "insert", true)) {
+ mt->select |= OJMS_INSERT;
+ }
+ if (parse_bool(&parser, "delete", true)) {
+ mt->select |= OJMS_DELETE;
+ }
+ if (parse_bool(&parser, "modify", true)) {
+ mt->select |= OJMS_MODIFY;
+ }
+ error = ovsdb_parser_finish(&parser);
+ if (error) {
+ goto error;
+ }
+ }
+ }
+
+ return ovsdb_jsonrpc_monitor_get_initial(m);
+
+error:
+ if (m) {
+ ovsdb_remove_replica(s->remote->server->db, &m->replica);
+ }
+
+ json = ovsdb_error_to_json(error);
+ ovsdb_error_destroy(error);
+ return json;
+}
+
+static struct jsonrpc_msg *
+ovsdb_jsonrpc_monitor_cancel(struct ovsdb_jsonrpc_session *s,
+ struct json_array *params,
+ const struct json *request_id)
+{
+ if (params->n != 1) {
+ return jsonrpc_create_error(json_string_create("invalid parameters"),
+ request_id);
+ } else {
+ struct ovsdb_jsonrpc_monitor *m;
+
+ m = ovsdb_jsonrpc_monitor_find(s, params->elems[0]);
+ if (!m) {
+ return jsonrpc_create_error(json_string_create("unknown monitor"),
+ request_id);
+ } else {
+ ovsdb_remove_replica(s->remote->server->db, &m->replica);
+ return jsonrpc_create_reply(json_object_create(), request_id);
+ }
+ }