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