json: Move from lib to include/openvswitch.
[cascardo/ovs.git] / ovsdb / ovsdb-client.c
1 /*
2  * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Nicira, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at:
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <config.h>
18
19 #include <ctype.h>
20 #include <errno.h>
21 #include <getopt.h>
22 #include <limits.h>
23 #include <signal.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <unistd.h>
27
28 #include "command-line.h"
29 #include "column.h"
30 #include "compiler.h"
31 #include "daemon.h"
32 #include "dirs.h"
33 #include "openvswitch/dynamic-string.h"
34 #include "fatal-signal.h"
35 #include "openvswitch/json.h"
36 #include "jsonrpc.h"
37 #include "lib/table.h"
38 #include "ovsdb.h"
39 #include "ovsdb-data.h"
40 #include "ovsdb-error.h"
41 #include "poll-loop.h"
42 #include "sort.h"
43 #include "svec.h"
44 #include "stream.h"
45 #include "stream-ssl.h"
46 #include "table.h"
47 #include "monitor.h"
48 #include "condition.h"
49 #include "timeval.h"
50 #include "unixctl.h"
51 #include "util.h"
52 #include "openvswitch/vlog.h"
53
54 VLOG_DEFINE_THIS_MODULE(ovsdb_client);
55
56 enum args_needed {
57     NEED_NONE,            /* No JSON-RPC connection or database name needed. */
58     NEED_RPC,             /* JSON-RPC connection needed. */
59     NEED_DATABASE         /* JSON-RPC connection and database name needed. */
60 };
61
62 struct ovsdb_client_command {
63     const char *name;
64     enum args_needed need;
65     int min_args;
66     int max_args;
67     void (*handler)(struct jsonrpc *rpc, const char *database,
68                     int argc, char *argv[]);
69 };
70
71 /* --timestamp: Print a timestamp before each update on "monitor" command? */
72 static bool timestamp;
73
74 /* Format for table output. */
75 static struct table_style table_style = TABLE_STYLE_DEFAULT;
76
77 static const struct ovsdb_client_command *get_all_commands(void);
78
79 OVS_NO_RETURN static void usage(void);
80 static void parse_options(int argc, char *argv[]);
81 static struct jsonrpc *open_jsonrpc(const char *server);
82 static void fetch_dbs(struct jsonrpc *, struct svec *dbs);
83
84 int
85 main(int argc, char *argv[])
86 {
87     const struct ovsdb_client_command *command;
88     char *database;
89     struct jsonrpc *rpc;
90
91     ovs_cmdl_proctitle_init(argc, argv);
92     set_program_name(argv[0]);
93     parse_options(argc, argv);
94     fatal_ignore_sigpipe();
95
96     daemon_become_new_user(false);
97     if (optind >= argc) {
98         ovs_fatal(0, "missing command name; use --help for help");
99     }
100
101     for (command = get_all_commands(); ; command++) {
102         if (!command->name) {
103             VLOG_FATAL("unknown command '%s'; use --help for help",
104                        argv[optind]);
105         } else if (!strcmp(command->name, argv[optind])) {
106             break;
107         }
108     }
109     optind++;
110
111     if (command->need != NEED_NONE) {
112         if (argc - optind > command->min_args
113             && (isalpha((unsigned char) argv[optind][0])
114                 && strchr(argv[optind], ':'))) {
115             rpc = open_jsonrpc(argv[optind++]);
116         } else {
117             char *sock = xasprintf("unix:%s/db.sock", ovs_rundir());
118             rpc = open_jsonrpc(sock);
119             free(sock);
120         }
121     } else {
122         rpc = NULL;
123     }
124
125     if (command->need == NEED_DATABASE) {
126         struct svec dbs;
127
128         svec_init(&dbs);
129         fetch_dbs(rpc, &dbs);
130         if (argc - optind > command->min_args
131             && svec_contains(&dbs, argv[optind])) {
132             database = xstrdup(argv[optind++]);
133         } else if (dbs.n == 1) {
134             database = xstrdup(dbs.names[0]);
135         } else if (svec_contains(&dbs, "Open_vSwitch")) {
136             database = xstrdup("Open_vSwitch");
137         } else {
138             jsonrpc_close(rpc);
139             ovs_fatal(0, "no default database for `%s' command, please "
140                       "specify a database name", command->name);
141         }
142         svec_destroy(&dbs);
143     } else {
144         database = NULL;
145     }
146
147     if (argc - optind < command->min_args ||
148         argc - optind > command->max_args) {
149         free(database);
150         VLOG_FATAL("invalid syntax for '%s' (use --help for help)",
151                     command->name);
152     }
153
154     command->handler(rpc, database, argc - optind, argv + optind);
155
156     free(database);
157     jsonrpc_close(rpc);
158
159     if (ferror(stdout)) {
160         VLOG_FATAL("write to stdout failed");
161     }
162     if (ferror(stderr)) {
163         VLOG_FATAL("write to stderr failed");
164     }
165
166     return 0;
167 }
168
169 static void
170 parse_options(int argc, char *argv[])
171 {
172     enum {
173         OPT_BOOTSTRAP_CA_CERT = UCHAR_MAX + 1,
174         OPT_TIMESTAMP,
175         VLOG_OPTION_ENUMS,
176         DAEMON_OPTION_ENUMS,
177         TABLE_OPTION_ENUMS
178     };
179     static const struct option long_options[] = {
180         {"help", no_argument, NULL, 'h'},
181         {"version", no_argument, NULL, 'V'},
182         {"timestamp", no_argument, NULL, OPT_TIMESTAMP},
183         VLOG_LONG_OPTIONS,
184         DAEMON_LONG_OPTIONS,
185 #ifdef HAVE_OPENSSL
186         {"bootstrap-ca-cert", required_argument, NULL, OPT_BOOTSTRAP_CA_CERT},
187         STREAM_SSL_LONG_OPTIONS,
188 #endif
189         TABLE_LONG_OPTIONS,
190         {NULL, 0, NULL, 0},
191     };
192     char *short_options = ovs_cmdl_long_options_to_short_options(long_options);
193
194     for (;;) {
195         int c;
196
197         c = getopt_long(argc, argv, short_options, long_options, NULL);
198         if (c == -1) {
199             break;
200         }
201
202         switch (c) {
203         case 'h':
204             usage();
205
206         case 'V':
207             ovs_print_version(0, 0);
208             exit(EXIT_SUCCESS);
209
210         VLOG_OPTION_HANDLERS
211         DAEMON_OPTION_HANDLERS
212         TABLE_OPTION_HANDLERS(&table_style)
213         STREAM_SSL_OPTION_HANDLERS
214
215         case OPT_BOOTSTRAP_CA_CERT:
216             stream_ssl_set_ca_cert_file(optarg, true);
217             break;
218
219         case OPT_TIMESTAMP:
220             timestamp = true;
221             break;
222
223         case '?':
224             exit(EXIT_FAILURE);
225
226         case 0:
227             /* getopt_long() already set the value for us. */
228             break;
229
230         default:
231             abort();
232         }
233     }
234     free(short_options);
235 }
236
237 static void
238 usage(void)
239 {
240     printf("%s: Open vSwitch database JSON-RPC client\n"
241            "usage: %s [OPTIONS] COMMAND [ARG...]\n"
242            "\nValid commands are:\n"
243            "\n  list-dbs [SERVER]\n"
244            "    list databases available on SERVER\n"
245            "\n  get-schema [SERVER] [DATABASE]\n"
246            "    retrieve schema for DATABASE from SERVER\n"
247            "\n  get-schema-version [SERVER] [DATABASE]\n"
248            "    retrieve schema for DATABASE from SERVER and report only its\n"
249            "    version number on stdout\n"
250            "\n  list-tables [SERVER] [DATABASE]\n"
251            "    list tables for DATABASE on SERVER\n"
252            "\n  list-columns [SERVER] [DATABASE] [TABLE]\n"
253            "    list columns in TABLE (or all tables) in DATABASE on SERVER\n"
254            "\n  transact [SERVER] TRANSACTION\n"
255            "    run TRANSACTION (a JSON array of operations) on SERVER\n"
256            "    and print the results as JSON on stdout\n"
257            "\n  monitor [SERVER] [DATABASE] TABLE [COLUMN,...]...\n"
258            "    monitor contents of COLUMNs in TABLE in DATABASE on SERVER.\n"
259            "    COLUMNs may include !initial, !insert, !delete, !modify\n"
260            "    to avoid seeing the specified kinds of changes.\n"
261            "\n  monitor-cond [SERVER] [DATABASE] CONDITION TABLE [COLUMN,...]...\n"
262            "    monitor contents that match CONDITION of COLUMNs in TABLE in\n"
263            "    DATABASE on SERVER.\n"
264            "    COLUMNs may include !initial, !insert, !delete, !modify\n"
265            "    to avoid seeing the specified kinds of changes.\n"
266            "\n  monitor [SERVER] [DATABASE] ALL\n"
267            "    monitor all changes to all columns in all tables\n"
268            "    in DATBASE on SERVER.\n"
269            "\n  dump [SERVER] [DATABASE]\n"
270            "    dump contents of DATABASE on SERVER to stdout\n"
271            "\n  lock [SERVER] LOCK\n"
272            "    create or wait for LOCK in SERVER\n"
273            "\n  steal [SERVER] LOCK\n"
274            "    steal LOCK from SERVER\n"
275            "\n  unlock [SERVER] LOCK\n"
276            "    unlock LOCK from SERVER\n"
277            "\nThe default SERVER is unix:%s/db.sock.\n"
278            "The default DATABASE is Open_vSwitch.\n",
279            program_name, program_name, ovs_rundir());
280     stream_usage("SERVER", true, true, true);
281     printf("\nOutput formatting options:\n"
282            "  -f, --format=FORMAT         set output formatting to FORMAT\n"
283            "                              (\"table\", \"html\", \"csv\", "
284            "or \"json\")\n"
285            "  --no-headings               omit table heading row\n"
286            "  --pretty                    pretty-print JSON in output\n"
287            "  --timestamp                 timestamp \"monitor\" output");
288     daemon_usage();
289     vlog_usage();
290     printf("\nOther options:\n"
291            "  -h, --help                  display this help message\n"
292            "  -V, --version               display version information\n");
293     exit(EXIT_SUCCESS);
294 }
295 \f
296 static void
297 check_txn(int error, struct jsonrpc_msg **reply_)
298 {
299     struct jsonrpc_msg *reply = *reply_;
300
301     if (error) {
302         ovs_fatal(error, "transaction failed");
303     }
304
305     if (reply->error) {
306         ovs_fatal(error, "transaction returned error: %s",
307                   json_to_string(reply->error, table_style.json_flags));
308     }
309 }
310
311 static struct json *
312 parse_json(const char *s)
313 {
314     struct json *json = json_from_string(s);
315     if (json->type == JSON_STRING) {
316         ovs_fatal(0, "\"%s\": %s", s, json->u.string);
317     }
318     return json;
319 }
320
321 static struct jsonrpc *
322 open_jsonrpc(const char *server)
323 {
324     struct stream *stream;
325     int error;
326
327     error = stream_open_block(jsonrpc_stream_open(server, &stream,
328                               DSCP_DEFAULT), &stream);
329     if (error == EAFNOSUPPORT) {
330         struct pstream *pstream;
331
332         error = jsonrpc_pstream_open(server, &pstream, DSCP_DEFAULT);
333         if (error) {
334             ovs_fatal(error, "failed to connect or listen to \"%s\"", server);
335         }
336
337         VLOG_INFO("%s: waiting for connection...", server);
338         error = pstream_accept_block(pstream, &stream);
339         if (error) {
340             ovs_fatal(error, "failed to accept connection on \"%s\"", server);
341         }
342
343         pstream_close(pstream);
344     } else if (error) {
345         ovs_fatal(error, "failed to connect to \"%s\"", server);
346     }
347
348     return jsonrpc_open(stream);
349 }
350
351 static void
352 print_json(struct json *json)
353 {
354     char *string = json_to_string(json, table_style.json_flags);
355     fputs(string, stdout);
356     free(string);
357 }
358
359 static void
360 print_and_free_json(struct json *json)
361 {
362     print_json(json);
363     json_destroy(json);
364 }
365
366 static void
367 check_ovsdb_error(struct ovsdb_error *error)
368 {
369     if (error) {
370         ovs_fatal(0, "%s", ovsdb_error_to_string(error));
371     }
372 }
373
374 static struct ovsdb_schema *
375 fetch_schema(struct jsonrpc *rpc, const char *database)
376 {
377     struct jsonrpc_msg *request, *reply;
378     struct ovsdb_schema *schema;
379
380     request = jsonrpc_create_request("get_schema",
381                                      json_array_create_1(
382                                          json_string_create(database)),
383                                      NULL);
384     check_txn(jsonrpc_transact_block(rpc, request, &reply), &reply);
385     check_ovsdb_error(ovsdb_schema_from_json(reply->result, &schema));
386     jsonrpc_msg_destroy(reply);
387
388     return schema;
389 }
390
391 static void
392 fetch_dbs(struct jsonrpc *rpc, struct svec *dbs)
393 {
394     struct jsonrpc_msg *request, *reply;
395     size_t i;
396
397     request = jsonrpc_create_request("list_dbs", json_array_create_empty(),
398                                      NULL);
399
400     check_txn(jsonrpc_transact_block(rpc, request, &reply), &reply);
401     if (reply->result->type != JSON_ARRAY) {
402         ovs_fatal(0, "list_dbs response is not array");
403     }
404
405     for (i = 0; i < reply->result->u.array.n; i++) {
406         const struct json *name = reply->result->u.array.elems[i];
407
408         if (name->type != JSON_STRING) {
409             ovs_fatal(0, "list_dbs response %"PRIuSIZE" is not string", i);
410         }
411         svec_add(dbs, name->u.string);
412     }
413     jsonrpc_msg_destroy(reply);
414     svec_sort(dbs);
415 }
416 \f
417 static void
418 do_list_dbs(struct jsonrpc *rpc, const char *database OVS_UNUSED,
419             int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
420 {
421     const char *db_name;
422     struct svec dbs;
423     size_t i;
424
425     svec_init(&dbs);
426     fetch_dbs(rpc, &dbs);
427     SVEC_FOR_EACH (i, db_name, &dbs) {
428         puts(db_name);
429     }
430     svec_destroy(&dbs);
431 }
432
433 static void
434 do_get_schema(struct jsonrpc *rpc, const char *database,
435               int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
436 {
437     struct ovsdb_schema *schema = fetch_schema(rpc, database);
438     print_and_free_json(ovsdb_schema_to_json(schema));
439     ovsdb_schema_destroy(schema);
440 }
441
442 static void
443 do_get_schema_version(struct jsonrpc *rpc, const char *database,
444                       int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
445 {
446     struct ovsdb_schema *schema = fetch_schema(rpc, database);
447     puts(schema->version);
448     ovsdb_schema_destroy(schema);
449 }
450
451 static void
452 do_list_tables(struct jsonrpc *rpc, const char *database,
453                int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
454 {
455     struct ovsdb_schema *schema;
456     struct shash_node *node;
457     struct table t;
458
459     schema = fetch_schema(rpc, database);
460     table_init(&t);
461     table_add_column(&t, "Table");
462     SHASH_FOR_EACH (node, &schema->tables) {
463         struct ovsdb_table_schema *ts = node->data;
464
465         table_add_row(&t);
466         table_add_cell(&t)->text = xstrdup(ts->name);
467     }
468     ovsdb_schema_destroy(schema);
469     table_print(&t, &table_style);
470     table_destroy(&t);
471 }
472
473 static void
474 do_list_columns(struct jsonrpc *rpc, const char *database,
475                 int argc OVS_UNUSED, char *argv[])
476 {
477     const char *table_name = argv[0];
478     struct ovsdb_schema *schema;
479     struct shash_node *table_node;
480     struct table t;
481
482     schema = fetch_schema(rpc, database);
483     table_init(&t);
484     if (!table_name) {
485         table_add_column(&t, "Table");
486     }
487     table_add_column(&t, "Column");
488     table_add_column(&t, "Type");
489     SHASH_FOR_EACH (table_node, &schema->tables) {
490         struct ovsdb_table_schema *ts = table_node->data;
491
492         if (!table_name || !strcmp(table_name, ts->name)) {
493             struct shash_node *column_node;
494
495             SHASH_FOR_EACH (column_node, &ts->columns) {
496                 const struct ovsdb_column *column = column_node->data;
497
498                 table_add_row(&t);
499                 if (!table_name) {
500                     table_add_cell(&t)->text = xstrdup(ts->name);
501                 }
502                 table_add_cell(&t)->text = xstrdup(column->name);
503                 table_add_cell(&t)->json = ovsdb_type_to_json(&column->type);
504             }
505         }
506     }
507     ovsdb_schema_destroy(schema);
508     table_print(&t, &table_style);
509     table_destroy(&t);
510 }
511
512 static void
513 do_transact(struct jsonrpc *rpc, const char *database OVS_UNUSED,
514             int argc OVS_UNUSED, char *argv[])
515 {
516     struct jsonrpc_msg *request, *reply;
517     struct json *transaction;
518
519     transaction = parse_json(argv[0]);
520
521     request = jsonrpc_create_request("transact", transaction, NULL);
522     check_txn(jsonrpc_transact_block(rpc, request, &reply), &reply);
523     print_json(reply->result);
524     putchar('\n');
525     jsonrpc_msg_destroy(reply);
526 }
527 \f
528 /* "monitor" command. */
529
530 struct monitored_table {
531     struct ovsdb_table_schema *table;
532     struct ovsdb_column_set columns;
533 };
534
535 static void
536 monitor_print_row(struct json *row, const char *type, const char *uuid,
537                   const struct ovsdb_column_set *columns, struct table *t)
538 {
539     size_t i;
540
541     if (!row) {
542         ovs_error(0, "missing %s row", type);
543         return;
544     } else if (row->type != JSON_OBJECT) {
545         ovs_error(0, "<row> is not object");
546         return;
547     }
548
549     table_add_row(t);
550     table_add_cell(t)->text = xstrdup(uuid);
551     table_add_cell(t)->text = xstrdup(type);
552     for (i = 0; i < columns->n_columns; i++) {
553         const struct ovsdb_column *column = columns->columns[i];
554         struct json *value = shash_find_data(json_object(row), column->name);
555         struct cell *cell = table_add_cell(t);
556         if (value) {
557             cell->json = json_clone(value);
558             cell->type = &column->type;
559         }
560     }
561 }
562
563 static void
564 monitor_print_table(struct json *table_update,
565                     const struct monitored_table *mt, char *caption,
566                     bool initial)
567 {
568     const struct ovsdb_table_schema *table = mt->table;
569     const struct ovsdb_column_set *columns = &mt->columns;
570     struct shash_node *node;
571     struct table t;
572     size_t i;
573
574     if (table_update->type != JSON_OBJECT) {
575         ovs_error(0, "<table-update> for table %s is not object", table->name);
576         return;
577     }
578
579     table_init(&t);
580     table_set_timestamp(&t, timestamp);
581     table_set_caption(&t, caption);
582
583     table_add_column(&t, "row");
584     table_add_column(&t, "action");
585     for (i = 0; i < columns->n_columns; i++) {
586         table_add_column(&t, "%s", columns->columns[i]->name);
587     }
588     SHASH_FOR_EACH (node, json_object(table_update)) {
589         struct json *row_update = node->data;
590         struct json *old, *new;
591
592         if (row_update->type != JSON_OBJECT) {
593             ovs_error(0, "<row-update> is not object");
594             continue;
595         }
596         old = shash_find_data(json_object(row_update), "old");
597         new = shash_find_data(json_object(row_update), "new");
598         if (initial) {
599             monitor_print_row(new, "initial", node->name, columns, &t);
600         } else if (!old) {
601             monitor_print_row(new, "insert", node->name, columns, &t);
602         } else if (!new) {
603             monitor_print_row(old, "delete", node->name, columns, &t);
604         } else {
605             monitor_print_row(old, "old", node->name, columns, &t);
606             monitor_print_row(new, "new", "", columns, &t);
607         }
608     }
609     table_print(&t, &table_style);
610     table_destroy(&t);
611 }
612
613 static void
614 monitor_print(struct json *table_updates,
615               const struct monitored_table *mts, size_t n_mts,
616               bool initial)
617 {
618     size_t i;
619
620     if (table_updates->type != JSON_OBJECT) {
621         ovs_error(0, "<table-updates> is not object");
622         return;
623     }
624
625     for (i = 0; i < n_mts; i++) {
626         const struct monitored_table *mt = &mts[i];
627         struct json *table_update = shash_find_data(json_object(table_updates),
628                                                     mt->table->name);
629         if (table_update) {
630             monitor_print_table(table_update, mt,
631                                 n_mts > 1 ? xstrdup(mt->table->name) : NULL,
632                                 initial);
633         }
634     }
635 }
636
637 static void
638 monitor2_print_row(struct json *row, const char *type, const char *uuid,
639                    const struct ovsdb_column_set *columns, struct table *t)
640 {
641     if (!strcmp(type, "delete")) {
642         if (row->type != JSON_NULL) {
643             ovs_error(0, "delete method does not expect <row>");
644             return;
645         }
646
647         table_add_row(t);
648         table_add_cell(t)->text = xstrdup(uuid);
649         table_add_cell(t)->text = xstrdup(type);
650     } else {
651         if (!row || row->type != JSON_OBJECT) {
652             ovs_error(0, "<row> is not object");
653             return;
654         }
655         monitor_print_row(row, type, uuid, columns, t);
656     }
657 }
658
659 static void
660 monitor2_print_table(struct json *table_update2,
661                     const struct monitored_table *mt, char *caption)
662 {
663     const struct ovsdb_table_schema *table = mt->table;
664     const struct ovsdb_column_set *columns = &mt->columns;
665     struct shash_node *node;
666     struct table t;
667
668     if (table_update2->type != JSON_OBJECT) {
669         ovs_error(0, "<table-update> for table %s is not object", table->name);
670         return;
671     }
672
673     table_init(&t);
674     table_set_timestamp(&t, timestamp);
675     table_set_caption(&t, caption);
676
677     table_add_column(&t, "row");
678     table_add_column(&t, "action");
679     for (size_t i = 0; i < columns->n_columns; i++) {
680         table_add_column(&t, "%s", columns->columns[i]->name);
681     }
682     SHASH_FOR_EACH (node, json_object(table_update2)) {
683         struct json *row_update2 = node->data;
684         const char *operation;
685         struct json *row;
686         const char *ops[] = {"delete", "initial", "modify", "insert"};
687
688         if (row_update2->type != JSON_OBJECT) {
689             ovs_error(0, "<row-update2> is not object");
690             continue;
691         }
692
693         /* row_update2 contains one of objects indexed by ops[] */
694         for (int i = 0; i < ARRAY_SIZE(ops); i++) {
695             operation = ops[i];
696             row = shash_find_data(json_object(row_update2), operation);
697
698             if (row) {
699                 monitor2_print_row(row, operation, node->name, columns, &t);
700                 break;
701             }
702         }
703     }
704     table_print(&t, &table_style);
705     table_destroy(&t);
706 }
707
708 static void
709 monitor2_print(struct json *table_updates2,
710                const struct monitored_table *mts, size_t n_mts)
711 {
712     size_t i;
713
714     if (table_updates2->type != JSON_OBJECT) {
715         ovs_error(0, "<table-updates2> is not object");
716         return;
717     }
718
719     for (i = 0; i < n_mts; i++) {
720         const struct monitored_table *mt = &mts[i];
721         struct json *table_update = shash_find_data(
722                                         json_object(table_updates2),
723                                         mt->table->name);
724         if (table_update) {
725             monitor2_print_table(table_update, mt,
726                                 n_mts > 1 ? xstrdup(mt->table->name) : NULL);
727         }
728     }
729 }
730
731 static void
732 add_column(const char *server, const struct ovsdb_column *column,
733            struct ovsdb_column_set *columns, struct json *columns_json)
734 {
735     if (ovsdb_column_set_contains(columns, column->index)) {
736         ovs_fatal(0, "%s: column \"%s\" mentioned multiple times",
737                   server, column->name);
738     }
739     ovsdb_column_set_add(columns, column);
740     json_array_add(columns_json, json_string_create(column->name));
741 }
742
743 static struct json *
744 parse_monitor_columns(char *arg, const char *server, const char *database,
745                       const struct ovsdb_table_schema *table,
746                       struct ovsdb_column_set *columns)
747 {
748     bool initial, insert, delete, modify;
749     struct json *mr, *columns_json;
750     char *save_ptr = NULL;
751     char *token;
752
753     mr = json_object_create();
754     columns_json = json_array_create_empty();
755     json_object_put(mr, "columns", columns_json);
756
757     initial = insert = delete = modify = true;
758     for (token = strtok_r(arg, ",", &save_ptr); token != NULL;
759          token = strtok_r(NULL, ",", &save_ptr)) {
760         if (!strcmp(token, "!initial")) {
761             initial = false;
762         } else if (!strcmp(token, "!insert")) {
763             insert = false;
764         } else if (!strcmp(token, "!delete")) {
765             delete = false;
766         } else if (!strcmp(token, "!modify")) {
767             modify = false;
768         } else {
769             const struct ovsdb_column *column;
770
771             column = ovsdb_table_schema_get_column(table, token);
772             if (!column) {
773                 ovs_fatal(0, "%s: table \"%s\" in %s does not have a "
774                           "column named \"%s\"",
775                           server, table->name, database, token);
776             }
777             add_column(server, column, columns, columns_json);
778         }
779     }
780
781     if (columns_json->u.array.n == 0) {
782         const struct shash_node **nodes;
783         size_t i, n;
784
785         n = shash_count(&table->columns);
786         nodes = shash_sort(&table->columns);
787         for (i = 0; i < n; i++) {
788             const struct ovsdb_column *column = nodes[i]->data;
789             if (column->index != OVSDB_COL_UUID
790                 && column->index != OVSDB_COL_VERSION) {
791                 add_column(server, column, columns, columns_json);
792             }
793         }
794         free(nodes);
795
796         add_column(server, ovsdb_table_schema_get_column(table, "_version"),
797                    columns, columns_json);
798     }
799
800     if (!initial || !insert || !delete || !modify) {
801         struct json *select = json_object_create();
802         json_object_put(select, "initial", json_boolean_create(initial));
803         json_object_put(select, "insert", json_boolean_create(insert));
804         json_object_put(select, "delete", json_boolean_create(delete));
805         json_object_put(select, "modify", json_boolean_create(modify));
806         json_object_put(mr, "select", select);
807     }
808
809     return mr;
810 }
811
812 static void
813 ovsdb_client_exit(struct unixctl_conn *conn, int argc OVS_UNUSED,
814                   const char *argv[] OVS_UNUSED, void *exiting_)
815 {
816     bool *exiting = exiting_;
817     *exiting = true;
818     unixctl_command_reply(conn, NULL);
819 }
820
821 static void
822 ovsdb_client_block(struct unixctl_conn *conn, int argc OVS_UNUSED,
823                    const char *argv[] OVS_UNUSED, void *blocked_)
824 {
825     bool *blocked = blocked_;
826
827     if (!*blocked) {
828         *blocked = true;
829         unixctl_command_reply(conn, NULL);
830     } else {
831         unixctl_command_reply(conn, "already blocking");
832     }
833 }
834
835 static void
836 ovsdb_client_unblock(struct unixctl_conn *conn, int argc OVS_UNUSED,
837                      const char *argv[] OVS_UNUSED, void *blocked_)
838 {
839     bool *blocked = blocked_;
840
841     if (*blocked) {
842         *blocked = false;
843         unixctl_command_reply(conn, NULL);
844     } else {
845         unixctl_command_reply(conn, "already unblocked");
846     }
847 }
848
849 static void
850 ovsdb_client_cond_change(struct unixctl_conn *conn, int argc OVS_UNUSED,
851                      const char *argv[], void *rpc_)
852 {
853     struct jsonrpc *rpc = rpc_;
854     struct json *monitor_cond_update_requests = json_object_create();
855     struct json *monitor_cond_update_request = json_object_create();
856     struct json *params;
857     struct jsonrpc_msg *request;
858
859     json_object_put(monitor_cond_update_request, "where",
860                     json_from_string(argv[2]));
861     json_object_put(monitor_cond_update_requests,
862                     argv[1],
863                     json_array_create_1(monitor_cond_update_request));
864
865     params = json_array_create_3(json_null_create(),json_null_create(),
866                                  monitor_cond_update_requests);
867
868     request = jsonrpc_create_request("monitor_cond_change", params, NULL);
869     jsonrpc_send(rpc, request);
870
871     VLOG_DBG("cond change %s %s", argv[1], argv[2]);
872     unixctl_command_reply(conn, "condiiton changed");
873 }
874
875 static void
876 add_monitored_table(int argc, char *argv[],
877                     const char *server, const char *database,
878                     struct json *condition,
879                     struct ovsdb_table_schema *table,
880                     struct json *monitor_requests,
881                     struct monitored_table **mts,
882                     size_t *n_mts, size_t *allocated_mts)
883 {
884     struct json *monitor_request_array, *mr;
885     struct monitored_table *mt;
886
887     if (*n_mts >= *allocated_mts) {
888         *mts = x2nrealloc(*mts, allocated_mts, sizeof **mts);
889     }
890     mt = &(*mts)[(*n_mts)++];
891     mt->table = table;
892     ovsdb_column_set_init(&mt->columns);
893
894     monitor_request_array = json_array_create_empty();
895     if (argc > 1) {
896         int i;
897
898         for (i = 1; i < argc; i++) {
899             mr = parse_monitor_columns(argv[i], server, database, table,
900                                        &mt->columns);
901             if (i == 1 && condition) {
902                 json_object_put(mr, "where", condition);
903             }
904             json_array_add(monitor_request_array, mr);
905         }
906     } else {
907         /* Allocate a writable empty string since parse_monitor_columns()
908          * is going to strtok() it and that's risky with literal "". */
909         char empty[] = "";
910
911         mr = parse_monitor_columns(empty, server, database,
912                                    table, &mt->columns);
913         if (condition) {
914             json_object_put(mr, "where", condition);
915         }
916         json_array_add(monitor_request_array, mr);
917     }
918
919     json_object_put(monitor_requests, table->name, monitor_request_array);
920 }
921
922 static void
923 destroy_monitored_table(struct monitored_table *mts, size_t n)
924 {
925     int i;
926
927     for (i = 0; i < n; i++) {
928         struct monitored_table *mt = &mts[i];
929         ovsdb_column_set_destroy(&mt->columns);
930     }
931
932     free(mts);
933 }
934
935 static void
936 do_monitor__(struct jsonrpc *rpc, const char *database,
937              enum ovsdb_monitor_version version,
938              int argc, char *argv[], struct json *condition)
939 {
940     const char *server = jsonrpc_get_name(rpc);
941     const char *table_name = argv[0];
942     struct unixctl_server *unixctl;
943     struct ovsdb_schema *schema;
944     struct jsonrpc_msg *request;
945     struct json *monitor, *monitor_requests, *request_id;
946     bool exiting = false;
947     bool blocked = false;
948
949     struct monitored_table *mts;
950     size_t n_mts, allocated_mts;
951
952     ovs_assert(version < OVSDB_MONITOR_VERSION_MAX);
953
954     daemon_save_fd(STDOUT_FILENO);
955     daemonize_start(false);
956     if (get_detach()) {
957         int error;
958
959         error = unixctl_server_create(NULL, &unixctl);
960         if (error) {
961             ovs_fatal(error, "failed to create unixctl server");
962         }
963
964         unixctl_command_register("exit", "", 0, 0,
965                                  ovsdb_client_exit, &exiting);
966         unixctl_command_register("ovsdb-client/block", "", 0, 0,
967                                  ovsdb_client_block, &blocked);
968         unixctl_command_register("ovsdb-client/unblock", "", 0, 0,
969                                  ovsdb_client_unblock, &blocked);
970         unixctl_command_register("ovsdb-client/cond_change", "TABLE COND", 2, 2,
971                                  ovsdb_client_cond_change, rpc);
972     } else {
973         unixctl = NULL;
974     }
975
976     schema = fetch_schema(rpc, database);
977
978     monitor_requests = json_object_create();
979
980     mts = NULL;
981     n_mts = allocated_mts = 0;
982     if (strcmp(table_name, "ALL")) {
983         struct ovsdb_table_schema *table;
984
985         table = shash_find_data(&schema->tables, table_name);
986         if (!table) {
987             ovs_fatal(0, "%s: %s does not have a table named \"%s\"",
988                       server, database, table_name);
989         }
990
991         add_monitored_table(argc, argv, server, database, condition, table,
992                             monitor_requests, &mts, &n_mts, &allocated_mts);
993     } else {
994         size_t n = shash_count(&schema->tables);
995         const struct shash_node **nodes = shash_sort(&schema->tables);
996         size_t i;
997
998         if (condition) {
999             ovs_fatal(0, "ALL tables are not allowed with condition");
1000         }
1001
1002         for (i = 0; i < n; i++) {
1003             struct ovsdb_table_schema *table = nodes[i]->data;
1004
1005             add_monitored_table(argc, argv, server, database, NULL, table,
1006                                 monitor_requests,
1007                                 &mts, &n_mts, &allocated_mts);
1008         }
1009         free(nodes);
1010     }
1011
1012     monitor = json_array_create_3(json_string_create(database),
1013                                   json_null_create(), monitor_requests);
1014     const char *method = version == OVSDB_MONITOR_V2 ? "monitor_cond"
1015                                                      : "monitor";
1016
1017     request = jsonrpc_create_request(method, monitor, NULL);
1018     request_id = json_clone(request->id);
1019     jsonrpc_send(rpc, request);
1020
1021     for (;;) {
1022         unixctl_server_run(unixctl);
1023         while (!blocked) {
1024             struct jsonrpc_msg *msg;
1025             int error;
1026
1027             error = jsonrpc_recv(rpc, &msg);
1028             if (error == EAGAIN) {
1029                 break;
1030             } else if (error) {
1031                 ovs_fatal(error, "%s: receive failed", server);
1032             }
1033
1034             if (msg->type == JSONRPC_REQUEST && !strcmp(msg->method, "echo")) {
1035                 jsonrpc_send(rpc, jsonrpc_create_reply(json_clone(msg->params),
1036                                                        msg->id));
1037             } else if (msg->type == JSONRPC_REPLY
1038                        && json_equal(msg->id, request_id)) {
1039                 switch(version) {
1040                 case OVSDB_MONITOR_V1:
1041                     monitor_print(msg->result, mts, n_mts, true);
1042                     break;
1043                 case OVSDB_MONITOR_V2:
1044                     monitor2_print(msg->result, mts, n_mts);
1045                     break;
1046                 case OVSDB_MONITOR_VERSION_MAX:
1047                 default:
1048                     OVS_NOT_REACHED();
1049                 }
1050                 fflush(stdout);
1051                 daemonize_complete();
1052             } else if (msg->type == JSONRPC_NOTIFY
1053                        && !strcmp(msg->method, "update")) {
1054                 struct json *params = msg->params;
1055                 if (params->type == JSON_ARRAY
1056                     && params->u.array.n == 2
1057                     && params->u.array.elems[0]->type == JSON_NULL) {
1058                     monitor_print(params->u.array.elems[1], mts, n_mts, false);
1059                     fflush(stdout);
1060                 }
1061             } else if (msg->type == JSONRPC_NOTIFY
1062                        && version == OVSDB_MONITOR_V2
1063                        && !strcmp(msg->method, "update2")) {
1064                 struct json *params = msg->params;
1065                 if (params->type == JSON_ARRAY
1066                     && params->u.array.n == 2
1067                     && params->u.array.elems[0]->type == JSON_NULL) {
1068                     monitor2_print(params->u.array.elems[1], mts, n_mts);
1069                     fflush(stdout);
1070                 }
1071             }
1072             jsonrpc_msg_destroy(msg);
1073         }
1074
1075         if (exiting) {
1076             break;
1077         }
1078
1079         jsonrpc_run(rpc);
1080         jsonrpc_wait(rpc);
1081         if (!blocked) {
1082             jsonrpc_recv_wait(rpc);
1083         }
1084         unixctl_server_wait(unixctl);
1085         poll_block();
1086     }
1087
1088     json_destroy(request_id);
1089     unixctl_server_destroy(unixctl);
1090     ovsdb_schema_destroy(schema);
1091     destroy_monitored_table(mts, n_mts);
1092 }
1093
1094 static void
1095 do_monitor(struct jsonrpc *rpc, const char *database,
1096            int argc, char *argv[])
1097 {
1098     do_monitor__(rpc, database, OVSDB_MONITOR_V1, argc, argv, NULL);
1099 }
1100
1101 static void
1102 do_monitor_cond(struct jsonrpc *rpc, const char *database,
1103            int argc, char *argv[])
1104 {
1105     struct ovsdb_condition cnd;
1106     struct json *condition = NULL;
1107     struct ovsdb_schema *schema;
1108     struct ovsdb_table_schema *table;
1109     const char *table_name = argv[1];
1110
1111     ovs_assert(argc > 1);
1112     schema = fetch_schema(rpc, database);
1113     table = shash_find_data(&schema->tables, table_name);
1114     if (!table) {
1115         ovs_fatal(0, "%s does not have a table named \"%s\"",
1116                   database, table_name);
1117     }
1118     condition = parse_json(argv[0]);
1119     check_ovsdb_error(ovsdb_condition_from_json(table, condition,
1120                                                     NULL, &cnd));
1121     ovsdb_condition_destroy(&cnd);
1122     do_monitor__(rpc, database, OVSDB_MONITOR_V2, --argc, ++argv, condition);
1123 }
1124
1125 struct dump_table_aux {
1126     struct ovsdb_datum **data;
1127     const struct ovsdb_column **columns;
1128     size_t n_columns;
1129 };
1130
1131 static int
1132 compare_data(size_t a_y, size_t b_y, size_t x,
1133              const struct dump_table_aux *aux)
1134 {
1135     return ovsdb_datum_compare_3way(&aux->data[a_y][x],
1136                                     &aux->data[b_y][x],
1137                                     &aux->columns[x]->type);
1138 }
1139
1140 static int
1141 compare_rows(size_t a_y, size_t b_y, void *aux_)
1142 {
1143     struct dump_table_aux *aux = aux_;
1144     size_t x;
1145
1146     /* Skip UUID columns on the first pass, since their values tend to be
1147      * random and make our results less reproducible. */
1148     for (x = 0; x < aux->n_columns; x++) {
1149         if (aux->columns[x]->type.key.type != OVSDB_TYPE_UUID) {
1150             int cmp = compare_data(a_y, b_y, x, aux);
1151             if (cmp) {
1152                 return cmp;
1153             }
1154         }
1155     }
1156
1157     /* Use UUID columns as tie-breakers. */
1158     for (x = 0; x < aux->n_columns; x++) {
1159         if (aux->columns[x]->type.key.type == OVSDB_TYPE_UUID) {
1160             int cmp = compare_data(a_y, b_y, x, aux);
1161             if (cmp) {
1162                 return cmp;
1163             }
1164         }
1165     }
1166
1167     return 0;
1168 }
1169
1170 static void
1171 swap_rows(size_t a_y, size_t b_y, void *aux_)
1172 {
1173     struct dump_table_aux *aux = aux_;
1174     struct ovsdb_datum *tmp = aux->data[a_y];
1175     aux->data[a_y] = aux->data[b_y];
1176     aux->data[b_y] = tmp;
1177 }
1178
1179 static int
1180 compare_columns(const void *a_, const void *b_)
1181 {
1182     const struct ovsdb_column *const *ap = a_;
1183     const struct ovsdb_column *const *bp = b_;
1184     const struct ovsdb_column *a = *ap;
1185     const struct ovsdb_column *b = *bp;
1186
1187     return strcmp(a->name, b->name);
1188 }
1189
1190 static void
1191 dump_table(const char *table_name, const struct shash *cols,
1192            struct json_array *rows)
1193 {
1194     const struct ovsdb_column **columns;
1195     size_t n_columns;
1196
1197     struct ovsdb_datum **data;
1198
1199     struct dump_table_aux aux;
1200     struct shash_node *node;
1201     struct table t;
1202     size_t x, y;
1203
1204     /* Sort columns by name, for reproducibility. */
1205     columns = xmalloc(shash_count(cols) * sizeof *columns);
1206     n_columns = 0;
1207     SHASH_FOR_EACH (node, cols) {
1208         struct ovsdb_column *column = node->data;
1209         if (strcmp(column->name, "_version")) {
1210             columns[n_columns++] = column;
1211         }
1212     }
1213     qsort(columns, n_columns, sizeof *columns, compare_columns);
1214
1215     /* Extract data from table. */
1216     data = xmalloc(rows->n * sizeof *data);
1217     for (y = 0; y < rows->n; y++) {
1218         struct shash *row;
1219
1220         if (rows->elems[y]->type != JSON_OBJECT) {
1221             ovs_fatal(0,  "row %"PRIuSIZE" in table %s response is not a JSON object: "
1222                       "%s", y, table_name, json_to_string(rows->elems[y], 0));
1223         }
1224         row = json_object(rows->elems[y]);
1225
1226         data[y] = xmalloc(n_columns * sizeof **data);
1227         for (x = 0; x < n_columns; x++) {
1228             const struct json *json = shash_find_data(row, columns[x]->name);
1229             if (!json) {
1230                 ovs_fatal(0, "row %"PRIuSIZE" in table %s response lacks %s column",
1231                           y, table_name, columns[x]->name);
1232             }
1233
1234             check_ovsdb_error(ovsdb_datum_from_json(&data[y][x],
1235                                                     &columns[x]->type,
1236                                                     json, NULL));
1237         }
1238     }
1239
1240     /* Sort rows by column values, for reproducibility. */
1241     aux.data = data;
1242     aux.columns = columns;
1243     aux.n_columns = n_columns;
1244     sort(rows->n, compare_rows, swap_rows, &aux);
1245
1246     /* Add column headings. */
1247     table_init(&t);
1248     table_set_caption(&t, xasprintf("%s table", table_name));
1249     for (x = 0; x < n_columns; x++) {
1250         table_add_column(&t, "%s", columns[x]->name);
1251     }
1252
1253     /* Print rows. */
1254     for (y = 0; y < rows->n; y++) {
1255         table_add_row(&t);
1256         for (x = 0; x < n_columns; x++) {
1257             struct cell *cell = table_add_cell(&t);
1258             cell->json = ovsdb_datum_to_json(&data[y][x], &columns[x]->type);
1259             cell->type = &columns[x]->type;
1260             ovsdb_datum_destroy(&data[y][x], &columns[x]->type);
1261         }
1262         free(data[y]);
1263     }
1264     table_print(&t, &table_style);
1265     table_destroy(&t);
1266
1267     free(data);
1268     free(columns);
1269 }
1270
1271 static void
1272 do_dump(struct jsonrpc *rpc, const char *database,
1273         int argc, char *argv[])
1274 {
1275     struct jsonrpc_msg *request, *reply;
1276     struct ovsdb_schema *schema;
1277     struct json *transaction;
1278
1279     const struct shash_node *node, **tables;
1280     size_t n_tables;
1281     struct ovsdb_table_schema *tschema;
1282     const struct shash *columns;
1283     struct shash custom_columns;
1284
1285     size_t i;
1286
1287     shash_init(&custom_columns);
1288     schema = fetch_schema(rpc, database);
1289     if (argc) {
1290         node = shash_find(&schema->tables, argv[0]);
1291         if (!node) {
1292             ovs_fatal(0, "No table \"%s\" found.", argv[0]);
1293         }
1294         tables = xmemdup(&node, sizeof(&node));
1295         n_tables = 1;
1296         tschema = tables[0]->data;
1297         for (i = 1; i < argc; i++) {
1298             node = shash_find(&tschema->columns, argv[i]);
1299             if (!node) {
1300                 ovs_fatal(0, "Table \"%s\" has no column %s.", argv[0], argv[1]);
1301             }
1302             shash_add(&custom_columns, argv[1], node->data);
1303         }
1304     } else {
1305         tables = shash_sort(&schema->tables);
1306         n_tables = shash_count(&schema->tables);
1307     }
1308
1309     /* Construct transaction to retrieve entire database. */
1310     transaction = json_array_create_1(json_string_create(database));
1311     for (i = 0; i < n_tables; i++) {
1312         const struct ovsdb_table_schema *ts = tables[i]->data;
1313         struct json *op, *jcolumns;
1314
1315         if (argc > 1) {
1316             columns = &custom_columns;
1317         } else {
1318             columns = &ts->columns;
1319         }
1320         jcolumns = json_array_create_empty();
1321         SHASH_FOR_EACH (node, columns) {
1322             const struct ovsdb_column *column = node->data;
1323
1324             if (strcmp(column->name, "_version")) {
1325                 json_array_add(jcolumns, json_string_create(column->name));
1326             }
1327         }
1328
1329         op = json_object_create();
1330         json_object_put_string(op, "op", "select");
1331         json_object_put_string(op, "table", tables[i]->name);
1332         json_object_put(op, "where", json_array_create_empty());
1333         json_object_put(op, "columns", jcolumns);
1334         json_array_add(transaction, op);
1335     }
1336
1337     /* Send request, get reply. */
1338     request = jsonrpc_create_request("transact", transaction, NULL);
1339     check_txn(jsonrpc_transact_block(rpc, request, &reply), &reply);
1340
1341     /* Print database contents. */
1342     if (reply->result->type != JSON_ARRAY
1343         || reply->result->u.array.n != n_tables) {
1344         ovs_fatal(0, "reply is not array of %"PRIuSIZE" elements: %s",
1345                   n_tables, json_to_string(reply->result, 0));
1346     }
1347     for (i = 0; i < n_tables; i++) {
1348         const struct ovsdb_table_schema *ts = tables[i]->data;
1349         const struct json *op_result = reply->result->u.array.elems[i];
1350         struct json *rows;
1351
1352         if (op_result->type != JSON_OBJECT
1353             || !(rows = shash_find_data(json_object(op_result), "rows"))
1354             || rows->type != JSON_ARRAY) {
1355             ovs_fatal(0, "%s table reply is not an object with a \"rows\" "
1356                       "member array: %s",
1357                       ts->name, json_to_string(op_result, 0));
1358         }
1359
1360         if (argc > 1) {
1361             dump_table(tables[i]->name, &custom_columns, &rows->u.array);
1362         } else {
1363             dump_table(tables[i]->name, &ts->columns, &rows->u.array);
1364         }
1365     }
1366
1367     jsonrpc_msg_destroy(reply);
1368     shash_destroy(&custom_columns);
1369     free(tables);
1370     ovsdb_schema_destroy(schema);
1371 }
1372
1373 static void
1374 do_help(struct jsonrpc *rpc OVS_UNUSED, const char *database OVS_UNUSED,
1375         int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
1376 {
1377     usage();
1378 }
1379
1380 \f
1381 /* "lock" command. */
1382
1383 struct ovsdb_client_lock_req {
1384     const char *method;
1385     char *lock;
1386 };
1387
1388 static void
1389 lock_req_init(struct ovsdb_client_lock_req *lock_req,
1390               const char *method, const char *lock_name)
1391 {
1392     if (lock_req->method || lock_req->lock) {
1393         return;
1394     }
1395     lock_req->method = method;
1396     lock_req->lock = xstrdup(lock_name);
1397 }
1398
1399 static bool
1400 lock_req_is_set(struct ovsdb_client_lock_req *lock_req)
1401 {
1402     return lock_req->method;
1403 }
1404
1405 static void
1406 lock_req_destroy(struct ovsdb_client_lock_req *lock_req)
1407 {
1408     free(lock_req->lock);
1409     lock_req->method = NULL;
1410     lock_req->lock = NULL;
1411 }
1412
1413 /* Create a lock class request. Caller is responsible for free
1414  * the 'request' message. */
1415 static struct jsonrpc_msg *
1416 create_lock_request(struct ovsdb_client_lock_req *lock_req)
1417 {
1418     struct json *locks, *lock;
1419
1420     locks = json_array_create_empty();
1421     lock = json_string_create(lock_req->lock);
1422     json_array_add(locks, lock);
1423
1424     return jsonrpc_create_request(lock_req->method, locks, NULL);
1425 }
1426
1427 static void
1428 ovsdb_client_lock(struct unixctl_conn *conn, int argc OVS_UNUSED,
1429                   const char *argv[], void *lock_req_)
1430 {
1431     struct ovsdb_client_lock_req *lock_req = lock_req_;
1432     lock_req_init(lock_req, "lock", argv[1]);
1433     unixctl_command_reply(conn, NULL);
1434 }
1435
1436 static void
1437 ovsdb_client_unlock(struct unixctl_conn *conn, int argc OVS_UNUSED,
1438                     const char *argv[], void *lock_req_)
1439 {
1440     struct ovsdb_client_lock_req *lock_req = lock_req_;
1441     lock_req_init(lock_req, "unlock", argv[1]);
1442     unixctl_command_reply(conn, NULL);
1443 }
1444
1445 static void
1446 ovsdb_client_steal(struct unixctl_conn *conn, int argc OVS_UNUSED,
1447                    const char *argv[], void *lock_req_)
1448 {
1449     struct ovsdb_client_lock_req *lock_req = lock_req_;
1450     lock_req_init(lock_req, "steal", argv[1]);
1451     unixctl_command_reply(conn, NULL);
1452 }
1453
1454 static void
1455 do_lock(struct jsonrpc *rpc, const char *method, const char *lock)
1456 {
1457     struct ovsdb_client_lock_req lock_req = {NULL, NULL};
1458     struct unixctl_server *unixctl;
1459     struct jsonrpc_msg *request;
1460     struct json *request_id = NULL;
1461     bool exiting = false;
1462     bool enable_lock_request = true; /* Don't send another request before
1463                                         getting a reply of the previous
1464                                         request. */
1465     daemon_save_fd(STDOUT_FILENO);
1466     daemonize_start(false);
1467     lock_req_init(&lock_req, method, lock);
1468
1469     if (get_detach()) {
1470         int error;
1471
1472         error = unixctl_server_create(NULL, &unixctl);
1473         if (error) {
1474             ovs_fatal(error, "failed to create unixctl server");
1475         }
1476
1477         unixctl_command_register("unlock", "LOCK", 1, 1,
1478                                   ovsdb_client_unlock, &lock_req);
1479         unixctl_command_register("steal", "LOCK", 1, 1,
1480                                   ovsdb_client_steal, &lock_req);
1481         unixctl_command_register("lock", "LOCK", 1, 1,
1482                                   ovsdb_client_lock, &lock_req);
1483         unixctl_command_register("exit", "", 0, 0,
1484                                  ovsdb_client_exit, &exiting);
1485     } else {
1486         unixctl = NULL;
1487     }
1488
1489     for (;;) {
1490         struct jsonrpc_msg *msg;
1491         int error;
1492
1493         unixctl_server_run(unixctl);
1494         if (enable_lock_request && lock_req_is_set(&lock_req)) {
1495             request = create_lock_request(&lock_req);
1496             request_id = json_clone(request->id);
1497             jsonrpc_send(rpc, request);
1498             lock_req_destroy(&lock_req);
1499         }
1500
1501         error = jsonrpc_recv(rpc, &msg);
1502         if (error == EAGAIN) {
1503             goto no_msg;
1504         } else if (error) {
1505             ovs_fatal(error, "%s: receive failed", jsonrpc_get_name(rpc));
1506         }
1507
1508         if (msg->type == JSONRPC_REQUEST && !strcmp(msg->method, "echo")) {
1509             jsonrpc_send(rpc, jsonrpc_create_reply(json_clone(msg->params),
1510                                                    msg->id));
1511         } else if (msg->type == JSONRPC_REPLY
1512                    && json_equal(msg->id, request_id)) {
1513             print_json(msg->result);
1514             putchar('\n');
1515             fflush(stdout);
1516             enable_lock_request = true;
1517             json_destroy(request_id);
1518             request_id = NULL;
1519             daemonize_complete();
1520         } else if (msg->type == JSONRPC_NOTIFY) {
1521             puts(msg->method);
1522             print_json(msg->params);
1523             putchar('\n');
1524             fflush(stdout);
1525         }
1526
1527         jsonrpc_msg_destroy(msg);
1528
1529 no_msg:
1530         if (exiting) {
1531             break;
1532         }
1533
1534         jsonrpc_run(rpc);
1535         jsonrpc_wait(rpc);
1536         jsonrpc_recv_wait(rpc);
1537
1538         unixctl_server_wait(unixctl);
1539         poll_block();
1540     }
1541
1542     json_destroy(request_id);
1543     unixctl_server_destroy(unixctl);
1544 }
1545
1546 static void
1547 do_lock_create(struct jsonrpc *rpc, const char *database OVS_UNUSED,
1548                int argc OVS_UNUSED, char *argv[])
1549 {
1550     do_lock(rpc, "lock", argv[0]);
1551 }
1552
1553 static void
1554 do_lock_steal(struct jsonrpc *rpc, const char *database OVS_UNUSED,
1555               int argc OVS_UNUSED, char *argv[])
1556 {
1557     do_lock(rpc, "steal", argv[0]);
1558 }
1559
1560 static void
1561 do_lock_unlock(struct jsonrpc *rpc, const char *database OVS_UNUSED,
1562                int argc OVS_UNUSED, char *argv[])
1563 {
1564     do_lock(rpc, "unlock", argv[0]);
1565 }
1566
1567 /* All command handlers (except for "help") are expected to take an optional
1568  * server socket name (e.g. "unix:...") as their first argument.  The socket
1569  * name argument must be included in max_args (but left out of min_args).  The
1570  * command name and socket name are not included in the arguments passed to the
1571  * handler: the argv[0] passed to the handler is the first argument after the
1572  * optional server socket name.  The connection to the server is available as
1573  * global variable 'rpc'. */
1574 static const struct ovsdb_client_command all_commands[] = {
1575     { "list-dbs",           NEED_RPC,      0, 0,       do_list_dbs },
1576     { "get-schema",         NEED_DATABASE, 0, 0,       do_get_schema },
1577     { "get-schema-version", NEED_DATABASE, 0, 0,       do_get_schema_version },
1578     { "list-tables",        NEED_DATABASE, 0, 0,       do_list_tables },
1579     { "list-columns",       NEED_DATABASE, 0, 1,       do_list_columns },
1580     { "transact",           NEED_RPC,      1, 1,       do_transact },
1581     { "monitor",            NEED_DATABASE, 1, INT_MAX, do_monitor },
1582     { "monitor-cond",       NEED_DATABASE, 2, 3,       do_monitor_cond },
1583     { "dump",               NEED_DATABASE, 0, INT_MAX, do_dump },
1584     { "lock",               NEED_RPC,      1, 1,       do_lock_create },
1585     { "steal",              NEED_RPC,      1, 1,       do_lock_steal },
1586     { "unlock",             NEED_RPC,      1, 1,       do_lock_unlock },
1587     { "help",               NEED_NONE,     0, INT_MAX, do_help },
1588
1589     { NULL,                 0,             0, 0,       NULL },
1590 };
1591
1592 static const struct ovsdb_client_command *get_all_commands(void)
1593 {
1594     return all_commands;
1595 }