d60d7ca84a45a171c7738390abe2fea0d6b3f573
[sliver-openvswitch.git] / ovsdb / ovsdb-client.c
1 /*
2  * Copyright (c) 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at:
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <config.h>
18
19 #include <ctype.h>
20 #include <errno.h>
21 #include <getopt.h>
22 #include <limits.h>
23 #include <signal.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <unistd.h>
27
28 #include "command-line.h"
29 #include "column.h"
30 #include "compiler.h"
31 #include "daemon.h"
32 #include "dirs.h"
33 #include "dynamic-string.h"
34 #include "fatal-signal.h"
35 #include "json.h"
36 #include "jsonrpc.h"
37 #include "lib/table.h"
38 #include "ovsdb.h"
39 #include "ovsdb-data.h"
40 #include "ovsdb-error.h"
41 #include "poll-loop.h"
42 #include "sort.h"
43 #include "svec.h"
44 #include "stream.h"
45 #include "stream-ssl.h"
46 #include "table.h"
47 #include "timeval.h"
48 #include "unixctl.h"
49 #include "util.h"
50 #include "vlog.h"
51
52 VLOG_DEFINE_THIS_MODULE(ovsdb_client);
53
54 enum args_needed {
55     NEED_NONE,            /* No JSON-RPC connection or database name needed. */
56     NEED_RPC,             /* JSON-RPC connection needed. */
57     NEED_DATABASE         /* JSON-RPC connection and database name needed. */
58 };
59
60 struct ovsdb_client_command {
61     const char *name;
62     enum args_needed need;
63     int min_args;
64     int max_args;
65     void (*handler)(struct jsonrpc *rpc, const char *database,
66                     int argc, char *argv[]);
67 };
68
69 /* --timestamp: Print a timestamp before each update on "monitor" command? */
70 static bool timestamp;
71
72 /* Format for table output. */
73 static struct table_style table_style = TABLE_STYLE_DEFAULT;
74
75 static const struct ovsdb_client_command *get_all_commands(void);
76
77 static void usage(void) NO_RETURN;
78 static void parse_options(int argc, char *argv[]);
79 static struct jsonrpc *open_jsonrpc(const char *server);
80 static void fetch_dbs(struct jsonrpc *, struct svec *dbs);
81
82 int
83 main(int argc, char *argv[])
84 {
85     const struct ovsdb_client_command *command;
86     const char *database;
87     struct jsonrpc *rpc;
88
89     proctitle_init(argc, argv);
90     set_program_name(argv[0]);
91     parse_options(argc, argv);
92     fatal_ignore_sigpipe();
93
94     if (optind >= argc) {
95         ovs_fatal(0, "missing command name; use --help for help");
96     }
97
98     for (command = get_all_commands(); ; command++) {
99         if (!command->name) {
100             VLOG_FATAL("unknown command '%s'; use --help for help",
101                        argv[optind]);
102         } else if (!strcmp(command->name, argv[optind])) {
103             break;
104         }
105     }
106     optind++;
107
108     if (command->need != NEED_NONE) {
109         if (argc - optind > command->min_args
110             && (isalpha((unsigned char) argv[optind][0])
111                 && strchr(argv[optind], ':'))) {
112             rpc = open_jsonrpc(argv[optind++]);
113         } else {
114             char *sock = xasprintf("unix:%s/db.sock", ovs_rundir());
115             rpc = open_jsonrpc(sock);
116             free(sock);
117         }
118     } else {
119         rpc = NULL;
120     }
121
122     if (command->need == NEED_DATABASE) {
123         struct svec dbs;
124
125         svec_init(&dbs);
126         fetch_dbs(rpc, &dbs);
127         if (argc - optind > command->min_args
128             && svec_contains(&dbs, argv[optind])) {
129             database = argv[optind++];
130         } else if (dbs.n == 1) {
131             database = xstrdup(dbs.names[0]);
132         } else if (svec_contains(&dbs, "Open_vSwitch")) {
133             database = "Open_vSwitch";
134         } else {
135             ovs_fatal(0, "no default database for `%s' command, please "
136                       "specify a database name", command->name);
137         }
138         svec_destroy(&dbs);
139     } else {
140         database = NULL;
141     }
142
143     if (argc - optind < command->min_args ||
144         argc - optind > command->max_args) {
145         VLOG_FATAL("invalid syntax for '%s' (use --help for help)",
146                     command->name);
147     }
148
149     command->handler(rpc, database, argc - optind, argv + optind);
150
151     jsonrpc_close(rpc);
152
153     if (ferror(stdout)) {
154         VLOG_FATAL("write to stdout failed");
155     }
156     if (ferror(stderr)) {
157         VLOG_FATAL("write to stderr failed");
158     }
159
160     return 0;
161 }
162
163 static void
164 parse_options(int argc, char *argv[])
165 {
166     enum {
167         OPT_BOOTSTRAP_CA_CERT = UCHAR_MAX + 1,
168         OPT_TIMESTAMP,
169         DAEMON_OPTION_ENUMS,
170         TABLE_OPTION_ENUMS
171     };
172     static const struct option long_options[] = {
173         {"verbose", optional_argument, NULL, 'v'},
174         {"help", no_argument, NULL, 'h'},
175         {"version", no_argument, NULL, 'V'},
176         {"timestamp", no_argument, NULL, OPT_TIMESTAMP},
177         DAEMON_LONG_OPTIONS,
178 #ifdef HAVE_OPENSSL
179         {"bootstrap-ca-cert", required_argument, NULL, OPT_BOOTSTRAP_CA_CERT},
180         STREAM_SSL_LONG_OPTIONS,
181 #endif
182         TABLE_LONG_OPTIONS,
183         {NULL, 0, NULL, 0},
184     };
185     char *short_options = long_options_to_short_options(long_options);
186
187     for (;;) {
188         int c;
189
190         c = getopt_long(argc, argv, short_options, long_options, NULL);
191         if (c == -1) {
192             break;
193         }
194
195         switch (c) {
196         case 'h':
197             usage();
198
199         case 'V':
200             ovs_print_version(0, 0);
201             exit(EXIT_SUCCESS);
202
203         case 'v':
204             vlog_set_verbosity(optarg);
205             break;
206
207         DAEMON_OPTION_HANDLERS
208
209         TABLE_OPTION_HANDLERS(&table_style)
210
211         STREAM_SSL_OPTION_HANDLERS
212
213         case OPT_BOOTSTRAP_CA_CERT:
214             stream_ssl_set_ca_cert_file(optarg, true);
215             break;
216
217         case OPT_TIMESTAMP:
218             timestamp = true;
219             break;
220
221         case '?':
222             exit(EXIT_FAILURE);
223
224         case 0:
225             /* getopt_long() already set the value for us. */
226             break;
227
228         default:
229             abort();
230         }
231     }
232     free(short_options);
233 }
234
235 static void
236 usage(void)
237 {
238     printf("%s: Open vSwitch database JSON-RPC client\n"
239            "usage: %s [OPTIONS] COMMAND [ARG...]\n"
240            "\nValid commands are:\n"
241            "\n  list-dbs [SERVER]\n"
242            "    list databases available on SERVER\n"
243            "\n  get-schema [SERVER] [DATABASE]\n"
244            "    retrieve schema for DATABASE from SERVER\n"
245            "\n  get-schema-version [SERVER] [DATABASE]\n"
246            "    retrieve schema for DATABASE from SERVER and report only its\n"
247            "    version number on stdout\n"
248            "\n  list-tables [SERVER] [DATABASE]\n"
249            "    list tables for DATABASE on SERVER\n"
250            "\n  list-columns [SERVER] [DATABASE] [TABLE]\n"
251            "    list columns in TABLE (or all tables) in DATABASE on SERVER\n"
252            "\n  transact [SERVER] TRANSACTION\n"
253            "    run TRANSACTION (a JSON array of operations) on SERVER\n"
254            "    and print the results as JSON on stdout\n"
255            "\n  monitor [SERVER] [DATABASE] TABLE [COLUMN,...]...\n"
256            "    monitor contents of COLUMNs in TABLE in DATABASE on SERVER.\n"
257            "    COLUMNs may include !initial, !insert, !delete, !modify\n"
258            "    to avoid seeing the specified kinds of changes.\n"
259            "\n  monitor [SERVER] [DATABASE] ALL\n"
260            "    monitor all changes to all columns in all tables\n"
261            "    in DATBASE on SERVER.\n"
262            "\n  dump [SERVER] [DATABASE]\n"
263            "    dump contents of DATABASE on SERVER to stdout\n"
264            "\nThe default SERVER is unix:%s/db.sock.\n"
265            "The default DATABASE is Open_vSwitch.\n",
266            program_name, program_name, ovs_rundir());
267     stream_usage("SERVER", true, true, true);
268     printf("\nOutput formatting options:\n"
269            "  -f, --format=FORMAT         set output formatting to FORMAT\n"
270            "                              (\"table\", \"html\", \"csv\", "
271            "or \"json\")\n"
272            "  --no-headings               omit table heading row\n"
273            "  --pretty                    pretty-print JSON in output\n"
274            "  --timestamp                 timestamp \"monitor\" output");
275     daemon_usage();
276     vlog_usage();
277     printf("\nOther options:\n"
278            "  -h, --help                  display this help message\n"
279            "  -V, --version               display version information\n");
280     exit(EXIT_SUCCESS);
281 }
282 \f
283 static void
284 check_txn(int error, struct jsonrpc_msg **reply_)
285 {
286     struct jsonrpc_msg *reply = *reply_;
287
288     if (error) {
289         ovs_fatal(error, "transaction failed");
290     }
291
292     if (reply->error) {
293         ovs_fatal(error, "transaction returned error: %s",
294                   json_to_string(reply->error, table_style.json_flags));
295     }
296 }
297
298 static struct json *
299 parse_json(const char *s)
300 {
301     struct json *json = json_from_string(s);
302     if (json->type == JSON_STRING) {
303         ovs_fatal(0, "\"%s\": %s", s, json->u.string);
304     }
305     return json;
306 }
307
308 static struct jsonrpc *
309 open_jsonrpc(const char *server)
310 {
311     struct stream *stream;
312     int error;
313
314     error = stream_open_block(jsonrpc_stream_open(server, &stream,
315                               DSCP_DEFAULT), &stream);
316     if (error == EAFNOSUPPORT) {
317         struct pstream *pstream;
318
319         error = jsonrpc_pstream_open(server, &pstream, DSCP_DEFAULT);
320         if (error) {
321             ovs_fatal(error, "failed to connect or listen to \"%s\"", server);
322         }
323
324         VLOG_INFO("%s: waiting for connection...", server);
325         error = pstream_accept_block(pstream, &stream);
326         if (error) {
327             ovs_fatal(error, "failed to accept connection on \"%s\"", server);
328         }
329
330         pstream_close(pstream);
331     } else if (error) {
332         ovs_fatal(error, "failed to connect to \"%s\"", server);
333     }
334
335     return jsonrpc_open(stream);
336 }
337
338 static void
339 print_json(struct json *json)
340 {
341     char *string = json_to_string(json, table_style.json_flags);
342     fputs(string, stdout);
343     free(string);
344 }
345
346 static void
347 print_and_free_json(struct json *json)
348 {
349     print_json(json);
350     json_destroy(json);
351 }
352
353 static void
354 check_ovsdb_error(struct ovsdb_error *error)
355 {
356     if (error) {
357         ovs_fatal(0, "%s", ovsdb_error_to_string(error));
358     }
359 }
360
361 static struct ovsdb_schema *
362 fetch_schema(struct jsonrpc *rpc, const char *database)
363 {
364     struct jsonrpc_msg *request, *reply;
365     struct ovsdb_schema *schema;
366
367     request = jsonrpc_create_request("get_schema",
368                                      json_array_create_1(
369                                          json_string_create(database)),
370                                      NULL);
371     check_txn(jsonrpc_transact_block(rpc, request, &reply), &reply);
372     check_ovsdb_error(ovsdb_schema_from_json(reply->result, &schema));
373     jsonrpc_msg_destroy(reply);
374
375     return schema;
376 }
377
378 static void
379 fetch_dbs(struct jsonrpc *rpc, struct svec *dbs)
380 {
381     struct jsonrpc_msg *request, *reply;
382     size_t i;
383
384     request = jsonrpc_create_request("list_dbs", json_array_create_empty(),
385                                      NULL);
386
387     check_txn(jsonrpc_transact_block(rpc, request, &reply), &reply);
388     if (reply->result->type != JSON_ARRAY) {
389         ovs_fatal(0, "list_dbs response is not array");
390     }
391
392     for (i = 0; i < reply->result->u.array.n; i++) {
393         const struct json *name = reply->result->u.array.elems[i];
394
395         if (name->type != JSON_STRING) {
396             ovs_fatal(0, "list_dbs response %"PRIuSIZE" is not string", i);
397         }
398         svec_add(dbs, name->u.string);
399     }
400     jsonrpc_msg_destroy(reply);
401     svec_sort(dbs);
402 }
403 \f
404 static void
405 do_list_dbs(struct jsonrpc *rpc, const char *database OVS_UNUSED,
406             int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
407 {
408     const char *db_name;
409     struct svec dbs;
410     size_t i;
411
412     svec_init(&dbs);
413     fetch_dbs(rpc, &dbs);
414     SVEC_FOR_EACH (i, db_name, &dbs) {
415         puts(db_name);
416     }
417     svec_destroy(&dbs);
418 }
419
420 static void
421 do_get_schema(struct jsonrpc *rpc, const char *database,
422               int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
423 {
424     struct ovsdb_schema *schema = fetch_schema(rpc, database);
425     print_and_free_json(ovsdb_schema_to_json(schema));
426     ovsdb_schema_destroy(schema);
427 }
428
429 static void
430 do_get_schema_version(struct jsonrpc *rpc, const char *database,
431                       int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
432 {
433     struct ovsdb_schema *schema = fetch_schema(rpc, database);
434     puts(schema->version);
435     ovsdb_schema_destroy(schema);
436 }
437
438 static void
439 do_list_tables(struct jsonrpc *rpc, const char *database,
440                int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
441 {
442     struct ovsdb_schema *schema;
443     struct shash_node *node;
444     struct table t;
445
446     schema = fetch_schema(rpc, database);
447     table_init(&t);
448     table_add_column(&t, "Table");
449     SHASH_FOR_EACH (node, &schema->tables) {
450         struct ovsdb_table_schema *ts = node->data;
451
452         table_add_row(&t);
453         table_add_cell(&t)->text = xstrdup(ts->name);
454     }
455     ovsdb_schema_destroy(schema);
456     table_print(&t, &table_style);
457 }
458
459 static void
460 do_list_columns(struct jsonrpc *rpc, const char *database,
461                 int argc OVS_UNUSED, char *argv[])
462 {
463     const char *table_name = argv[0];
464     struct ovsdb_schema *schema;
465     struct shash_node *table_node;
466     struct table t;
467
468     schema = fetch_schema(rpc, database);
469     table_init(&t);
470     if (!table_name) {
471         table_add_column(&t, "Table");
472     }
473     table_add_column(&t, "Column");
474     table_add_column(&t, "Type");
475     SHASH_FOR_EACH (table_node, &schema->tables) {
476         struct ovsdb_table_schema *ts = table_node->data;
477
478         if (!table_name || !strcmp(table_name, ts->name)) {
479             struct shash_node *column_node;
480
481             SHASH_FOR_EACH (column_node, &ts->columns) {
482                 const struct ovsdb_column *column = column_node->data;
483
484                 table_add_row(&t);
485                 if (!table_name) {
486                     table_add_cell(&t)->text = xstrdup(ts->name);
487                 }
488                 table_add_cell(&t)->text = xstrdup(column->name);
489                 table_add_cell(&t)->json = ovsdb_type_to_json(&column->type);
490             }
491         }
492     }
493     ovsdb_schema_destroy(schema);
494     table_print(&t, &table_style);
495 }
496
497 static void
498 do_transact(struct jsonrpc *rpc, const char *database OVS_UNUSED,
499             int argc OVS_UNUSED, char *argv[])
500 {
501     struct jsonrpc_msg *request, *reply;
502     struct json *transaction;
503
504     transaction = parse_json(argv[0]);
505
506     request = jsonrpc_create_request("transact", transaction, NULL);
507     check_txn(jsonrpc_transact_block(rpc, request, &reply), &reply);
508     print_json(reply->result);
509     putchar('\n');
510     jsonrpc_msg_destroy(reply);
511 }
512 \f
513 /* "monitor" command. */
514
515 struct monitored_table {
516     struct ovsdb_table_schema *table;
517     struct ovsdb_column_set columns;
518 };
519
520 static void
521 monitor_print_row(struct json *row, const char *type, const char *uuid,
522                   const struct ovsdb_column_set *columns, struct table *t)
523 {
524     size_t i;
525
526     if (!row) {
527         ovs_error(0, "missing %s row", type);
528         return;
529     } else if (row->type != JSON_OBJECT) {
530         ovs_error(0, "<row> is not object");
531         return;
532     }
533
534     table_add_row(t);
535     table_add_cell(t)->text = xstrdup(uuid);
536     table_add_cell(t)->text = xstrdup(type);
537     for (i = 0; i < columns->n_columns; i++) {
538         const struct ovsdb_column *column = columns->columns[i];
539         struct json *value = shash_find_data(json_object(row), column->name);
540         struct cell *cell = table_add_cell(t);
541         if (value) {
542             cell->json = json_clone(value);
543             cell->type = &column->type;
544         }
545     }
546 }
547
548 static void
549 monitor_print_table(struct json *table_update,
550                     const struct monitored_table *mt, char *caption,
551                     bool initial)
552 {
553     const struct ovsdb_table_schema *table = mt->table;
554     const struct ovsdb_column_set *columns = &mt->columns;
555     struct shash_node *node;
556     struct table t;
557     size_t i;
558
559     if (table_update->type != JSON_OBJECT) {
560         ovs_error(0, "<table-update> for table %s is not object", table->name);
561         return;
562     }
563
564     table_init(&t);
565     table_set_timestamp(&t, timestamp);
566     table_set_caption(&t, caption);
567
568     table_add_column(&t, "row");
569     table_add_column(&t, "action");
570     for (i = 0; i < columns->n_columns; i++) {
571         table_add_column(&t, "%s", columns->columns[i]->name);
572     }
573     SHASH_FOR_EACH (node, json_object(table_update)) {
574         struct json *row_update = node->data;
575         struct json *old, *new;
576
577         if (row_update->type != JSON_OBJECT) {
578             ovs_error(0, "<row-update> is not object");
579             continue;
580         }
581         old = shash_find_data(json_object(row_update), "old");
582         new = shash_find_data(json_object(row_update), "new");
583         if (initial) {
584             monitor_print_row(new, "initial", node->name, columns, &t);
585         } else if (!old) {
586             monitor_print_row(new, "insert", node->name, columns, &t);
587         } else if (!new) {
588             monitor_print_row(old, "delete", node->name, columns, &t);
589         } else {
590             monitor_print_row(old, "old", node->name, columns, &t);
591             monitor_print_row(new, "new", "", columns, &t);
592         }
593     }
594     table_print(&t, &table_style);
595     table_destroy(&t);
596 }
597
598 static void
599 monitor_print(struct json *table_updates,
600               const struct monitored_table *mts, size_t n_mts,
601               bool initial)
602 {
603     size_t i;
604
605     if (table_updates->type != JSON_OBJECT) {
606         ovs_error(0, "<table-updates> is not object");
607         return;
608     }
609
610     for (i = 0; i < n_mts; i++) {
611         const struct monitored_table *mt = &mts[i];
612         struct json *table_update = shash_find_data(json_object(table_updates),
613                                                     mt->table->name);
614         if (table_update) {
615             monitor_print_table(table_update, mt,
616                                 n_mts > 1 ? xstrdup(mt->table->name) : NULL,
617                                 initial);
618         }
619     }
620 }
621
622 static void
623 add_column(const char *server, const struct ovsdb_column *column,
624            struct ovsdb_column_set *columns, struct json *columns_json)
625 {
626     if (ovsdb_column_set_contains(columns, column->index)) {
627         ovs_fatal(0, "%s: column \"%s\" mentioned multiple times",
628                   server, column->name);
629     }
630     ovsdb_column_set_add(columns, column);
631     json_array_add(columns_json, json_string_create(column->name));
632 }
633
634 static struct json *
635 parse_monitor_columns(char *arg, const char *server, const char *database,
636                       const struct ovsdb_table_schema *table,
637                       struct ovsdb_column_set *columns)
638 {
639     bool initial, insert, delete, modify;
640     struct json *mr, *columns_json;
641     char *save_ptr = NULL;
642     char *token;
643
644     mr = json_object_create();
645     columns_json = json_array_create_empty();
646     json_object_put(mr, "columns", columns_json);
647
648     initial = insert = delete = modify = true;
649     for (token = strtok_r(arg, ",", &save_ptr); token != NULL;
650          token = strtok_r(NULL, ",", &save_ptr)) {
651         if (!strcmp(token, "!initial")) {
652             initial = false;
653         } else if (!strcmp(token, "!insert")) {
654             insert = false;
655         } else if (!strcmp(token, "!delete")) {
656             delete = false;
657         } else if (!strcmp(token, "!modify")) {
658             modify = false;
659         } else {
660             const struct ovsdb_column *column;
661
662             column = ovsdb_table_schema_get_column(table, token);
663             if (!column) {
664                 ovs_fatal(0, "%s: table \"%s\" in %s does not have a "
665                           "column named \"%s\"",
666                           server, table->name, database, token);
667             }
668             add_column(server, column, columns, columns_json);
669         }
670     }
671
672     if (columns_json->u.array.n == 0) {
673         const struct shash_node **nodes;
674         size_t i, n;
675
676         n = shash_count(&table->columns);
677         nodes = shash_sort(&table->columns);
678         for (i = 0; i < n; i++) {
679             const struct ovsdb_column *column = nodes[i]->data;
680             if (column->index != OVSDB_COL_UUID
681                 && column->index != OVSDB_COL_VERSION) {
682                 add_column(server, column, columns, columns_json);
683             }
684         }
685         free(nodes);
686
687         add_column(server, ovsdb_table_schema_get_column(table, "_version"),
688                    columns, columns_json);
689     }
690
691     if (!initial || !insert || !delete || !modify) {
692         struct json *select = json_object_create();
693         json_object_put(select, "initial", json_boolean_create(initial));
694         json_object_put(select, "insert", json_boolean_create(insert));
695         json_object_put(select, "delete", json_boolean_create(delete));
696         json_object_put(select, "modify", json_boolean_create(modify));
697         json_object_put(mr, "select", select);
698     }
699
700     return mr;
701 }
702
703 static void
704 ovsdb_client_exit(struct unixctl_conn *conn, int argc OVS_UNUSED,
705                   const char *argv[] OVS_UNUSED, void *exiting_)
706 {
707     bool *exiting = exiting_;
708     *exiting = true;
709     unixctl_command_reply(conn, NULL);
710 }
711
712 static void
713 ovsdb_client_block(struct unixctl_conn *conn, int argc OVS_UNUSED,
714                    const char *argv[] OVS_UNUSED, void *blocked_)
715 {
716     bool *blocked = blocked_;
717
718     if (!*blocked) {
719         *blocked = true;
720         unixctl_command_reply(conn, NULL);
721     } else {
722         unixctl_command_reply(conn, "already blocking");
723     }
724 }
725
726 static void
727 ovsdb_client_unblock(struct unixctl_conn *conn, int argc OVS_UNUSED,
728                      const char *argv[] OVS_UNUSED, void *blocked_)
729 {
730     bool *blocked = blocked_;
731
732     if (*blocked) {
733         *blocked = false;
734         unixctl_command_reply(conn, NULL);
735     } else {
736         unixctl_command_reply(conn, "already unblocked");
737     }
738 }
739
740 static void
741 add_monitored_table(int argc, char *argv[],
742                     const char *server, const char *database,
743                     struct ovsdb_table_schema *table,
744                     struct json *monitor_requests,
745                     struct monitored_table **mts,
746                     size_t *n_mts, size_t *allocated_mts)
747 {
748     struct json *monitor_request_array;
749     struct monitored_table *mt;
750
751     if (*n_mts >= *allocated_mts) {
752         *mts = x2nrealloc(*mts, allocated_mts, sizeof **mts);
753     }
754     mt = &(*mts)[(*n_mts)++];
755     mt->table = table;
756     ovsdb_column_set_init(&mt->columns);
757
758     monitor_request_array = json_array_create_empty();
759     if (argc > 1) {
760         int i;
761
762         for (i = 1; i < argc; i++) {
763             json_array_add(
764                 monitor_request_array,
765                 parse_monitor_columns(argv[i], server, database, table,
766                                       &mt->columns));
767         }
768     } else {
769         /* Allocate a writable empty string since parse_monitor_columns()
770          * is going to strtok() it and that's risky with literal "". */
771         char empty[] = "";
772         json_array_add(
773             monitor_request_array,
774             parse_monitor_columns(empty, server, database,
775                                   table, &mt->columns));
776     }
777
778     json_object_put(monitor_requests, table->name, monitor_request_array);
779 }
780
781 static void
782 do_monitor(struct jsonrpc *rpc, const char *database,
783            int argc, char *argv[])
784 {
785     const char *server = jsonrpc_get_name(rpc);
786     const char *table_name = argv[0];
787     struct unixctl_server *unixctl;
788     struct ovsdb_schema *schema;
789     struct jsonrpc_msg *request;
790     struct json *monitor, *monitor_requests, *request_id;
791     bool exiting = false;
792     bool blocked = false;
793
794     struct monitored_table *mts;
795     size_t n_mts, allocated_mts;
796
797     daemon_save_fd(STDOUT_FILENO);
798     daemonize_start();
799     if (get_detach()) {
800         int error;
801
802         error = unixctl_server_create(NULL, &unixctl);
803         if (error) {
804             ovs_fatal(error, "failed to create unixctl server");
805         }
806
807         unixctl_command_register("exit", "", 0, 0,
808                                  ovsdb_client_exit, &exiting);
809         unixctl_command_register("ovsdb-client/block", "", 0, 0,
810                                  ovsdb_client_block, &blocked);
811         unixctl_command_register("ovsdb-client/unblock", "", 0, 0,
812                                  ovsdb_client_unblock, &blocked);
813     } else {
814         unixctl = NULL;
815     }
816
817     schema = fetch_schema(rpc, database);
818
819     monitor_requests = json_object_create();
820
821     mts = NULL;
822     n_mts = allocated_mts = 0;
823     if (strcmp(table_name, "ALL")) {
824         struct ovsdb_table_schema *table;
825
826         table = shash_find_data(&schema->tables, table_name);
827         if (!table) {
828             ovs_fatal(0, "%s: %s does not have a table named \"%s\"",
829                       server, database, table_name);
830         }
831
832         add_monitored_table(argc, argv, server, database, table,
833                             monitor_requests, &mts, &n_mts, &allocated_mts);
834     } else {
835         size_t n = shash_count(&schema->tables);
836         const struct shash_node **nodes = shash_sort(&schema->tables);
837         size_t i;
838
839         for (i = 0; i < n; i++) {
840             struct ovsdb_table_schema *table = nodes[i]->data;
841
842             add_monitored_table(argc, argv, server, database, table,
843                                 monitor_requests,
844                                 &mts, &n_mts, &allocated_mts);
845         }
846         free(nodes);
847     }
848
849     monitor = json_array_create_3(json_string_create(database),
850                                   json_null_create(), monitor_requests);
851     request = jsonrpc_create_request("monitor", monitor, NULL);
852     request_id = json_clone(request->id);
853     jsonrpc_send(rpc, request);
854
855     for (;;) {
856         unixctl_server_run(unixctl);
857         while (!blocked) {
858             struct jsonrpc_msg *msg;
859             int error;
860
861             error = jsonrpc_recv(rpc, &msg);
862             if (error == EAGAIN) {
863                 break;
864             } else if (error) {
865                 ovs_fatal(error, "%s: receive failed", server);
866             }
867
868             if (msg->type == JSONRPC_REQUEST && !strcmp(msg->method, "echo")) {
869                 jsonrpc_send(rpc, jsonrpc_create_reply(json_clone(msg->params),
870                                                        msg->id));
871             } else if (msg->type == JSONRPC_REPLY
872                        && json_equal(msg->id, request_id)) {
873                 monitor_print(msg->result, mts, n_mts, true);
874                 fflush(stdout);
875                 daemonize_complete();
876             } else if (msg->type == JSONRPC_NOTIFY
877                        && !strcmp(msg->method, "update")) {
878                 struct json *params = msg->params;
879                 if (params->type == JSON_ARRAY
880                     && params->u.array.n == 2
881                     && params->u.array.elems[0]->type == JSON_NULL) {
882                     monitor_print(params->u.array.elems[1], mts, n_mts, false);
883                     fflush(stdout);
884                 }
885             }
886             jsonrpc_msg_destroy(msg);
887         }
888
889         if (exiting) {
890             break;
891         }
892
893         jsonrpc_run(rpc);
894         jsonrpc_wait(rpc);
895         if (!blocked) {
896             jsonrpc_recv_wait(rpc);
897         }
898         unixctl_server_wait(unixctl);
899         poll_block();
900     }
901 }
902
903 struct dump_table_aux {
904     struct ovsdb_datum **data;
905     const struct ovsdb_column **columns;
906     size_t n_columns;
907 };
908
909 static int
910 compare_data(size_t a_y, size_t b_y, size_t x,
911              const struct dump_table_aux *aux)
912 {
913     return ovsdb_datum_compare_3way(&aux->data[a_y][x],
914                                     &aux->data[b_y][x],
915                                     &aux->columns[x]->type);
916 }
917
918 static int
919 compare_rows(size_t a_y, size_t b_y, void *aux_)
920 {
921     struct dump_table_aux *aux = aux_;
922     size_t x;
923
924     /* Skip UUID columns on the first pass, since their values tend to be
925      * random and make our results less reproducible. */
926     for (x = 0; x < aux->n_columns; x++) {
927         if (aux->columns[x]->type.key.type != OVSDB_TYPE_UUID) {
928             int cmp = compare_data(a_y, b_y, x, aux);
929             if (cmp) {
930                 return cmp;
931             }
932         }
933     }
934
935     /* Use UUID columns as tie-breakers. */
936     for (x = 0; x < aux->n_columns; x++) {
937         if (aux->columns[x]->type.key.type == OVSDB_TYPE_UUID) {
938             int cmp = compare_data(a_y, b_y, x, aux);
939             if (cmp) {
940                 return cmp;
941             }
942         }
943     }
944
945     return 0;
946 }
947
948 static void
949 swap_rows(size_t a_y, size_t b_y, void *aux_)
950 {
951     struct dump_table_aux *aux = aux_;
952     struct ovsdb_datum *tmp = aux->data[a_y];
953     aux->data[a_y] = aux->data[b_y];
954     aux->data[b_y] = tmp;
955 }
956
957 static int
958 compare_columns(const void *a_, const void *b_)
959 {
960     const struct ovsdb_column *const *ap = a_;
961     const struct ovsdb_column *const *bp = b_;
962     const struct ovsdb_column *a = *ap;
963     const struct ovsdb_column *b = *bp;
964
965     return strcmp(a->name, b->name);
966 }
967
968 static void
969 dump_table(const struct ovsdb_table_schema *ts, struct json_array *rows)
970 {
971     const struct ovsdb_column **columns;
972     size_t n_columns;
973
974     struct ovsdb_datum **data;
975
976     struct dump_table_aux aux;
977     struct shash_node *node;
978     struct table t;
979     size_t x, y;
980
981     /* Sort columns by name, for reproducibility. */
982     columns = xmalloc(shash_count(&ts->columns) * sizeof *columns);
983     n_columns = 0;
984     SHASH_FOR_EACH (node, &ts->columns) {
985         struct ovsdb_column *column = node->data;
986         if (strcmp(column->name, "_version")) {
987             columns[n_columns++] = column;
988         }
989     }
990     qsort(columns, n_columns, sizeof *columns, compare_columns);
991
992     /* Extract data from table. */
993     data = xmalloc(rows->n * sizeof *data);
994     for (y = 0; y < rows->n; y++) {
995         struct shash *row;
996
997         if (rows->elems[y]->type != JSON_OBJECT) {
998             ovs_fatal(0,  "row %"PRIuSIZE" in table %s response is not a JSON object: "
999                       "%s", y, ts->name, json_to_string(rows->elems[y], 0));
1000         }
1001         row = json_object(rows->elems[y]);
1002
1003         data[y] = xmalloc(n_columns * sizeof **data);
1004         for (x = 0; x < n_columns; x++) {
1005             const struct json *json = shash_find_data(row, columns[x]->name);
1006             if (!json) {
1007                 ovs_fatal(0, "row %"PRIuSIZE" in table %s response lacks %s column",
1008                           y, ts->name, columns[x]->name);
1009             }
1010
1011             check_ovsdb_error(ovsdb_datum_from_json(&data[y][x],
1012                                                     &columns[x]->type,
1013                                                     json, NULL));
1014         }
1015     }
1016
1017     /* Sort rows by column values, for reproducibility. */
1018     aux.data = data;
1019     aux.columns = columns;
1020     aux.n_columns = n_columns;
1021     sort(rows->n, compare_rows, swap_rows, &aux);
1022
1023     /* Add column headings. */
1024     table_init(&t);
1025     table_set_caption(&t, xasprintf("%s table", ts->name));
1026     for (x = 0; x < n_columns; x++) {
1027         table_add_column(&t, "%s", columns[x]->name);
1028     }
1029
1030     /* Print rows. */
1031     for (y = 0; y < rows->n; y++) {
1032         table_add_row(&t);
1033         for (x = 0; x < n_columns; x++) {
1034             struct cell *cell = table_add_cell(&t);
1035             cell->json = ovsdb_datum_to_json(&data[y][x], &columns[x]->type);
1036             cell->type = &columns[x]->type;
1037             ovsdb_datum_destroy(&data[y][x], &columns[x]->type);
1038         }
1039         free(data[y]);
1040     }
1041     table_print(&t, &table_style);
1042     table_destroy(&t);
1043
1044     free(data);
1045     free(columns);
1046 }
1047
1048 static void
1049 do_dump(struct jsonrpc *rpc, const char *database,
1050         int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
1051 {
1052     struct jsonrpc_msg *request, *reply;
1053     struct ovsdb_schema *schema;
1054     struct json *transaction;
1055
1056     const struct shash_node **tables;
1057     size_t n_tables;
1058
1059     size_t i;
1060
1061     schema = fetch_schema(rpc, database);
1062     tables = shash_sort(&schema->tables);
1063     n_tables = shash_count(&schema->tables);
1064
1065     /* Construct transaction to retrieve entire database. */
1066     transaction = json_array_create_1(json_string_create(database));
1067     for (i = 0; i < n_tables; i++) {
1068         const struct ovsdb_table_schema *ts = tables[i]->data;
1069         struct json *op, *columns;
1070         struct shash_node *node;
1071
1072         columns = json_array_create_empty();
1073         SHASH_FOR_EACH (node, &ts->columns) {
1074             const struct ovsdb_column *column = node->data;
1075
1076             if (strcmp(column->name, "_version")) {
1077                 json_array_add(columns, json_string_create(column->name));
1078             }
1079         }
1080
1081         op = json_object_create();
1082         json_object_put_string(op, "op", "select");
1083         json_object_put_string(op, "table", tables[i]->name);
1084         json_object_put(op, "where", json_array_create_empty());
1085         json_object_put(op, "columns", columns);
1086         json_array_add(transaction, op);
1087     }
1088
1089     /* Send request, get reply. */
1090     request = jsonrpc_create_request("transact", transaction, NULL);
1091     check_txn(jsonrpc_transact_block(rpc, request, &reply), &reply);
1092
1093     /* Print database contents. */
1094     if (reply->result->type != JSON_ARRAY
1095         || reply->result->u.array.n != n_tables) {
1096         ovs_fatal(0, "reply is not array of %"PRIuSIZE" elements: %s",
1097                   n_tables, json_to_string(reply->result, 0));
1098     }
1099     for (i = 0; i < n_tables; i++) {
1100         const struct ovsdb_table_schema *ts = tables[i]->data;
1101         const struct json *op_result = reply->result->u.array.elems[i];
1102         struct json *rows;
1103
1104         if (op_result->type != JSON_OBJECT
1105             || !(rows = shash_find_data(json_object(op_result), "rows"))
1106             || rows->type != JSON_ARRAY) {
1107             ovs_fatal(0, "%s table reply is not an object with a \"rows\" "
1108                       "member array: %s",
1109                       ts->name, json_to_string(op_result, 0));
1110         }
1111
1112         dump_table(ts, &rows->u.array);
1113     }
1114
1115     jsonrpc_msg_destroy(reply);
1116     free(tables);
1117     ovsdb_schema_destroy(schema);
1118 }
1119
1120 static void
1121 do_help(struct jsonrpc *rpc OVS_UNUSED, const char *database OVS_UNUSED,
1122         int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
1123 {
1124     usage();
1125 }
1126
1127 /* All command handlers (except for "help") are expected to take an optional
1128  * server socket name (e.g. "unix:...") as their first argument.  The socket
1129  * name argument must be included in max_args (but left out of min_args).  The
1130  * command name and socket name are not included in the arguments passed to the
1131  * handler: the argv[0] passed to the handler is the first argument after the
1132  * optional server socket name.  The connection to the server is available as
1133  * global variable 'rpc'. */
1134 static const struct ovsdb_client_command all_commands[] = {
1135     { "list-dbs",           NEED_RPC,      0, 0,       do_list_dbs },
1136     { "get-schema",         NEED_DATABASE, 0, 0,       do_get_schema },
1137     { "get-schema-version", NEED_DATABASE, 0, 0,       do_get_schema_version },
1138     { "list-tables",        NEED_DATABASE, 0, 0,       do_list_tables },
1139     { "list-columns",       NEED_DATABASE, 0, 1,       do_list_columns },
1140     { "transact",           NEED_RPC,      1, 1,       do_transact },
1141     { "monitor",            NEED_DATABASE, 1, INT_MAX, do_monitor },
1142     { "dump",               NEED_DATABASE, 0, 0,       do_dump },
1143
1144     { "help",               NEED_NONE,     0, INT_MAX, do_help },
1145
1146     { NULL,                 0,             0, 0,       NULL },
1147 };
1148
1149 static const struct ovsdb_client_command *get_all_commands(void)
1150 {
1151     return all_commands;
1152 }