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