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