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