+static void
+add_column(const char *server, const struct ovsdb_column *column,
+ struct ovsdb_column_set *columns, struct json *columns_json)
+{
+ if (ovsdb_column_set_contains(columns, column->index)) {
+ ovs_fatal(0, "%s: column \"%s\" mentioned multiple times",
+ server, column->name);
+ }
+ ovsdb_column_set_add(columns, column);
+ json_array_add(columns_json, json_string_create(column->name));
+}
+
+static struct json *
+parse_monitor_columns(char *arg, const char *server, const char *database,
+ const struct ovsdb_table_schema *table,
+ struct ovsdb_column_set *columns)
+{
+ bool initial, insert, delete, modify;
+ struct json *mr, *columns_json;
+ char *save_ptr = NULL;
+ char *token;
+
+ mr = json_object_create();
+ columns_json = json_array_create_empty();
+ json_object_put(mr, "columns", columns_json);
+
+ initial = insert = delete = modify = true;
+ for (token = strtok_r(arg, ",", &save_ptr); token != NULL;
+ token = strtok_r(NULL, ",", &save_ptr)) {
+ if (!strcmp(token, "!initial")) {
+ initial = false;
+ } else if (!strcmp(token, "!insert")) {
+ insert = false;
+ } else if (!strcmp(token, "!delete")) {
+ delete = false;
+ } else if (!strcmp(token, "!modify")) {
+ modify = false;
+ } else {
+ const struct ovsdb_column *column;
+
+ column = ovsdb_table_schema_get_column(table, token);
+ if (!column) {
+ ovs_fatal(0, "%s: table \"%s\" in %s does not have a "
+ "column named \"%s\"",
+ server, table->name, database, token);
+ }
+ add_column(server, column, columns, columns_json);
+ }
+ }
+
+ if (columns_json->u.array.n == 0) {
+ const struct shash_node **nodes;
+ size_t i, n;
+
+ n = shash_count(&table->columns);
+ nodes = shash_sort(&table->columns);
+ for (i = 0; i < n; i++) {
+ const struct ovsdb_column *column = nodes[i]->data;
+ if (column->index != OVSDB_COL_UUID
+ && column->index != OVSDB_COL_VERSION) {
+ add_column(server, column, columns, columns_json);
+ }
+ }
+ free(nodes);
+
+ add_column(server, ovsdb_table_schema_get_column(table,"_version"),
+ columns, columns_json);
+ }
+
+ if (!initial || !insert || !delete || !modify) {
+ struct json *select = json_object_create();
+ json_object_put(select, "initial", json_boolean_create(initial));
+ json_object_put(select, "insert", json_boolean_create(insert));
+ json_object_put(select, "delete", json_boolean_create(delete));
+ json_object_put(select, "modify", json_boolean_create(modify));
+ json_object_put(mr, "select", select);
+ }
+
+ return mr;
+}
+