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