2 * Copyright (c) 2015, 2016, 2017 Nicira, Inc.
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:
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
23 #include "db-ctl-base.h"
25 #include "command-line.h"
28 #include "openvswitch/dynamic-string.h"
29 #include "fatal-signal.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"
43 VLOG_DEFINE_THIS_MODULE(db_ctl_base
);
45 /* This array defines the 'show' command output format. User can check the
46 * definition in utilities/ovs-vsctl.c as reference.
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[]'.
52 * The definition must end with an all-NULL entry. It is initalized once
53 * when ctl_init() is called.
56 static const struct cmd_show_table
*cmd_show_tables
;
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()
62 static void (*ctl_exit_func
)(int status
) = NULL
;
63 OVS_NO_RETURN
static void ctl_exit(int status
);
66 static const struct ovsdb_idl_class
*idl_class
;
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
;
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
*);
81 static struct option
*
82 find_option(const char *name
, struct option
*options
, size_t n_options
)
86 for (i
= 0; i
< n_options
; i
++) {
87 if (!strcmp(options
[i
].name
, name
)) {
94 static struct option
*
95 add_option(struct option
**optionsp
, size_t *n_optionsp
,
96 size_t *allocated_optionsp
)
98 if (*n_optionsp
>= *allocated_optionsp
) {
99 *optionsp
= x2nrealloc(*optionsp
, allocated_optionsp
,
102 return &(*optionsp
)[(*n_optionsp
)++];
105 /* Converts the command arguments into format that can be parsed by
106 * bash completion script.
108 * Therein, arguments will be attached with following prefixes:
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
117 print_command_arguments(const struct ctl_command_syntax
*command
)
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.
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.
130 uint32_t oew_stack
= 0;
132 const char *arguments
= command
->arguments
;
133 int length
= strlen(arguments
);
138 /* Output buffer, written backward from end. */
139 char *output
= xmalloc(2 * length
);
140 char *outp
= output
+ 2 * length
;
143 bool in_repeated
= false;
144 bool whole_word_is_optional
= false;
146 for (const char *inp
= arguments
+ length
; inp
> arguments
; ) {
150 if (inp
[1] == '\0' || inp
[1] == ' ' || inp
[1] == '.') {
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;
162 whole_word_is_optional
= false;
167 if (!whole_word_is_optional
) {
168 *--outp
= in_repeated
? '+' : '!';
172 whole_word_is_optional
= false;
182 if (arguments
[0] != '[' && outp
!= output
+ 2 * length
- 1) {
183 *--outp
= in_repeated
? '+' : '!';
190 to_lower_and_underscores(unsigned c
)
192 return c
== '-' ? '_' : tolower(c
);
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
200 score_partial_match(const char *name
, const char *s
)
204 if (!strcmp(name
, s
)) {
207 for (score
= 0; ; score
++, name
++, s
++) {
208 if (to_lower_and_underscores(*name
) != to_lower_and_underscores(*s
)) {
210 } else if (*name
== '\0') {
214 return *s
== '\0' ? score
: 0;
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
)
223 struct ovsdb_symbol
*symbol
;
228 return xasprintf("row id \"%s\" does not begin with \"@\"", id
);
232 *newp
= ovsdb_symbol_table_get(symtab
, id
) == NULL
;
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 "
240 symbol
->created
= true;
246 record_id_equals(const union ovsdb_atom
*name
, enum ovsdb_atomic_type type
,
247 const char *record_id
)
249 if (type
== OVSDB_TYPE_STRING
) {
250 if (!strcmp(name
->string
, record_id
)) {
255 size_t len
= strlen(record_id
);
257 && uuid_from_string(&uuid
, name
->string
)
258 && !strncmp(name
->string
, record_id
, len
)) {
264 ovs_assert(type
== OVSDB_TYPE_INTEGER
);
265 return name
->integer
== strtoll(record_id
, NULL
, 10);
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
)
275 ovs_assert(multiple_matches
);
276 *multiple_matches
= false;
278 if (!id
->name_column
) {
282 const struct ovsdb_idl_row
*referrer
= NULL
;
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
;
289 name_type
= key
= id
->name_column
->type
.key
.type
;
290 value
= OVSDB_TYPE_VOID
;
292 key
= OVSDB_TYPE_STRING
;
293 name_type
= value
= id
->name_column
->type
.value
.type
;
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")]) {
302 ovs_assert(name_type
== OVSDB_TYPE_STRING
);
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
,
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
);
316 /* Extract the name from the column. */
317 const union ovsdb_atom
*name
;
319 name
= datum
->n
== 1 ? &datum
->keys
[0] : NULL
;
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
,
325 name
= i
== UINT_MAX
? NULL
: &datum
->values
[i
];
331 /* If the name equals 'record_id', take it. */
332 if (record_id_equals(name
, name_type
, record_id
)) {
334 *multiple_matches
= true;
344 const struct ovsdb_idl_row
*final
= referrer
;
345 if (id
->uuid_column
) {
346 const struct ovsdb_datum
*uuid
;
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
);
352 final
= ovsdb_idl_get_row_for_uuid(ctx
->idl
, table
,
353 &uuid
->keys
[0].uuid
);
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
)
366 const struct ovsdb_idl_row
*row
= NULL
;
371 if (uuid_from_string(&uuid
, record_id
)) {
372 row
= ovsdb_idl_get_row_for_uuid(ctx
->idl
, table
, &uuid
);
375 if (!strcmp(record_id
, ".")) {
376 row
= ovsdb_idl_first_row(ctx
->idl
, table
);
377 if (row
&& ovsdb_idl_next_row(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
;
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
);
403 if (!row
&& uuid_is_partial_string(record_id
) >= 4) {
404 for (const struct ovsdb_idl_row
*r
= ovsdb_idl_first_row(ctx
->idl
,
407 r
= ovsdb_idl_next_row(r
)) {
408 if (uuid_is_partial_match(&r
->uuid
, record_id
)) {
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
));
421 if (must_exist
&& !row
) {
422 return xasprintf("no row \"%s\" in table %s", record_id
, table
->name
);
430 get_column(const struct ovsdb_idl_table_class
*table
, const char *column_name
,
431 const struct ovsdb_idl_column
**columnp
)
433 struct sset best_matches
= SSET_INITIALIZER(&best_matches
);
434 const struct ovsdb_idl_column
*best_match
= NULL
;
435 unsigned int best_score
= 0;
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
);
444 sset_add(&best_matches
, column
->name
);
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
;
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
);
464 sset_destroy(&best_matches
);
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
)
474 char *error
= get_column(table
, column_name
, columnp
);
478 ovsdb_idl_add_column(ctx
->idl
, *columnp
);
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
)
486 const struct ovsdb_idl_table_class
*table
;
487 char *error
= get_table(table_name
, &table
);
491 ovsdb_idl_add_table(ctx
->idl
, table
);
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
);
499 if (id
->uuid_column
) {
500 ovsdb_idl_add_column(ctx
->idl
, id
->uuid_column
);
511 missing_operator_error(const char *arg
, const char **allowed_operators
,
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) {
524 for (i
= 1; i
< n_allowed
- 1; i
++) {
525 ds_put_format(&s
, ", \"%s\"", allowed_operators
[i
]);
527 ds_put_format(&s
, ", or \"%s\"", allowed_operators
[i
]);
529 ds_put_format(&s
, " followed by a value.");
531 return ds_steal_cstr(&s
);
534 /* Breaks 'arg' apart into a number of fields in the following order:
536 * - The name of a column in 'table', stored into '*columnp'. The column
537 * name may be abbreviated.
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
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'.
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
,
557 const char **allowed_operators
, size_t n_allowed
,
564 ovs_assert(!(operatorp
&& !valuep
));
570 /* Parse column name. */
571 error
= ovsdb_token_parse(&p
, &column_name
);
575 if (column_name
[0] == '\0') {
577 error
= xasprintf("%s: missing column name", arg
);
580 error
= get_column(table
, column_name
, columnp
);
586 /* Parse key string. */
589 error
= ovsdb_token_parse(&p
, keyp
);
595 /* Parse value string. */
601 if (!allowed_operators
) {
602 static const char *equals
= "=";
603 allowed_operators
= &equals
;
609 for (i
= 0; i
< n_allowed
; i
++) {
610 const char *op
= allowed_operators
[i
];
611 size_t op_len
= strlen(op
);
613 if (op_len
> best_len
&& !strncmp(op
, p
, op_len
) && p
[op_len
]) {
619 error
= missing_operator_error(arg
, allowed_operators
, n_allowed
);
626 *valuep
= xstrdup(p
+ best_len
);
629 error
= xasprintf("%s: trailing garbage \"%s\" in argument",
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
)
654 const struct ovsdb_idl_column
*column
;
656 char *column_name
= NULL
;
660 error
= ovsdb_token_parse(&p
, &column_name
);
664 if (column_name
[0] == '\0') {
665 error
= xasprintf("%s: missing column name", arg
);
669 error
= pre_get_column(ctx
, table
, column_name
, &column
);
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
)
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
);
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}")
706 #define RELOP(ENUM, STRING) ENUM,
712 is_set_operator(enum relop op
)
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
);
721 evaluate_relop(const struct ovsdb_datum
*a
, const struct ovsdb_datum
*b
,
722 const struct ovsdb_type
*type
, enum relop op
)
727 return ovsdb_datum_compare_3way(a
, b
, type
) == 0;
730 return ovsdb_datum_compare_3way(a
, b
, type
) != 0;
732 return ovsdb_datum_compare_3way(a
, b
, type
) < 0;
734 return ovsdb_datum_compare_3way(a
, b
, type
) > 0;
736 return ovsdb_datum_compare_3way(a
, b
, type
) <= 0;
738 return ovsdb_datum_compare_3way(a
, b
, type
) >= 0;
741 return b
->n
> a
->n
&& ovsdb_datum_includes_all(a
, b
, type
);
743 return a
->n
> b
->n
&& ovsdb_datum_includes_all(b
, a
, type
);
746 return ovsdb_datum_includes_all(a
, b
, type
);
748 return ovsdb_datum_includes_all(b
, a
, type
);
749 case RELOP_SET_NOT_IN
:
750 return ovsdb_datum_excludes_all(a
, b
, type
);
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
)
766 static const char *operators
[] = {
767 #define RELOP(ENUM, STRING) STRING,
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
;
781 ovs_assert(satisfied
);
783 error
= parse_column_key_value(arg
, table
, &column
, &key_string
,
784 &operator, operators
, ARRAY_SIZE(operators
),
790 error
= xasprintf("%s: missing value", arg
);
795 type
.n_max
= UINT_MAX
;
797 have_datum
= ovsdb_idl_read(row
, column
);
799 union ovsdb_atom want_key
;
800 struct ovsdb_datum b
;
803 if (column
->type
.value
.type
== OVSDB_TYPE_VOID
) {
804 error
= xasprintf("cannot specify key to check for non-map column "
809 error
= ovsdb_atom_from_string(&want_key
, NULL
, &column
->type
.key
,
815 type
.key
= type
.value
;
816 type
.value
.type
= OVSDB_TYPE_VOID
;
817 error
= ovsdb_datum_from_string(&b
, &type
, value_string
, symtab
);
822 idx
= ovsdb_datum_find_key(have_datum
,
823 &want_key
, column
->type
.key
.type
);
824 if (idx
== UINT_MAX
&& !is_set_operator(operator)) {
827 struct ovsdb_datum a
;
829 if (idx
!= UINT_MAX
) {
831 a
.keys
= &have_datum
->values
[idx
];
839 retval
= evaluate_relop(&a
, &b
, &type
, operator);
842 ovsdb_atom_destroy(&want_key
, column
->type
.key
.type
);
843 ovsdb_datum_destroy(&b
, &type
);
845 struct ovsdb_datum want_datum
;
847 error
= ovsdb_datum_from_string(&want_datum
, &column
->type
,
848 value_string
, symtab
);
852 retval
= evaluate_relop(have_datum
, &want_datum
, &type
, operator);
853 ovsdb_datum_destroy(&want_datum
, &column
->type
);
865 invalidate_cache(struct ctl_context
*ctx
)
867 if (ctx
->invalidate_cache_cb
) {
868 (ctx
->invalidate_cache_cb
)(ctx
);
873 pre_cmd_get(struct ctl_context
*ctx
)
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
;
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");
889 ctx
->error
= pre_get_table(ctx
, table_name
, &table
);
893 for (i
= 3; i
< ctx
->argc
; i
++) {
894 if (!strcasecmp(ctx
->argv
[i
], "_uuid")
895 || !strcasecmp(ctx
->argv
[i
], "-uuid")) {
899 ctx
->error
= pre_parse_column_key_value(ctx
, ctx
->argv
[i
], table
);
907 cmd_get(struct ctl_context
*ctx
)
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
;
918 if (id
&& !must_exist
) {
919 ctl_error(ctx
, "--if-exists and --id may not be specified together");
923 ctx
->error
= get_table(table_name
, &table
);
927 ctx
->error
= ctl_get_row(ctx
, table
, record_id
, must_exist
, &row
);
936 struct ovsdb_symbol
*symbol
= NULL
;
939 ctx
->error
= create_symbol(ctx
->symtab
, id
, &symbol
, &new);
944 ctl_error(ctx
, "row id \"%s\" specified on \"get\" command was "
945 "used before it was defined", id
);
948 symbol
->uuid
= row
->uuid
;
950 /* This symbol refers to a row that already exists, so disable warnings
951 * about it being unreferenced. */
952 symbol
->strong_ref
= true;
954 for (i
= 3; i
< ctx
->argc
; i
++) {
955 const struct ovsdb_idl_column
*column
;
956 const struct ovsdb_datum
*datum
;
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
));
968 ctx
->error
= parse_column_key_value(ctx
->argv
[i
], table
, &column
,
969 &key_string
, NULL
, NULL
, 0, NULL
);
974 ovsdb_idl_txn_verify(row
, column
);
975 datum
= ovsdb_idl_read(row
, column
);
977 union ovsdb_atom key
;
980 if (column
->type
.value
.type
== OVSDB_TYPE_VOID
) {
982 "cannot specify key to get for non-map column %s",
988 ctx
->error
= ovsdb_atom_from_string(&key
, NULL
, &column
->type
.key
,
989 key_string
, ctx
->symtab
);
995 idx
= ovsdb_datum_find_key(datum
, &key
,
996 column
->type
.key
.type
);
997 if (idx
== UINT_MAX
) {
1000 ctx
, "no key \"%s\" in %s record \"%s\" column %s",
1001 key_string
, table
->name
, record_id
, column
->name
);
1003 ovsdb_atom_destroy(&key
, column
->type
.key
.type
);
1007 ovsdb_atom_to_string(&datum
->values
[idx
],
1008 column
->type
.value
.type
, out
);
1010 ovsdb_atom_destroy(&key
, column
->type
.key
.type
);
1012 ovsdb_datum_to_string(datum
, &column
->type
, out
);
1014 ds_put_char(out
, '\n');
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
,
1027 const struct ovsdb_idl_column
**columns
;
1030 if (!column_names
) {
1033 n_columns
= table
->n_columns
+ 1;
1034 columns
= xmalloc(n_columns
* sizeof *columns
);
1036 for (i
= 0; i
< table
->n_columns
; i
++) {
1037 columns
[i
+ 1] = &table
->columns
[i
];
1040 char *s
= xstrdup(column_names
);
1041 size_t allocated_columns
;
1042 char *save_ptr
= 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
;
1051 if (!strcasecmp(column_name
, "_uuid")) {
1054 char *error
= get_column(table
, column_name
, &column
);
1061 if (n_columns
>= allocated_columns
) {
1062 columns
= x2nrealloc(columns
, &allocated_columns
,
1065 columns
[n_columns
++] = column
;
1070 return xstrdup("must specify at least one column name");
1073 *columnsp
= columns
;
1074 *n_columnsp
= n_columns
;
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
)
1083 const struct ovsdb_idl_column
**columns
;
1088 error
= parse_column_names(column_names
, table
, &columns
, &n_columns
);
1092 for (i
= 0; i
< n_columns
; i
++) {
1094 ovsdb_idl_add_column(ctx
->idl
, columns
[i
]);
1102 pre_cmd_list(struct ctl_context
*ctx
)
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
;
1108 ctx
->error
= pre_get_table(ctx
, table_name
, &table
);
1112 ctx
->error
= pre_list_columns(ctx
, table
, column_names
);
1118 static struct table
*
1119 list_make_table(const struct ovsdb_idl_column
**columns
, size_t n_columns
)
1124 out
= xmalloc(sizeof *out
);
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";
1131 table_add_column(out
, "%s", column_name
);
1138 list_record(const struct ovsdb_idl_row
*row
,
1139 const struct ovsdb_idl_column
**columns
, size_t n_columns
,
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
);
1154 struct ovsdb_datum datum
;
1155 union ovsdb_atom atom
;
1157 atom
.uuid
= row
->uuid
;
1160 datum
.values
= NULL
;
1163 cell
->json
= ovsdb_datum_to_json(&datum
, &ovsdb_type_uuid
);
1164 cell
->type
= &ovsdb_type_uuid
;
1166 const struct ovsdb_datum
*datum
= ovsdb_idl_read(row
, column
);
1168 cell
->json
= ovsdb_datum_to_json(datum
, &column
->type
);
1169 cell
->type
= &column
->type
;
1175 cmd_list(struct ctl_context
*ctx
)
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
;
1186 ctx
->error
= get_table(table_name
, &table
);
1190 ctx
->error
= parse_column_names(column_names
, table
, &columns
, &n_columns
);
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
;
1199 ctx
->error
= ctl_get_row(ctx
, table
, ctx
->argv
[i
], must_exist
,
1205 list_record(row
, columns
, n_columns
, out
);
1208 const struct ovsdb_idl_row
*row
;
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
);
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
)
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;
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
);
1235 sset_add(&best_matches
, table
->name
);
1243 error
= xasprintf("unknown table \"%s\"", table_name
);
1244 } else if (sset_count(&best_matches
) == 1) {
1245 *tablep
= best_match
;
1247 char *matches
= sset_join(&best_matches
, ", ", "");
1248 error
= xasprintf("\"%s\" matches multiple table names: %s",
1249 table_name
, matches
);
1252 sset_destroy(&best_matches
);
1257 pre_cmd_find(struct ctl_context
*ctx
)
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
;
1264 ctx
->error
= pre_get_table(ctx
, table_name
, &table
);
1268 ctx
->error
= pre_list_columns(ctx
, table
, column_names
);
1272 for (i
= 2; i
< ctx
->argc
; i
++) {
1273 ctx
->error
= pre_parse_column_key_value(ctx
, ctx
->argv
[i
], table
);
1281 cmd_find(struct ctl_context
*ctx
)
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
;
1291 ctx
->error
= get_table(table_name
, &table
);
1295 ctx
->error
= parse_column_names(column_names
, table
, &columns
, &n_columns
);
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
)) {
1304 for (i
= 2; i
< ctx
->argc
; i
++) {
1305 bool satisfied
= false;
1307 ctx
->error
= check_condition(table
, row
, ctx
->argv
[i
],
1308 ctx
->symtab
, &satisfied
);
1317 list_record(row
, columns
, n_columns
, out
);
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
)
1331 const struct ovsdb_idl_column
*column
;
1332 char *key_string
= NULL
;
1333 char *value_string
= NULL
;
1336 error
= parse_column_key_value(arg
, table
, &column
, &key_string
,
1337 NULL
, NULL
, 0, &value_string
);
1341 if (!value_string
) {
1342 error
= xasprintf("%s: missing value", arg
);
1345 error
= check_mutable(row
, column
);
1351 union ovsdb_atom key
, value
;
1352 struct ovsdb_datum datum
;
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
);
1360 error
= ovsdb_atom_from_string(&key
, NULL
, &column
->type
.key
,
1361 key_string
, symtab
);
1365 error
= ovsdb_atom_from_string(&value
, NULL
, &column
->type
.value
,
1366 value_string
, symtab
);
1371 ovsdb_datum_init_empty(&datum
);
1372 ovsdb_datum_add_unsafe(&datum
, &key
, &value
, &column
->type
, NULL
);
1374 ovsdb_atom_destroy(&key
, column
->type
.key
.type
);
1375 ovsdb_atom_destroy(&value
, column
->type
.value
.type
);
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
);
1382 struct ovsdb_datum datum
;
1384 error
= ovsdb_datum_from_string(&datum
, &column
->type
,
1385 value_string
, symtab
);
1389 ovsdb_idl_txn_write(row
, column
, &datum
);
1400 pre_cmd_set(struct ctl_context
*ctx
)
1402 const char *table_name
= ctx
->argv
[1];
1403 const struct ovsdb_idl_table_class
*table
;
1406 ctx
->error
= pre_get_table(ctx
, table_name
, &table
);
1410 for (i
= 3; i
< ctx
->argc
; i
++) {
1411 ctx
->error
= pre_parse_column_key_value(ctx
, ctx
->argv
[i
], table
);
1419 cmd_set(struct ctl_context
*ctx
)
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
;
1428 ctx
->error
= get_table(table_name
, &table
);
1432 ctx
->error
= ctl_get_row(ctx
, table
, record_id
, must_exist
, &row
);
1440 for (i
= 3; i
< ctx
->argc
; i
++) {
1441 ctx
->error
= set_column(table
, row
, ctx
->argv
[i
], ctx
->symtab
);
1447 invalidate_cache(ctx
);
1451 pre_cmd_add(struct ctl_context
*ctx
)
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
;
1458 ctx
->error
= pre_get_table(ctx
, table_name
, &table
);
1462 ctx
->error
= pre_get_column(ctx
, table
, column_name
, &column
);
1469 cmd_add(struct ctl_context
*ctx
)
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
;
1482 ctx
->error
= get_table(table_name
, &table
);
1486 ctx
->error
= get_column(table
, column_name
, &column
);
1490 ctx
->error
= ctl_get_row(ctx
, table
, record_id
, must_exist
, &row
);
1497 ctx
->error
= check_mutable(row
, column
);
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
;
1510 add_type
.n_max
= UINT_MAX
;
1511 ctx
->error
= ovsdb_datum_from_string(&add
, &add_type
, ctx
->argv
[i
],
1514 ovsdb_datum_destroy(&old
, &column
->type
);
1517 ovsdb_datum_union(&old
, &add
, type
, false);
1518 ovsdb_datum_destroy(&add
, type
);
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",
1524 type
->value
.type
== OVSDB_TYPE_VOID
? "values" : "pairs",
1525 column
->name
, table
->name
, type
->n_max
);
1526 ovsdb_datum_destroy(&old
, &column
->type
);
1529 ovsdb_idl_txn_verify(row
, column
);
1530 ovsdb_idl_txn_write(row
, column
, &old
);
1532 invalidate_cache(ctx
);
1536 pre_cmd_remove(struct ctl_context
*ctx
)
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
;
1543 ctx
->error
= pre_get_table(ctx
, table_name
, &table
);
1547 ctx
->error
= pre_get_column(ctx
, table
, column_name
, &column
);
1554 cmd_remove(struct ctl_context
*ctx
)
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
;
1567 ctx
->error
= get_table(table_name
, &table
);
1571 ctx
->error
= get_column(table
, column_name
, &column
);
1575 ctx
->error
= ctl_get_row(ctx
, table
, record_id
, must_exist
, &row
);
1582 ctx
->error
= check_mutable(row
, column
);
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
;
1596 rm_type
.n_max
= UINT_MAX
;
1597 error
= ovsdb_datum_from_string(&rm
, &rm_type
,
1598 ctx
->argv
[i
], ctx
->symtab
);
1601 if (ovsdb_type_is_map(&rm_type
)) {
1602 rm_type
.value
.type
= OVSDB_TYPE_VOID
;
1604 ctx
->error
= ovsdb_datum_from_string(&rm
, &rm_type
,
1608 ovsdb_datum_destroy(&old
, &column
->type
);
1613 ovsdb_datum_destroy(&old
, &column
->type
);
1617 ovsdb_datum_subtract(&old
, type
, &rm
, &rm_type
);
1618 ovsdb_datum_destroy(&rm
, &rm_type
);
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
);
1628 ovsdb_idl_txn_verify(row
, column
);
1629 ovsdb_idl_txn_write(row
, column
, &old
);
1631 invalidate_cache(ctx
);
1635 pre_cmd_clear(struct ctl_context
*ctx
)
1637 const char *table_name
= ctx
->argv
[1];
1638 const struct ovsdb_idl_table_class
*table
;
1641 ctx
->error
= pre_get_table(ctx
, table_name
, &table
);
1645 for (i
= 3; i
< ctx
->argc
; i
++) {
1646 const struct ovsdb_idl_column
*column
;
1648 ctx
->error
= pre_get_column(ctx
, table
, ctx
->argv
[i
], &column
);
1656 cmd_clear(struct ctl_context
*ctx
)
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
;
1665 ctx
->error
= get_table(table_name
, &table
);
1669 ctx
->error
= ctl_get_row(ctx
, table
, record_id
, must_exist
, &row
);
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
;
1682 ctx
->error
= get_column(table
, ctx
->argv
[i
], &column
);
1686 ctx
->error
= check_mutable(row
, column
);
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
);
1699 ovsdb_datum_init_empty(&datum
);
1700 ovsdb_idl_txn_write(row
, column
, &datum
);
1703 invalidate_cache(ctx
);
1707 pre_create(struct ctl_context
*ctx
)
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
;
1713 ctx
->error
= get_table(table_name
, &table
);
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
);
1724 cmd_create(struct ctl_context
*ctx
)
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
;
1733 ctx
->error
= get_table(table_name
, &table
);
1738 struct ovsdb_symbol
*symbol
= NULL
;
1740 ctx
->error
= create_symbol(ctx
->symtab
, id
, &symbol
, NULL
);
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;
1750 uuid
= &symbol
->uuid
;
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
);
1760 ds_put_format(&ctx
->output
, UUID_FMT
, UUID_ARGS(&row
->uuid
));
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.
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
1773 post_create(struct ctl_context
*ctx
)
1775 const struct uuid
*real
;
1778 if (!uuid_from_string(&dummy
, ds_cstr(&ctx
->output
))) {
1781 real
= ovsdb_idl_txn_get_insert_uuid(ctx
->txn
, &dummy
);
1783 ds_clear(&ctx
->output
);
1784 ds_put_format(&ctx
->output
, UUID_FMT
, UUID_ARGS(real
));
1786 ds_put_char(&ctx
->output
, '\n');
1790 pre_cmd_destroy(struct ctl_context
*ctx
)
1792 const char *table_name
= ctx
->argv
[1];
1794 ctx
->error
= pre_get_table(ctx
, table_name
, NULL
);
1801 cmd_destroy(struct ctl_context
*ctx
)
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
;
1809 ctx
->error
= get_table(table_name
, &table
);
1814 if (delete_all
&& ctx
->argc
> 2) {
1815 ctl_error(ctx
, "--all and records argument should not be specified "
1820 if (delete_all
&& !must_exist
) {
1821 ctl_error(ctx
, "--all and --if-exists should not be specified "
1827 const struct ovsdb_idl_row
*row
;
1828 const struct ovsdb_idl_row
*next_row
;
1830 for (row
= ovsdb_idl_first_row(ctx
->idl
, table
);
1832 next_row
= ovsdb_idl_next_row(row
);
1833 ovsdb_idl_txn_delete(row
);
1837 for (i
= 2; i
< ctx
->argc
; i
++) {
1838 const struct ovsdb_idl_row
*row
;
1840 ctx
->error
= ctl_get_row(ctx
, table
, ctx
->argv
[i
], must_exist
,
1846 ovsdb_idl_txn_delete(row
);
1850 invalidate_cache(ctx
);
1854 pre_cmd_wait_until(struct ctl_context
*ctx
)
1856 const char *table_name
= ctx
->argv
[1];
1857 const struct ovsdb_idl_table_class
*table
;
1860 ctx
->error
= pre_get_table(ctx
, table_name
, &table
);
1865 for (i
= 3; i
< ctx
->argc
; i
++) {
1866 ctx
->error
= pre_parse_column_key_value(ctx
, ctx
->argv
[i
], table
);
1874 cmd_wait_until(struct ctl_context
*ctx
)
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
;
1882 ctx
->error
= get_table(table_name
, &table
);
1886 ctx
->error
= ctl_get_row(ctx
, table
, record_id
, false, &row
);
1891 ctx
->try_again
= true;
1895 for (i
= 3; i
< ctx
->argc
; i
++) {
1898 ctx
->error
= check_condition(table
, row
, ctx
->argv
[i
], ctx
->symtab
,
1904 ctx
->try_again
= true;
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
)
1915 const struct ctl_command_syntax
*p
;
1916 struct shash_node
*node
;
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
];
1928 if (option
[0] != '-') {
1932 equals
= strchr(option
, '=');
1934 key
= xmemdup0(option
, equals
- option
);
1935 value
= xstrdup(equals
+ 1);
1937 key
= xstrdup(option
);
1941 if (shash_find(&command
->options
, key
)) {
1944 error
= xasprintf("'%s' option specified multiple times", argv
[i
]);
1947 shash_add_nocopy(&command
->options
, key
, value
);
1950 error
= xstrdup("missing command name (use --help for help)");
1954 p
= shash_find_data(&all_commands
, argv
[i
]);
1956 error
= xasprintf("unknown command '%s'; use --help for help",
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
;
1965 if (!strchr("=,? ", end
)) {
1966 error
= xasprintf("'%s' command has no '%s' option",
1967 argv
[i
], node
->name
);
1970 if (end
!= '?' && (end
== '=') != (node
->data
!= NULL
)) {
1972 error
= xasprintf("missing argument to '%s' option on '%s' "
1973 "command", node
->name
, argv
[i
]);
1976 error
= xasprintf("'%s' option on '%s' does not accept an "
1977 "argument", node
->name
, argv
[i
]);
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
);
1988 } else if (n_arg
> p
->max_args
) {
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
);
2001 error
= xasprintf("'%s' command takes at most %d arguments",
2002 p
->name
, p
->max_args
);
2006 command
->syntax
= p
;
2007 command
->argc
= n_arg
+ 1;
2008 command
->argv
= &argv
[i
];
2012 shash_destroy_free_data(&command
->options
);
2017 pre_cmd_show(struct ctl_context
*ctx
)
2019 const struct cmd_show_table
*show
;
2021 for (show
= cmd_show_tables
; show
->table
; show
++) {
2024 ovsdb_idl_add_table(ctx
->idl
, show
->table
);
2025 if (show
->name_column
) {
2026 ovsdb_idl_add_column(ctx
->idl
, show
->name_column
);
2028 for (i
= 0; i
< ARRAY_SIZE(show
->columns
); i
++) {
2029 const struct ovsdb_idl_column
*column
= show
->columns
[i
];
2031 ovsdb_idl_add_column(ctx
->idl
, column
);
2034 if (show
->wref_table
.table
) {
2035 ovsdb_idl_add_table(ctx
->idl
, show
->wref_table
.table
);
2037 if (show
->wref_table
.name_column
) {
2038 ovsdb_idl_add_column(ctx
->idl
, show
->wref_table
.name_column
);
2040 if (show
->wref_table
.wref_column
) {
2041 ovsdb_idl_add_column(ctx
->idl
, show
->wref_table
.wref_column
);
2046 static const struct cmd_show_table
*
2047 cmd_show_find_table_by_row(const struct ovsdb_idl_row
*row
)
2049 const struct cmd_show_table
*show
;
2051 for (show
= cmd_show_tables
; show
->table
; show
++) {
2052 if (show
->table
== row
->table
->class_
) {
2059 static const struct cmd_show_table
*
2060 cmd_show_find_table_by_name(const char *name
)
2062 const struct cmd_show_table
*show
;
2064 for (show
= cmd_show_tables
; show
->table
; show
++) {
2065 if (!strcmp(show
->table
->name
, name
)) {
2072 /* Prints table entries that weak reference the 'cur_row'. */
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
)
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
;
2084 if (!table
|| !name_column
|| !wref_column
) {
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. */
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');
2105 /* 'shown' records the tables that has been displayed by the current
2106 * command to avoid duplicated prints.
2109 cmd_show_row(struct ctl_context
*ctx
, const struct ovsdb_idl_row
*row
,
2110 int level
, struct sset
*shown
)
2112 const struct cmd_show_table
*show
= cmd_show_find_table_by_row(row
);
2115 ds_put_char_multiple(&ctx
->output
, ' ', level
* 4);
2116 if (show
&& show
->name_column
) {
2117 const struct ovsdb_datum
*datum
;
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
);
2123 ds_put_format(&ctx
->output
, UUID_FMT
, UUID_ARGS(&row
->uuid
));
2125 ds_put_char(&ctx
->output
, '\n');
2127 if (!show
|| sset_find(shown
, show
->table
->name
)) {
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
;
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
;
2146 ref_show
= cmd_show_find_table_by_name(
2147 column
->type
.key
.uuid
.refTableName
);
2149 for (j
= 0; j
< datum
->n
; j
++) {
2150 const struct ovsdb_idl_row
*ref_row
;
2152 ref_row
= ovsdb_idl_get_row_for_uuid(ctx
->idl
,
2154 &datum
->keys
[j
].uuid
);
2156 cmd_show_row(ctx
, ref_row
, level
+ 1, shown
);
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
;
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
;
2177 ref_row
= ovsdb_idl_get_row_for_uuid(ctx
->idl
,
2179 &datum
->values
[j
].uuid
);
2181 ds_put_char_multiple(&ctx
->output
, ' ', (level
+ 2) * 4);
2182 ovsdb_atom_to_string(&datum
->keys
[j
], column
->type
.key
.type
,
2184 ds_put_char(&ctx
->output
, '=');
2186 const struct ovsdb_datum
*ref_datum
;
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
,
2194 ds_put_cstr(&ctx
->output
, "\"<null>\"");
2196 ds_put_char(&ctx
->output
, '\n');
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');
2209 cmd_show_weak_ref(ctx
, show
, row
, level
);
2210 sset_find_and_delete_assert(shown
, show
->table
->name
);
2214 cmd_show(struct ctl_context
*ctx
)
2216 const struct ovsdb_idl_row
*row
;
2217 struct sset shown
= SSET_INITIALIZER(&shown
);
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
);
2224 ovs_assert(sset_is_empty(&shown
));
2225 sset_destroy(&shown
);
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
2234 ctl_add_cmd_options(struct option
**options_p
, size_t *n_options_p
,
2235 size_t *allocated_options_p
, int opt_val
)
2238 const struct shash_node
*node
;
2239 size_t n_existing_options
= *n_options_p
;
2241 SHASH_FOR_EACH (node
, &all_commands
) {
2242 const struct ctl_command_syntax
*p
= node
->data
;
2244 if (p
->options
[0]) {
2245 char *save_ptr
= NULL
;
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]);
2255 size_t n
= strcspn(name
, "=?");
2256 int has_arg
= (name
[n
] == '\0' ? no_argument
2257 : name
[n
] == '=' ? required_argument
2258 : optional_argument
);
2261 o
= find_option(name
, *options_p
, *n_options_p
);
2263 ovs_assert(o
- *options_p
>= n_existing_options
);
2264 ovs_assert(o
->has_arg
== has_arg
);
2266 o
= add_option(options_p
, n_options_p
, allocated_options_p
);
2267 o
->name
= xstrdup(name
);
2268 o
->has_arg
= has_arg
;
2277 o
= add_option(options_p
, n_options_p
, allocated_options_p
);
2278 memset(o
, 0, sizeof *o
);
2281 /* Parses command-line input for commands. */
2283 ctl_parse_commands(int argc
, char *argv
[], struct shash
*local_options
,
2284 struct ctl_command
**commandsp
, size_t *n_commandsp
)
2286 struct ctl_command
*commands
;
2287 size_t n_commands
, allocated_commands
;
2292 n_commands
= allocated_commands
= 0;
2297 for (start
= i
= 0; i
<= argc
; i
++) {
2298 if (i
== argc
|| !strcmp(argv
[i
], "--")) {
2300 if (n_commands
>= allocated_commands
) {
2301 struct ctl_command
*c
;
2303 commands
= x2nrealloc(commands
, &allocated_commands
,
2305 for (c
= commands
; c
< &commands
[n_commands
]; c
++) {
2306 shash_moved(&c
->options
);
2309 error
= parse_command(i
- start
, &argv
[start
], local_options
,
2310 &commands
[n_commands
]);
2312 struct ctl_command
*c
;
2314 for (c
= commands
; c
< &commands
[n_commands
]; c
++) {
2315 shash_destroy_free_data(&c
->options
);
2323 } else if (!shash_is_empty(local_options
)) {
2324 return xstrdup("missing command name (use --help for help)");
2330 return xstrdup("missing command name (use --help for help)");
2332 *commandsp
= commands
;
2333 *n_commandsp
= n_commands
;
2337 /* Prints all registered commands. */
2339 ctl_print_commands(void)
2341 const struct shash_node
*node
;
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
;
2349 for (item
= strsep(&options
, ","); item
!= NULL
;
2350 item
= strsep(&options
, ",")) {
2351 if (item
[0] != '\0') {
2352 printf("[%s] ", item
);
2355 printf(",%s,", p
->name
);
2356 print_command_arguments(p
);
2359 free(options_begin
);
2365 /* Given array of options 'options', prints them. */
2367 ctl_print_options(const struct option
*options
)
2369 for (; options
->name
; options
++) {
2370 const struct option
*o
= options
;
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" : "");
2381 /* Returns the default local database path. */
2383 ctl_default_db(void)
2387 def
= xasprintf("unix:%s/db.sock", ovs_rundir());
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
2396 ctl_might_write_to_db(const struct ctl_command
*commands
, size_t n
)
2398 for (size_t i
= 0; i
< n
; i
++) {
2399 if (commands
[i
].syntax
->mode
== RW
) {
2406 /* Report an error while running in the command context. Caller should return
2407 * to its caller immediately after reporting the error. */
2409 ctl_error(struct ctl_context
*ctx
, const char *format
, ...)
2416 VLOG_ERR("Discarding unhandled error: %s", ctx
->error
);
2420 va_start(args
, format
);
2421 ctx
->error
= xvasprintf(format
, args
);
2426 ctl_fatal(const char *format
, ...)
2431 va_start(args
, format
);
2432 message
= xvasprintf(format
, args
);
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
);
2441 /* Frees the current transaction and the underlying IDL and then calls
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. */
2448 ctl_exit(int status
)
2450 if (ctl_exit_func
) {
2451 ctl_exit_func(status
);
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
},
2483 ctl_register_command(const struct ctl_command_syntax
*command
)
2485 shash_add_assert(&all_commands
, command
->name
, command
);
2488 /* Registers commands represented by 'struct ctl_command_syntax's to
2489 * 'all_commands'. The last element of 'commands' must be an all-NULL
2492 ctl_register_commands(const struct ctl_command_syntax
*commands
)
2494 const struct ctl_command_syntax
*p
;
2496 for (p
= commands
; p
->name
; p
++) {
2497 ctl_register_command(p
);
2501 /* Registers the 'db_ctl_commands' to 'all_commands'. */
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
))
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
);
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
);
2523 /* Returns the text for the database commands usage. */
2525 ctl_get_db_cmd_usage(void)
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";
2542 ctl_list_db_tables_usage(void)
2544 static struct ds s
= DS_EMPTY_INITIALIZER
;
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
;
2553 svec_add(&options
, "by UUID");
2554 if (idl_classes
[i
].is_singleton
) {
2555 svec_add(&options
, "as \".\"");
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
) {
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
,
2570 if (referrer
!= &idl_classes
[i
]) {
2571 ds_put_format(&o
, " of %s", referrer
->name
);
2574 ds_put_format(&o
, " with matching \"%s:%s\"",
2575 id
->name_column
->name
, id
->key
);
2577 ds_put_format(&o
, " with matching \"%s\"", id
->name_column
->name
);
2579 } else if (id
->key
) {
2580 ds_put_format(&o
, "by \"%s:%s\"", id
->name_column
->name
, id
->key
);
2582 ds_put_format(&o
, "by \"%s\"", id
->name_column
->name
);
2584 svec_add_nocopy(&options
, ds_steal_cstr(&o
));
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
]);
2591 ds_put_char(&s
, '\n');
2592 svec_destroy(&options
);
2598 /* Initializes 'ctx' from 'command'. */
2600 ctl_context_init_command(struct ctl_context
*ctx
,
2601 struct ctl_command
*command
)
2603 ctx
->argc
= command
->argc
;
2604 ctx
->argv
= command
->argv
;
2605 ctx
->options
= command
->options
;
2607 ds_swap(&ctx
->output
, &command
->output
);
2608 ctx
->table
= command
->table
;
2609 ctx
->try_again
= false;
2613 /* Initializes the entire 'ctx'. */
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
*))
2621 ctl_context_init_command(ctx
, command
);
2625 ctx
->symtab
= symtab
;
2626 ctx
->invalidate_cache_cb
= invalidate_cache_cb
;
2629 /* Completes processing of 'command' within 'ctx'. */
2631 ctl_context_done_command(struct ctl_context
*ctx
,
2632 struct ctl_command
*command
)
2634 ds_swap(&ctx
->output
, &command
->output
);
2635 command
->table
= ctx
->table
;
2640 /* Finishes up with 'ctx'.
2642 * If command is nonnull, first calls ctl_context_done_command() to complete
2643 * processing that command within 'ctx'. */
2645 ctl_context_done(struct ctl_context
*ctx
,
2646 struct ctl_command
*command
)
2649 ctl_context_done_command(ctx
, command
);
2651 invalidate_cache(ctx
);
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
)
2658 const struct ovsdb_idl_table_class
*table
;
2661 error
= get_table(table_name
, &table
);
2665 error
= set_column(table
, row
, arg
, symtab
);