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