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