ovsdb-client: Add JSON output format.
[sliver-openvswitch.git] / ovsdb / ovsdb-client.c
1 /*
2  * Copyright (c) 2009, 2010 Nicira Networks.
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 <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 "dynamic-string.h"
33 #include "json.h"
34 #include "jsonrpc.h"
35 #include "ovsdb.h"
36 #include "ovsdb-data.h"
37 #include "ovsdb-error.h"
38 #include "sort.h"
39 #include "stream.h"
40 #include "stream-ssl.h"
41 #include "table.h"
42 #include "timeval.h"
43 #include "util.h"
44 #include "vlog.h"
45
46 VLOG_DEFINE_THIS_MODULE(ovsdb_client);
47
48 /* --format: Output formatting. */
49 static enum {
50     FMT_TABLE,                  /* Textual table. */
51     FMT_HTML,                   /* HTML table. */
52     FMT_CSV,                    /* Comma-separated lines. */
53     FMT_JSON                    /* JSON. */
54 } output_format;
55
56 /* --no-headings: Whether table output should include headings. */
57 static int output_headings = true;
58
59 /* --pretty: Flags to pass to json_to_string(). */
60 static int json_flags = JSSF_SORT;
61
62 /* --data: Format of data in output tables. */
63 static enum {
64     DF_STRING,                  /* String format. */
65     DF_JSON,                    /* JSON. */
66 } data_format;
67
68 static const struct command all_commands[];
69
70 static void usage(void) NO_RETURN;
71 static void parse_options(int argc, char *argv[]);
72
73 int
74 main(int argc, char *argv[])
75 {
76     proctitle_init(argc, argv);
77     set_program_name(argv[0]);
78     parse_options(argc, argv);
79     signal(SIGPIPE, SIG_IGN);
80     run_command(argc - optind, argv + optind, all_commands);
81     return 0;
82 }
83
84 static void
85 parse_options(int argc, char *argv[])
86 {
87     enum {
88         OPT_BOOTSTRAP_CA_CERT = UCHAR_MAX + 1
89     };
90     static struct option long_options[] = {
91         {"format", required_argument, 0, 'f'},
92         {"data", required_argument, 0, 'd'},
93         {"no-headings", no_argument, &output_headings, 0},
94         {"pretty", no_argument, &json_flags, JSSF_PRETTY | JSSF_SORT},
95         {"verbose", optional_argument, 0, 'v'},
96         {"help", no_argument, 0, 'h'},
97         {"version", no_argument, 0, 'V'},
98         DAEMON_LONG_OPTIONS,
99 #ifdef HAVE_OPENSSL
100         {"bootstrap-ca-cert", required_argument, 0, OPT_BOOTSTRAP_CA_CERT},
101         STREAM_SSL_LONG_OPTIONS
102 #endif
103         {0, 0, 0, 0},
104     };
105     char *short_options = long_options_to_short_options(long_options);
106
107     for (;;) {
108         int c;
109
110         c = getopt_long(argc, argv, short_options, long_options, NULL);
111         if (c == -1) {
112             break;
113         }
114
115         switch (c) {
116         case 'f':
117             if (!strcmp(optarg, "table")) {
118                 output_format = FMT_TABLE;
119             } else if (!strcmp(optarg, "html")) {
120                 output_format = FMT_HTML;
121             } else if (!strcmp(optarg, "csv")) {
122                 output_format = FMT_CSV;
123             } else if (!strcmp(optarg, "json")) {
124                 output_format = FMT_JSON;
125             } else {
126                 ovs_fatal(0, "unknown output format \"%s\"", optarg);
127             }
128             break;
129
130         case 'd':
131             if (!strcmp(optarg, "string")) {
132                 data_format = DF_STRING;
133             } else if (!strcmp(optarg, "json")) {
134                 data_format = DF_JSON;
135             } else {
136                 ovs_fatal(0, "unknown data format \"%s\"", optarg);
137             }
138             break;
139
140         case 'h':
141             usage();
142
143         case 'V':
144             OVS_PRINT_VERSION(0, 0);
145             exit(EXIT_SUCCESS);
146
147         case 'v':
148             vlog_set_verbosity(optarg);
149             break;
150
151         DAEMON_OPTION_HANDLERS
152
153 #ifdef HAVE_OPENSSL
154         STREAM_SSL_OPTION_HANDLERS
155
156         case OPT_BOOTSTRAP_CA_CERT:
157             stream_ssl_set_ca_cert_file(optarg, true);
158             break;
159 #endif
160
161         case '?':
162             exit(EXIT_FAILURE);
163
164         case 0:
165             /* getopt_long() already set the value for us. */
166             break;
167
168         default:
169             abort();
170         }
171     }
172     free(short_options);
173 }
174
175 static void
176 usage(void)
177 {
178     printf("%s: Open vSwitch database JSON-RPC client\n"
179            "usage: %s [OPTIONS] COMMAND [ARG...]\n"
180            "\nValid commands are:\n"
181            "\n  list-dbs SERVER\n"
182            "    list databases available on SERVER\n"
183            "\n  get-schema SERVER DATABASE\n"
184            "    retrieve schema for DATABASE from SERVER\n"
185            "\n  list-tables SERVER DATABASE\n"
186            "    list tables for DATABASE on SERVER\n"
187            "\n  list-columns SERVER DATABASE [TABLE]\n"
188            "    list columns in TABLE (or all tables) in DATABASE on SERVER\n"
189            "\n  transact SERVER TRANSACTION\n"
190            "    run TRANSACTION (a JSON array of operations) on SERVER\n"
191            "    and print the results as JSON on stdout\n"
192            "\n  monitor SERVER DATABASE TABLE [COLUMN,...]...\n"
193            "    monitor contents of COLUMNs in TABLE in DATABASE on SERVER.\n"
194            "    COLUMNs may include !initial, !insert, !delete, !modify\n"
195            "    to avoid seeing the specified kinds of changes.\n"
196            "\n  dump SERVER DATABASE\n"
197            "    dump contents of DATABASE on SERVER to stdout\n",
198            program_name, program_name);
199     stream_usage("SERVER", true, true, true);
200     printf("\nOutput formatting options:\n"
201            "  -f, --format=FORMAT         set output formatting to FORMAT\n"
202            "                              (\"table\", \"html\", \"csv\", "
203            "or \"json\")\n"
204            "  --no-headings               omit table heading row\n"
205            "  --pretty                    pretty-print JSON in output");
206     daemon_usage();
207     vlog_usage();
208     printf("\nOther options:\n"
209            "  -h, --help                  display this help message\n"
210            "  -V, --version               display version information\n");
211     exit(EXIT_SUCCESS);
212 }
213 \f
214 static struct json *
215 parse_json(const char *s)
216 {
217     struct json *json = json_from_string(s);
218     if (json->type == JSON_STRING) {
219         ovs_fatal(0, "\"%s\": %s", s, json->u.string);
220     }
221     return json;
222 }
223
224 static struct jsonrpc *
225 open_jsonrpc(const char *server)
226 {
227     struct stream *stream;
228     int error;
229
230     error = stream_open_block(jsonrpc_stream_open(server, &stream), &stream);
231     if (error == EAFNOSUPPORT) {
232         struct pstream *pstream;
233
234         error = jsonrpc_pstream_open(server, &pstream);
235         if (error) {
236             ovs_fatal(error, "failed to connect or listen to \"%s\"", server);
237         }
238
239         VLOG_INFO("%s: waiting for connection...", server);
240         error = pstream_accept_block(pstream, &stream);
241         if (error) {
242             ovs_fatal(error, "failed to accept connection on \"%s\"", server);
243         }
244
245         pstream_close(pstream);
246     } else if (error) {
247         ovs_fatal(error, "failed to connect to \"%s\"", server);
248     }
249
250     return jsonrpc_open(stream);
251 }
252
253 static void
254 print_json(struct json *json)
255 {
256     char *string = json_to_string(json, json_flags);
257     fputs(string, stdout);
258     free(string);
259 }
260
261 static void
262 print_and_free_json(struct json *json)
263 {
264     print_json(json);
265     json_destroy(json);
266 }
267
268 static void
269 check_ovsdb_error(struct ovsdb_error *error)
270 {
271     if (error) {
272         ovs_fatal(0, "%s", ovsdb_error_to_string(error));
273     }
274 }
275
276 static struct ovsdb_schema *
277 fetch_schema_from_rpc(struct jsonrpc *rpc, const char *database)
278 {
279     struct jsonrpc_msg *request, *reply;
280     struct ovsdb_schema *schema;
281     int error;
282
283     request = jsonrpc_create_request("get_schema",
284                                      json_array_create_1(
285                                          json_string_create(database)),
286                                      NULL);
287     error = jsonrpc_transact_block(rpc, request, &reply);
288     if (error) {
289         ovs_fatal(error, "transaction failed");
290     }
291     check_ovsdb_error(ovsdb_schema_from_json(reply->result, &schema));
292     jsonrpc_msg_destroy(reply);
293
294     return schema;
295 }
296
297 static struct ovsdb_schema *
298 fetch_schema(const char *server, const char *database)
299 {
300     struct ovsdb_schema *schema;
301     struct jsonrpc *rpc;
302
303     rpc = open_jsonrpc(server);
304     schema = fetch_schema_from_rpc(rpc, database);
305     jsonrpc_close(rpc);
306
307     return schema;
308 }
309 \f
310 struct column {
311     char *heading;
312 };
313
314 struct cell {
315     /* Literal text. */
316     char *text;
317
318     /* JSON. */
319     struct json *json;
320     const struct ovsdb_type *type;
321 };
322
323 static const char *
324 cell_to_text(const struct cell *cell_)
325 {
326     struct cell *cell = (struct cell *) cell_;
327     if (!cell->text) {
328         if (cell->json) {
329             if (data_format == DF_JSON || !cell->type) {
330                 cell->text = json_to_string(cell->json, JSSF_SORT);
331             } else if (data_format == DF_STRING) {
332                 struct ovsdb_datum datum;
333                 struct ovsdb_error *error;
334                 struct ds s;
335
336                 error = ovsdb_datum_from_json(&datum, cell->type, cell->json,
337                                               NULL);
338                 if (!error) {
339                     ds_init(&s);
340                     ovsdb_datum_to_string(&datum, cell->type, &s);
341                     ovsdb_datum_destroy(&datum, cell->type);
342                     cell->text = ds_steal_cstr(&s);
343                 } else {
344                     cell->text = json_to_string(cell->json, JSSF_SORT);
345                 }
346             } else {
347                 NOT_REACHED();
348             }
349         } else {
350             cell->text = xstrdup("");
351         }
352     }
353
354     return cell->text;
355 }
356
357 static void
358 cell_destroy(struct cell *cell)
359 {
360     free(cell->text);
361     json_destroy(cell->json);
362 }
363
364 struct table {
365     struct cell *cells;
366     struct column *columns;
367     size_t n_columns, allocated_columns;
368     size_t n_rows, allocated_rows;
369     size_t current_column;
370     char *caption;
371 };
372
373 static void
374 table_init(struct table *table)
375 {
376     memset(table, 0, sizeof *table);
377 }
378
379 static void
380 table_destroy(struct table *table)
381 {
382     size_t i;
383
384     for (i = 0; i < table->n_columns; i++) {
385         free(table->columns[i].heading);
386     }
387     free(table->columns);
388
389     for (i = 0; i < table->n_columns * table->n_rows; i++) {
390         cell_destroy(&table->cells[i]);
391     }
392     free(table->cells);
393
394     free(table->caption);
395 }
396
397 static void
398 table_set_caption(struct table *table, char *caption)
399 {
400     free(table->caption);
401     table->caption = caption;
402 }
403
404 static void
405 table_add_column(struct table *table, const char *heading, ...)
406     PRINTF_FORMAT(2, 3);
407
408 static void
409 table_add_column(struct table *table, const char *heading, ...)
410 {
411     struct column *column;
412     va_list args;
413
414     assert(!table->n_rows);
415     if (table->n_columns >= table->allocated_columns) {
416         table->columns = x2nrealloc(table->columns, &table->allocated_columns,
417                                     sizeof *table->columns);
418     }
419     column = &table->columns[table->n_columns++];
420
421     va_start(args, heading);
422     column->heading = xvasprintf(heading, args);
423     va_end(args);
424 }
425
426 static struct cell *
427 table_cell__(const struct table *table, size_t row, size_t column)
428 {
429     return &table->cells[column + row * table->n_columns];
430 }
431
432 static void
433 table_add_row(struct table *table)
434 {
435     size_t x, y;
436
437     if (table->n_rows >= table->allocated_rows) {
438         table->cells = x2nrealloc(table->cells, &table->allocated_rows,
439                                   table->n_columns * sizeof *table->cells);
440     }
441
442     y = table->n_rows++;
443     table->current_column = 0;
444     for (x = 0; x < table->n_columns; x++) {
445         struct cell *cell = table_cell__(table, y, x);
446         memset(cell, 0, sizeof *cell);
447     }
448 }
449
450 static struct cell *
451 table_add_cell(struct table *table)
452 {
453     size_t x, y;
454
455     assert(table->n_rows > 0);
456     assert(table->current_column < table->n_columns);
457
458     x = table->current_column++;
459     y = table->n_rows - 1;
460
461     return table_cell__(table, y, x);
462 }
463
464 static void
465 table_print_table_line__(struct ds *line)
466 {
467     puts(ds_cstr(line));
468     ds_clear(line);
469 }
470
471 static void
472 table_print_table__(const struct table *table)
473 {
474     static int n = 0;
475     struct ds line = DS_EMPTY_INITIALIZER;
476     int *widths;
477     size_t x, y;
478
479     if (n++ > 0) {
480         putchar('\n');
481     }
482
483     if (table->caption) {
484         puts(table->caption);
485     }
486
487     widths = xmalloc(table->n_columns * sizeof *widths);
488     for (x = 0; x < table->n_columns; x++) {
489         const struct column *column = &table->columns[x];
490
491         widths[x] = strlen(column->heading);
492         for (y = 0; y < table->n_rows; y++) {
493             const char *text = cell_to_text(table_cell__(table, y, x));
494             size_t length = strlen(text);
495
496             if (length > widths[x])
497                 widths[x] = length;
498         }
499     }
500
501     if (output_headings) {
502         for (x = 0; x < table->n_columns; x++) {
503             const struct column *column = &table->columns[x];
504             if (x) {
505                 ds_put_char(&line, ' ');
506             }
507             ds_put_format(&line, "%-*s", widths[x], column->heading);
508         }
509         table_print_table_line__(&line);
510
511         for (x = 0; x < table->n_columns; x++) {
512             if (x) {
513                 ds_put_char(&line, ' ');
514             }
515             ds_put_char_multiple(&line, '-', widths[x]);
516         }
517         table_print_table_line__(&line);
518     }
519
520     for (y = 0; y < table->n_rows; y++) {
521         for (x = 0; x < table->n_columns; x++) {
522             const char *text = cell_to_text(table_cell__(table, y, x));
523             if (x) {
524                 ds_put_char(&line, ' ');
525             }
526             ds_put_format(&line, "%-*s", widths[x], text);
527         }
528         table_print_table_line__(&line);
529     }
530
531     ds_destroy(&line);
532     free(widths);
533 }
534
535 static void
536 table_escape_html_text__(const char *s, size_t n)
537 {
538     size_t i;
539
540     for (i = 0; i < n; i++) {
541         char c = s[i];
542
543         switch (c) {
544         case '&':
545             fputs("&amp;", stdout);
546             break;
547         case '<':
548             fputs("&lt;", stdout);
549             break;
550         case '>':
551             fputs("&gt;", stdout);
552             break;
553         case '"':
554             fputs("&quot;", stdout);
555             break;
556         default:
557             putchar(c);
558             break;
559         }
560     }
561 }
562
563 static void
564 table_print_html_cell__(const char *element, const char *content)
565 {
566     const char *p;
567
568     printf("    <%s>", element);
569     for (p = content; *p; ) {
570         struct uuid uuid;
571
572         if (uuid_from_string_prefix(&uuid, p)) {
573             printf("<a href=\"#%.*s\">%.*s</a>", UUID_LEN, p, 8, p);
574             p += UUID_LEN;
575         } else {
576             table_escape_html_text__(p, 1);
577             p++;
578         }
579     }
580     printf("</%s>\n", element);
581 }
582
583 static void
584 table_print_html__(const struct table *table)
585 {
586     size_t x, y;
587
588     fputs("<table border=1>\n", stdout);
589
590     if (table->caption) {
591         table_print_html_cell__("caption", table->caption);
592     }
593
594     if (output_headings) {
595         fputs("  <tr>\n", stdout);
596         for (x = 0; x < table->n_columns; x++) {
597             const struct column *column = &table->columns[x];
598             table_print_html_cell__("th", column->heading);
599         }
600         fputs("  </tr>\n", stdout);
601     }
602
603     for (y = 0; y < table->n_rows; y++) {
604         fputs("  <tr>\n", stdout);
605         for (x = 0; x < table->n_columns; x++) {
606             const char *content = cell_to_text(table_cell__(table, y, x));
607
608             if (!strcmp(table->columns[x].heading, "_uuid")) {
609                 fputs("    <td><a name=\"", stdout);
610                 table_escape_html_text__(content, strlen(content));
611                 fputs("\">", stdout);
612                 table_escape_html_text__(content, 8);
613                 fputs("</a></td>\n", stdout);
614             } else {
615                 table_print_html_cell__("td", content);
616             }
617         }
618         fputs("  </tr>\n", stdout);
619     }
620
621     fputs("</table>\n", stdout);
622 }
623
624 static void
625 table_print_csv_cell__(const char *content)
626 {
627     const char *p;
628
629     if (!strpbrk(content, "\n\",")) {
630         fputs(content, stdout);
631     } else {
632         putchar('"');
633         for (p = content; *p != '\0'; p++) {
634             switch (*p) {
635             case '"':
636                 fputs("\"\"", stdout);
637                 break;
638             default:
639                 putchar(*p);
640                 break;
641             }
642         }
643         putchar('"');
644     }
645 }
646
647 static void
648 table_print_csv__(const struct table *table)
649 {
650     static int n = 0;
651     size_t x, y;
652
653     if (n++ > 0) {
654         putchar('\n');
655     }
656
657     if (table->caption) {
658         puts(table->caption);
659     }
660
661     if (output_headings) {
662         for (x = 0; x < table->n_columns; x++) {
663             const struct column *column = &table->columns[x];
664             if (x) {
665                 putchar(',');
666             }
667             table_print_csv_cell__(column->heading);
668         }
669         putchar('\n');
670     }
671
672     for (y = 0; y < table->n_rows; y++) {
673         for (x = 0; x < table->n_columns; x++) {
674             if (x) {
675                 putchar(',');
676             }
677             table_print_csv_cell__(cell_to_text(table_cell__(table, y, x)));
678         }
679         putchar('\n');
680     }
681 }
682
683 static void
684 table_print_json__(const struct table *table)
685 {
686     struct json *json, *headings, *data;
687     size_t x, y;
688     char *s;
689
690     json = json_object_create();
691     if (table->caption) {
692         json_object_put_string(json, "caption", table->caption);
693     }
694
695     headings = json_array_create_empty();
696     for (x = 0; x < table->n_columns; x++) {
697         const struct column *column = &table->columns[x];
698         json_array_add(headings, json_string_create(column->heading));
699     }
700     json_object_put(json, "headings", headings);
701
702     data = json_array_create_empty();
703     for (y = 0; y < table->n_rows; y++) {
704         struct json *row = json_array_create_empty();
705         for (x = 0; x < table->n_columns; x++) {
706             const struct cell *cell = table_cell__(table, y, x);
707             if (cell->text) {
708                 json_array_add(row, json_string_create(cell->text));
709             } else {
710                 json_array_add(row, json_clone(cell->json));
711             }
712         }
713         json_array_add(data, row);
714     }
715     json_object_put(json, "data", data);
716
717     s = json_to_string(json, json_flags);
718     json_destroy(json);
719     puts(s);
720     free(s);
721 }
722
723 static void
724 table_print(const struct table *table)
725 {
726     switch (output_format) {
727     case FMT_TABLE:
728         table_print_table__(table);
729         break;
730
731     case FMT_HTML:
732         table_print_html__(table);
733         break;
734
735     case FMT_CSV:
736         table_print_csv__(table);
737         break;
738
739     case FMT_JSON:
740         table_print_json__(table);
741         break;
742     }
743 }
744 \f
745 static void
746 do_list_dbs(int argc OVS_UNUSED, char *argv[])
747 {
748     struct jsonrpc_msg *request, *reply;
749     struct jsonrpc *rpc;
750     int error;
751     size_t i;
752
753     rpc = open_jsonrpc(argv[1]);
754     request = jsonrpc_create_request("list_dbs", json_array_create_empty(),
755                                      NULL);
756     error = jsonrpc_transact_block(rpc, request, &reply);
757     if (error) {
758         ovs_fatal(error, "transaction failed");
759     }
760
761     if (reply->result->type != JSON_ARRAY) {
762         ovs_fatal(0, "list_dbs response is not array");
763     }
764
765     for (i = 0; i < reply->result->u.array.n; i++) {
766         const struct json *name = reply->result->u.array.elems[i];
767
768         if (name->type != JSON_STRING) {
769             ovs_fatal(0, "list_dbs response %zu is not string", i);
770         }
771         puts(name->u.string);
772     }
773     jsonrpc_msg_destroy(reply);
774 }
775
776 static void
777 do_get_schema(int argc OVS_UNUSED, char *argv[])
778 {
779     struct ovsdb_schema *schema = fetch_schema(argv[1], argv[2]);
780     print_and_free_json(ovsdb_schema_to_json(schema));
781     ovsdb_schema_destroy(schema);
782 }
783
784 static void
785 do_list_tables(int argc OVS_UNUSED, char *argv[])
786 {
787     struct ovsdb_schema *schema;
788     struct shash_node *node;
789     struct table t;
790
791     schema = fetch_schema(argv[1], argv[2]);
792     table_init(&t);
793     table_add_column(&t, "Table");
794     SHASH_FOR_EACH (node, &schema->tables) {
795         struct ovsdb_table_schema *ts = node->data;
796
797         table_add_row(&t);
798         table_add_cell(&t)->text = xstrdup(ts->name);
799     }
800     ovsdb_schema_destroy(schema);
801     table_print(&t);
802 }
803
804 static void
805 do_list_columns(int argc OVS_UNUSED, char *argv[])
806 {
807     const char *table_name = argv[3];
808     struct ovsdb_schema *schema;
809     struct shash_node *table_node;
810     struct table t;
811
812     schema = fetch_schema(argv[1], argv[2]);
813     table_init(&t);
814     if (!table_name) {
815         table_add_column(&t, "Table");
816     }
817     table_add_column(&t, "Column");
818     table_add_column(&t, "Type");
819     SHASH_FOR_EACH (table_node, &schema->tables) {
820         struct ovsdb_table_schema *ts = table_node->data;
821
822         if (!table_name || !strcmp(table_name, ts->name)) {
823             struct shash_node *column_node;
824
825             SHASH_FOR_EACH (column_node, &ts->columns) {
826                 const struct ovsdb_column *column = column_node->data;
827
828                 table_add_row(&t);
829                 if (!table_name) {
830                     table_add_cell(&t)->text = xstrdup(ts->name);
831                 }
832                 table_add_cell(&t)->text = xstrdup(column->name);
833                 table_add_cell(&t)->json = ovsdb_type_to_json(&column->type);
834             }
835         }
836     }
837     ovsdb_schema_destroy(schema);
838     table_print(&t);
839 }
840
841 static void
842 do_transact(int argc OVS_UNUSED, char *argv[])
843 {
844     struct jsonrpc_msg *request, *reply;
845     struct json *transaction;
846     struct jsonrpc *rpc;
847     int error;
848
849     transaction = parse_json(argv[2]);
850
851     rpc = open_jsonrpc(argv[1]);
852     request = jsonrpc_create_request("transact", transaction, NULL);
853     error = jsonrpc_transact_block(rpc, request, &reply);
854     if (error) {
855         ovs_fatal(error, "transaction failed");
856     }
857     if (reply->error) {
858         ovs_fatal(error, "transaction returned error: %s",
859                   json_to_string(reply->error, json_flags));
860     }
861     print_json(reply->result);
862     putchar('\n');
863     jsonrpc_msg_destroy(reply);
864     jsonrpc_close(rpc);
865 }
866
867 static void
868 monitor_print_row(struct json *row, const char *type, const char *uuid,
869                   const struct ovsdb_column_set *columns, struct table *t)
870 {
871     size_t i;
872
873     if (!row) {
874         ovs_error(0, "missing %s row", type);
875         return;
876     } else if (row->type != JSON_OBJECT) {
877         ovs_error(0, "<row> is not object");
878         return;
879     }
880
881     table_add_row(t);
882     table_add_cell(t)->text = xstrdup(uuid);
883     table_add_cell(t)->text = xstrdup(type);
884     for (i = 0; i < columns->n_columns; i++) {
885         const struct ovsdb_column *column = columns->columns[i];
886         struct json *value = shash_find_data(json_object(row), column->name);
887         struct cell *cell = table_add_cell(t);
888         if (value) {
889             cell->json = json_clone(value);
890             cell->type = &column->type;
891         }
892     }
893 }
894
895 static void
896 monitor_print(struct json *table_updates,
897               const struct ovsdb_table_schema *table,
898               const struct ovsdb_column_set *columns, bool initial)
899 {
900     struct json *table_update;
901     struct shash_node *node;
902     struct table t;
903     size_t i;
904
905     table_init(&t);
906
907     if (table_updates->type != JSON_OBJECT) {
908         ovs_error(0, "<table-updates> is not object");
909         return;
910     }
911     table_update = shash_find_data(json_object(table_updates), table->name);
912     if (!table_update) {
913         return;
914     }
915     if (table_update->type != JSON_OBJECT) {
916         ovs_error(0, "<table-update> is not object");
917         return;
918     }
919
920     table_add_column(&t, "row");
921     table_add_column(&t, "action");
922     for (i = 0; i < columns->n_columns; i++) {
923         table_add_column(&t, "%s", columns->columns[i]->name);
924     }
925     SHASH_FOR_EACH (node, json_object(table_update)) {
926         struct json *row_update = node->data;
927         struct json *old, *new;
928
929         if (row_update->type != JSON_OBJECT) {
930             ovs_error(0, "<row-update> is not object");
931             continue;
932         }
933         old = shash_find_data(json_object(row_update), "old");
934         new = shash_find_data(json_object(row_update), "new");
935         if (initial) {
936             monitor_print_row(new, "initial", node->name, columns, &t);
937         } else if (!old) {
938             monitor_print_row(new, "insert", node->name, columns, &t);
939         } else if (!new) {
940             monitor_print_row(old, "delete", node->name, columns, &t);
941         } else {
942             monitor_print_row(old, "old", node->name, columns, &t);
943             monitor_print_row(new, "new", "", columns, &t);
944         }
945     }
946     table_print(&t);
947     table_destroy(&t);
948 }
949
950 static void
951 add_column(const char *server, const struct ovsdb_column *column,
952            struct ovsdb_column_set *columns, struct json *columns_json)
953 {
954     if (ovsdb_column_set_contains(columns, column->index)) {
955         ovs_fatal(0, "%s: column \"%s\" mentioned multiple times",
956                   server, column->name);
957     }
958     ovsdb_column_set_add(columns, column);
959     json_array_add(columns_json, json_string_create(column->name));
960 }
961
962 static struct json *
963 parse_monitor_columns(char *arg, const char *server, const char *database,
964                       const struct ovsdb_table_schema *table,
965                       struct ovsdb_column_set *columns)
966 {
967     bool initial, insert, delete, modify;
968     struct json *mr, *columns_json;
969     char *save_ptr = NULL;
970     char *token;
971
972     mr = json_object_create();
973     columns_json = json_array_create_empty();
974     json_object_put(mr, "columns", columns_json);
975
976     initial = insert = delete = modify = true;
977     for (token = strtok_r(arg, ",", &save_ptr); token != NULL;
978          token = strtok_r(NULL, ",", &save_ptr)) {
979         if (!strcmp(token, "!initial")) {
980             initial = false;
981         } else if (!strcmp(token, "!insert")) {
982             insert = false;
983         } else if (!strcmp(token, "!delete")) {
984             delete = false;
985         } else if (!strcmp(token, "!modify")) {
986             modify = false;
987         } else {
988             const struct ovsdb_column *column;
989
990             column = ovsdb_table_schema_get_column(table, token);
991             if (!column) {
992                 ovs_fatal(0, "%s: table \"%s\" in %s does not have a "
993                           "column named \"%s\"",
994                           server, table->name, database, token);
995             }
996             add_column(server, column, columns, columns_json);
997         }
998     }
999
1000     if (columns_json->u.array.n == 0) {
1001         const struct shash_node **nodes;
1002         size_t i, n;
1003
1004         n = shash_count(&table->columns);
1005         nodes = shash_sort(&table->columns);
1006         for (i = 0; i < n; i++) {
1007             const struct ovsdb_column *column = nodes[i]->data;
1008             if (column->index != OVSDB_COL_UUID
1009                 && column->index != OVSDB_COL_VERSION) {
1010                 add_column(server, column, columns, columns_json);
1011             }
1012         }
1013         free(nodes);
1014
1015         add_column(server, ovsdb_table_schema_get_column(table,"_version"),
1016                    columns, columns_json);
1017     }
1018
1019     if (!initial || !insert || !delete || !modify) {
1020         struct json *select = json_object_create();
1021         json_object_put(select, "initial", json_boolean_create(initial));
1022         json_object_put(select, "insert", json_boolean_create(insert));
1023         json_object_put(select, "delete", json_boolean_create(delete));
1024         json_object_put(select, "modify", json_boolean_create(modify));
1025         json_object_put(mr, "select", select);
1026     }
1027
1028     return mr;
1029 }
1030
1031 static void
1032 do_monitor(int argc, char *argv[])
1033 {
1034     const char *server = argv[1];
1035     const char *database = argv[2];
1036     const char *table_name = argv[3];
1037     struct ovsdb_column_set columns = OVSDB_COLUMN_SET_INITIALIZER;
1038     struct ovsdb_table_schema *table;
1039     struct ovsdb_schema *schema;
1040     struct jsonrpc_msg *request;
1041     struct jsonrpc *rpc;
1042     struct json *monitor, *monitor_request_array,
1043         *monitor_requests, *request_id;
1044
1045     rpc = open_jsonrpc(server);
1046
1047     schema = fetch_schema_from_rpc(rpc, database);
1048     table = shash_find_data(&schema->tables, table_name);
1049     if (!table) {
1050         ovs_fatal(0, "%s: %s does not have a table named \"%s\"",
1051                   server, database, table_name);
1052     }
1053
1054     monitor_request_array = json_array_create_empty();
1055     if (argc > 4) {
1056         int i;
1057
1058         for (i = 4; i < argc; i++) {
1059             json_array_add(
1060                 monitor_request_array,
1061                 parse_monitor_columns(argv[i], server, database, table,
1062                                       &columns));
1063         }
1064     } else {
1065         /* Allocate a writable empty string since parse_monitor_columns() is
1066          * going to strtok() it and that's risky with literal "". */
1067         char empty[] = "";
1068         json_array_add(
1069             monitor_request_array,
1070             parse_monitor_columns(empty, server, database, table, &columns));
1071     }
1072
1073     monitor_requests = json_object_create();
1074     json_object_put(monitor_requests, table_name, monitor_request_array);
1075
1076     monitor = json_array_create_3(json_string_create(database),
1077                                   json_null_create(), monitor_requests);
1078     request = jsonrpc_create_request("monitor", monitor, NULL);
1079     request_id = json_clone(request->id);
1080     jsonrpc_send(rpc, request);
1081     for (;;) {
1082         struct jsonrpc_msg *msg;
1083         int error;
1084
1085         error = jsonrpc_recv_block(rpc, &msg);
1086         if (error) {
1087             ovsdb_schema_destroy(schema);
1088             ovs_fatal(error, "%s: receive failed", server);
1089         }
1090
1091         if (msg->type == JSONRPC_REQUEST && !strcmp(msg->method, "echo")) {
1092             jsonrpc_send(rpc, jsonrpc_create_reply(json_clone(msg->params),
1093                                                    msg->id));
1094         } else if (msg->type == JSONRPC_REPLY
1095                    && json_equal(msg->id, request_id)) {
1096             monitor_print(msg->result, table, &columns, true);
1097             fflush(stdout);
1098             if (get_detach()) {
1099                 /* daemonize() closes the standard file descriptors.  We output
1100                  * to stdout, so we need to save and restore STDOUT_FILENO. */
1101                 int fd = dup(STDOUT_FILENO);
1102                 daemonize();
1103                 dup2(fd, STDOUT_FILENO);
1104                 close(fd);
1105             }
1106         } else if (msg->type == JSONRPC_NOTIFY
1107                    && !strcmp(msg->method, "update")) {
1108             struct json *params = msg->params;
1109             if (params->type == JSON_ARRAY
1110                 && params->u.array.n == 2
1111                 && params->u.array.elems[0]->type == JSON_NULL) {
1112                 monitor_print(params->u.array.elems[1],
1113                               table, &columns, false);
1114                 fflush(stdout);
1115             }
1116         }
1117         jsonrpc_msg_destroy(msg);
1118     }
1119 }
1120
1121 struct dump_table_aux {
1122     struct ovsdb_datum **data;
1123     const struct ovsdb_column **columns;
1124     size_t n_columns;
1125 };
1126
1127 static int
1128 compare_data(size_t a_y, size_t b_y, size_t x,
1129              const struct dump_table_aux *aux)
1130 {
1131     return ovsdb_datum_compare_3way(&aux->data[a_y][x],
1132                                     &aux->data[b_y][x],
1133                                     &aux->columns[x]->type);
1134 }
1135
1136 static int
1137 compare_rows(size_t a_y, size_t b_y, void *aux_)
1138 {
1139     struct dump_table_aux *aux = aux_;
1140     size_t x;
1141
1142     /* Skip UUID columns on the first pass, since their values tend to be
1143      * random and make our results less reproducible. */
1144     for (x = 0; x < aux->n_columns; x++) {
1145         if (aux->columns[x]->type.key.type != OVSDB_TYPE_UUID) {
1146             int cmp = compare_data(a_y, b_y, x, aux);
1147             if (cmp) {
1148                 return cmp;
1149             }
1150         }
1151     }
1152
1153     /* Use UUID columns as tie-breakers. */
1154     for (x = 0; x < aux->n_columns; x++) {
1155         if (aux->columns[x]->type.key.type == OVSDB_TYPE_UUID) {
1156             int cmp = compare_data(a_y, b_y, x, aux);
1157             if (cmp) {
1158                 return cmp;
1159             }
1160         }
1161     }
1162
1163     return 0;
1164 }
1165
1166 static void
1167 swap_rows(size_t a_y, size_t b_y, void *aux_)
1168 {
1169     struct dump_table_aux *aux = aux_;
1170     struct ovsdb_datum *tmp = aux->data[a_y];
1171     aux->data[a_y] = aux->data[b_y];
1172     aux->data[b_y] = tmp;
1173 }
1174
1175 static int
1176 compare_columns(const void *a_, const void *b_)
1177 {
1178     const struct ovsdb_column *const *ap = a_;
1179     const struct ovsdb_column *const *bp = b_;
1180     const struct ovsdb_column *a = *ap;
1181     const struct ovsdb_column *b = *bp;
1182
1183     return strcmp(a->name, b->name);
1184 }
1185
1186 static void
1187 dump_table(const struct ovsdb_table_schema *ts, struct json_array *rows)
1188 {
1189     const struct ovsdb_column **columns;
1190     size_t n_columns;
1191
1192     struct ovsdb_datum **data;
1193
1194     struct dump_table_aux aux;
1195     struct shash_node *node;
1196     struct table t;
1197     size_t x, y;
1198
1199     /* Sort columns by name, for reproducibility. */
1200     columns = xmalloc(shash_count(&ts->columns) * sizeof *columns);
1201     n_columns = 0;
1202     SHASH_FOR_EACH (node, &ts->columns) {
1203         struct ovsdb_column *column = node->data;
1204         if (strcmp(column->name, "_version")) {
1205             columns[n_columns++] = column;
1206         }
1207     }
1208     qsort(columns, n_columns, sizeof *columns, compare_columns);
1209
1210     /* Extract data from table. */
1211     data = xmalloc(rows->n * sizeof *data);
1212     for (y = 0; y < rows->n; y++) {
1213         struct shash *row;
1214
1215         if (rows->elems[y]->type != JSON_OBJECT) {
1216             ovs_fatal(0,  "row %zu in table %s response is not a JSON object: "
1217                       "%s", y, ts->name, json_to_string(rows->elems[y], 0));
1218         }
1219         row = json_object(rows->elems[y]);
1220
1221         data[y] = xmalloc(n_columns * sizeof **data);
1222         for (x = 0; x < n_columns; x++) {
1223             const struct json *json = shash_find_data(row, columns[x]->name);
1224             if (!json) {
1225                 ovs_fatal(0, "row %zu in table %s response lacks %s column",
1226                           y, ts->name, columns[x]->name);
1227             }
1228
1229             check_ovsdb_error(ovsdb_datum_from_json(&data[y][x],
1230                                                     &columns[x]->type,
1231                                                     json, NULL));
1232         }
1233     }
1234
1235     /* Sort rows by column values, for reproducibility. */
1236     aux.data = data;
1237     aux.columns = columns;
1238     aux.n_columns = n_columns;
1239     sort(rows->n, compare_rows, swap_rows, &aux);
1240
1241     /* Add column headings. */
1242     table_init(&t);
1243     table_set_caption(&t, xasprintf("%s table", ts->name));
1244     for (x = 0; x < n_columns; x++) {
1245         table_add_column(&t, "%s", columns[x]->name);
1246     }
1247
1248     /* Print rows. */
1249     for (y = 0; y < rows->n; y++) {
1250         table_add_row(&t);
1251         for (x = 0; x < n_columns; x++) {
1252             struct cell *cell = table_add_cell(&t);
1253             cell->json = ovsdb_datum_to_json(&data[y][x], &columns[x]->type);
1254             cell->type = &columns[x]->type;
1255         }
1256     }
1257     table_print(&t);
1258     table_destroy(&t);
1259 }
1260
1261 static void
1262 do_dump(int argc OVS_UNUSED, char *argv[])
1263 {
1264     const char *server = argv[1];
1265     const char *database = argv[2];
1266
1267     struct jsonrpc_msg *request, *reply;
1268     struct ovsdb_schema *schema;
1269     struct json *transaction;
1270     struct jsonrpc *rpc;
1271     int error;
1272
1273     const struct shash_node **tables;
1274     size_t n_tables;
1275
1276     size_t i;
1277
1278     rpc = open_jsonrpc(server);
1279
1280     schema = fetch_schema_from_rpc(rpc, database);
1281     tables = shash_sort(&schema->tables);
1282     n_tables = shash_count(&schema->tables);
1283
1284     /* Construct transaction to retrieve entire database. */
1285     transaction = json_array_create_1(json_string_create(database));
1286     for (i = 0; i < n_tables; i++) {
1287         const struct ovsdb_table_schema *ts = tables[i]->data;
1288         struct json *op, *columns;
1289         struct shash_node *node;
1290
1291         columns = json_array_create_empty();
1292         SHASH_FOR_EACH (node, &ts->columns) {
1293             const struct ovsdb_column *column = node->data;
1294
1295             if (strcmp(column->name, "_version")) {
1296                 json_array_add(columns, json_string_create(column->name));
1297             }
1298         }
1299
1300         op = json_object_create();
1301         json_object_put_string(op, "op", "select");
1302         json_object_put_string(op, "table", tables[i]->name);
1303         json_object_put(op, "where", json_array_create_empty());
1304         json_object_put(op, "columns", columns);
1305         json_array_add(transaction, op);
1306     }
1307
1308     /* Send request, get reply. */
1309     request = jsonrpc_create_request("transact", transaction, NULL);
1310     error = jsonrpc_transact_block(rpc, request, &reply);
1311     if (error) {
1312         ovs_fatal(error, "transaction failed");
1313     }
1314
1315     /* Print database contents. */
1316     if (reply->result->type != JSON_ARRAY
1317         || reply->result->u.array.n != n_tables) {
1318         ovs_fatal(0, "reply is not array of %zu elements: %s",
1319                   n_tables, json_to_string(reply->result, 0));
1320     }
1321     for (i = 0; i < n_tables; i++) {
1322         const struct ovsdb_table_schema *ts = tables[i]->data;
1323         const struct json *op_result = reply->result->u.array.elems[i];
1324         struct json *rows;
1325
1326         if (op_result->type != JSON_OBJECT
1327             || !(rows = shash_find_data(json_object(op_result), "rows"))
1328             || rows->type != JSON_ARRAY) {
1329             ovs_fatal(0, "%s table reply is not an object with a \"rows\" "
1330                       "member array: %s",
1331                       ts->name, json_to_string(op_result, 0));
1332         }
1333
1334         dump_table(ts, &rows->u.array);
1335     }
1336 }
1337
1338 static void
1339 do_help(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
1340 {
1341     usage();
1342 }
1343
1344 static const struct command all_commands[] = {
1345     { "list-dbs", 1, 1, do_list_dbs },
1346     { "get-schema", 2, 2, do_get_schema },
1347     { "list-tables", 2, 2, do_list_tables },
1348     { "list-columns", 2, 3, do_list_columns },
1349     { "transact", 2, 2, do_transact },
1350     { "monitor", 3, INT_MAX, do_monitor },
1351     { "dump", 2, 2, do_dump },
1352     { "help", 0, INT_MAX, do_help },
1353     { NULL, 0, 0, NULL },
1354 };