ovsdb-client: Introduce new data formatting style as the default.
[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 "stream.h"
39 #include "stream-ssl.h"
40 #include "table.h"
41 #include "timeval.h"
42 #include "util.h"
43
44 #include "vlog.h"
45 #define THIS_MODULE VLM_ovsdb_client
46
47 /* --format: Output formatting. */
48 static enum {
49     FMT_TABLE,                  /* Textual table. */
50     FMT_HTML,                   /* HTML table. */
51     FMT_CSV                     /* Comma-separated lines. */
52 } output_format;
53
54 /* --no-headings: Whether table output should include headings. */
55 static int output_headings = true;
56
57 /* --pretty: Flags to pass to json_to_string(). */
58 static int json_flags = JSSF_SORT;
59
60 /* --data: Format of data in output tables. */
61 static enum {
62     DF_STRING,                  /* String format. */
63     DF_JSON,                    /* JSON. */
64 } data_format;
65
66 static const struct command all_commands[];
67
68 static void usage(void) NO_RETURN;
69 static void parse_options(int argc, char *argv[]);
70
71 int
72 main(int argc, char *argv[])
73 {
74     proctitle_init(argc, argv);
75     set_program_name(argv[0]);
76     time_init();
77     vlog_init();
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 {
124                 ovs_fatal(0, "unknown output format \"%s\"", optarg);
125             }
126             break;
127
128         case 'd':
129             if (!strcmp(optarg, "string")) {
130                 data_format = DF_STRING;
131             } else if (!strcmp(optarg, "json")) {
132                 data_format = DF_JSON;
133             } else {
134                 ovs_fatal(0, "unknown data format \"%s\"", optarg);
135             }
136             break;
137
138         case 'h':
139             usage();
140
141         case 'V':
142             OVS_PRINT_VERSION(0, 0);
143             exit(EXIT_SUCCESS);
144
145         case 'v':
146             vlog_set_verbosity(optarg);
147             break;
148
149         DAEMON_OPTION_HANDLERS
150
151 #ifdef HAVE_OPENSSL
152         STREAM_SSL_OPTION_HANDLERS
153
154         case OPT_BOOTSTRAP_CA_CERT:
155             stream_ssl_set_ca_cert_file(optarg, true);
156             break;
157 #endif
158
159         case '?':
160             exit(EXIT_FAILURE);
161
162         case 0:
163             /* getopt_long() already set the value for us. */
164             break;
165
166         default:
167             abort();
168         }
169     }
170     free(short_options);
171 }
172
173 static void
174 usage(void)
175 {
176     printf("%s: Open vSwitch database JSON-RPC client\n"
177            "usage: %s [OPTIONS] COMMAND [ARG...]\n"
178            "\nValid commands are:\n"
179            "\n  list-dbs SERVER\n"
180            "    list databases available on SERVER\n"
181            "\n  get-schema SERVER DATABASE\n"
182            "    retrieve schema for DATABASE from SERVER\n"
183            "\n  list-tables SERVER DATABSE\n"
184            "    list tables for DATABSAE on SERVER\n"
185            "\n  list-columns SERVER DATABASE [TABLE]\n"
186            "    list columns in TABLE (or all tables) in DATABASE on SERVER\n"
187            "\n  transact SERVER TRANSACTION\n"
188            "    run TRANSACTION (a JSON array of operations) on SERVER\n"
189            "    and print the results as JSON on stdout\n"
190            "\n  monitor SERVER DATABASE TABLE [COLUMN,...] [SELECT,...]\n"
191            "    monitor contents of (COLUMNs in) TABLE in DATABASE on SERVER\n"
192            "    Valid SELECTs are: initial, insert, delete, modify\n",
193            program_name, program_name);
194     stream_usage("SERVER", true, true, true);
195     printf("\nOutput formatting options:\n"
196            "  -f, --format=FORMAT         set output formatting to FORMAT\n"
197            "                              (\"table\", \"html\", or \"csv\"\n"
198            "  --no-headings               omit table heading row\n"
199            "  --pretty                    pretty-print JSON in output");
200     daemon_usage();
201     vlog_usage();
202     printf("\nOther options:\n"
203            "  -h, --help                  display this help message\n"
204            "  -V, --version               display version information\n");
205     exit(EXIT_SUCCESS);
206 }
207 \f
208 static struct json *
209 parse_json(const char *s)
210 {
211     struct json *json = json_from_string(s);
212     if (json->type == JSON_STRING) {
213         ovs_fatal(0, "\"%s\": %s", s, json->u.string);
214     }
215     return json;
216 }
217
218 static struct jsonrpc *
219 open_jsonrpc(const char *server)
220 {
221     struct stream *stream;
222     int error;
223
224     error = stream_open_block(server, &stream);
225     if (error == EAFNOSUPPORT) {
226         struct pstream *pstream;
227
228         error = pstream_open(server, &pstream);
229         if (error) {
230             ovs_fatal(error, "failed to connect or listen to \"%s\"", server);
231         }
232
233         VLOG_INFO("%s: waiting for connection...", server);
234         error = pstream_accept_block(pstream, &stream);
235         if (error) {
236             ovs_fatal(error, "failed to accept connection on \"%s\"", server);
237         }
238
239         pstream_close(pstream);
240     } else if (error) {
241         ovs_fatal(error, "failed to connect to \"%s\"", server);
242     }
243
244     return jsonrpc_open(stream);
245 }
246
247 static void
248 print_json(struct json *json)
249 {
250     char *string = json_to_string(json, json_flags);
251     fputs(string, stdout);
252     free(string);
253 }
254
255 static void
256 print_and_free_json(struct json *json)
257 {
258     print_json(json);
259     json_destroy(json);
260 }
261
262 static void
263 check_ovsdb_error(struct ovsdb_error *error)
264 {
265     if (error) {
266         ovs_fatal(0, "%s", ovsdb_error_to_string(error));
267     }
268 }
269
270 static struct ovsdb_schema *
271 fetch_schema_from_rpc(struct jsonrpc *rpc, const char *database)
272 {
273     struct jsonrpc_msg *request, *reply;
274     struct ovsdb_schema *schema;
275     int error;
276
277     request = jsonrpc_create_request("get_schema",
278                                      json_array_create_1(
279                                          json_string_create(database)),
280                                      NULL);
281     error = jsonrpc_transact_block(rpc, request, &reply);
282     if (error) {
283         ovs_fatal(error, "transaction failed");
284     }
285     check_ovsdb_error(ovsdb_schema_from_json(reply->result, &schema));
286     jsonrpc_msg_destroy(reply);
287
288     return schema;
289 }
290
291 static struct ovsdb_schema *
292 fetch_schema(const char *server, const char *database)
293 {
294     struct ovsdb_schema *schema;
295     struct jsonrpc *rpc;
296
297     rpc = open_jsonrpc(server);
298     schema = fetch_schema_from_rpc(rpc, database);
299     jsonrpc_close(rpc);
300
301     return schema;
302 }
303 \f
304 struct column {
305     char *heading;
306     int width;
307 };
308
309 struct table {
310     char **cells;
311     struct column *columns;
312     size_t n_columns, allocated_columns;
313     size_t n_rows, allocated_rows;
314     size_t current_column;
315 };
316
317 static void
318 table_init(struct table *table)
319 {
320     memset(table, 0, sizeof *table);
321 }
322
323 static void
324 table_destroy(struct table *table)
325 {
326     size_t i;
327
328     for (i = 0; i < table->n_columns; i++) {
329         free(table->columns[i].heading);
330     }
331     free(table->columns);
332
333     for (i = 0; i < table->n_columns * table->n_rows; i++) {
334         free(table->cells[i]);
335     }
336     free(table->cells);
337 }
338
339 static void
340 table_add_column(struct table *table, const char *heading, ...)
341     PRINTF_FORMAT(2, 3);
342
343 static void
344 table_add_column(struct table *table, const char *heading, ...)
345 {
346     struct column *column;
347     va_list args;
348
349     assert(!table->n_rows);
350     if (table->n_columns >= table->allocated_columns) {
351         table->columns = x2nrealloc(table->columns, &table->allocated_columns,
352                                     sizeof *table->columns);
353     }
354     column = &table->columns[table->n_columns++];
355
356     va_start(args, heading);
357     column->heading = xvasprintf(heading, args);
358     column->width = strlen(column->heading);
359     va_end(args);
360 }
361
362 static char **
363 table_cell__(const struct table *table, size_t row, size_t column)
364 {
365     return &table->cells[column + row * table->n_columns];
366 }
367
368 static void
369 table_add_row(struct table *table)
370 {
371     size_t x, y;
372
373     if (table->n_rows >= table->allocated_rows) {
374         table->cells = x2nrealloc(table->cells, &table->allocated_rows,
375                                   table->n_columns * sizeof *table->cells);
376     }
377
378     y = table->n_rows++;
379     table->current_column = 0;
380     for (x = 0; x < table->n_columns; x++) {
381         *table_cell__(table, y, x) = NULL;
382     }
383 }
384
385 static void
386 table_add_cell_nocopy(struct table *table, char *s)
387 {
388     size_t x, y;
389     int length;
390
391     assert(table->n_rows > 0);
392     assert(table->current_column < table->n_columns);
393
394     x = table->current_column++;
395     y = table->n_rows - 1;
396     *table_cell__(table, y, x) = s;
397
398     length = strlen(s);
399     if (length > table->columns[x].width) {
400         table->columns[x].width = length;
401     }
402 }
403
404 static void
405 table_add_cell(struct table *table, const char *format, ...)
406 {
407     va_list args;
408
409     va_start(args, format);
410     table_add_cell_nocopy(table, xvasprintf(format, args));
411     va_end(args);
412 }
413
414 static void
415 table_print_table_line__(struct ds *line)
416 {
417     puts(ds_cstr(line));
418     ds_clear(line);
419 }
420
421 static void
422 table_print_table__(const struct table *table)
423 {
424     struct ds line = DS_EMPTY_INITIALIZER;
425     size_t x, y;
426
427     if (output_headings) {
428         for (x = 0; x < table->n_columns; x++) {
429             const struct column *column = &table->columns[x];
430             if (x) {
431                 ds_put_char(&line, ' ');
432             }
433             ds_put_format(&line, "%-*s", column->width, column->heading);
434         }
435         table_print_table_line__(&line);
436
437         for (x = 0; x < table->n_columns; x++) {
438             const struct column *column = &table->columns[x];
439             int i;
440
441             if (x) {
442                 ds_put_char(&line, ' ');
443             }
444             for (i = 0; i < column->width; i++) {
445                 ds_put_char(&line, '-');
446             }
447         }
448         table_print_table_line__(&line);
449     }
450
451     for (y = 0; y < table->n_rows; y++) {
452         for (x = 0; x < table->n_columns; x++) {
453             const char *cell = *table_cell__(table, y, x);
454             if (x) {
455                 ds_put_char(&line, ' ');
456             }
457             ds_put_format(&line, "%-*s", table->columns[x].width, cell);
458         }
459         table_print_table_line__(&line);
460     }
461
462     ds_destroy(&line);
463 }
464
465 static void
466 table_print_html_cell__(const char *element, const char *content)
467 {
468     const char *p;
469
470     printf("    <%s>", element);
471     for (p = content; *p != '\0'; p++) {
472         switch (*p) {
473         case '&':
474             fputs("&amp;", stdout);
475             break;
476         case '<':
477             fputs("&lt;", stdout);
478             break;
479         case '>':
480             fputs("&gt;", stdout);
481             break;
482         default:
483             putchar(*p);
484             break;
485         }
486     }
487     printf("</%s>\n", element);
488 }
489
490 static void
491 table_print_html__(const struct table *table)
492 {
493     size_t x, y;
494
495     fputs("<table>\n", stdout);
496
497     if (output_headings) {
498         fputs("  <tr>\n", stdout);
499         for (x = 0; x < table->n_columns; x++) {
500             const struct column *column = &table->columns[x];
501             table_print_html_cell__("th", column->heading);
502         }
503         fputs("  </tr>\n", stdout);
504     }
505
506     for (y = 0; y < table->n_rows; y++) {
507         fputs("  <tr>\n", stdout);
508         for (x = 0; x < table->n_columns; x++) {
509             table_print_html_cell__("td", *table_cell__(table, y, x));
510         }
511         fputs("  </tr>\n", stdout);
512     }
513
514     fputs("</table>\n", stdout);
515 }
516
517 static void
518 table_print_csv_cell__(const char *content)
519 {
520     const char *p;
521
522     if (!strpbrk(content, "\n\",")) {
523         fputs(content, stdout);
524     } else {
525         putchar('"');
526         for (p = content; *p != '\0'; p++) {
527             switch (*p) {
528             case '"':
529                 fputs("\"\"", stdout);
530                 break;
531             default:
532                 putchar(*p);
533                 break;
534             }
535         }
536         putchar('"');
537     }
538 }
539
540 static void
541 table_print_csv__(const struct table *table)
542 {
543     size_t x, y;
544
545     if (output_headings) {
546         for (x = 0; x < table->n_columns; x++) {
547             const struct column *column = &table->columns[x];
548             if (x) {
549                 putchar(',');
550             }
551             table_print_csv_cell__(column->heading);
552         }
553         putchar('\n');
554     }
555
556     for (y = 0; y < table->n_rows; y++) {
557         for (x = 0; x < table->n_columns; x++) {
558             if (x) {
559                 putchar(',');
560             }
561             table_print_csv_cell__(*table_cell__(table, y, x));
562         }
563         putchar('\n');
564     }
565 }
566
567 static void
568 table_print(const struct table *table)
569 {
570     switch (output_format) {
571     case FMT_TABLE:
572         table_print_table__(table);
573         break;
574
575     case FMT_HTML:
576         table_print_html__(table);
577         break;
578
579     case FMT_CSV:
580         table_print_csv__(table);
581         break;
582     }
583 }
584 \f
585 static void
586 do_list_dbs(int argc OVS_UNUSED, char *argv[])
587 {
588     struct jsonrpc_msg *request, *reply;
589     struct jsonrpc *rpc;
590     int error;
591     size_t i;
592
593     rpc = open_jsonrpc(argv[1]);
594     request = jsonrpc_create_request("list_dbs", json_array_create_empty(),
595                                      NULL);
596     error = jsonrpc_transact_block(rpc, request, &reply);
597     if (error) {
598         ovs_fatal(error, "transaction failed");
599     }
600
601     if (reply->result->type != JSON_ARRAY) {
602         ovs_fatal(0, "list_dbs response is not array");
603     }
604
605     for (i = 0; i < reply->result->u.array.n; i++) {
606         const struct json *name = reply->result->u.array.elems[i];
607
608         if (name->type != JSON_STRING) {
609             ovs_fatal(0, "list_dbs response %zu is not string", i);
610         }
611         puts(name->u.string);
612     }
613     jsonrpc_msg_destroy(reply);
614 }
615
616 static void
617 do_get_schema(int argc OVS_UNUSED, char *argv[])
618 {
619     struct ovsdb_schema *schema = fetch_schema(argv[1], argv[2]);
620     print_and_free_json(ovsdb_schema_to_json(schema));
621     ovsdb_schema_destroy(schema);
622 }
623
624 static void
625 do_list_tables(int argc OVS_UNUSED, char *argv[])
626 {
627     struct ovsdb_schema *schema;
628     struct shash_node *node;
629     struct table t;
630
631     schema = fetch_schema(argv[1], argv[2]);
632     table_init(&t);
633     table_add_column(&t, "Table");
634     table_add_column(&t, "Comment");
635     SHASH_FOR_EACH (node, &schema->tables) {
636         struct ovsdb_table_schema *ts = node->data;
637
638         table_add_row(&t);
639         table_add_cell(&t, ts->name);
640         if (ts->comment) {
641             table_add_cell(&t, ts->comment);
642         }
643     }
644     ovsdb_schema_destroy(schema);
645     table_print(&t);
646 }
647
648 static void
649 do_list_columns(int argc OVS_UNUSED, char *argv[])
650 {
651     const char *table_name = argv[3];
652     struct ovsdb_schema *schema;
653     struct shash_node *table_node;
654     struct table t;
655
656     schema = fetch_schema(argv[1], argv[2]);
657     table_init(&t);
658     if (!table_name) {
659         table_add_column(&t, "Table");
660     }
661     table_add_column(&t, "Column");
662     table_add_column(&t, "Type");
663     table_add_column(&t, "Comment");
664     SHASH_FOR_EACH (table_node, &schema->tables) {
665         struct ovsdb_table_schema *ts = table_node->data;
666
667         if (!table_name || !strcmp(table_name, ts->name)) {
668             struct shash_node *column_node;
669
670             SHASH_FOR_EACH (column_node, &ts->columns) {
671                 const struct ovsdb_column *column = column_node->data;
672                 struct json *type = ovsdb_type_to_json(&column->type);
673
674                 table_add_row(&t);
675                 if (!table_name) {
676                     table_add_cell(&t, ts->name);
677                 }
678                 table_add_cell(&t, column->name);
679                 table_add_cell_nocopy(&t, json_to_string(type, JSSF_SORT));
680                 if (column->comment) {
681                     table_add_cell(&t, column->comment);
682                 }
683
684                 json_destroy(type);
685             }
686         }
687     }
688     ovsdb_schema_destroy(schema);
689     table_print(&t);
690 }
691
692 static void
693 do_transact(int argc OVS_UNUSED, char *argv[])
694 {
695     struct jsonrpc_msg *request, *reply;
696     struct json *transaction;
697     struct jsonrpc *rpc;
698     int error;
699
700     transaction = parse_json(argv[2]);
701
702     rpc = open_jsonrpc(argv[1]);
703     request = jsonrpc_create_request("transact", transaction, NULL);
704     error = jsonrpc_transact_block(rpc, request, &reply);
705     if (error) {
706         ovs_fatal(error, "transaction failed");
707     }
708     if (reply->error) {
709         ovs_fatal(error, "transaction returned error: %s",
710                   json_to_string(reply->error, json_flags));
711     }
712     print_json(reply->result);
713     putchar('\n');
714     jsonrpc_msg_destroy(reply);
715     jsonrpc_close(rpc);
716 }
717
718 static char *
719 format_data(const struct json *json, const struct ovsdb_type *type)
720 {
721     if (data_format == DF_JSON) {
722         return json_to_string(json, JSSF_SORT);
723     } else if (data_format == DF_STRING) {
724         struct ovsdb_datum datum;
725         struct ovsdb_error *error;
726         struct ds s;
727
728         error = ovsdb_datum_from_json(&datum, type, json, NULL);
729         if (error) {
730             return json_to_string(json, JSSF_SORT);
731         }
732
733         ds_init(&s);
734         ovsdb_datum_to_string(&datum, type, &s);
735         ovsdb_datum_destroy(&datum, type);
736         return ds_steal_cstr(&s);
737     } else {
738         NOT_REACHED();
739     }
740 }
741
742 static void
743 monitor_print_row(struct json *row, const char *type, const char *uuid,
744                   const struct ovsdb_column_set *columns, struct table *t)
745 {
746     size_t i;
747
748     if (!row) {
749         ovs_error(0, "missing %s row", type);
750         return;
751     } else if (row->type != JSON_OBJECT) {
752         ovs_error(0, "<row> is not object");
753         return;
754     }
755
756     table_add_row(t);
757     table_add_cell(t, uuid);
758     table_add_cell(t, type);
759     for (i = 0; i < columns->n_columns; i++) {
760         const struct ovsdb_column *column = columns->columns[i];
761         struct json *value = shash_find_data(json_object(row), column->name);
762         if (value) {
763             table_add_cell_nocopy(t, format_data(value, &column->type));
764         } else {
765             table_add_cell(t, "");
766         }
767     }
768 }
769
770 static void
771 monitor_print(struct json *table_updates,
772               const struct ovsdb_table_schema *table,
773               const struct ovsdb_column_set *columns, bool initial)
774 {
775     struct json *table_update;
776     struct shash_node *node;
777     struct table t;
778     size_t i;
779
780     table_init(&t);
781
782     if (table_updates->type != JSON_OBJECT) {
783         ovs_error(0, "<table-updates> is not object");
784         return;
785     }
786     table_update = shash_find_data(json_object(table_updates), table->name);
787     if (!table_update) {
788         return;
789     }
790     if (table_update->type != JSON_OBJECT) {
791         ovs_error(0, "<table-update> is not object");
792         return;
793     }
794
795     table_add_column(&t, "row");
796     table_add_column(&t, "action");
797     for (i = 0; i < columns->n_columns; i++) {
798         table_add_column(&t, "%s", columns->columns[i]->name);
799     }
800     SHASH_FOR_EACH (node, json_object(table_update)) {
801         struct json *row_update = node->data;
802         struct json *old, *new;
803
804         if (row_update->type != JSON_OBJECT) {
805             ovs_error(0, "<row-update> is not object");
806             continue;
807         }
808         old = shash_find_data(json_object(row_update), "old");
809         new = shash_find_data(json_object(row_update), "new");
810         if (initial) {
811             monitor_print_row(new, "initial", node->name, columns, &t);
812         } else if (!old) {
813             monitor_print_row(new, "insert", node->name, columns, &t);
814         } else if (!new) {
815             monitor_print_row(old, "delete", node->name, columns, &t);
816         } else {
817             monitor_print_row(old, "old", node->name, columns, &t);
818             monitor_print_row(new, "new", "", columns, &t);
819         }
820     }
821     table_print(&t);
822     table_destroy(&t);
823 }
824
825 static void
826 do_monitor(int argc, char *argv[])
827 {
828     const char *server = argv[1];
829     const char *database = argv[2];
830     const char *table_name = argv[3];
831     struct ovsdb_column_set columns = OVSDB_COLUMN_SET_INITIALIZER;
832     struct ovsdb_table_schema *table;
833     struct ovsdb_schema *schema;
834     struct jsonrpc_msg *request;
835     struct jsonrpc *rpc;
836     struct json *select, *monitor, *monitor_request, *monitor_requests,
837         *request_id;
838
839     rpc = open_jsonrpc(server);
840
841     schema = fetch_schema_from_rpc(rpc, database);
842     table = shash_find_data(&schema->tables, table_name);
843     if (!table) {
844         ovs_fatal(0, "%s: %s does not have a table named \"%s\"",
845                   server, database, table_name);
846     }
847
848     if (argc >= 5 && *argv[4] != '\0') {
849         char *save_ptr = NULL;
850         char *token;
851
852         for (token = strtok_r(argv[4], ",", &save_ptr); token != NULL;
853              token = strtok_r(NULL, ",", &save_ptr)) {
854             const struct ovsdb_column *column;
855             column = ovsdb_table_schema_get_column(table, token);
856             if (!column) {
857                 ovs_fatal(0, "%s: table \"%s\" in %s does not have a "
858                           "column named \"%s\"",
859                           server, table_name, database, token);
860             }
861             ovsdb_column_set_add(&columns, column);
862         }
863     } else {
864         struct shash_node *node;
865
866         SHASH_FOR_EACH (node, &table->columns) {
867             const struct ovsdb_column *column = node->data;
868             if (column->index != OVSDB_COL_UUID) {
869                 ovsdb_column_set_add(&columns, column);
870             }
871         }
872     }
873
874     if (argc >= 6 && *argv[5] != '\0') {
875         char *save_ptr = NULL;
876         char *token;
877
878         select = json_object_create();
879         for (token = strtok_r(argv[5], ",", &save_ptr); token != NULL;
880              token = strtok_r(NULL, ",", &save_ptr)) {
881             json_object_put(select, token, json_boolean_create(true));
882         }
883     } else {
884         select = NULL;
885     }
886
887     monitor_request = json_object_create();
888     json_object_put(monitor_request,
889                     "columns", ovsdb_column_set_to_json(&columns));
890     if (select) {
891         json_object_put(monitor_request, "select", select);
892     }
893
894     monitor_requests = json_object_create();
895     json_object_put(monitor_requests, table_name, monitor_request);
896
897     monitor = json_array_create_3(json_string_create(database),
898                                   json_null_create(), monitor_requests);
899     request = jsonrpc_create_request("monitor", monitor, NULL);
900     request_id = json_clone(request->id);
901     jsonrpc_send(rpc, request);
902     for (;;) {
903         struct jsonrpc_msg *msg;
904         int error;
905
906         error = jsonrpc_recv_block(rpc, &msg);
907         if (error) {
908             ovsdb_schema_destroy(schema);
909             ovs_fatal(error, "%s: receive failed", server);
910         }
911
912         if (msg->type == JSONRPC_REQUEST && !strcmp(msg->method, "echo")) {
913             jsonrpc_send(rpc, jsonrpc_create_reply(json_clone(msg->params),
914                                                    msg->id));
915         } else if (msg->type == JSONRPC_REPLY
916                    && json_equal(msg->id, request_id)) {
917             monitor_print(msg->result, table, &columns, true);
918             fflush(stdout);
919             if (get_detach()) {
920                 /* daemonize() closes the standard file descriptors.  We output
921                  * to stdout, so we need to save and restore STDOUT_FILENO. */
922                 int fd = dup(STDOUT_FILENO);
923                 daemonize();
924                 dup2(fd, STDOUT_FILENO);
925                 close(fd);
926             }
927         } else if (msg->type == JSONRPC_NOTIFY
928                    && !strcmp(msg->method, "update")) {
929             struct json *params = msg->params;
930             if (params->type == JSON_ARRAY
931                 && params->u.array.n == 2
932                 && params->u.array.elems[0]->type == JSON_NULL) {
933                 monitor_print(params->u.array.elems[1],
934                               table, &columns, false);
935                 fflush(stdout);
936             }
937         }
938         jsonrpc_msg_destroy(msg);
939     }
940 }
941
942 static void
943 do_help(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
944 {
945     usage();
946 }
947
948 static const struct command all_commands[] = {
949     { "list-dbs", 1, 1, do_list_dbs },
950     { "get-schema", 2, 2, do_get_schema },
951     { "list-tables", 2, 2, do_list_tables },
952     { "list-columns", 2, 3, do_list_columns },
953     { "transact", 2, 2, do_transact },
954     { "monitor", 3, 5, do_monitor },
955     { "help", 0, INT_MAX, do_help },
956     { NULL, 0, 0, NULL },
957 };