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