Catalli's threaded switch
[sliver-openvswitch.git] / ovsdb / ovsdb-client.c
index 9dd8094..b8a2fa4 100644 (file)
@@ -41,9 +41,9 @@
 #include "table.h"
 #include "timeval.h"
 #include "util.h"
-
 #include "vlog.h"
-#define THIS_MODULE VLM_ovsdb_client
+
+VLOG_DEFINE_THIS_MODULE(ovsdb_client)
 
 /* --format: Output formatting. */
 static enum {
@@ -74,8 +74,6 @@ main(int argc, char *argv[])
 {
     proctitle_init(argc, argv);
     set_program_name(argv[0]);
-    time_init();
-    vlog_init();
     parse_options(argc, argv);
     signal(SIGPIPE, SIG_IGN);
     run_command(argc - optind, argv + optind, all_commands);
@@ -188,9 +186,10 @@ usage(void)
            "\n  transact SERVER TRANSACTION\n"
            "    run TRANSACTION (a JSON array of operations) on SERVER\n"
            "    and print the results as JSON on stdout\n"
-           "\n  monitor SERVER DATABASE TABLE [COLUMN,...] [SELECT,...]\n"
-           "    monitor contents of (COLUMNs in) TABLE in DATABASE on SERVER\n"
-           "    Valid SELECTs are: initial, insert, delete, modify\n"
+           "\n  monitor SERVER DATABASE TABLE [COLUMN,...]...\n"
+           "    monitor contents of COLUMNs in TABLE in DATABASE on SERVER.\n"
+           "    COLUMNs may include !initial, !insert, !delete, !modify\n"
+           "    to avoid seeing the specified kinds of changes.\n"
            "\n  dump SERVER DATABASE\n"
            "    dump contents of DATABASE on SERVER to stdout\n",
            program_name, program_name);
@@ -224,11 +223,11 @@ open_jsonrpc(const char *server)
     struct stream *stream;
     int error;
 
-    error = stream_open_block(server, &stream);
+    error = stream_open_block(jsonrpc_stream_open(server, &stream), &stream);
     if (error == EAFNOSUPPORT) {
         struct pstream *pstream;
 
-        error = pstream_open(server, &pstream);
+        error = jsonrpc_pstream_open(server, &pstream);
         if (error) {
             ovs_fatal(error, "failed to connect or listen to \"%s\"", server);
         }
@@ -695,15 +694,11 @@ do_list_tables(int argc OVS_UNUSED, char *argv[])
     schema = fetch_schema(argv[1], argv[2]);
     table_init(&t);
     table_add_column(&t, "Table");
-    table_add_column(&t, "Comment");
     SHASH_FOR_EACH (node, &schema->tables) {
         struct ovsdb_table_schema *ts = node->data;
 
         table_add_row(&t);
         table_add_cell(&t, ts->name);
-        if (ts->comment) {
-            table_add_cell(&t, ts->comment);
-        }
     }
     ovsdb_schema_destroy(schema);
     table_print(&t);
@@ -724,7 +719,6 @@ do_list_columns(int argc OVS_UNUSED, char *argv[])
     }
     table_add_column(&t, "Column");
     table_add_column(&t, "Type");
-    table_add_column(&t, "Comment");
     SHASH_FOR_EACH (table_node, &schema->tables) {
         struct ovsdb_table_schema *ts = table_node->data;
 
@@ -741,9 +735,6 @@ do_list_columns(int argc OVS_UNUSED, char *argv[])
                 }
                 table_add_cell(&t, column->name);
                 table_add_cell_nocopy(&t, json_to_string(type, JSSF_SORT));
-                if (column->comment) {
-                    table_add_cell(&t, column->comment);
-                }
 
                 json_destroy(type);
             }
@@ -886,6 +877,87 @@ monitor_print(struct json *table_updates,
     table_destroy(&t);
 }
 
+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;
+}
+
 static void
 do_monitor(int argc, char *argv[])
 {
@@ -897,8 +969,8 @@ do_monitor(int argc, char *argv[])
     struct ovsdb_schema *schema;
     struct jsonrpc_msg *request;
     struct jsonrpc *rpc;
-    struct json *select, *monitor, *monitor_request, *monitor_requests,
-        *request_id;
+    struct json *monitor, *monitor_request_array,
+        *monitor_requests, *request_id;
 
     rpc = open_jsonrpc(server);
 
@@ -909,54 +981,27 @@ do_monitor(int argc, char *argv[])
                   server, database, table_name);
     }
 
-    if (argc >= 5 && *argv[4] != '\0') {
-        char *save_ptr = NULL;
-        char *token;
-
-        for (token = strtok_r(argv[4], ",", &save_ptr); token != NULL;
-             token = strtok_r(NULL, ",", &save_ptr)) {
-            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);
-            }
-            ovsdb_column_set_add(&columns, column);
-        }
-    } else {
-        struct shash_node *node;
-
-        SHASH_FOR_EACH (node, &table->columns) {
-            const struct ovsdb_column *column = node->data;
-            if (column->index != OVSDB_COL_UUID) {
-                ovsdb_column_set_add(&columns, column);
-            }
-        }
-    }
-
-    if (argc >= 6 && *argv[5] != '\0') {
-        char *save_ptr = NULL;
-        char *token;
+    monitor_request_array = json_array_create_empty();
+    if (argc > 4) {
+        int i;
 
-        select = json_object_create();
-        for (token = strtok_r(argv[5], ",", &save_ptr); token != NULL;
-             token = strtok_r(NULL, ",", &save_ptr)) {
-            json_object_put(select, token, json_boolean_create(true));
+        for (i = 4; i < argc; i++) {
+            json_array_add(
+                monitor_request_array,
+                parse_monitor_columns(argv[i], server, database, table,
+                                      &columns));
         }
     } else {
-        select = NULL;
-    }
-
-    monitor_request = json_object_create();
-    json_object_put(monitor_request,
-                    "columns", ovsdb_column_set_to_json(&columns));
-    if (select) {
-        json_object_put(monitor_request, "select", select);
+        /* Allocate a writable empty string since parse_monitor_columns() is
+         * going to strtok() it and that's risky with literal "". */
+        char empty[] = "";
+        json_array_add(
+            monitor_request_array,
+            parse_monitor_columns(empty, server, database, table, &columns));
     }
 
     monitor_requests = json_object_create();
-    json_object_put(monitor_requests, table_name, monitor_request);
+    json_object_put(monitor_requests, table_name, monitor_request_array);
 
     monitor = json_array_create_3(json_string_create(database),
                                   json_null_create(), monitor_requests);
@@ -1250,7 +1295,7 @@ static const struct command all_commands[] = {
     { "list-tables", 2, 2, do_list_tables },
     { "list-columns", 2, 3, do_list_columns },
     { "transact", 2, 2, do_transact },
-    { "monitor", 3, 5, do_monitor },
+    { "monitor", 3, INT_MAX, do_monitor },
     { "dump", 2, 2, do_dump },
     { "help", 0, INT_MAX, do_help },
     { NULL, 0, 0, NULL },