]> git.proxmox.com Git - mirror_ovs.git/blame - lib/db-ctl-base.c
other-config: Add tc-policy switch to control tc flower flag
[mirror_ovs.git] / lib / db-ctl-base.c
CommitLineData
07ff77cc 1/*
3f5b5f7b 2 * Copyright (c) 2015, 2016, 2017 Nicira, Inc.
07ff77cc
AW
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 <getopt.h>
21#include <unistd.h>
22
23#include "db-ctl-base.h"
24
25#include "command-line.h"
26#include "compiler.h"
27#include "dirs.h"
3e8a2ad1 28#include "openvswitch/dynamic-string.h"
07ff77cc
AW
29#include "fatal-signal.h"
30#include "hash.h"
ee89ea7b 31#include "openvswitch/json.h"
07ff77cc
AW
32#include "openvswitch/vlog.h"
33#include "ovsdb-data.h"
34#include "ovsdb-idl.h"
35#include "ovsdb-idl-provider.h"
ee89ea7b 36#include "openvswitch/shash.h"
6530be3b 37#include "sset.h"
07ff77cc
AW
38#include "string.h"
39#include "table.h"
40#include "util.h"
41
42VLOG_DEFINE_THIS_MODULE(db_ctl_base);
43
ce6f1d1f
AZ
44/* This array defines the 'show' command output format. User can check the
45 * definition in utilities/ovs-vsctl.c as reference.
46 *
47 * Particularly, if an element in 'columns[]' represents a reference to
48 * another table, the referred table must also be defined as an entry in
49 * in 'cmd_show_tables[]'.
50 *
51 * The definition must end with an all-NULL entry. It is initalized once
52 * when ctl_init() is called.
53 *
54 * */
d33340a5 55static const struct cmd_show_table *cmd_show_tables;
ce6f1d1f
AZ
56
57/* ctl_exit() is called by ctl_fatal(). User can optionally supply an exit
58 * function ctl_exit_func() via ctl_init. If supplied, this function will
59 * be called by ctl_exit()
60 */
61static void (*ctl_exit_func)(int status) = NULL;
62OVS_NO_RETURN static void ctl_exit(int status);
07ff77cc 63
3f5b5f7b
BP
64/* Two arrays with 'n_classes' elements, which represent the tables in this
65 * database and how the user can refer to their rows. */
66static const struct ctl_table_class *ctl_classes;
67static const struct ovsdb_idl_table_class *idl_classes;
68static size_t n_classes;
802cb46e 69
07ff77cc 70static struct shash all_commands = SHASH_INITIALIZER(&all_commands);
3f5b5f7b
BP
71static const struct ovsdb_idl_table_class *get_table(const char *table_name);
72static void set_column(const struct ovsdb_idl_table_class *,
15ffc202
AZ
73 const struct ovsdb_idl_row *, const char *,
74 struct ovsdb_symbol_table *);
07ff77cc
AW
75
76\f
51a73ff0
AW
77static struct option *
78find_option(const char *name, struct option *options, size_t n_options)
79{
80 size_t i;
81
82 for (i = 0; i < n_options; i++) {
83 if (!strcmp(options[i].name, name)) {
84 return &options[i];
85 }
86 }
87 return NULL;
88}
89
90static struct option *
91add_option(struct option **optionsp, size_t *n_optionsp,
92 size_t *allocated_optionsp)
93{
94 if (*n_optionsp >= *allocated_optionsp) {
95 *optionsp = x2nrealloc(*optionsp, allocated_optionsp,
96 sizeof **optionsp);
97 }
98 return &(*optionsp)[(*n_optionsp)++];
99}
100
101/* Converts the command arguments into format that can be parsed by
102 * bash completion script.
103 *
104 * Therein, arguments will be attached with following prefixes:
105 *
106 * !argument :: The argument is required
107 * ?argument :: The argument is optional
108 * *argument :: The argument may appear any number (0 or more) times
109 * +argument :: The argument may appear one or more times
110 *
111 */
112static void
113print_command_arguments(const struct ctl_command_syntax *command)
114{
115 /*
116 * The argument string is parsed in reverse. We use a stack 'oew_stack' to
117 * keep track of nested optionals. Whenever a ']' is encountered, we push
118 * a bit to 'oew_stack'. The bit is set to 1 if the ']' is not nested.
119 * Subsequently, we pop an entry everytime '[' is met.
120 *
121 * We use 'whole_word_is_optional' value to decide whether or not a ! or +
122 * should be added on encountering a space: if the optional surrounds the
123 * whole word then it shouldn't be, but if it is only a part of the word
124 * (i.e. [key=]value), it should be.
125 */
126 uint32_t oew_stack = 0;
127
128 const char *arguments = command->arguments;
129 int length = strlen(arguments);
130 if (!length) {
131 return;
132 }
133
134 /* Output buffer, written backward from end. */
135 char *output = xmalloc(2 * length);
136 char *outp = output + 2 * length;
137 *--outp = '\0';
138
139 bool in_repeated = false;
140 bool whole_word_is_optional = false;
141
142 for (const char *inp = arguments + length; inp > arguments; ) {
143 switch (*--inp) {
144 case ']':
145 oew_stack <<= 1;
146 if (inp[1] == '\0' || inp[1] == ' ' || inp[1] == '.') {
147 oew_stack |= 1;
148 }
149 break;
150 case '[':
151 /* Checks if the whole word is optional, and sets the
152 * 'whole_word_is_optional' accordingly. */
153 if ((inp == arguments || inp[-1] == ' ') && oew_stack & 1) {
154 *--outp = in_repeated ? '*' : '?';
155 whole_word_is_optional = true;
156 } else {
157 *--outp = '?';
158 whole_word_is_optional = false;
159 }
160 oew_stack >>= 1;
161 break;
162 case ' ':
163 if (!whole_word_is_optional) {
164 *--outp = in_repeated ? '+' : '!';
165 }
166 *--outp = ' ';
167 in_repeated = false;
168 whole_word_is_optional = false;
169 break;
170 case '.':
171 in_repeated = true;
172 break;
173 default:
174 *--outp = *inp;
175 break;
176 }
177 }
178 if (arguments[0] != '[' && outp != output + 2 * length - 1) {
179 *--outp = in_repeated ? '+' : '!';
180 }
181 printf("%s", outp);
182 free(output);
183}
184
07ff77cc
AW
185static void
186die_if_error(char *error)
187{
188 if (error) {
189 ctl_fatal("%s", error);
190 }
191}
192
193static int
194to_lower_and_underscores(unsigned c)
195{
196 return c == '-' ? '_' : tolower(c);
197}
198
3f5b5f7b
BP
199/* Returns a score representing how well 's' matches 'name'. Higher return
200 * values indicate a better match. The order of the arguments is important:
201 * 'name' is the name of an entity such as a table or a column, and 's' is user
202 * input. */
07ff77cc
AW
203static unsigned int
204score_partial_match(const char *name, const char *s)
205{
206 int score;
207
208 if (!strcmp(name, s)) {
209 return UINT_MAX;
210 }
211 for (score = 0; ; score++, name++, s++) {
212 if (to_lower_and_underscores(*name) != to_lower_and_underscores(*s)) {
213 break;
214 } else if (*name == '\0') {
215 return UINT_MAX - 1;
216 }
217 }
218 return *s == '\0' ? score : 0;
219}
220
221static struct ovsdb_symbol *
222create_symbol(struct ovsdb_symbol_table *symtab, const char *id, bool *newp)
223{
224 struct ovsdb_symbol *symbol;
225
226 if (id[0] != '@') {
227 ctl_fatal("row id \"%s\" does not begin with \"@\"", id);
228 }
229
230 if (newp) {
231 *newp = ovsdb_symbol_table_get(symtab, id) == NULL;
232 }
233
234 symbol = ovsdb_symbol_table_insert(symtab, id);
235 if (symbol->created) {
236 ctl_fatal("row id \"%s\" may only be specified on one --id option",
237 id);
238 }
239 symbol->created = true;
240 return symbol;
241}
242
2cbe3963
BP
243static bool
244record_id_equals(const union ovsdb_atom *name, enum ovsdb_atomic_type type,
245 const char *record_id)
246{
247 if (type == OVSDB_TYPE_STRING) {
248 if (!strcmp(name->string, record_id)) {
249 return true;
250 }
251
252 struct uuid uuid;
253 size_t len = strlen(record_id);
254 if (len >= 4
255 && uuid_from_string(&uuid, name->string)
256 && !strncmp(name->string, record_id, len)) {
257 return true;
258 }
259
260 return false;
261 } else {
262 ovs_assert(type == OVSDB_TYPE_INTEGER);
263 return name->integer == strtoll(record_id, NULL, 10);
264 }
265}
266
07ff77cc 267static const struct ovsdb_idl_row *
3f5b5f7b
BP
268get_row_by_id(struct ctl_context *ctx,
269 const struct ovsdb_idl_table_class *table,
07ff77cc
AW
270 const struct ctl_row_id *id, const char *record_id)
271{
07ff77cc 272
a0b02897 273 if (!id->name_column) {
07ff77cc
AW
274 return NULL;
275 }
276
3f5b5f7b 277 const struct ovsdb_idl_row *referrer = NULL;
3f5b5f7b 278
15931827
BP
279 /* Figure out the 'key' and 'value' types for the column that we're going
280 * to look at. One of these ('name_type') is the type of the name we're
281 * going to compare against 'record_id'. */
282 enum ovsdb_atomic_type key, value, name_type;
283 if (!id->key) {
284 name_type = key = id->name_column->type.key.type;
285 value = OVSDB_TYPE_VOID;
286 } else {
287 key = OVSDB_TYPE_STRING;
288 name_type = value = id->name_column->type.value.type;
289 }
290
291 /* We only support integer and string names (so far). */
292 if (name_type == OVSDB_TYPE_INTEGER) {
3f5b5f7b 293 if (!record_id[0] || record_id[strspn(record_id, "0123456789")]) {
07ff77cc
AW
294 return NULL;
295 }
296 } else {
15931827 297 ovs_assert(name_type == OVSDB_TYPE_STRING);
3f5b5f7b 298 }
4ba9c6bf 299
a0b02897
BP
300 const struct ovsdb_idl_class *class = ovsdb_idl_get_class(ctx->idl);
301 const struct ovsdb_idl_table_class *id_table
302 = ovsdb_idl_table_class_from_column(class, id->name_column);
3f5b5f7b 303 for (const struct ovsdb_idl_row *row = ovsdb_idl_first_row(ctx->idl,
a0b02897 304 id_table);
3f5b5f7b
BP
305 row != NULL;
306 row = ovsdb_idl_next_row(row)) {
15931827
BP
307 /* Pick out the name column's data. */
308 const struct ovsdb_datum *datum = ovsdb_idl_get(
309 row, id->name_column, key, value);
310
311 /* Extract the name from the column. */
312 const union ovsdb_atom *name;
313 if (!id->key) {
314 name = datum->n == 1 ? &datum->keys[0] : NULL;
315 } else {
316 const union ovsdb_atom key
317 = { .string = CONST_CAST(char *, id->key) };
318 unsigned int i = ovsdb_datum_find_key(datum, &key,
319 OVSDB_TYPE_STRING);
320 name = i == UINT_MAX ? NULL : &datum->values[i];
321 }
322 if (!name) {
323 continue;
324 }
325
326 /* If the name equals 'record_id', take it. */
2cbe3963 327 if (record_id_equals(name, name_type, record_id)) {
15931827
BP
328 if (referrer) {
329 ctl_fatal("multiple rows in %s match \"%s\"",
330 id_table->name, record_id);
07ff77cc 331 }
15931827 332 referrer = row;
4ba9c6bf 333 }
07ff77cc
AW
334 }
335 if (!referrer) {
336 return NULL;
337 }
338
3f5b5f7b 339 const struct ovsdb_idl_row *final = referrer;
07ff77cc
AW
340 if (id->uuid_column) {
341 const struct ovsdb_datum *uuid;
342
343 ovsdb_idl_txn_verify(referrer, id->uuid_column);
344 uuid = ovsdb_idl_get(referrer, id->uuid_column,
345 OVSDB_TYPE_UUID, OVSDB_TYPE_VOID);
346 if (uuid->n == 1) {
3f5b5f7b 347 final = ovsdb_idl_get_row_for_uuid(ctx->idl, table,
07ff77cc
AW
348 &uuid->keys[0].uuid);
349 }
07ff77cc 350 }
07ff77cc
AW
351 return final;
352}
353
bed7aef9
BP
354const struct ovsdb_idl_row *
355ctl_get_row(struct ctl_context *ctx,
356 const struct ovsdb_idl_table_class *table, const char *record_id,
357 bool must_exist)
07ff77cc 358{
3f5b5f7b 359 const struct ovsdb_idl_row *row = NULL;
07ff77cc
AW
360 struct uuid uuid;
361
07ff77cc 362 if (uuid_from_string(&uuid, record_id)) {
3f5b5f7b 363 row = ovsdb_idl_get_row_for_uuid(ctx->idl, table, &uuid);
07ff77cc
AW
364 }
365 if (!row) {
3f5b5f7b
BP
366 if (!strcmp(record_id, ".")) {
367 row = ovsdb_idl_first_row(ctx->idl, table);
368 if (row && ovsdb_idl_next_row(row)) {
369 row = NULL;
370 }
371 }
372 }
373 if (!row) {
374 const struct ctl_table_class *ctl_class
375 = &ctl_classes[table - idl_classes];
376 for (int i = 0; i < ARRAY_SIZE(ctl_class->row_ids); i++) {
377 row = get_row_by_id(ctx, table, &ctl_class->row_ids[i],
378 record_id);
07ff77cc
AW
379 if (row) {
380 break;
381 }
382 }
383 }
2052f3a1 384 if (!row && uuid_is_partial_string(record_id) >= 4) {
4e3000a0
BP
385 for (const struct ovsdb_idl_row *r = ovsdb_idl_first_row(ctx->idl,
386 table);
387 r != NULL;
388 r = ovsdb_idl_next_row(r)) {
61be08e4 389 if (uuid_is_partial_match(&r->uuid, record_id)) {
4e3000a0
BP
390 if (!row) {
391 row = r;
392 } else {
393 ctl_fatal("%s contains 2 or more rows whose UUIDs begin "
394 "with %s: at least "UUID_FMT" and "UUID_FMT,
395 table->name, record_id,
396 UUID_ARGS(&row->uuid),
397 UUID_ARGS(&r->uuid));
398 }
399 }
400 }
401 }
07ff77cc 402 if (must_exist && !row) {
3f5b5f7b 403 ctl_fatal("no row \"%s\" in table %s", record_id, table->name);
07ff77cc
AW
404 }
405 return row;
406}
407
408static char *
3f5b5f7b 409get_column(const struct ovsdb_idl_table_class *table, const char *column_name,
07ff77cc
AW
410 const struct ovsdb_idl_column **columnp)
411{
412 const struct ovsdb_idl_column *best_match = NULL;
413 unsigned int best_score = 0;
414 size_t i;
415
3f5b5f7b
BP
416 for (i = 0; i < table->n_columns; i++) {
417 const struct ovsdb_idl_column *column = &table->columns[i];
07ff77cc
AW
418 unsigned int score = score_partial_match(column->name, column_name);
419 if (score > best_score) {
420 best_match = column;
421 best_score = score;
422 } else if (score == best_score) {
423 best_match = NULL;
424 }
425 }
426
427 *columnp = best_match;
428 if (best_match) {
429 return NULL;
430 } else if (best_score) {
431 return xasprintf("%s contains more than one column whose name "
3f5b5f7b 432 "matches \"%s\"", table->name, column_name);
07ff77cc
AW
433 } else {
434 return xasprintf("%s does not contain a column whose name matches "
3f5b5f7b 435 "\"%s\"", table->name, column_name);
07ff77cc
AW
436 }
437}
438
439static void
440pre_get_column(struct ctl_context *ctx,
3f5b5f7b
BP
441 const struct ovsdb_idl_table_class *table,
442 const char *column_name,
07ff77cc
AW
443 const struct ovsdb_idl_column **columnp)
444{
445 die_if_error(get_column(table, column_name, columnp));
446 ovsdb_idl_add_column(ctx->idl, *columnp);
447}
448
3f5b5f7b 449static const struct ovsdb_idl_table_class *
07ff77cc
AW
450pre_get_table(struct ctl_context *ctx, const char *table_name)
451{
3f5b5f7b
BP
452 const struct ovsdb_idl_table_class *table = get_table(table_name);
453 ovsdb_idl_add_table(ctx->idl, table);
07ff77cc 454
3f5b5f7b
BP
455 const struct ctl_table_class *ctl = &ctl_classes[table - idl_classes];
456 for (int i = 0; i < ARRAY_SIZE(ctl->row_ids); i++) {
457 const struct ctl_row_id *id = &ctl->row_ids[i];
07ff77cc
AW
458 if (id->name_column) {
459 ovsdb_idl_add_column(ctx->idl, id->name_column);
460 }
461 if (id->uuid_column) {
462 ovsdb_idl_add_column(ctx->idl, id->uuid_column);
463 }
464 }
465
3f5b5f7b 466 return table;
07ff77cc
AW
467}
468
469static char *
470missing_operator_error(const char *arg, const char **allowed_operators,
471 size_t n_allowed)
472{
473 struct ds s;
474
475 ds_init(&s);
476 ds_put_format(&s, "%s: argument does not end in ", arg);
477 ds_put_format(&s, "\"%s\"", allowed_operators[0]);
478 if (n_allowed == 2) {
479 ds_put_format(&s, " or \"%s\"", allowed_operators[1]);
480 } else if (n_allowed > 2) {
481 size_t i;
482
483 for (i = 1; i < n_allowed - 1; i++) {
484 ds_put_format(&s, ", \"%s\"", allowed_operators[i]);
485 }
486 ds_put_format(&s, ", or \"%s\"", allowed_operators[i]);
487 }
488 ds_put_format(&s, " followed by a value.");
489
490 return ds_steal_cstr(&s);
491}
492
493/* Breaks 'arg' apart into a number of fields in the following order:
494 *
495 * - The name of a column in 'table', stored into '*columnp'. The column
496 * name may be abbreviated.
497 *
498 * - Optionally ':' followed by a key string. The key is stored as a
499 * malloc()'d string into '*keyp', or NULL if no key is present in
500 * 'arg'.
501 *
502 * - If 'valuep' is nonnull, an operator followed by a value string. The
503 * allowed operators are the 'n_allowed' string in 'allowed_operators',
504 * or just "=" if 'n_allowed' is 0. If 'operatorp' is nonnull, then the
505 * index of the operator within 'allowed_operators' is stored into
506 * '*operatorp'. The value is stored as a malloc()'d string into
507 * '*valuep', or NULL if no value is present in 'arg'.
508 *
509 * On success, returns NULL. On failure, returned a malloc()'d string error
510 * message and stores NULL into all of the nonnull output arguments. */
511static char * OVS_WARN_UNUSED_RESULT
512parse_column_key_value(const char *arg,
3f5b5f7b 513 const struct ovsdb_idl_table_class *table,
07ff77cc
AW
514 const struct ovsdb_idl_column **columnp, char **keyp,
515 int *operatorp,
516 const char **allowed_operators, size_t n_allowed,
517 char **valuep)
518{
519 const char *p = arg;
520 char *column_name;
521 char *error;
522
523 ovs_assert(!(operatorp && !valuep));
524 *keyp = NULL;
525 if (valuep) {
526 *valuep = NULL;
527 }
528
529 /* Parse column name. */
530 error = ovsdb_token_parse(&p, &column_name);
531 if (error) {
532 goto error;
533 }
534 if (column_name[0] == '\0') {
535 free(column_name);
536 error = xasprintf("%s: missing column name", arg);
537 goto error;
538 }
539 error = get_column(table, column_name, columnp);
540 free(column_name);
541 if (error) {
542 goto error;
543 }
544
545 /* Parse key string. */
546 if (*p == ':') {
547 p++;
548 error = ovsdb_token_parse(&p, keyp);
549 if (error) {
550 goto error;
551 }
552 }
553
554 /* Parse value string. */
555 if (valuep) {
556 size_t best_len;
557 size_t i;
558 int best;
559
560 if (!allowed_operators) {
561 static const char *equals = "=";
562 allowed_operators = &equals;
563 n_allowed = 1;
564 }
565
566 best = -1;
567 best_len = 0;
568 for (i = 0; i < n_allowed; i++) {
569 const char *op = allowed_operators[i];
570 size_t op_len = strlen(op);
571
572 if (op_len > best_len && !strncmp(op, p, op_len) && p[op_len]) {
573 best_len = op_len;
574 best = i;
575 }
576 }
577 if (best < 0) {
578 error = missing_operator_error(arg, allowed_operators, n_allowed);
579 goto error;
580 }
581
582 if (operatorp) {
583 *operatorp = best;
584 }
585 *valuep = xstrdup(p + best_len);
586 } else {
587 if (*p != '\0') {
588 error = xasprintf("%s: trailing garbage \"%s\" in argument",
589 arg, p);
590 goto error;
591 }
592 }
593 return NULL;
594
595 error:
596 *columnp = NULL;
597 free(*keyp);
598 *keyp = NULL;
599 if (valuep) {
600 free(*valuep);
601 *valuep = NULL;
602 if (operatorp) {
603 *operatorp = -1;
604 }
605 }
606 return error;
607}
608
609static const struct ovsdb_idl_column *
610pre_parse_column_key_value(struct ctl_context *ctx,
611 const char *arg,
3f5b5f7b 612 const struct ovsdb_idl_table_class *table)
07ff77cc
AW
613{
614 const struct ovsdb_idl_column *column;
615 const char *p;
616 char *column_name;
617
618 p = arg;
619 die_if_error(ovsdb_token_parse(&p, &column_name));
620 if (column_name[0] == '\0') {
621 ctl_fatal("%s: missing column name", arg);
622 }
623
624 pre_get_column(ctx, table, column_name, &column);
625 free(column_name);
626
627 return column;
628}
629
630static void
631check_mutable(const struct ovsdb_idl_row *row,
632 const struct ovsdb_idl_column *column)
633{
634 if (!ovsdb_idl_is_mutable(row, column)) {
635 ctl_fatal("cannot modify read-only column %s in table %s",
636 column->name, row->table->class->name);
637 }
638}
639
640#define RELOPS \
641 RELOP(RELOP_EQ, "=") \
642 RELOP(RELOP_NE, "!=") \
643 RELOP(RELOP_LT, "<") \
644 RELOP(RELOP_GT, ">") \
645 RELOP(RELOP_LE, "<=") \
646 RELOP(RELOP_GE, ">=") \
647 RELOP(RELOP_SET_EQ, "{=}") \
648 RELOP(RELOP_SET_NE, "{!=}") \
649 RELOP(RELOP_SET_LT, "{<}") \
650 RELOP(RELOP_SET_GT, "{>}") \
651 RELOP(RELOP_SET_LE, "{<=}") \
652 RELOP(RELOP_SET_GE, "{>=}")
653
654enum relop {
655#define RELOP(ENUM, STRING) ENUM,
656 RELOPS
657#undef RELOP
658};
659
660static bool
661is_set_operator(enum relop op)
662{
663 return (op == RELOP_SET_EQ || op == RELOP_SET_NE ||
664 op == RELOP_SET_LT || op == RELOP_SET_GT ||
665 op == RELOP_SET_LE || op == RELOP_SET_GE);
666}
667
668static bool
669evaluate_relop(const struct ovsdb_datum *a, const struct ovsdb_datum *b,
670 const struct ovsdb_type *type, enum relop op)
671{
672 switch (op) {
673 case RELOP_EQ:
674 case RELOP_SET_EQ:
675 return ovsdb_datum_compare_3way(a, b, type) == 0;
676 case RELOP_NE:
677 case RELOP_SET_NE:
678 return ovsdb_datum_compare_3way(a, b, type) != 0;
679 case RELOP_LT:
680 return ovsdb_datum_compare_3way(a, b, type) < 0;
681 case RELOP_GT:
682 return ovsdb_datum_compare_3way(a, b, type) > 0;
683 case RELOP_LE:
684 return ovsdb_datum_compare_3way(a, b, type) <= 0;
685 case RELOP_GE:
686 return ovsdb_datum_compare_3way(a, b, type) >= 0;
687
688 case RELOP_SET_LT:
689 return b->n > a->n && ovsdb_datum_includes_all(a, b, type);
690 case RELOP_SET_GT:
691 return a->n > b->n && ovsdb_datum_includes_all(b, a, type);
692 case RELOP_SET_LE:
693 return ovsdb_datum_includes_all(a, b, type);
694 case RELOP_SET_GE:
695 return ovsdb_datum_includes_all(b, a, type);
696
697 default:
698 OVS_NOT_REACHED();
699 }
700}
701
702static bool
3f5b5f7b 703is_condition_satisfied(const struct ovsdb_idl_table_class *table,
07ff77cc
AW
704 const struct ovsdb_idl_row *row, const char *arg,
705 struct ovsdb_symbol_table *symtab)
706{
707 static const char *operators[] = {
708#define RELOP(ENUM, STRING) STRING,
709 RELOPS
710#undef RELOP
711 };
712
713 const struct ovsdb_idl_column *column;
714 const struct ovsdb_datum *have_datum;
715 char *key_string, *value_string;
716 struct ovsdb_type type;
717 int operator;
718 bool retval;
719 char *error;
720
721 error = parse_column_key_value(arg, table, &column, &key_string,
722 &operator, operators, ARRAY_SIZE(operators),
723 &value_string);
724 die_if_error(error);
725 if (!value_string) {
726 ctl_fatal("%s: missing value", arg);
727 }
728
729 type = column->type;
730 type.n_max = UINT_MAX;
731
732 have_datum = ovsdb_idl_read(row, column);
733 if (key_string) {
734 union ovsdb_atom want_key;
735 struct ovsdb_datum b;
736 unsigned int idx;
737
738 if (column->type.value.type == OVSDB_TYPE_VOID) {
739 ctl_fatal("cannot specify key to check for non-map column %s",
740 column->name);
741 }
742
1ab39058 743 die_if_error(ovsdb_atom_from_string(&want_key, NULL, &column->type.key,
07ff77cc
AW
744 key_string, symtab));
745
746 type.key = type.value;
747 type.value.type = OVSDB_TYPE_VOID;
748 die_if_error(ovsdb_datum_from_string(&b, &type, value_string, symtab));
749
750 idx = ovsdb_datum_find_key(have_datum,
751 &want_key, column->type.key.type);
752 if (idx == UINT_MAX && !is_set_operator(operator)) {
753 retval = false;
754 } else {
755 struct ovsdb_datum a;
756
757 if (idx != UINT_MAX) {
758 a.n = 1;
759 a.keys = &have_datum->values[idx];
760 a.values = NULL;
761 } else {
762 a.n = 0;
763 a.keys = NULL;
764 a.values = NULL;
765 }
766
767 retval = evaluate_relop(&a, &b, &type, operator);
768 }
769
770 ovsdb_atom_destroy(&want_key, column->type.key.type);
771 ovsdb_datum_destroy(&b, &type);
772 } else {
773 struct ovsdb_datum want_datum;
774
775 die_if_error(ovsdb_datum_from_string(&want_datum, &column->type,
776 value_string, symtab));
777 retval = evaluate_relop(have_datum, &want_datum, &type, operator);
778 ovsdb_datum_destroy(&want_datum, &column->type);
779 }
780
781 free(key_string);
782 free(value_string);
783
784 return retval;
785}
786
787static void
788invalidate_cache(struct ctl_context *ctx)
789{
790 if (ctx->invalidate_cache) {
791 (ctx->invalidate_cache)(ctx);
792 }
793}
794\f
795static void
796pre_cmd_get(struct ctl_context *ctx)
797{
798 const char *id = shash_find_data(&ctx->options, "--id");
799 const char *table_name = ctx->argv[1];
3f5b5f7b 800 const struct ovsdb_idl_table_class *table;
07ff77cc
AW
801 int i;
802
803 /* Using "get" without --id or a column name could possibly make sense.
804 * Maybe, for example, a *ctl command run wants to assert that a row
805 * exists. But it is unlikely that an interactive user would want to do
806 * that, so issue a warning if we're running on a terminal. */
807 if (!id && ctx->argc <= 3 && isatty(STDOUT_FILENO)) {
808 VLOG_WARN("\"get\" command without row arguments or \"--id\" is "
809 "possibly erroneous");
810 }
811
812 table = pre_get_table(ctx, table_name);
813 for (i = 3; i < ctx->argc; i++) {
814 if (!strcasecmp(ctx->argv[i], "_uuid")
815 || !strcasecmp(ctx->argv[i], "-uuid")) {
816 continue;
817 }
818
819 pre_parse_column_key_value(ctx, ctx->argv[i], table);
820 }
821}
822
823static void
824cmd_get(struct ctl_context *ctx)
825{
826 const char *id = shash_find_data(&ctx->options, "--id");
827 bool must_exist = !shash_find(&ctx->options, "--if-exists");
828 const char *table_name = ctx->argv[1];
829 const char *record_id = ctx->argv[2];
3f5b5f7b 830 const struct ovsdb_idl_table_class *table;
07ff77cc
AW
831 const struct ovsdb_idl_row *row;
832 struct ds *out = &ctx->output;
833 int i;
834
835 if (id && !must_exist) {
836 ctl_fatal("--if-exists and --id may not be specified together");
837 }
838
839 table = get_table(table_name);
bed7aef9 840 row = ctl_get_row(ctx, table, record_id, must_exist);
07ff77cc
AW
841 if (!row) {
842 return;
843 }
844
845 if (id) {
846 struct ovsdb_symbol *symbol;
847 bool new;
848
849 symbol = create_symbol(ctx->symtab, id, &new);
850 if (!new) {
851 ctl_fatal("row id \"%s\" specified on \"get\" command was used "
852 "before it was defined", id);
853 }
854 symbol->uuid = row->uuid;
855
856 /* This symbol refers to a row that already exists, so disable warnings
857 * about it being unreferenced. */
858 symbol->strong_ref = true;
859 }
860 for (i = 3; i < ctx->argc; i++) {
861 const struct ovsdb_idl_column *column;
862 const struct ovsdb_datum *datum;
863 char *key_string;
864
865 /* Special case for obtaining the UUID of a row. We can't just do this
866 * through parse_column_key_value() below since it returns a "struct
867 * ovsdb_idl_column" and the UUID column doesn't have one. */
868 if (!strcasecmp(ctx->argv[i], "_uuid")
869 || !strcasecmp(ctx->argv[i], "-uuid")) {
870 ds_put_format(out, UUID_FMT"\n", UUID_ARGS(&row->uuid));
871 continue;
872 }
873
874 die_if_error(parse_column_key_value(ctx->argv[i], table,
875 &column, &key_string,
876 NULL, NULL, 0, NULL));
877
878 ovsdb_idl_txn_verify(row, column);
879 datum = ovsdb_idl_read(row, column);
880 if (key_string) {
881 union ovsdb_atom key;
882 unsigned int idx;
883
884 if (column->type.value.type == OVSDB_TYPE_VOID) {
885 ctl_fatal("cannot specify key to get for non-map column %s",
886 column->name);
887 }
888
1ab39058 889 die_if_error(ovsdb_atom_from_string(&key, NULL,
07ff77cc
AW
890 &column->type.key,
891 key_string, ctx->symtab));
892
893 idx = ovsdb_datum_find_key(datum, &key,
894 column->type.key.type);
895 if (idx == UINT_MAX) {
896 if (must_exist) {
897 ctl_fatal("no key \"%s\" in %s record \"%s\" column %s",
3f5b5f7b 898 key_string, table->name, record_id,
07ff77cc
AW
899 column->name);
900 }
901 } else {
902 ovsdb_atom_to_string(&datum->values[idx],
903 column->type.value.type, out);
904 }
905 ovsdb_atom_destroy(&key, column->type.key.type);
906 } else {
907 ovsdb_datum_to_string(datum, &column->type, out);
908 }
909 ds_put_char(out, '\n');
910
911 free(key_string);
912 }
913}
914
915static void
916parse_column_names(const char *column_names,
3f5b5f7b 917 const struct ovsdb_idl_table_class *table,
07ff77cc
AW
918 const struct ovsdb_idl_column ***columnsp,
919 size_t *n_columnsp)
920{
921 const struct ovsdb_idl_column **columns;
922 size_t n_columns;
923
924 if (!column_names) {
925 size_t i;
926
3f5b5f7b 927 n_columns = table->n_columns + 1;
07ff77cc
AW
928 columns = xmalloc(n_columns * sizeof *columns);
929 columns[0] = NULL;
3f5b5f7b
BP
930 for (i = 0; i < table->n_columns; i++) {
931 columns[i + 1] = &table->columns[i];
07ff77cc
AW
932 }
933 } else {
934 char *s = xstrdup(column_names);
935 size_t allocated_columns;
936 char *save_ptr = NULL;
937 char *column_name;
938
939 columns = NULL;
940 allocated_columns = n_columns = 0;
941 for (column_name = strtok_r(s, ", ", &save_ptr); column_name;
942 column_name = strtok_r(NULL, ", ", &save_ptr)) {
943 const struct ovsdb_idl_column *column;
944
945 if (!strcasecmp(column_name, "_uuid")) {
946 column = NULL;
947 } else {
948 die_if_error(get_column(table, column_name, &column));
949 }
950 if (n_columns >= allocated_columns) {
951 columns = x2nrealloc(columns, &allocated_columns,
952 sizeof *columns);
953 }
954 columns[n_columns++] = column;
955 }
956 free(s);
957
958 if (!n_columns) {
959 ctl_fatal("must specify at least one column name");
960 }
961 }
962 *columnsp = columns;
963 *n_columnsp = n_columns;
964}
965
966static void
967pre_list_columns(struct ctl_context *ctx,
3f5b5f7b 968 const struct ovsdb_idl_table_class *table,
07ff77cc
AW
969 const char *column_names)
970{
971 const struct ovsdb_idl_column **columns;
972 size_t n_columns;
973 size_t i;
974
975 parse_column_names(column_names, table, &columns, &n_columns);
976 for (i = 0; i < n_columns; i++) {
977 if (columns[i]) {
978 ovsdb_idl_add_column(ctx->idl, columns[i]);
979 }
980 }
981 free(columns);
982}
983
984static void
985pre_cmd_list(struct ctl_context *ctx)
986{
987 const char *column_names = shash_find_data(&ctx->options, "--columns");
988 const char *table_name = ctx->argv[1];
3f5b5f7b 989 const struct ovsdb_idl_table_class *table;
07ff77cc
AW
990
991 table = pre_get_table(ctx, table_name);
992 pre_list_columns(ctx, table, column_names);
993}
994
995static struct table *
996list_make_table(const struct ovsdb_idl_column **columns, size_t n_columns)
997{
998 struct table *out;
999 size_t i;
1000
1001 out = xmalloc(sizeof *out);
1002 table_init(out);
1003
1004 for (i = 0; i < n_columns; i++) {
1005 const struct ovsdb_idl_column *column = columns[i];
1006 const char *column_name = column ? column->name : "_uuid";
1007
1008 table_add_column(out, "%s", column_name);
1009 }
1010
1011 return out;
1012}
1013
1014static void
1015list_record(const struct ovsdb_idl_row *row,
1016 const struct ovsdb_idl_column **columns, size_t n_columns,
1017 struct table *out)
1018{
1019 size_t i;
1020
1021 if (!row) {
1022 return;
1023 }
1024
1025 table_add_row(out);
1026 for (i = 0; i < n_columns; i++) {
1027 const struct ovsdb_idl_column *column = columns[i];
1028 struct cell *cell = table_add_cell(out);
1029
1030 if (!column) {
1031 struct ovsdb_datum datum;
1032 union ovsdb_atom atom;
1033
1034 atom.uuid = row->uuid;
1035
1036 datum.keys = &atom;
1037 datum.values = NULL;
1038 datum.n = 1;
1039
1040 cell->json = ovsdb_datum_to_json(&datum, &ovsdb_type_uuid);
1041 cell->type = &ovsdb_type_uuid;
1042 } else {
1043 const struct ovsdb_datum *datum = ovsdb_idl_read(row, column);
1044
1045 cell->json = ovsdb_datum_to_json(datum, &column->type);
1046 cell->type = &column->type;
1047 }
1048 }
1049}
1050
1051static void
1052cmd_list(struct ctl_context *ctx)
1053{
1054 const char *column_names = shash_find_data(&ctx->options, "--columns");
1055 bool must_exist = !shash_find(&ctx->options, "--if-exists");
1056 const struct ovsdb_idl_column **columns;
1057 const char *table_name = ctx->argv[1];
3f5b5f7b 1058 const struct ovsdb_idl_table_class *table;
07ff77cc
AW
1059 struct table *out;
1060 size_t n_columns;
1061 int i;
1062
1063 table = get_table(table_name);
1064 parse_column_names(column_names, table, &columns, &n_columns);
1065 out = ctx->table = list_make_table(columns, n_columns);
1066 if (ctx->argc > 2) {
1067 for (i = 2; i < ctx->argc; i++) {
bed7aef9 1068 list_record(ctl_get_row(ctx, table, ctx->argv[i], must_exist),
07ff77cc
AW
1069 columns, n_columns, out);
1070 }
1071 } else {
1072 const struct ovsdb_idl_row *row;
1073
3f5b5f7b 1074 for (row = ovsdb_idl_first_row(ctx->idl, table); row != NULL;
07ff77cc
AW
1075 row = ovsdb_idl_next_row(row)) {
1076 list_record(row, columns, n_columns, out);
1077 }
1078 }
1079 free(columns);
1080}
1081
3f5b5f7b
BP
1082/* Finds and returns the "struct ovsdb_idl_table_class *" with 'table_name' by
1083 * searching the tables in these schema. */
1084static const struct ovsdb_idl_table_class *
be697302
AZ
1085get_table(const char *table_name)
1086{
3f5b5f7b 1087 const struct ovsdb_idl_table_class *best_match = NULL;
be697302
AZ
1088 unsigned int best_score = 0;
1089
3f5b5f7b
BP
1090 for (const struct ovsdb_idl_table_class *table = idl_classes;
1091 table < &idl_classes[n_classes]; table++) {
1092 unsigned int score = score_partial_match(table->name, table_name);
be697302
AZ
1093 if (score > best_score) {
1094 best_match = table;
1095 best_score = score;
1096 } else if (score == best_score) {
1097 best_match = NULL;
1098 }
1099 }
1100 if (best_match) {
1101 return best_match;
1102 } else if (best_score) {
1103 ctl_fatal("multiple table names match \"%s\"", table_name);
1104 } else {
1105 ctl_fatal("unknown table \"%s\"", table_name);
1106 }
1107 return NULL;
1108}
1109
07ff77cc
AW
1110static void
1111pre_cmd_find(struct ctl_context *ctx)
1112{
1113 const char *column_names = shash_find_data(&ctx->options, "--columns");
1114 const char *table_name = ctx->argv[1];
3f5b5f7b 1115 const struct ovsdb_idl_table_class *table;
07ff77cc
AW
1116 int i;
1117
1118 table = pre_get_table(ctx, table_name);
1119 pre_list_columns(ctx, table, column_names);
1120 for (i = 2; i < ctx->argc; i++) {
1121 pre_parse_column_key_value(ctx, ctx->argv[i], table);
1122 }
1123}
1124
1125static void
1126cmd_find(struct ctl_context *ctx)
1127{
1128 const char *column_names = shash_find_data(&ctx->options, "--columns");
1129 const struct ovsdb_idl_column **columns;
1130 const char *table_name = ctx->argv[1];
3f5b5f7b 1131 const struct ovsdb_idl_table_class *table;
07ff77cc
AW
1132 const struct ovsdb_idl_row *row;
1133 struct table *out;
1134 size_t n_columns;
1135
1136 table = get_table(table_name);
1137 parse_column_names(column_names, table, &columns, &n_columns);
1138 out = ctx->table = list_make_table(columns, n_columns);
3f5b5f7b 1139 for (row = ovsdb_idl_first_row(ctx->idl, table); row;
07ff77cc
AW
1140 row = ovsdb_idl_next_row(row)) {
1141 int i;
1142
1143 for (i = 2; i < ctx->argc; i++) {
1144 if (!is_condition_satisfied(table, row, ctx->argv[i],
1145 ctx->symtab)) {
1146 goto next_row;
1147 }
1148 }
1149 list_record(row, columns, n_columns, out);
1150
1151 next_row: ;
1152 }
1153 free(columns);
1154}
1155
be697302
AZ
1156/* Sets the column of 'row' in 'table'. */
1157static void
3f5b5f7b 1158set_column(const struct ovsdb_idl_table_class *table,
be697302
AZ
1159 const struct ovsdb_idl_row *row, const char *arg,
1160 struct ovsdb_symbol_table *symtab)
1161{
1162 const struct ovsdb_idl_column *column;
1163 char *key_string, *value_string;
1164 char *error;
1165
1166 error = parse_column_key_value(arg, table, &column, &key_string,
1167 NULL, NULL, 0, &value_string);
1168 die_if_error(error);
1169 if (!value_string) {
1170 ctl_fatal("%s: missing value", arg);
1171 }
1172 check_mutable(row, column);
1173
1174 if (key_string) {
1175 union ovsdb_atom key, value;
1176 struct ovsdb_datum datum;
1177
1178 if (column->type.value.type == OVSDB_TYPE_VOID) {
1179 ctl_fatal("cannot specify key to set for non-map column %s",
1180 column->name);
1181 }
1182
1ab39058 1183 die_if_error(ovsdb_atom_from_string(&key, NULL, &column->type.key,
be697302 1184 key_string, symtab));
1ab39058 1185 die_if_error(ovsdb_atom_from_string(&value, NULL, &column->type.value,
be697302
AZ
1186 value_string, symtab));
1187
1188 ovsdb_datum_init_empty(&datum);
1ab39058 1189 ovsdb_datum_add_unsafe(&datum, &key, &value, &column->type, NULL);
be697302
AZ
1190
1191 ovsdb_atom_destroy(&key, column->type.key.type);
1192 ovsdb_atom_destroy(&value, column->type.value.type);
1193
1194 ovsdb_datum_union(&datum, ovsdb_idl_read(row, column),
1195 &column->type, false);
1196 ovsdb_idl_txn_verify(row, column);
1197 ovsdb_idl_txn_write(row, column, &datum);
1198 } else {
1199 struct ovsdb_datum datum;
1200
1201 die_if_error(ovsdb_datum_from_string(&datum, &column->type,
1202 value_string, symtab));
1203 ovsdb_idl_txn_write(row, column, &datum);
1204 }
1205
1206 free(key_string);
1207 free(value_string);
1208}
1209
07ff77cc
AW
1210static void
1211pre_cmd_set(struct ctl_context *ctx)
1212{
1213 const char *table_name = ctx->argv[1];
3f5b5f7b 1214 const struct ovsdb_idl_table_class *table;
07ff77cc
AW
1215 int i;
1216
1217 table = pre_get_table(ctx, table_name);
1218 for (i = 3; i < ctx->argc; i++) {
1219 pre_parse_column_key_value(ctx, ctx->argv[i], table);
1220 }
1221}
1222
1223static void
1224cmd_set(struct ctl_context *ctx)
1225{
1226 bool must_exist = !shash_find(&ctx->options, "--if-exists");
1227 const char *table_name = ctx->argv[1];
1228 const char *record_id = ctx->argv[2];
3f5b5f7b 1229 const struct ovsdb_idl_table_class *table;
07ff77cc
AW
1230 const struct ovsdb_idl_row *row;
1231 int i;
1232
1233 table = get_table(table_name);
bed7aef9 1234 row = ctl_get_row(ctx, table, record_id, must_exist);
07ff77cc
AW
1235 if (!row) {
1236 return;
1237 }
1238
1239 for (i = 3; i < ctx->argc; i++) {
1240 set_column(table, row, ctx->argv[i], ctx->symtab);
1241 }
1242
1243 invalidate_cache(ctx);
1244}
1245
1246static void
1247pre_cmd_add(struct ctl_context *ctx)
1248{
1249 const char *table_name = ctx->argv[1];
1250 const char *column_name = ctx->argv[3];
3f5b5f7b 1251 const struct ovsdb_idl_table_class *table;
07ff77cc
AW
1252 const struct ovsdb_idl_column *column;
1253
1254 table = pre_get_table(ctx, table_name);
1255 pre_get_column(ctx, table, column_name, &column);
1256}
1257
1258static void
1259cmd_add(struct ctl_context *ctx)
1260{
1261 bool must_exist = !shash_find(&ctx->options, "--if-exists");
1262 const char *table_name = ctx->argv[1];
1263 const char *record_id = ctx->argv[2];
1264 const char *column_name = ctx->argv[3];
3f5b5f7b 1265 const struct ovsdb_idl_table_class *table;
07ff77cc
AW
1266 const struct ovsdb_idl_column *column;
1267 const struct ovsdb_idl_row *row;
1268 const struct ovsdb_type *type;
1269 struct ovsdb_datum old;
1270 int i;
1271
1272 table = get_table(table_name);
1273 die_if_error(get_column(table, column_name, &column));
bed7aef9 1274 row = ctl_get_row(ctx, table, record_id, must_exist);
07ff77cc
AW
1275 if (!row) {
1276 return;
1277 }
1278 check_mutable(row, column);
1279
1280 type = &column->type;
1281 ovsdb_datum_clone(&old, ovsdb_idl_read(row, column), &column->type);
1282 for (i = 4; i < ctx->argc; i++) {
1283 struct ovsdb_type add_type;
1284 struct ovsdb_datum add;
1285
1286 add_type = *type;
1287 add_type.n_min = 1;
1288 add_type.n_max = UINT_MAX;
1289 die_if_error(ovsdb_datum_from_string(&add, &add_type, ctx->argv[i],
1290 ctx->symtab));
1291 ovsdb_datum_union(&old, &add, type, false);
1292 ovsdb_datum_destroy(&add, type);
1293 }
1294 if (old.n > type->n_max) {
1295 ctl_fatal("\"add\" operation would put %u %s in column %s of "
1296 "table %s but the maximum number is %u",
1297 old.n,
1298 type->value.type == OVSDB_TYPE_VOID ? "values" : "pairs",
3f5b5f7b 1299 column->name, table->name, type->n_max);
07ff77cc
AW
1300 }
1301 ovsdb_idl_txn_verify(row, column);
1302 ovsdb_idl_txn_write(row, column, &old);
1303
1304 invalidate_cache(ctx);
1305}
1306
1307static void
1308pre_cmd_remove(struct ctl_context *ctx)
1309{
1310 const char *table_name = ctx->argv[1];
1311 const char *column_name = ctx->argv[3];
3f5b5f7b 1312 const struct ovsdb_idl_table_class *table;
07ff77cc
AW
1313 const struct ovsdb_idl_column *column;
1314
1315 table = pre_get_table(ctx, table_name);
1316 pre_get_column(ctx, table, column_name, &column);
1317}
1318
1319static void
1320cmd_remove(struct ctl_context *ctx)
1321{
1322 bool must_exist = !shash_find(&ctx->options, "--if-exists");
1323 const char *table_name = ctx->argv[1];
1324 const char *record_id = ctx->argv[2];
1325 const char *column_name = ctx->argv[3];
3f5b5f7b 1326 const struct ovsdb_idl_table_class *table;
07ff77cc
AW
1327 const struct ovsdb_idl_column *column;
1328 const struct ovsdb_idl_row *row;
1329 const struct ovsdb_type *type;
1330 struct ovsdb_datum old;
1331 int i;
1332
1333 table = get_table(table_name);
1334 die_if_error(get_column(table, column_name, &column));
bed7aef9 1335 row = ctl_get_row(ctx, table, record_id, must_exist);
07ff77cc
AW
1336 if (!row) {
1337 return;
1338 }
1339 check_mutable(row, column);
1340
1341 type = &column->type;
1342 ovsdb_datum_clone(&old, ovsdb_idl_read(row, column), &column->type);
1343 for (i = 4; i < ctx->argc; i++) {
1344 struct ovsdb_type rm_type;
1345 struct ovsdb_datum rm;
1346 char *error;
1347
1348 rm_type = *type;
1349 rm_type.n_min = 1;
1350 rm_type.n_max = UINT_MAX;
1351 error = ovsdb_datum_from_string(&rm, &rm_type,
1352 ctx->argv[i], ctx->symtab);
1353
1354 if (error) {
1355 if (ovsdb_type_is_map(&rm_type)) {
1356 rm_type.value.type = OVSDB_TYPE_VOID;
1357 free(error);
1358 die_if_error(ovsdb_datum_from_string(
1359 &rm, &rm_type, ctx->argv[i], ctx->symtab));
1360 } else {
1361 ctl_fatal("%s", error);
1362 }
1363 }
1364 ovsdb_datum_subtract(&old, type, &rm, &rm_type);
1365 ovsdb_datum_destroy(&rm, &rm_type);
1366 }
1367 if (old.n < type->n_min) {
1368 ctl_fatal("\"remove\" operation would put %u %s in column %s of "
1369 "table %s but the minimum number is %u",
1370 old.n,
1371 type->value.type == OVSDB_TYPE_VOID ? "values" : "pairs",
3f5b5f7b 1372 column->name, table->name, type->n_min);
07ff77cc
AW
1373 }
1374 ovsdb_idl_txn_verify(row, column);
1375 ovsdb_idl_txn_write(row, column, &old);
1376
1377 invalidate_cache(ctx);
1378}
1379
1380static void
1381pre_cmd_clear(struct ctl_context *ctx)
1382{
1383 const char *table_name = ctx->argv[1];
3f5b5f7b 1384 const struct ovsdb_idl_table_class *table;
07ff77cc
AW
1385 int i;
1386
1387 table = pre_get_table(ctx, table_name);
1388 for (i = 3; i < ctx->argc; i++) {
1389 const struct ovsdb_idl_column *column;
1390
1391 pre_get_column(ctx, table, ctx->argv[i], &column);
1392 }
1393}
1394
1395static void
1396cmd_clear(struct ctl_context *ctx)
1397{
1398 bool must_exist = !shash_find(&ctx->options, "--if-exists");
1399 const char *table_name = ctx->argv[1];
1400 const char *record_id = ctx->argv[2];
3f5b5f7b 1401 const struct ovsdb_idl_table_class *table;
07ff77cc
AW
1402 const struct ovsdb_idl_row *row;
1403 int i;
1404
1405 table = get_table(table_name);
bed7aef9 1406 row = ctl_get_row(ctx, table, record_id, must_exist);
07ff77cc
AW
1407 if (!row) {
1408 return;
1409 }
1410
1411 for (i = 3; i < ctx->argc; i++) {
1412 const struct ovsdb_idl_column *column;
1413 const struct ovsdb_type *type;
1414 struct ovsdb_datum datum;
1415
1416 die_if_error(get_column(table, ctx->argv[i], &column));
1417 check_mutable(row, column);
1418
1419 type = &column->type;
1420 if (type->n_min > 0) {
1421 ctl_fatal("\"clear\" operation cannot be applied to column %s "
1422 "of table %s, which is not allowed to be empty",
3f5b5f7b 1423 column->name, table->name);
07ff77cc
AW
1424 }
1425
1426 ovsdb_datum_init_empty(&datum);
1427 ovsdb_idl_txn_write(row, column, &datum);
1428 }
1429
1430 invalidate_cache(ctx);
1431}
1432
1433static void
1434pre_create(struct ctl_context *ctx)
1435{
1436 const char *id = shash_find_data(&ctx->options, "--id");
1437 const char *table_name = ctx->argv[1];
3f5b5f7b 1438 const struct ovsdb_idl_table_class *table;
07ff77cc
AW
1439
1440 table = get_table(table_name);
3f5b5f7b 1441 if (!id && !table->is_root) {
07ff77cc 1442 VLOG_WARN("applying \"create\" command to table %s without --id "
3f5b5f7b 1443 "option will have no effect", table->name);
07ff77cc
AW
1444 }
1445}
1446
1447static void
1448cmd_create(struct ctl_context *ctx)
1449{
1450 const char *id = shash_find_data(&ctx->options, "--id");
1451 const char *table_name = ctx->argv[1];
3f5b5f7b 1452 const struct ovsdb_idl_table_class *table = get_table(table_name);
07ff77cc
AW
1453 const struct ovsdb_idl_row *row;
1454 const struct uuid *uuid;
1455 int i;
1456
1457 if (id) {
1458 struct ovsdb_symbol *symbol = create_symbol(ctx->symtab, id, NULL);
3f5b5f7b 1459 if (table->is_root) {
07ff77cc
AW
1460 /* This table is in the root set, meaning that rows created in it
1461 * won't disappear even if they are unreferenced, so disable
1462 * warnings about that by pretending that there is a reference. */
1463 symbol->strong_ref = true;
1464 }
1465 uuid = &symbol->uuid;
1466 } else {
1467 uuid = NULL;
1468 }
1469
3f5b5f7b 1470 row = ovsdb_idl_txn_insert(ctx->txn, table, uuid);
07ff77cc
AW
1471 for (i = 2; i < ctx->argc; i++) {
1472 set_column(table, row, ctx->argv[i], ctx->symtab);
1473 }
1474 ds_put_format(&ctx->output, UUID_FMT, UUID_ARGS(&row->uuid));
1475}
1476
1477/* This function may be used as the 'postprocess' function for commands that
1478 * insert new rows into the database. It expects that the command's 'run'
1479 * function prints the UUID reported by ovsdb_idl_txn_insert() as the command's
1480 * sole output. It replaces that output by the row's permanent UUID assigned
1481 * by the database server and appends a new-line.
1482 *
1483 * Currently we use this only for "create", because the higher-level commands
1484 * are supposed to be independent of the actual structure of the vswitch
1485 * configuration. */
1486static void
1487post_create(struct ctl_context *ctx)
1488{
1489 const struct uuid *real;
1490 struct uuid dummy;
1491
1492 if (!uuid_from_string(&dummy, ds_cstr(&ctx->output))) {
1493 OVS_NOT_REACHED();
1494 }
1495 real = ovsdb_idl_txn_get_insert_uuid(ctx->txn, &dummy);
1496 if (real) {
1497 ds_clear(&ctx->output);
1498 ds_put_format(&ctx->output, UUID_FMT, UUID_ARGS(real));
1499 }
1500 ds_put_char(&ctx->output, '\n');
1501}
1502
1503static void
1504pre_cmd_destroy(struct ctl_context *ctx)
1505{
1506 const char *table_name = ctx->argv[1];
1507
1508 pre_get_table(ctx, table_name);
1509}
1510
1511static void
1512cmd_destroy(struct ctl_context *ctx)
1513{
1514 bool must_exist = !shash_find(&ctx->options, "--if-exists");
1515 bool delete_all = shash_find(&ctx->options, "--all");
1516 const char *table_name = ctx->argv[1];
3f5b5f7b 1517 const struct ovsdb_idl_table_class *table;
07ff77cc
AW
1518 int i;
1519
1520 table = get_table(table_name);
1521
1522 if (delete_all && ctx->argc > 2) {
1523 ctl_fatal("--all and records argument should not be specified together");
1524 }
1525
1526 if (delete_all && !must_exist) {
1527 ctl_fatal("--all and --if-exists should not be specified together");
1528 }
1529
1530 if (delete_all) {
1531 const struct ovsdb_idl_row *row;
1532 const struct ovsdb_idl_row *next_row;
1533
3f5b5f7b 1534 for (row = ovsdb_idl_first_row(ctx->idl, table);
07ff77cc
AW
1535 row;) {
1536 next_row = ovsdb_idl_next_row(row);
1537 ovsdb_idl_txn_delete(row);
1538 row = next_row;
1539 }
1540 } else {
1541 for (i = 2; i < ctx->argc; i++) {
1542 const struct ovsdb_idl_row *row;
1543
bed7aef9 1544 row = ctl_get_row(ctx, table, ctx->argv[i], must_exist);
07ff77cc
AW
1545 if (row) {
1546 ovsdb_idl_txn_delete(row);
1547 }
1548 }
1549 }
1550 invalidate_cache(ctx);
1551}
1552
1553static void
1554pre_cmd_wait_until(struct ctl_context *ctx)
1555{
1556 const char *table_name = ctx->argv[1];
3f5b5f7b 1557 const struct ovsdb_idl_table_class *table;
07ff77cc
AW
1558 int i;
1559
1560 table = pre_get_table(ctx, table_name);
1561
1562 for (i = 3; i < ctx->argc; i++) {
1563 pre_parse_column_key_value(ctx, ctx->argv[i], table);
1564 }
1565}
1566
1567static void
1568cmd_wait_until(struct ctl_context *ctx)
1569{
1570 const char *table_name = ctx->argv[1];
1571 const char *record_id = ctx->argv[2];
3f5b5f7b 1572 const struct ovsdb_idl_table_class *table;
07ff77cc
AW
1573 const struct ovsdb_idl_row *row;
1574 int i;
1575
1576 table = get_table(table_name);
1577
bed7aef9 1578 row = ctl_get_row(ctx, table, record_id, false);
07ff77cc
AW
1579 if (!row) {
1580 ctx->try_again = true;
1581 return;
1582 }
1583
1584 for (i = 3; i < ctx->argc; i++) {
1585 if (!is_condition_satisfied(table, row, ctx->argv[i], ctx->symtab)) {
1586 ctx->try_again = true;
1587 return;
1588 }
1589 }
1590}
1591
1592/* Parses one command. */
1593static void
1594parse_command(int argc, char *argv[], struct shash *local_options,
1595 struct ctl_command *command)
1596{
1597 const struct ctl_command_syntax *p;
1598 struct shash_node *node;
1599 int n_arg;
1600 int i;
1601
1602 shash_init(&command->options);
1603 shash_swap(local_options, &command->options);
1604 for (i = 0; i < argc; i++) {
1605 const char *option = argv[i];
1606 const char *equals;
1607 char *key, *value;
1608
1609 if (option[0] != '-') {
1610 break;
1611 }
1612
1613 equals = strchr(option, '=');
1614 if (equals) {
1615 key = xmemdup0(option, equals - option);
1616 value = xstrdup(equals + 1);
1617 } else {
1618 key = xstrdup(option);
1619 value = NULL;
1620 }
1621
1622 if (shash_find(&command->options, key)) {
1623 ctl_fatal("'%s' option specified multiple times", argv[i]);
1624 }
1625 shash_add_nocopy(&command->options, key, value);
1626 }
1627 if (i == argc) {
1628 ctl_fatal("missing command name (use --help for help)");
1629 }
1630
1631 p = shash_find_data(&all_commands, argv[i]);
1632 if (!p) {
1633 ctl_fatal("unknown command '%s'; use --help for help", argv[i]);
1634 }
1635
1636 SHASH_FOR_EACH (node, &command->options) {
1637 const char *s = strstr(p->options, node->name);
1638 int end = s ? s[strlen(node->name)] : EOF;
1639
c2f4c39b 1640 if (!strchr("=,? ", end)) {
07ff77cc
AW
1641 ctl_fatal("'%s' command has no '%s' option",
1642 argv[i], node->name);
1643 }
c2f4c39b 1644 if (end != '?' && (end == '=') != (node->data != NULL)) {
07ff77cc
AW
1645 if (end == '=') {
1646 ctl_fatal("missing argument to '%s' option on '%s' "
1647 "command", node->name, argv[i]);
1648 } else {
1649 ctl_fatal("'%s' option on '%s' does not accept an "
1650 "argument", node->name, argv[i]);
1651 }
1652 }
1653 }
1654
1655 n_arg = argc - i - 1;
1656 if (n_arg < p->min_args) {
1657 ctl_fatal("'%s' command requires at least %d arguments",
1658 p->name, p->min_args);
1659 } else if (n_arg > p->max_args) {
1660 int j;
1661
1662 for (j = i + 1; j < argc; j++) {
1663 if (argv[j][0] == '-') {
1664 ctl_fatal("'%s' command takes at most %d arguments "
1665 "(note that options must precede command "
1666 "names and follow a \"--\" argument)",
1667 p->name, p->max_args);
1668 }
1669 }
1670
1671 ctl_fatal("'%s' command takes at most %d arguments",
1672 p->name, p->max_args);
1673 }
1674
1675 command->syntax = p;
1676 command->argc = n_arg + 1;
1677 command->argv = &argv[i];
1678}
1679
af046a16
AW
1680static void
1681pre_cmd_show(struct ctl_context *ctx)
1682{
d33340a5 1683 const struct cmd_show_table *show;
af046a16
AW
1684
1685 for (show = cmd_show_tables; show->table; show++) {
1686 size_t i;
1687
1688 ovsdb_idl_add_table(ctx->idl, show->table);
1689 if (show->name_column) {
1690 ovsdb_idl_add_column(ctx->idl, show->name_column);
1691 }
1692 for (i = 0; i < ARRAY_SIZE(show->columns); i++) {
1693 const struct ovsdb_idl_column *column = show->columns[i];
1694 if (column) {
1695 ovsdb_idl_add_column(ctx->idl, column);
1696 }
1697 }
016e4684
AW
1698 if (show->wref_table.table) {
1699 ovsdb_idl_add_table(ctx->idl, show->wref_table.table);
1700 }
1701 if (show->wref_table.name_column) {
1702 ovsdb_idl_add_column(ctx->idl, show->wref_table.name_column);
1703 }
1704 if (show->wref_table.wref_column) {
1705 ovsdb_idl_add_column(ctx->idl, show->wref_table.wref_column);
1706 }
af046a16
AW
1707 }
1708}
1709
d33340a5 1710static const struct cmd_show_table *
af046a16
AW
1711cmd_show_find_table_by_row(const struct ovsdb_idl_row *row)
1712{
d33340a5 1713 const struct cmd_show_table *show;
af046a16
AW
1714
1715 for (show = cmd_show_tables; show->table; show++) {
1716 if (show->table == row->table->class) {
1717 return show;
1718 }
1719 }
1720 return NULL;
1721}
1722
d33340a5 1723static const struct cmd_show_table *
af046a16
AW
1724cmd_show_find_table_by_name(const char *name)
1725{
d33340a5 1726 const struct cmd_show_table *show;
af046a16
AW
1727
1728 for (show = cmd_show_tables; show->table; show++) {
1729 if (!strcmp(show->table->name, name)) {
1730 return show;
1731 }
1732 }
1733 return NULL;
1734}
1735
016e4684
AW
1736/* Prints table entries that weak reference the 'cur_row'. */
1737static void
1738cmd_show_weak_ref(struct ctl_context *ctx, const struct cmd_show_table *show,
1739 const struct ovsdb_idl_row *cur_row, int level)
1740{
1741 const struct ovsdb_idl_row *row_wref;
1742 const struct ovsdb_idl_table_class *table = show->wref_table.table;
1743 const struct ovsdb_idl_column *name_column
1744 = show->wref_table.name_column;
1745 const struct ovsdb_idl_column *wref_column
1746 = show->wref_table.wref_column;
1747
1748 if (!table || !name_column || !wref_column) {
1749 return;
1750 }
1751
1752 for (row_wref = ovsdb_idl_first_row(ctx->idl, table); row_wref;
1753 row_wref = ovsdb_idl_next_row(row_wref)) {
1754 const struct ovsdb_datum *wref_datum
1755 = ovsdb_idl_read(row_wref, wref_column);
1756 /* If weak reference refers to the 'cur_row', prints it. */
1757 if (wref_datum->n
1758 && uuid_equals(&cur_row->uuid, &wref_datum->keys[0].uuid)) {
1759 const struct ovsdb_datum *name_datum
1760 = ovsdb_idl_read(row_wref, name_column);
1761 ds_put_char_multiple(&ctx->output, ' ', (level + 1) * 4);
1762 ds_put_format(&ctx->output, "%s ", table->name);
1763 ovsdb_datum_to_string(name_datum, &name_column->type, &ctx->output);
1764 ds_put_char(&ctx->output, '\n');
1765 }
1766 }
1767}
1768
6530be3b
AZ
1769/* 'shown' records the tables that has been displayed by the current
1770 * command to avoid duplicated prints.
1771 */
af046a16
AW
1772static void
1773cmd_show_row(struct ctl_context *ctx, const struct ovsdb_idl_row *row,
6530be3b 1774 int level, struct sset *shown)
af046a16 1775{
d33340a5 1776 const struct cmd_show_table *show = cmd_show_find_table_by_row(row);
af046a16
AW
1777 size_t i;
1778
1779 ds_put_char_multiple(&ctx->output, ' ', level * 4);
1780 if (show && show->name_column) {
1781 const struct ovsdb_datum *datum;
1782
1783 ds_put_format(&ctx->output, "%s ", show->table->name);
1784 datum = ovsdb_idl_read(row, show->name_column);
1785 ovsdb_datum_to_string(datum, &show->name_column->type, &ctx->output);
1786 } else {
1787 ds_put_format(&ctx->output, UUID_FMT, UUID_ARGS(&row->uuid));
1788 }
1789 ds_put_char(&ctx->output, '\n');
1790
6530be3b 1791 if (!show || sset_find(shown, show->table->name)) {
af046a16
AW
1792 return;
1793 }
1794
6530be3b 1795 sset_add(shown, show->table->name);
af046a16
AW
1796 for (i = 0; i < ARRAY_SIZE(show->columns); i++) {
1797 const struct ovsdb_idl_column *column = show->columns[i];
1798 const struct ovsdb_datum *datum;
1799
1800 if (!column) {
1801 break;
1802 }
1803
1804 datum = ovsdb_idl_read(row, column);
1805 if (column->type.key.type == OVSDB_TYPE_UUID &&
1806 column->type.key.u.uuid.refTableName) {
d33340a5 1807 const struct cmd_show_table *ref_show;
af046a16
AW
1808 size_t j;
1809
1810 ref_show = cmd_show_find_table_by_name(
1811 column->type.key.u.uuid.refTableName);
1812 if (ref_show) {
1813 for (j = 0; j < datum->n; j++) {
1814 const struct ovsdb_idl_row *ref_row;
1815
1816 ref_row = ovsdb_idl_get_row_for_uuid(ctx->idl,
1817 ref_show->table,
1818 &datum->keys[j].uuid);
1819 if (ref_row) {
6530be3b 1820 cmd_show_row(ctx, ref_row, level + 1, shown);
af046a16
AW
1821 }
1822 }
1823 continue;
1824 }
31d2b7c0
AW
1825 } else if (ovsdb_type_is_map(&column->type) &&
1826 column->type.value.type == OVSDB_TYPE_UUID &&
1827 column->type.value.u.uuid.refTableName) {
d33340a5 1828 const struct cmd_show_table *ref_show;
31d2b7c0
AW
1829 size_t j;
1830
1831 /* Prints the key to ref'ed table name map if the ref'ed table
1832 * is also defined in 'cmd_show_tables'. */
1833 ref_show = cmd_show_find_table_by_name(
1834 column->type.value.u.uuid.refTableName);
1835 if (ref_show && ref_show->name_column) {
1836 ds_put_char_multiple(&ctx->output, ' ', (level + 1) * 4);
1837 ds_put_format(&ctx->output, "%s:\n", column->name);
1838 for (j = 0; j < datum->n; j++) {
1839 const struct ovsdb_idl_row *ref_row;
1840
1841 ref_row = ovsdb_idl_get_row_for_uuid(ctx->idl,
1842 ref_show->table,
1843 &datum->values[j].uuid);
1844
1845 ds_put_char_multiple(&ctx->output, ' ', (level + 2) * 4);
1846 ovsdb_atom_to_string(&datum->keys[j], column->type.key.type,
1847 &ctx->output);
1848 ds_put_char(&ctx->output, '=');
1849 if (ref_row) {
1850 const struct ovsdb_datum *ref_datum;
1851
1852 ref_datum = ovsdb_idl_read(ref_row,
1853 ref_show->name_column);
1854 ovsdb_datum_to_string(ref_datum,
1855 &ref_show->name_column->type,
1856 &ctx->output);
1857 } else {
1858 ds_put_cstr(&ctx->output, "\"<null>\"");
1859 }
1860 ds_put_char(&ctx->output, '\n');
1861 }
1862 continue;
1863 }
af046a16
AW
1864 }
1865
1866 if (!ovsdb_datum_is_default(datum, &column->type)) {
1867 ds_put_char_multiple(&ctx->output, ' ', (level + 1) * 4);
1868 ds_put_format(&ctx->output, "%s: ", column->name);
1869 ovsdb_datum_to_string(datum, &column->type, &ctx->output);
1870 ds_put_char(&ctx->output, '\n');
1871 }
1872 }
016e4684 1873 cmd_show_weak_ref(ctx, show, row, level);
6530be3b 1874 sset_find_and_delete_assert(shown, show->table->name);
af046a16
AW
1875}
1876
1877static void
1878cmd_show(struct ctl_context *ctx)
1879{
1880 const struct ovsdb_idl_row *row;
6530be3b 1881 struct sset shown = SSET_INITIALIZER(&shown);
af046a16
AW
1882
1883 for (row = ovsdb_idl_first_row(ctx->idl, cmd_show_tables[0].table);
1884 row; row = ovsdb_idl_next_row(row)) {
6530be3b 1885 cmd_show_row(ctx, row, 0, &shown);
af046a16 1886 }
6530be3b
AZ
1887
1888 ovs_assert(sset_is_empty(&shown));
1889 sset_destroy(&shown);
af046a16
AW
1890}
1891
07ff77cc 1892\f
51a73ff0
AW
1893/* Given pointer to dynamic array 'options_p', array's current size
1894 * 'allocated_options_p' and number of added options 'n_options_p',
1895 * adds all command options to the array. Enlarges the array if
1896 * necessary. */
1897void
1898ctl_add_cmd_options(struct option **options_p, size_t *n_options_p,
1899 size_t *allocated_options_p, int opt_val)
1900{
1901 struct option *o;
1902 const struct shash_node *node;
1903 size_t n_existing_options = *n_options_p;
1904
a35da174 1905 SHASH_FOR_EACH (node, &all_commands) {
51a73ff0
AW
1906 const struct ctl_command_syntax *p = node->data;
1907
1908 if (p->options[0]) {
1909 char *save_ptr = NULL;
1910 char *name;
1911 char *s;
1912
1913 s = xstrdup(p->options);
1914 for (name = strtok_r(s, ",", &save_ptr); name != NULL;
1915 name = strtok_r(NULL, ",", &save_ptr)) {
51a73ff0
AW
1916 ovs_assert(name[0] == '-' && name[1] == '-' && name[2]);
1917 name += 2;
1918
c2f4c39b
BP
1919 size_t n = strcspn(name, "=?");
1920 int has_arg = (name[n] == '\0' ? no_argument
1921 : name[n] == '=' ? required_argument
1922 : optional_argument);
1923 name[n] = '\0';
51a73ff0
AW
1924
1925 o = find_option(name, *options_p, *n_options_p);
1926 if (o) {
1927 ovs_assert(o - *options_p >= n_existing_options);
1928 ovs_assert(o->has_arg == has_arg);
1929 } else {
1930 o = add_option(options_p, n_options_p, allocated_options_p);
1931 o->name = xstrdup(name);
1932 o->has_arg = has_arg;
1933 o->flag = NULL;
1934 o->val = opt_val;
1935 }
1936 }
1937
1938 free(s);
1939 }
1940 }
1941 o = add_option(options_p, n_options_p, allocated_options_p);
1942 memset(o, 0, sizeof *o);
1943}
1944
07ff77cc
AW
1945/* Parses command-line input for commands. */
1946struct ctl_command *
1947ctl_parse_commands(int argc, char *argv[], struct shash *local_options,
1948 size_t *n_commandsp)
1949{
1950 struct ctl_command *commands;
1951 size_t n_commands, allocated_commands;
1952 int i, start;
1953
1954 commands = NULL;
1955 n_commands = allocated_commands = 0;
1956
1957 for (start = i = 0; i <= argc; i++) {
1958 if (i == argc || !strcmp(argv[i], "--")) {
1959 if (i > start) {
1960 if (n_commands >= allocated_commands) {
1961 struct ctl_command *c;
1962
1963 commands = x2nrealloc(commands, &allocated_commands,
1964 sizeof *commands);
1965 for (c = commands; c < &commands[n_commands]; c++) {
1966 shash_moved(&c->options);
1967 }
1968 }
1969 parse_command(i - start, &argv[start], local_options,
1970 &commands[n_commands++]);
1971 } else if (!shash_is_empty(local_options)) {
1972 ctl_fatal("missing command name (use --help for help)");
1973 }
1974 start = i + 1;
1975 }
1976 }
1977 if (!n_commands) {
1978 ctl_fatal("missing command name (use --help for help)");
1979 }
1980 *n_commandsp = n_commands;
1981 return commands;
1982}
1983
51a73ff0
AW
1984/* Prints all registered commands. */
1985void
1986ctl_print_commands(void)
1987{
1988 const struct shash_node *node;
1989
a35da174 1990 SHASH_FOR_EACH (node, &all_commands) {
51a73ff0
AW
1991 const struct ctl_command_syntax *p = node->data;
1992 char *options = xstrdup(p->options);
1993 char *options_begin = options;
1994 char *item;
1995
1996 for (item = strsep(&options, ","); item != NULL;
1997 item = strsep(&options, ",")) {
1998 if (item[0] != '\0') {
1999 printf("[%s] ", item);
2000 }
2001 }
2002 printf(",%s,", p->name);
2003 print_command_arguments(p);
2004 printf("\n");
2005
2006 free(options_begin);
2007 }
2008
2009 exit(EXIT_SUCCESS);
2010}
2011
2012/* Given array of options 'options', prints them. */
2013void
2014ctl_print_options(const struct option *options)
2015{
2016 for (; options->name; options++) {
2017 const struct option *o = options;
2018
2019 printf("--%s%s\n", o->name, o->has_arg ? "=ARG" : "");
2020 if (o->flag == NULL && o->val > 0 && o->val <= UCHAR_MAX) {
2021 printf("-%c%s\n", o->val, o->has_arg ? " ARG" : "");
2022 }
2023 }
2024
2025 exit(EXIT_SUCCESS);
2026}
2027
2028/* Returns the default local database path. */
2029char *
2030ctl_default_db(void)
2031{
2032 static char *def;
2033 if (!def) {
2034 def = xasprintf("unix:%s/db.sock", ovs_rundir());
2035 }
2036 return def;
2037}
2038
07ff77cc
AW
2039/* Returns true if it looks like this set of arguments might modify the
2040 * database, otherwise false. (Not very smart, so it's prone to false
2041 * positives.) */
2042bool
2043ctl_might_write_to_db(char **argv)
2044{
2045 for (; *argv; argv++) {
a35da174
AZ
2046 const struct ctl_command_syntax *p = shash_find_data(&all_commands,
2047 *argv);
07ff77cc
AW
2048 if (p && p->mode == RW) {
2049 return true;
2050 }
2051 }
2052 return false;
2053}
2054
2055void
2056ctl_fatal(const char *format, ...)
2057{
2058 char *message;
2059 va_list args;
2060
2061 va_start(args, format);
2062 message = xvasprintf(format, args);
2063 va_end(args);
2064
922fed06 2065 vlog_set_levels(&this_module, VLF_CONSOLE, VLL_OFF);
07ff77cc
AW
2066 VLOG_ERR("%s", message);
2067 ovs_error(0, "%s", message);
2068 ctl_exit(EXIT_FAILURE);
2069}
2070
2071/* Frees the current transaction and the underlying IDL and then calls
2072 * exit(status).
2073 *
2074 * Freeing the transaction and the IDL is not strictly necessary, but it makes
2075 * for a clean memory leak report from valgrind in the normal case. That makes
2076 * it easier to notice real memory leaks. */
bccd843b 2077static void
07ff77cc
AW
2078ctl_exit(int status)
2079{
ce6f1d1f
AZ
2080 if (ctl_exit_func) {
2081 ctl_exit_func(status);
07ff77cc 2082 }
07ff77cc
AW
2083 exit(status);
2084}
2085
2086/* Comman database commands to be registered. */
2087static const struct ctl_command_syntax db_ctl_commands[] = {
2088 {"comment", 0, INT_MAX, "[ARG]...", NULL, NULL, NULL, "", RO},
2089 {"get", 2, INT_MAX, "TABLE RECORD [COLUMN[:KEY]]...",pre_cmd_get, cmd_get,
2090 NULL, "--if-exists,--id=", RO},
2091 {"list", 1, INT_MAX, "TABLE [RECORD]...", pre_cmd_list, cmd_list, NULL,
2092 "--if-exists,--columns=", RO},
2093 {"find", 1, INT_MAX, "TABLE [COLUMN[:KEY]=VALUE]...", pre_cmd_find,
2094 cmd_find, NULL, "--columns=", RO},
2095 {"set", 3, INT_MAX, "TABLE RECORD COLUMN[:KEY]=VALUE...", pre_cmd_set,
2096 cmd_set, NULL, "--if-exists", RW},
2097 {"add", 4, INT_MAX, "TABLE RECORD COLUMN [KEY=]VALUE...", pre_cmd_add,
2098 cmd_add, NULL, "--if-exists", RW},
2099 {"remove", 4, INT_MAX, "TABLE RECORD COLUMN KEY|VALUE|KEY=VALUE...",
2100 pre_cmd_remove, cmd_remove, NULL, "--if-exists", RW},
2101 {"clear", 3, INT_MAX, "TABLE RECORD COLUMN...", pre_cmd_clear, cmd_clear,
2102 NULL, "--if-exists", RW},
2103 {"create", 2, INT_MAX, "TABLE COLUMN[:KEY]=VALUE...", pre_create,
2104 cmd_create, post_create, "--id=", RW},
2105 {"destroy", 1, INT_MAX, "TABLE [RECORD]...", pre_cmd_destroy, cmd_destroy,
2106 NULL, "--if-exists,--all", RW},
2107 {"wait-until", 2, INT_MAX, "TABLE RECORD [COLUMN[:KEY]=VALUE]...",
2108 pre_cmd_wait_until, cmd_wait_until, NULL, "", RO},
2109 {NULL, 0, 0, NULL, NULL, NULL, NULL, NULL, RO},
2110};
2111
71e8dc2a
BP
2112static void
2113ctl_register_command(const struct ctl_command_syntax *command)
2114{
2115 shash_add_assert(&all_commands, command->name, command);
2116}
2117
07ff77cc
AW
2118/* Registers commands represented by 'struct ctl_command_syntax's to
2119 * 'all_commands'. The last element of 'commands' must be an all-NULL
2120 * element. */
2121void
2122ctl_register_commands(const struct ctl_command_syntax *commands)
2123{
2124 const struct ctl_command_syntax *p;
2125
2126 for (p = commands; p->name; p++) {
71e8dc2a 2127 ctl_register_command(p);
07ff77cc
AW
2128 }
2129}
2130
2131/* Registers the 'db_ctl_commands' to 'all_commands'. */
2132void
3f5b5f7b
BP
2133ctl_init__(const struct ovsdb_idl_table_class *idl_classes_,
2134 const struct ctl_table_class *ctl_classes_,
2135 size_t n_classes_,
2136 const struct cmd_show_table cmd_show_tables_[],
2137 void (*ctl_exit_func_)(int status))
2138{
2139 idl_classes = idl_classes_;
2140 ctl_classes = ctl_classes_;
2141 n_classes = n_classes_;
ce6f1d1f 2142 ctl_exit_func = ctl_exit_func_;
07ff77cc 2143 ctl_register_commands(db_ctl_commands);
71e8dc2a
BP
2144
2145 cmd_show_tables = cmd_show_tables_;
2146 if (cmd_show_tables) {
2147 static const struct ctl_command_syntax show =
2148 {"show", 0, 0, "", pre_cmd_show, cmd_show, NULL, "", RO};
2149 ctl_register_command(&show);
2150 }
07ff77cc
AW
2151}
2152
07ff77cc
AW
2153/* Returns the text for the database commands usage. */
2154const char *
2155ctl_get_db_cmd_usage(void)
2156{
2157 return "Database commands:\n\
2158 list TBL [REC] list RECord (or all records) in TBL\n\
2159 find TBL CONDITION... list records satisfying CONDITION in TBL\n\
2160 get TBL REC COL[:KEY] print values of COLumns in RECord in TBL\n\
2161 set TBL REC COL[:KEY]=VALUE set COLumn values in RECord in TBL\n\
2162 add TBL REC COL [KEY=]VALUE add (KEY=)VALUE to COLumn in RECord in TBL\n\
2163 remove TBL REC COL [KEY=]VALUE remove (KEY=)VALUE from COLumn\n\
2164 clear TBL REC COL clear values from COLumn in RECord in TBL\n\
2165 create TBL COL[:KEY]=VALUE create and initialize new record\n\
2166 destroy TBL REC delete RECord from TBL\n\
2167 wait-until TBL REC [COL[:KEY]=VALUE] wait until condition is true\n\
2168Potentially unsafe database commands require --force option.\n";
2169}
2170
2171/* Initializes 'ctx' from 'command'. */
2172void
2173ctl_context_init_command(struct ctl_context *ctx,
2174 struct ctl_command *command)
2175{
2176 ctx->argc = command->argc;
2177 ctx->argv = command->argv;
2178 ctx->options = command->options;
2179
2180 ds_swap(&ctx->output, &command->output);
2181 ctx->table = command->table;
2182 ctx->try_again = false;
2183}
2184
2185/* Initializes the entire 'ctx'. */
2186void
2187ctl_context_init(struct ctl_context *ctx, struct ctl_command *command,
2188 struct ovsdb_idl *idl, struct ovsdb_idl_txn *txn,
2189 struct ovsdb_symbol_table *symtab,
2190 void (*invalidate_cache)(struct ctl_context *))
2191{
2192 if (command) {
2193 ctl_context_init_command(ctx, command);
2194 }
2195 ctx->idl = idl;
2196 ctx->txn = txn;
2197 ctx->symtab = symtab;
2198 ctx->invalidate_cache = invalidate_cache;
2199}
2200
2201/* Completes processing of 'command' within 'ctx'. */
2202void
2203ctl_context_done_command(struct ctl_context *ctx,
2204 struct ctl_command *command)
2205{
2206 ds_swap(&ctx->output, &command->output);
2207 command->table = ctx->table;
2208}
2209
2210/* Finishes up with 'ctx'.
2211 *
2212 * If command is nonnull, first calls ctl_context_done_command() to complete
2213 * processing that command within 'ctx'. */
2214void
2215ctl_context_done(struct ctl_context *ctx,
2216 struct ctl_command *command)
2217{
2218 if (command) {
2219 ctl_context_done_command(ctx, command);
2220 }
2221 invalidate_cache(ctx);
2222}
2223
15ffc202
AZ
2224void ctl_set_column(const char *table_name,
2225 const struct ovsdb_idl_row *row, const char *arg,
2226 struct ovsdb_symbol_table *symtab)
2227{
2228 set_column(get_table(table_name), row, arg, symtab);
2229}