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