2 * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2015, 2016, 2017 Nicira, Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at:
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
25 #include "byte-order.h"
26 #include "command-line.h"
27 #include "openvswitch/dynamic-string.h"
28 #include "openvswitch/json.h"
30 #include "ovsdb-data.h"
31 #include "ovsdb-error.h"
32 #include "ovsdb-idl.h"
33 #include "ovsdb-types.h"
34 #include "ovsdb/column.h"
35 #include "ovsdb/condition.h"
36 #include "ovsdb/file.h"
37 #include "ovsdb/log.h"
38 #include "ovsdb/mutation.h"
39 #include "ovsdb/ovsdb.h"
40 #include "ovsdb/query.h"
41 #include "ovsdb/row.h"
42 #include "ovsdb/server.h"
43 #include "ovsdb/storage.h"
44 #include "ovsdb/table.h"
45 #include "ovsdb/transaction.h"
46 #include "ovsdb/trigger.h"
47 #include "openvswitch/poll-loop.h"
50 #include "tests/idltest.h"
53 #include "openvswitch/vlog.h"
55 struct test_ovsdb_pvt_context
{
59 /* Magic to pass to ovsdb_log_open(). */
60 static const char *magic
= OVSDB_MAGIC
;
62 OVS_NO_RETURN
static void usage(void);
63 static void parse_options(int argc
, char *argv
[],
64 struct test_ovsdb_pvt_context
*pvt
);
65 static struct ovs_cmdl_command
*get_all_commands(void);
68 main(int argc
, char *argv
[])
70 struct test_ovsdb_pvt_context pvt
= {.track
= false};
71 struct ovs_cmdl_context ctx
= { .argc
= 0, .pvt
= &pvt
};
72 set_program_name(argv
[0]);
73 parse_options(argc
, argv
, &pvt
);
74 ctx
.argc
= argc
- optind
;
75 ctx
.argv
= argv
+ optind
;
76 ovs_cmdl_run_command(&ctx
, get_all_commands());
81 parse_options(int argc
, char *argv
[], struct test_ovsdb_pvt_context
*pvt
)
84 OPT_MAGIC
= CHAR_MAX
+ 1,
85 OPT_NO_RENAME_OPEN_FILES
87 static const struct option long_options
[] = {
88 {"timeout", required_argument
, NULL
, 't'},
89 {"verbose", optional_argument
, NULL
, 'v'},
90 {"change-track", optional_argument
, NULL
, 'c'},
91 {"magic", required_argument
, NULL
, OPT_MAGIC
},
92 {"no-rename-open-files", no_argument
, NULL
, OPT_NO_RENAME_OPEN_FILES
},
93 {"help", no_argument
, NULL
, 'h'},
96 char *short_options
= ovs_cmdl_long_options_to_short_options(long_options
);
97 unsigned int timeout
= 0;
102 c
= getopt_long(argc
, argv
, short_options
, long_options
, NULL
);
109 if (!str_to_uint(optarg
, 10, &timeout
) || !timeout
) {
110 ovs_fatal(0, "value %s on -t or --timeout is invalid", optarg
);
118 vlog_set_verbosity(optarg
);
129 case OPT_NO_RENAME_OPEN_FILES
:
130 ovsdb_log_disable_renaming_open_files();
142 ctl_timeout_setup(timeout
);
148 printf("%s: Open vSwitch database test utility\n"
149 "usage: %s [OPTIONS] COMMAND [ARG...]\n\n"
150 " [--magic=MAGIC] [--no-rename-open-files] "
151 " log-io FILE FLAGS COMMAND...\n"
152 " open FILE with FLAGS (and MAGIC), run COMMANDs\n"
154 " test ovsdb_atom_default()\n"
156 " test ovsdb_datum_default()\n"
157 " parse-atomic-type TYPE\n"
158 " parse TYPE as OVSDB atomic type, and re-serialize\n"
159 " parse-base-type TYPE\n"
160 " parse TYPE as OVSDB base type, and re-serialize\n"
162 " parse JSON as OVSDB type, and re-serialize\n"
163 " parse-atoms TYPE ATOM...\n"
164 " parse JSON ATOMs as atoms of TYPE, and re-serialize\n"
165 " parse-atom-strings TYPE ATOM...\n"
166 " parse string ATOMs as atoms of given TYPE, and re-serialize\n"
167 " sort-atoms TYPE ATOM...\n"
168 " print JSON ATOMs in sorted order\n"
169 " parse-data TYPE DATUM...\n"
170 " parse JSON DATUMs as data of given TYPE, and re-serialize\n"
171 " parse-data-strings TYPE DATUM...\n"
172 " parse string DATUMs as data of given TYPE, and re-serialize\n"
173 " parse-column NAME OBJECT\n"
174 " parse column NAME with info OBJECT, and re-serialize\n"
175 " parse-table NAME OBJECT [DEFAULT-IS-ROOT]\n"
176 " parse table NAME with info OBJECT\n"
177 " parse-row TABLE ROW..., and re-serialize\n"
178 " parse each ROW of defined TABLE\n"
179 " compare-row TABLE ROW...\n"
180 " mutually compare all of the ROWs, print those that are equal\n"
181 " parse-conditions TABLE CONDITION...\n"
182 " parse each CONDITION on TABLE, and re-serialize\n"
183 " evaluate-conditions TABLE [CONDITION,...] [ROW,...]\n"
184 " test CONDITIONS on TABLE against each ROW, print results\n"
185 " evaluate-conditions-any TABLE [CONDITION,...] [ROW,...]\n"
186 " test CONDITIONS to match any of the CONDITONS on TABLE\n"
187 " against each ROW, print results\n"
188 " compare-conditions TABLE [CONDITION,...]\n"
189 " mutually compare all of the CONDITION, print results for\n"
191 " parse-mutations TABLE MUTATION...\n"
192 " parse each MUTATION on TABLE, and re-serialize\n"
193 " execute-mutations TABLE [MUTATION,...] [ROW,...]\n"
194 " execute MUTATIONS on TABLE on each ROW, print results\n"
195 " query TABLE [ROW,...] [CONDITION,...]\n"
196 " add each ROW to TABLE, then query and print the rows that\n"
197 " satisfy each CONDITION.\n"
198 " query-distinct TABLE [ROW,...] [CONDITION,...] COLUMNS\n"
199 " add each ROW to TABLE, then query and print the rows that\n"
200 " satisfy each CONDITION and have distinct COLUMNS.\n"
201 " parse-schema JSON\n"
202 " parse JSON as an OVSDB schema, and re-serialize\n"
203 " transact COMMAND\n"
204 " execute each specified transactional COMMAND:\n"
211 " execute SCHEMA TRANSACTION...\n"
212 " executes each TRANSACTION on an initially empty database\n"
213 " the specified SCHEMA\n"
214 " execute-readonly SCHEMA TRANSACTION...\n"
215 " same as execute, except the TRANSACTION will be executed\n"
216 " against the database server that is in read only mode\n"
217 " trigger SCHEMA TRANSACTION...\n"
218 " executes each TRANSACTION on an initially empty database\n"
219 " the specified SCHEMA. A TRANSACTION of the form\n"
220 " [\"advance\", NUMBER] advances NUMBER milliseconds in\n"
221 " simulated time, for causing triggers to time out.\n"
222 " idl SERVER [TRANSACTION...]\n"
223 " connect to SERVER and dump the contents of the database\n"
224 " as seen initially by the IDL implementation and after\n"
225 " executing each TRANSACTION. (Each TRANSACTION must modify\n"
226 " the database or this command will hang.)\n"
227 " idl-partial-update-map-column SERVER \n"
228 " connect to SERVER and executes different operations to\n"
229 " test the capacity of updating elements inside a map column\n"
230 " displaying the table information after each operation.\n"
231 " idl-partial-update-set-column SERVER \n"
232 " connect to SERVER and executes different operations to\n"
233 " test the capacity of updating elements inside a set column\n"
234 " displaying the table information after each operation.\n"
235 " idl-compound-index TEST_TO_EXECUTE\n"
236 " Execute the tests to verify compound-index feature.\n"
237 " The TEST_TO_EXECUTE are:\n"
238 " idl_compound_index_single_column:\n"
239 " test for indexes using one column.\n"
240 " idl_compound_index_double_column:\n"
241 " test for indexes using two columns.\n",
242 program_name
, program_name
);
244 printf("\nOther options:\n"
245 " -t, --timeout=SECS give up after SECS seconds\n"
246 " -h, --help display this help message\n"
247 " -c, --change-track used with the 'idl' command to\n"
248 " enable tracking of IDL changes\n");
252 /* Command helper functions. */
255 parse_json(const char *s
)
257 struct json
*json
= json_from_string(s
);
258 if (json
->type
== JSON_STRING
) {
259 ovs_fatal(0, "\"%s\": %s", s
, json
->string
);
265 unbox_json(struct json
*json
)
267 if (json
->type
== JSON_ARRAY
&& json
->array
.n
== 1) {
268 struct json
*inner
= json
->array
.elems
[0];
269 json
->array
.elems
[0] = NULL
;
278 print_and_free_json(struct json
*json
)
280 char *string
= json_to_string(json
, JSSF_SORT
);
287 print_and_free_ovsdb_error(struct ovsdb_error
*error
)
289 char *string
= ovsdb_error_to_string_free(error
);
295 check_ovsdb_error(struct ovsdb_error
*error
)
298 char *s
= ovsdb_error_to_string_free(error
);
299 ovs_fatal(0, "%s", s
);
304 die_if_error(char *error
)
307 ovs_fatal(0, "%s", error
);
311 /* Command implementations. */
314 do_log_io(struct ovs_cmdl_context
*ctx
)
316 const char *name
= ctx
->argv
[1];
317 char *mode_string
= ctx
->argv
[2];
319 struct ovsdb_error
*error
;
320 enum ovsdb_log_open_mode mode
;
323 if (!strcmp(mode_string
, "read-only")) {
324 mode
= OVSDB_LOG_READ_ONLY
;
325 } else if (!strcmp(mode_string
, "read/write")) {
326 mode
= OVSDB_LOG_READ_WRITE
;
327 } else if (!strcmp(mode_string
, "create")) {
328 mode
= OVSDB_LOG_CREATE
;
329 } else if (!strcmp(mode_string
, "create-excl")) {
330 mode
= OVSDB_LOG_CREATE_EXCL
;
332 ovs_fatal(0, "unknown log-io open mode \"%s\"", mode_string
);
335 struct ovsdb_log
*log
;
336 check_ovsdb_error(ovsdb_log_open(name
, magic
, mode
, -1, &log
));
337 printf("%s: open successful\n", name
);
339 struct ovsdb_log
*replacement
= NULL
;
341 for (i
= 3; i
< ctx
->argc
; i
++) {
342 const char *command
= ctx
->argv
[i
];
344 struct ovsdb_log
*target
;
345 const char *target_name
;
346 if (!strncmp(command
, "old-", 4)) {
350 } else if (!strncmp(command
, "new-", 4)) {
352 ovs_fatal(0, "%s: can't execute command without "
353 "replacement log", command
);
357 target
= replacement
;
358 target_name
= "(temp)";
364 if (!strcmp(command
, "read")) {
367 error
= ovsdb_log_read(target
, &json
);
369 printf("%s: read: ", target_name
);
371 print_and_free_json(json
);
373 printf("end of log\n");
377 } else if (!strncmp(command
, "write:", 6)) {
378 struct json
*json
= parse_json(command
+ 6);
379 error
= ovsdb_log_write_and_free(target
, json
);
380 } else if (!strcmp(command
, "commit")) {
381 error
= ovsdb_log_commit_block(target
);
382 } else if (!strcmp(command
, "replace_start")) {
383 ovs_assert(!replacement
);
384 error
= ovsdb_log_replace_start(log
, &replacement
);
385 } else if (!strcmp(command
, "replace_commit")) {
386 ovs_assert(replacement
);
387 error
= ovsdb_log_replace_commit(log
, replacement
);
389 } else if (!strcmp(command
, "replace_abort")) {
390 ovs_assert(replacement
);
391 ovsdb_log_replace_abort(replacement
);
395 ovs_fatal(0, "unknown log-io command \"%s\"", command
);
398 char *s
= ovsdb_error_to_string_free(error
);
399 printf("%s: %s failed: %s\n", target_name
, command
, s
);
402 printf("%s: %s successful\n", target_name
, command
);
406 ovsdb_log_close(log
);
410 do_default_atoms(struct ovs_cmdl_context
*ctx OVS_UNUSED
)
414 for (type
= 0; type
< OVSDB_N_TYPES
; type
++) {
415 union ovsdb_atom atom
;
417 if (type
== OVSDB_TYPE_VOID
) {
421 printf("%s: ", ovsdb_atomic_type_to_string(type
));
423 ovsdb_atom_init_default(&atom
, type
);
424 if (!ovsdb_atom_equals(&atom
, ovsdb_atom_default(type
), type
)) {
428 ovsdb_atom_destroy(&atom
, type
);
435 do_default_data(struct ovs_cmdl_context
*ctx OVS_UNUSED
)
440 for (n_min
= 0; n_min
<= 1; n_min
++) {
441 for (key
= 0; key
< OVSDB_N_TYPES
; key
++) {
442 if (key
== OVSDB_TYPE_VOID
) {
445 for (value
= 0; value
< OVSDB_N_TYPES
; value
++) {
446 struct ovsdb_datum datum
;
447 struct ovsdb_type type
;
449 ovsdb_base_type_init(&type
.key
, key
);
450 ovsdb_base_type_init(&type
.value
, value
);
453 ovs_assert(ovsdb_type_is_valid(&type
));
455 printf("key %s, value %s, n_min %u: ",
456 ovsdb_atomic_type_to_string(key
),
457 ovsdb_atomic_type_to_string(value
), n_min
);
459 ovsdb_datum_init_default(&datum
, &type
);
460 if (!ovsdb_datum_equals(&datum
, ovsdb_datum_default(&type
),
465 ovsdb_datum_destroy(&datum
, &type
);
466 ovsdb_type_destroy(&type
);
475 do_diff_data(struct ovs_cmdl_context
*ctx
)
477 struct ovsdb_type type
;
479 struct ovsdb_datum
new, old
, diff
, reincarnation
;
481 json
= unbox_json(parse_json(ctx
->argv
[1]));
482 check_ovsdb_error(ovsdb_type_from_json(&type
, json
));
485 /* Arguments in pairs of 'old' and 'new'. */
486 for (int i
= 2; i
< ctx
->argc
- 1; i
+=2) {
487 struct ovsdb_error
*error
;
489 json
= unbox_json(parse_json(ctx
->argv
[i
]));
490 check_ovsdb_error(ovsdb_datum_from_json(&old
, &type
, json
, NULL
));
493 json
= unbox_json(parse_json(ctx
->argv
[i
+1]));
494 check_ovsdb_error(ovsdb_transient_datum_from_json(&new, &type
, json
));
497 /* Generate the diff. */
498 ovsdb_datum_diff(&diff
, &old
, &new, &type
);
500 /* Apply diff to 'old' to create'reincarnation'. */
501 error
= ovsdb_datum_apply_diff(&reincarnation
, &old
, &diff
, &type
);
503 char *string
= ovsdb_error_to_string_free(error
);
504 ovs_fatal(0, "%s", string
);
507 /* Test to make sure 'new' equals 'reincarnation'. */
508 if (!ovsdb_datum_equals(&new, &reincarnation
, &type
)) {
509 ovs_fatal(0, "failed to apply diff");
513 json
= ovsdb_datum_to_json(&diff
, &type
);
515 print_and_free_json(json
);
517 /* Print reincarnation */
518 json
= ovsdb_datum_to_json(&reincarnation
, &type
);
519 printf ("apply diff: ");
520 print_and_free_json(json
);
522 ovsdb_datum_destroy(&new, &type
);
523 ovsdb_datum_destroy(&old
, &type
);
524 ovsdb_datum_destroy(&diff
, &type
);
525 ovsdb_datum_destroy(&reincarnation
, &type
);
530 ovsdb_type_destroy(&type
);
534 do_parse_atomic_type(struct ovs_cmdl_context
*ctx
)
536 enum ovsdb_atomic_type type
;
539 json
= unbox_json(parse_json(ctx
->argv
[1]));
540 check_ovsdb_error(ovsdb_atomic_type_from_json(&type
, json
));
542 print_and_free_json(ovsdb_atomic_type_to_json(type
));
546 do_parse_base_type(struct ovs_cmdl_context
*ctx
)
548 struct ovsdb_base_type base
;
551 json
= unbox_json(parse_json(ctx
->argv
[1]));
552 check_ovsdb_error(ovsdb_base_type_from_json(&base
, json
));
554 print_and_free_json(ovsdb_base_type_to_json(&base
));
555 ovsdb_base_type_destroy(&base
);
559 do_parse_type(struct ovs_cmdl_context
*ctx
)
561 struct ovsdb_type type
;
564 json
= unbox_json(parse_json(ctx
->argv
[1]));
565 check_ovsdb_error(ovsdb_type_from_json(&type
, json
));
567 print_and_free_json(ovsdb_type_to_json(&type
));
568 ovsdb_type_destroy(&type
);
572 do_parse_atoms(struct ovs_cmdl_context
*ctx
)
574 struct ovsdb_base_type base
;
578 json
= unbox_json(parse_json(ctx
->argv
[1]));
579 check_ovsdb_error(ovsdb_base_type_from_json(&base
, json
));
582 for (i
= 2; i
< ctx
->argc
; i
++) {
583 struct ovsdb_error
*error
;
584 union ovsdb_atom atom
;
586 json
= unbox_json(parse_json(ctx
->argv
[i
]));
587 error
= ovsdb_atom_from_json(&atom
, &base
, json
, NULL
);
591 print_and_free_ovsdb_error(error
);
593 print_and_free_json(ovsdb_atom_to_json(&atom
, base
.type
));
594 ovsdb_atom_destroy(&atom
, base
.type
);
597 ovsdb_base_type_destroy(&base
);
601 do_parse_atom_strings(struct ovs_cmdl_context
*ctx
)
603 struct ovsdb_base_type base
;
607 json
= unbox_json(parse_json(ctx
->argv
[1]));
608 check_ovsdb_error(ovsdb_base_type_from_json(&base
, json
));
611 for (i
= 2; i
< ctx
->argc
; i
++) {
612 union ovsdb_atom atom
, *range_end_atom
= NULL
;
615 die_if_error(ovsdb_atom_from_string(&atom
, &range_end_atom
, &base
,
616 ctx
->argv
[i
], NULL
));
619 ovsdb_atom_to_string(&atom
, base
.type
, &out
);
620 if (range_end_atom
) {
621 struct ds range_end_ds
;
622 ds_init(&range_end_ds
);
623 ovsdb_atom_to_string(range_end_atom
, base
.type
, &range_end_ds
);
624 ds_put_char(&out
, '-');
625 ds_put_cstr(&out
, ds_cstr(&range_end_ds
));;
626 ds_destroy(&range_end_ds
);
631 ovsdb_atom_destroy(&atom
, base
.type
);
632 if (range_end_atom
) {
633 ovsdb_atom_destroy(range_end_atom
, base
.type
);
634 free(range_end_atom
);
637 ovsdb_base_type_destroy(&base
);
641 do_parse_data__(int argc
, char *argv
[],
643 (*parse
)(struct ovsdb_datum
*datum
,
644 const struct ovsdb_type
*type
,
645 const struct json
*json
,
646 struct ovsdb_symbol_table
*symtab
))
648 struct ovsdb_type type
;
652 json
= unbox_json(parse_json(argv
[1]));
653 check_ovsdb_error(ovsdb_type_from_json(&type
, json
));
656 for (i
= 2; i
< argc
; i
++) {
657 struct ovsdb_datum datum
;
659 json
= unbox_json(parse_json(argv
[i
]));
660 check_ovsdb_error(parse(&datum
, &type
, json
, NULL
));
663 print_and_free_json(ovsdb_datum_to_json(&datum
, &type
));
665 ovsdb_datum_destroy(&datum
, &type
);
667 ovsdb_type_destroy(&type
);
671 do_parse_data(struct ovs_cmdl_context
*ctx
)
673 do_parse_data__(ctx
->argc
, ctx
->argv
, ovsdb_datum_from_json
);
677 do_parse_data_strings(struct ovs_cmdl_context
*ctx
)
679 struct ovsdb_type type
;
683 json
= unbox_json(parse_json(ctx
->argv
[1]));
684 check_ovsdb_error(ovsdb_type_from_json(&type
, json
));
687 for (i
= 2; i
< ctx
->argc
; i
++) {
688 struct ovsdb_datum datum
;
691 die_if_error(ovsdb_datum_from_string(&datum
, &type
, ctx
->argv
[i
], NULL
));
694 ovsdb_datum_to_string(&datum
, &type
, &out
);
698 ovsdb_datum_destroy(&datum
, &type
);
700 ovsdb_type_destroy(&type
);
703 static enum ovsdb_atomic_type compare_atoms_atomic_type
;
706 compare_atoms(const void *a_
, const void *b_
)
708 const union ovsdb_atom
*a
= a_
;
709 const union ovsdb_atom
*b
= b_
;
711 return ovsdb_atom_compare_3way(a
, b
, compare_atoms_atomic_type
);
715 do_sort_atoms(struct ovs_cmdl_context
*ctx
)
717 struct ovsdb_base_type base
;
718 union ovsdb_atom
*atoms
;
719 struct json
*json
, **json_atoms
;
723 json
= unbox_json(parse_json(ctx
->argv
[1]));
724 check_ovsdb_error(ovsdb_base_type_from_json(&base
, json
));
727 json
= unbox_json(parse_json(ctx
->argv
[2]));
728 if (json
->type
!= JSON_ARRAY
) {
729 ovs_fatal(0, "second argument must be array");
732 /* Convert JSON atoms to internal representation. */
733 n_atoms
= json
->array
.n
;
734 atoms
= xmalloc(n_atoms
* sizeof *atoms
);
735 for (i
= 0; i
< n_atoms
; i
++) {
736 check_ovsdb_error(ovsdb_atom_from_json(&atoms
[i
], &base
,
737 json
->array
.elems
[i
], NULL
));
742 compare_atoms_atomic_type
= base
.type
;
743 qsort(atoms
, n_atoms
, sizeof *atoms
, compare_atoms
);
745 /* Convert internal representation back to JSON. */
746 json_atoms
= xmalloc(n_atoms
* sizeof *json_atoms
);
747 for (i
= 0; i
< n_atoms
; i
++) {
748 json_atoms
[i
] = ovsdb_atom_to_json(&atoms
[i
], base
.type
);
749 ovsdb_atom_destroy(&atoms
[i
], base
.type
);
751 print_and_free_json(json_array_create(json_atoms
, n_atoms
));
753 ovsdb_base_type_destroy(&base
);
757 do_parse_column(struct ovs_cmdl_context
*ctx
)
759 struct ovsdb_column
*column
;
762 json
= parse_json(ctx
->argv
[2]);
763 check_ovsdb_error(ovsdb_column_from_json(json
, ctx
->argv
[1], &column
));
765 print_and_free_json(ovsdb_column_to_json(column
));
766 ovsdb_column_destroy(column
);
770 do_parse_table(struct ovs_cmdl_context
*ctx
)
772 struct ovsdb_table_schema
*ts
;
773 bool default_is_root
;
776 default_is_root
= ctx
->argc
> 3 && !strcmp(ctx
->argv
[3], "true");
778 json
= parse_json(ctx
->argv
[2]);
779 check_ovsdb_error(ovsdb_table_schema_from_json(json
, ctx
->argv
[1], &ts
));
781 print_and_free_json(ovsdb_table_schema_to_json(ts
, default_is_root
));
782 ovsdb_table_schema_destroy(ts
);
786 do_parse_rows(struct ovs_cmdl_context
*ctx
)
788 struct ovsdb_column_set all_columns
;
789 struct ovsdb_table_schema
*ts
;
790 struct ovsdb_table
*table
;
794 json
= unbox_json(parse_json(ctx
->argv
[1]));
795 check_ovsdb_error(ovsdb_table_schema_from_json(json
, "mytable", &ts
));
798 table
= ovsdb_table_create(ts
);
799 ovsdb_column_set_init(&all_columns
);
800 ovsdb_column_set_add_all(&all_columns
, table
);
802 for (i
= 2; i
< ctx
->argc
; i
++) {
803 struct ovsdb_column_set columns
;
804 struct ovsdb_row
*row
;
806 ovsdb_column_set_init(&columns
);
807 row
= ovsdb_row_create(table
);
809 json
= unbox_json(parse_json(ctx
->argv
[i
]));
810 check_ovsdb_error(ovsdb_row_from_json(row
, json
, NULL
, &columns
));
813 print_and_free_json(ovsdb_row_to_json(row
, &all_columns
));
815 if (columns
.n_columns
) {
821 for (j
= 0; j
< columns
.n_columns
; j
++) {
822 svec_add(&names
, columns
.columns
[j
]->name
);
825 s
= svec_join(&names
, ", ", "");
828 svec_destroy(&names
);
833 ovsdb_column_set_destroy(&columns
);
834 ovsdb_row_destroy(row
);
837 ovsdb_column_set_destroy(&all_columns
);
838 ovsdb_table_destroy(table
); /* Also destroys 'ts'. */
842 do_compare_rows(struct ovs_cmdl_context
*ctx
)
844 struct ovsdb_column_set all_columns
;
845 struct ovsdb_table_schema
*ts
;
846 struct ovsdb_table
*table
;
847 struct ovsdb_row
**rows
;
853 json
= unbox_json(parse_json(ctx
->argv
[1]));
854 check_ovsdb_error(ovsdb_table_schema_from_json(json
, "mytable", &ts
));
857 table
= ovsdb_table_create(ts
);
858 ovsdb_column_set_init(&all_columns
);
859 ovsdb_column_set_add_all(&all_columns
, table
);
861 n_rows
= ctx
->argc
- 2;
862 rows
= xmalloc(sizeof *rows
* n_rows
);
863 names
= xmalloc(sizeof *names
* n_rows
);
864 for (i
= 0; i
< n_rows
; i
++) {
865 rows
[i
] = ovsdb_row_create(table
);
867 json
= parse_json(ctx
->argv
[i
+ 2]);
868 if (json
->type
!= JSON_ARRAY
|| json
->array
.n
!= 2
869 || json
->array
.elems
[0]->type
!= JSON_STRING
) {
870 ovs_fatal(0, "\"%s\" does not have expected form "
871 "[\"name\", {data}]", ctx
->argv
[i
]);
873 names
[i
] = xstrdup(json
->array
.elems
[0]->string
);
874 check_ovsdb_error(ovsdb_row_from_json(rows
[i
], json
->array
.elems
[1],
878 for (i
= 0; i
< n_rows
; i
++) {
879 uint32_t i_hash
= ovsdb_row_hash_columns(rows
[i
], &all_columns
, 0);
880 for (j
= i
+ 1; j
< n_rows
; j
++) {
881 uint32_t j_hash
= ovsdb_row_hash_columns(rows
[j
], &all_columns
, 0);
882 if (ovsdb_row_equal_columns(rows
[i
], rows
[j
], &all_columns
)) {
883 printf("%s == %s\n", names
[i
], names
[j
]);
884 if (i_hash
!= j_hash
) {
885 printf("but hash(%s) != hash(%s)\n", names
[i
], names
[j
]);
888 } else if (i_hash
== j_hash
) {
889 printf("hash(%s) == hash(%s)\n", names
[i
], names
[j
]);
893 for (i
= 0; i
< n_rows
; i
++) {
894 ovsdb_row_destroy(rows
[i
]);
900 ovsdb_column_set_destroy(&all_columns
);
901 ovsdb_table_destroy(table
); /* Also destroys 'ts'. */
905 do_parse_conditions(struct ovs_cmdl_context
*ctx
)
907 struct ovsdb_table_schema
*ts
;
912 json
= unbox_json(parse_json(ctx
->argv
[1]));
913 check_ovsdb_error(ovsdb_table_schema_from_json(json
, "mytable", &ts
));
916 for (i
= 2; i
< ctx
->argc
; i
++) {
917 struct ovsdb_condition cnd
;
918 struct ovsdb_error
*error
;
920 json
= parse_json(ctx
->argv
[i
]);
921 error
= ovsdb_condition_from_json(ts
, json
, NULL
, &cnd
);
923 print_and_free_json(ovsdb_condition_to_json(&cnd
));
925 char *s
= ovsdb_error_to_string_free(error
);
926 ovs_error(0, "%s", s
);
932 ovsdb_condition_destroy(&cnd
);
934 ovsdb_table_schema_destroy(ts
);
939 #define OVSDB_CONDITION_EVERY 0
940 #define OVSDB_CONDITION_ANY 1
943 do_evaluate_condition__(struct ovs_cmdl_context
*ctx
, int mode
)
945 struct ovsdb_table_schema
*ts
;
946 struct ovsdb_table
*table
;
947 struct ovsdb_condition
*conditions
;
949 struct ovsdb_row
**rows
;
954 /* Parse table schema, create table. */
955 json
= unbox_json(parse_json(ctx
->argv
[1]));
956 check_ovsdb_error(ovsdb_table_schema_from_json(json
, "mytable", &ts
));
959 table
= ovsdb_table_create(ts
);
961 /* Parse conditions. */
962 json
= parse_json(ctx
->argv
[2]);
963 if (json
->type
!= JSON_ARRAY
) {
964 ovs_fatal(0, "CONDITION argument is not JSON array");
966 n_conditions
= json
->array
.n
;
967 conditions
= xmalloc(n_conditions
* sizeof *conditions
);
968 for (i
= 0; i
< n_conditions
; i
++) {
969 check_ovsdb_error(ovsdb_condition_from_json(ts
, json
->array
.elems
[i
],
970 NULL
, &conditions
[i
]));
975 json
= parse_json(ctx
->argv
[3]);
976 if (json
->type
!= JSON_ARRAY
) {
977 ovs_fatal(0, "ROW argument is not JSON array");
979 n_rows
= json
->array
.n
;
980 rows
= xmalloc(n_rows
* sizeof *rows
);
981 for (i
= 0; i
< n_rows
; i
++) {
982 rows
[i
] = ovsdb_row_create(table
);
983 check_ovsdb_error(ovsdb_row_from_json(rows
[i
], json
->array
.elems
[i
],
988 for (i
= 0; i
< n_conditions
; i
++) {
989 printf("condition %2"PRIuSIZE
":", i
);
990 for (j
= 0; j
< n_rows
; j
++) {
992 if (mode
== OVSDB_CONDITION_EVERY
) {
993 result
= ovsdb_condition_match_every_clause(rows
[j
],
996 result
= ovsdb_condition_match_any_clause(rows
[j
]->fields
,
1003 putchar(result
? 'T' : '-');
1008 for (i
= 0; i
< n_conditions
; i
++) {
1009 ovsdb_condition_destroy(&conditions
[i
]);
1012 for (i
= 0; i
< n_rows
; i
++) {
1013 ovsdb_row_destroy(rows
[i
]);
1016 ovsdb_table_destroy(table
); /* Also destroys 'ts'. */
1020 do_evaluate_conditions(struct ovs_cmdl_context
*ctx
)
1022 do_evaluate_condition__(ctx
, OVSDB_CONDITION_EVERY
);
1026 do_evaluate_conditions_any(struct ovs_cmdl_context
*ctx
)
1028 do_evaluate_condition__(ctx
, OVSDB_CONDITION_ANY
);
1032 do_compare_conditions(struct ovs_cmdl_context
*ctx
)
1034 struct ovsdb_table_schema
*ts
;
1035 struct ovsdb_table
*table
;
1036 struct ovsdb_condition
*conditions
;
1037 size_t n_conditions
;
1041 /* Parse table schema, create table. */
1042 json
= unbox_json(parse_json(ctx
->argv
[1]));
1043 check_ovsdb_error(ovsdb_table_schema_from_json(json
, "mytable", &ts
));
1046 table
= ovsdb_table_create(ts
);
1048 /* Parse conditions. */
1049 json
= parse_json(ctx
->argv
[2]);
1050 if (json
->type
!= JSON_ARRAY
) {
1051 ovs_fatal(0, "CONDITION argument is not JSON array");
1053 n_conditions
= json
->array
.n
;
1054 conditions
= xmalloc(n_conditions
* sizeof *conditions
);
1056 for (i
= 0; i
< n_conditions
; i
++) {
1057 check_ovsdb_error(ovsdb_condition_from_json(ts
, json
->array
.elems
[i
],
1058 NULL
, &conditions
[i
]));
1062 for (i
= 0; i
< n_conditions
- 1; i
++) {
1063 int res
= ovsdb_condition_cmp_3way(&conditions
[i
], &conditions
[i
+ 1]);
1064 printf("condition %"PRIuSIZE
"-%"PRIuSIZE
": %d\n", i
, i
+ 1, res
);
1067 for (i
= 0; i
< n_conditions
; i
++) {
1068 ovsdb_condition_destroy(&conditions
[i
]);
1071 ovsdb_table_destroy(table
); /* Also destroys 'ts'. */
1075 do_parse_mutations(struct ovs_cmdl_context
*ctx
)
1077 struct ovsdb_table_schema
*ts
;
1082 json
= unbox_json(parse_json(ctx
->argv
[1]));
1083 check_ovsdb_error(ovsdb_table_schema_from_json(json
, "mytable", &ts
));
1086 for (i
= 2; i
< ctx
->argc
; i
++) {
1087 struct ovsdb_mutation_set set
;
1088 struct ovsdb_error
*error
;
1090 json
= parse_json(ctx
->argv
[i
]);
1091 error
= ovsdb_mutation_set_from_json(ts
, json
, NULL
, &set
);
1093 print_and_free_json(ovsdb_mutation_set_to_json(&set
));
1095 char *s
= ovsdb_error_to_string_free(error
);
1096 ovs_error(0, "%s", s
);
1102 ovsdb_mutation_set_destroy(&set
);
1104 ovsdb_table_schema_destroy(ts
);
1110 do_execute_mutations(struct ovs_cmdl_context
*ctx
)
1112 struct ovsdb_table_schema
*ts
;
1113 struct ovsdb_table
*table
;
1114 struct ovsdb_mutation_set
*sets
;
1116 struct ovsdb_row
**rows
;
1121 /* Parse table schema, create table. */
1122 json
= unbox_json(parse_json(ctx
->argv
[1]));
1123 check_ovsdb_error(ovsdb_table_schema_from_json(json
, "mytable", &ts
));
1126 table
= ovsdb_table_create(ts
);
1128 /* Parse mutations. */
1129 json
= parse_json(ctx
->argv
[2]);
1130 if (json
->type
!= JSON_ARRAY
) {
1131 ovs_fatal(0, "MUTATION argument is not JSON array");
1133 n_sets
= json
->array
.n
;
1134 sets
= xmalloc(n_sets
* sizeof *sets
);
1135 for (i
= 0; i
< n_sets
; i
++) {
1136 check_ovsdb_error(ovsdb_mutation_set_from_json(ts
,
1137 json
->array
.elems
[i
],
1143 json
= parse_json(ctx
->argv
[3]);
1144 if (json
->type
!= JSON_ARRAY
) {
1145 ovs_fatal(0, "ROW argument is not JSON array");
1147 n_rows
= json
->array
.n
;
1148 rows
= xmalloc(n_rows
* sizeof *rows
);
1149 for (i
= 0; i
< n_rows
; i
++) {
1150 rows
[i
] = ovsdb_row_create(table
);
1151 check_ovsdb_error(ovsdb_row_from_json(rows
[i
], json
->array
.elems
[i
],
1156 for (i
= 0; i
< n_sets
; i
++) {
1157 printf("mutation %2"PRIuSIZE
":\n", i
);
1158 for (j
= 0; j
< n_rows
; j
++) {
1159 struct ovsdb_error
*error
;
1160 struct ovsdb_row
*row
;
1162 row
= ovsdb_row_clone(rows
[j
]);
1163 error
= ovsdb_mutation_set_execute(row
, &sets
[i
]);
1165 printf("row %"PRIuSIZE
": ", j
);
1167 print_and_free_ovsdb_error(error
);
1169 struct ovsdb_column_set columns
;
1170 struct shash_node
*node
;
1172 ovsdb_column_set_init(&columns
);
1173 SHASH_FOR_EACH (node
, &ts
->columns
) {
1174 struct ovsdb_column
*c
= node
->data
;
1175 if (!ovsdb_datum_equals(&row
->fields
[c
->index
],
1176 &rows
[j
]->fields
[c
->index
],
1178 ovsdb_column_set_add(&columns
, c
);
1181 if (columns
.n_columns
) {
1182 print_and_free_json(ovsdb_row_to_json(row
, &columns
));
1184 printf("no change\n");
1186 ovsdb_column_set_destroy(&columns
);
1188 ovsdb_row_destroy(row
);
1193 for (i
= 0; i
< n_sets
; i
++) {
1194 ovsdb_mutation_set_destroy(&sets
[i
]);
1197 for (i
= 0; i
< n_rows
; i
++) {
1198 ovsdb_row_destroy(rows
[i
]);
1201 ovsdb_table_destroy(table
); /* Also destroys 'ts'. */
1204 /* Inserts a row, without bothering to update metadata such as refcounts. */
1206 put_row(struct ovsdb_table
*table
, struct ovsdb_row
*row
)
1208 const struct uuid
*uuid
= ovsdb_row_get_uuid(row
);
1209 if (!ovsdb_table_get_row(table
, uuid
)) {
1210 hmap_insert(&table
->rows
, &row
->hmap_node
, uuid_hash(uuid
));
1214 struct do_query_cbdata
{
1215 struct uuid
*row_uuids
;
1221 do_query_cb(const struct ovsdb_row
*row
, void *cbdata_
)
1223 struct do_query_cbdata
*cbdata
= cbdata_
;
1226 for (i
= 0; i
< cbdata
->n_rows
; i
++) {
1227 if (uuid_equals(ovsdb_row_get_uuid(row
), &cbdata
->row_uuids
[i
])) {
1228 cbdata
->counts
[i
]++;
1236 do_query(struct ovs_cmdl_context
*ctx
)
1238 struct do_query_cbdata cbdata
;
1239 struct ovsdb_table_schema
*ts
;
1240 struct ovsdb_table
*table
;
1245 /* Parse table schema, create table. */
1246 json
= unbox_json(parse_json(ctx
->argv
[1]));
1247 check_ovsdb_error(ovsdb_table_schema_from_json(json
, "mytable", &ts
));
1250 table
= ovsdb_table_create(ts
);
1252 /* Parse rows, add to table. */
1253 json
= parse_json(ctx
->argv
[2]);
1254 if (json
->type
!= JSON_ARRAY
) {
1255 ovs_fatal(0, "ROW argument is not JSON array");
1257 cbdata
.n_rows
= json
->array
.n
;
1258 cbdata
.row_uuids
= xmalloc(cbdata
.n_rows
* sizeof *cbdata
.row_uuids
);
1259 cbdata
.counts
= xmalloc(cbdata
.n_rows
* sizeof *cbdata
.counts
);
1260 for (i
= 0; i
< cbdata
.n_rows
; i
++) {
1261 struct ovsdb_row
*row
= ovsdb_row_create(table
);
1262 uuid_generate(ovsdb_row_get_uuid_rw(row
));
1263 check_ovsdb_error(ovsdb_row_from_json(row
, json
->array
.elems
[i
],
1265 if (ovsdb_table_get_row(table
, ovsdb_row_get_uuid(row
))) {
1266 ovs_fatal(0, "duplicate UUID "UUID_FMT
" in table",
1267 UUID_ARGS(ovsdb_row_get_uuid(row
)));
1269 cbdata
.row_uuids
[i
] = *ovsdb_row_get_uuid(row
);
1270 put_row(table
, row
);
1274 /* Parse conditions and execute queries. */
1275 json
= parse_json(ctx
->argv
[3]);
1276 if (json
->type
!= JSON_ARRAY
) {
1277 ovs_fatal(0, "CONDITION argument is not JSON array");
1279 for (i
= 0; i
< json
->array
.n
; i
++) {
1280 struct ovsdb_condition cnd
;
1283 check_ovsdb_error(ovsdb_condition_from_json(ts
, json
->array
.elems
[i
],
1286 memset(cbdata
.counts
, 0, cbdata
.n_rows
* sizeof *cbdata
.counts
);
1287 ovsdb_query(table
, &cnd
, do_query_cb
, &cbdata
);
1289 printf("query %2"PRIuSIZE
":", i
);
1290 for (j
= 0; j
< cbdata
.n_rows
; j
++) {
1294 if (cbdata
.counts
[j
]) {
1295 printf("%d", cbdata
.counts
[j
]);
1296 if (cbdata
.counts
[j
] > 1) {
1306 ovsdb_condition_destroy(&cnd
);
1310 ovsdb_table_destroy(table
); /* Also destroys 'ts'. */
1315 struct do_query_distinct_class
{
1316 struct ovsdb_row
*example
;
1320 struct do_query_distinct_row
{
1322 struct do_query_distinct_class
*class;
1326 do_query_distinct(struct ovs_cmdl_context
*ctx
)
1328 struct ovsdb_column_set columns
;
1329 struct ovsdb_table_schema
*ts
;
1330 struct ovsdb_table
*table
;
1331 struct do_query_distinct_row
*rows
;
1333 struct do_query_distinct_class
*classes
;
1339 /* Parse table schema, create table. */
1340 json
= unbox_json(parse_json(ctx
->argv
[1]));
1341 check_ovsdb_error(ovsdb_table_schema_from_json(json
, "mytable", &ts
));
1344 table
= ovsdb_table_create(ts
);
1346 /* Parse column set. */
1347 json
= parse_json(ctx
->argv
[4]);
1348 check_ovsdb_error(ovsdb_column_set_from_json(json
, table
->schema
,
1352 /* Parse rows, add to table. */
1353 json
= parse_json(ctx
->argv
[2]);
1354 if (json
->type
!= JSON_ARRAY
) {
1355 ovs_fatal(0, "ROW argument is not JSON array");
1357 n_rows
= json
->array
.n
;
1358 rows
= xmalloc(n_rows
* sizeof *rows
);
1359 classes
= xmalloc(n_rows
* sizeof *classes
);
1361 for (i
= 0; i
< n_rows
; i
++) {
1362 struct ovsdb_row
*row
;
1366 row
= ovsdb_row_create(table
);
1367 uuid_generate(ovsdb_row_get_uuid_rw(row
));
1368 check_ovsdb_error(ovsdb_row_from_json(row
, json
->array
.elems
[i
],
1371 /* Initialize row and find equivalence class. */
1372 rows
[i
].uuid
= *ovsdb_row_get_uuid(row
);
1373 rows
[i
].class = NULL
;
1374 for (j
= 0; j
< n_classes
; j
++) {
1375 if (ovsdb_row_equal_columns(row
, classes
[j
].example
, &columns
)) {
1376 rows
[i
].class = &classes
[j
];
1380 if (!rows
[i
].class) {
1381 rows
[i
].class = &classes
[n_classes
];
1382 classes
[n_classes
].example
= ovsdb_row_clone(row
);
1386 /* Add row to table. */
1387 if (ovsdb_table_get_row(table
, ovsdb_row_get_uuid(row
))) {
1388 ovs_fatal(0, "duplicate UUID "UUID_FMT
" in table",
1389 UUID_ARGS(ovsdb_row_get_uuid(row
)));
1391 put_row(table
, row
);
1396 /* Parse conditions and execute queries. */
1397 json
= parse_json(ctx
->argv
[3]);
1398 if (json
->type
!= JSON_ARRAY
) {
1399 ovs_fatal(0, "CONDITION argument is not JSON array");
1401 for (i
= 0; i
< json
->array
.n
; i
++) {
1402 struct ovsdb_row_set results
;
1403 struct ovsdb_condition cnd
;
1406 check_ovsdb_error(ovsdb_condition_from_json(ts
, json
->array
.elems
[i
],
1409 for (j
= 0; j
< n_classes
; j
++) {
1410 classes
[j
].count
= 0;
1412 ovsdb_row_set_init(&results
);
1413 ovsdb_query_distinct(table
, &cnd
, &columns
, &results
);
1414 for (j
= 0; j
< results
.n_rows
; j
++) {
1417 for (k
= 0; k
< n_rows
; k
++) {
1418 if (uuid_equals(ovsdb_row_get_uuid(results
.rows
[j
]),
1420 rows
[k
].class->count
++;
1424 ovsdb_row_set_destroy(&results
);
1426 printf("query %2"PRIuSIZE
":", i
);
1427 for (j
= 0; j
< n_rows
; j
++) {
1428 int count
= rows
[j
].class->count
;
1435 printf("%d", count
);
1437 } else if (count
== 1) {
1438 putchar("abcdefghijklmnopqrstuvwxyz"[rows
[j
].class - classes
]);
1445 ovsdb_condition_destroy(&cnd
);
1449 for (i
= 0; i
< n_classes
; i
++) {
1450 ovsdb_row_destroy(classes
[i
].example
);
1453 ovsdb_table_destroy(table
); /* Also destroys 'ts'. */
1461 do_parse_schema(struct ovs_cmdl_context
*ctx
)
1463 struct ovsdb_schema
*schema
;
1466 json
= parse_json(ctx
->argv
[1]);
1467 check_ovsdb_error(ovsdb_schema_from_json(json
, &schema
));
1469 print_and_free_json(ovsdb_schema_to_json(schema
));
1470 ovsdb_schema_destroy(schema
);
1474 do_execute__(struct ovs_cmdl_context
*ctx
, bool ro
)
1476 struct ovsdb_schema
*schema
;
1481 /* Create database. */
1482 json
= parse_json(ctx
->argv
[1]);
1483 check_ovsdb_error(ovsdb_schema_from_json(json
, &schema
));
1485 db
= ovsdb_create(schema
, ovsdb_storage_create_unbacked());
1487 for (i
= 2; i
< ctx
->argc
; i
++) {
1488 struct json
*params
, *result
;
1491 params
= parse_json(ctx
->argv
[i
]);
1492 result
= ovsdb_execute(db
, NULL
, params
, ro
, NULL
, NULL
, 0, NULL
);
1493 s
= json_to_string(result
, JSSF_SORT
);
1496 json_destroy(params
);
1497 json_destroy(result
);
1504 do_execute_ro(struct ovs_cmdl_context
*ctx
)
1506 do_execute__(ctx
, true);
1510 do_execute(struct ovs_cmdl_context
*ctx
)
1512 do_execute__(ctx
, false);
1515 struct test_trigger
{
1516 struct ovsdb_trigger trigger
;
1521 do_trigger_dump(struct test_trigger
*t
, long long int now
, const char *title
)
1523 struct jsonrpc_msg
*reply
;
1526 reply
= ovsdb_trigger_steal_reply(&t
->trigger
);
1527 s
= json_to_string(reply
->result
, JSSF_SORT
);
1528 printf("t=%lld: trigger %d (%s): %s\n", now
, t
->number
, title
, s
);
1530 jsonrpc_msg_destroy(reply
);
1531 ovsdb_trigger_destroy(&t
->trigger
);
1536 do_trigger(struct ovs_cmdl_context
*ctx
)
1538 struct ovsdb_schema
*schema
;
1539 struct ovsdb_session session
;
1540 struct ovsdb_server server
;
1547 /* Create database. */
1548 json
= parse_json(ctx
->argv
[1]);
1549 check_ovsdb_error(ovsdb_schema_from_json(json
, &schema
));
1551 db
= ovsdb_create(schema
, ovsdb_storage_create_unbacked());
1553 ovsdb_server_init(&server
);
1554 ovsdb_server_add_db(&server
, db
);
1555 ovsdb_session_init(&session
, &server
);
1559 for (i
= 2; i
< ctx
->argc
; i
++) {
1560 struct json
*params
= parse_json(ctx
->argv
[i
]);
1561 if (params
->type
== JSON_ARRAY
1562 && json_array(params
)->n
== 2
1563 && json_array(params
)->elems
[0]->type
== JSON_STRING
1564 && !strcmp(json_string(json_array(params
)->elems
[0]), "advance")
1565 && json_array(params
)->elems
[1]->type
== JSON_INTEGER
) {
1566 now
+= json_integer(json_array(params
)->elems
[1]);
1567 json_destroy(params
);
1569 struct test_trigger
*t
= xmalloc(sizeof *t
);
1570 ovsdb_trigger_init(&session
, db
, &t
->trigger
,
1571 jsonrpc_create_request("transact", params
,
1573 now
, false, NULL
, NULL
);
1574 t
->number
= number
++;
1575 if (ovsdb_trigger_is_complete(&t
->trigger
)) {
1576 do_trigger_dump(t
, now
, "immediate");
1578 printf("t=%lld: new trigger %d\n", now
, t
->number
);
1582 ovsdb_trigger_run(db
, now
);
1584 struct test_trigger
*t
;
1585 LIST_FOR_EACH_POP (t
, trigger
.node
, &session
.completions
) {
1586 do_trigger_dump(t
, now
, "delayed");
1587 ovsdb_trigger_run(db
, now
);
1590 ovsdb_trigger_wait(db
, now
);
1591 poll_immediate_wake();
1595 ovsdb_server_destroy(&server
);
1600 do_help(struct ovs_cmdl_context
*ctx OVS_UNUSED
)
1605 /* "transact" command. */
1607 static struct ovsdb
*do_transact_db
;
1608 static struct ovsdb_txn
*do_transact_txn
;
1609 static struct ovsdb_table
*do_transact_table
;
1612 do_transact_commit(struct ovs_cmdl_context
*ctx OVS_UNUSED
)
1614 ovsdb_error_destroy(ovsdb_txn_replay_commit(do_transact_txn
));
1615 do_transact_txn
= NULL
;
1619 do_transact_abort(struct ovs_cmdl_context
*ctx OVS_UNUSED
)
1621 ovsdb_txn_abort(do_transact_txn
);
1622 do_transact_txn
= NULL
;
1626 uuid_from_integer(int integer
, struct uuid
*uuid
)
1629 uuid
->parts
[3] = integer
;
1632 static const struct ovsdb_row
*
1633 do_transact_find_row(const char *uuid_string
)
1635 const struct ovsdb_row
*row
;
1638 uuid_from_integer(atoi(uuid_string
), &uuid
);
1639 row
= ovsdb_table_get_row(do_transact_table
, &uuid
);
1641 ovs_fatal(0, "table does not contain row with UUID "UUID_FMT
,
1648 do_transact_set_integer(struct ovsdb_row
*row
, const char *column_name
,
1651 if (integer
!= -1) {
1652 const struct ovsdb_column
*column
;
1654 column
= ovsdb_table_schema_get_column(do_transact_table
->schema
,
1656 row
->fields
[column
->index
].keys
[0].integer
= integer
;
1661 do_transact_get_integer(const struct ovsdb_row
*row
, const char *column_name
)
1663 const struct ovsdb_column
*column
;
1665 column
= ovsdb_table_schema_get_column(do_transact_table
->schema
,
1667 return row
->fields
[column
->index
].keys
[0].integer
;
1671 do_transact_set_i_j(struct ovsdb_row
*row
,
1672 const char *i_string
, const char *j_string
)
1674 do_transact_set_integer(row
, "i", atoi(i_string
));
1675 do_transact_set_integer(row
, "j", atoi(j_string
));
1679 do_transact_insert(struct ovs_cmdl_context
*ctx
)
1681 struct ovsdb_row
*row
;
1684 row
= ovsdb_row_create(do_transact_table
);
1687 uuid
= ovsdb_row_get_uuid_rw(row
);
1688 uuid_from_integer(atoi(ctx
->argv
[1]), uuid
);
1689 if (ovsdb_table_get_row(do_transact_table
, uuid
)) {
1690 ovs_fatal(0, "table already contains row with UUID "UUID_FMT
,
1694 do_transact_set_i_j(row
, ctx
->argv
[2], ctx
->argv
[3]);
1697 ovsdb_txn_row_insert(do_transact_txn
, row
);
1701 do_transact_delete(struct ovs_cmdl_context
*ctx
)
1703 const struct ovsdb_row
*row
= do_transact_find_row(ctx
->argv
[1]);
1704 ovsdb_txn_row_delete(do_transact_txn
, row
);
1708 do_transact_modify(struct ovs_cmdl_context
*ctx
)
1710 const struct ovsdb_row
*row_ro
;
1711 struct ovsdb_row
*row_rw
;
1713 row_ro
= do_transact_find_row(ctx
->argv
[1]);
1714 row_rw
= ovsdb_txn_row_modify(do_transact_txn
, row_ro
);
1715 do_transact_set_i_j(row_rw
, ctx
->argv
[2], ctx
->argv
[3]);
1719 compare_rows_by_uuid(const void *a_
, const void *b_
)
1721 struct ovsdb_row
*const *ap
= a_
;
1722 struct ovsdb_row
*const *bp
= b_
;
1724 return uuid_compare_3way(ovsdb_row_get_uuid(*ap
), ovsdb_row_get_uuid(*bp
));
1728 do_transact_print(struct ovs_cmdl_context
*ctx OVS_UNUSED
)
1730 const struct ovsdb_row
**rows
;
1731 const struct ovsdb_row
*row
;
1735 n_rows
= hmap_count(&do_transact_table
->rows
);
1736 rows
= xmalloc(n_rows
* sizeof *rows
);
1738 HMAP_FOR_EACH (row
, hmap_node
, &do_transact_table
->rows
) {
1741 ovs_assert(i
== n_rows
);
1743 qsort(rows
, n_rows
, sizeof *rows
, compare_rows_by_uuid
);
1745 for (i
= 0; i
< n_rows
; i
++) {
1746 printf("\n%"PRId32
": i=%d, j=%d",
1747 ovsdb_row_get_uuid(rows
[i
])->parts
[3],
1748 do_transact_get_integer(rows
[i
], "i"),
1749 do_transact_get_integer(rows
[i
], "j"));
1756 do_transact(struct ovs_cmdl_context
*ctx
)
1758 static const struct ovs_cmdl_command do_transact_commands
[] = {
1759 { "commit", NULL
, 0, 0, do_transact_commit
, OVS_RO
},
1760 { "abort", NULL
, 0, 0, do_transact_abort
, OVS_RO
},
1761 { "insert", NULL
, 2, 3, do_transact_insert
, OVS_RO
},
1762 { "delete", NULL
, 1, 1, do_transact_delete
, OVS_RO
},
1763 { "modify", NULL
, 2, 3, do_transact_modify
, OVS_RO
},
1764 { "print", NULL
, 0, 0, do_transact_print
, OVS_RO
},
1765 { NULL
, NULL
, 0, 0, NULL
, OVS_RO
},
1768 struct ovsdb_schema
*schema
;
1773 json
= parse_json("{\"name\": \"testdb\", "
1777 " {\"i\": {\"type\": \"integer\"}, "
1778 " \"j\": {\"type\": \"integer\"}}}}}");
1779 check_ovsdb_error(ovsdb_schema_from_json(json
, &schema
));
1781 do_transact_db
= ovsdb_create(schema
, ovsdb_storage_create_unbacked());
1782 do_transact_table
= ovsdb_get_table(do_transact_db
, "mytable");
1783 ovs_assert(do_transact_table
!= NULL
);
1785 for (i
= 1; i
< ctx
->argc
; i
++) {
1786 struct json
*command
;
1790 struct ovs_cmdl_context transact_ctx
= { .argc
= 0, };
1792 command
= parse_json(ctx
->argv
[i
]);
1793 if (command
->type
!= JSON_ARRAY
) {
1794 ovs_fatal(0, "transaction %d must be JSON array "
1795 "with at least 1 element", i
);
1798 n_args
= command
->array
.n
;
1799 args
= xmalloc((n_args
+ 1) * sizeof *args
);
1800 for (j
= 0; j
< n_args
; j
++) {
1801 struct json
*s
= command
->array
.elems
[j
];
1802 if (s
->type
!= JSON_STRING
) {
1803 ovs_fatal(0, "transaction %d argument %d must be JSON string",
1806 args
[j
] = xstrdup(json_string(s
));
1808 args
[n_args
] = NULL
;
1810 if (!do_transact_txn
) {
1811 do_transact_txn
= ovsdb_txn_create(do_transact_db
);
1814 for (j
= 0; j
< n_args
; j
++) {
1818 fputs(args
[j
], stdout
);
1821 transact_ctx
.argc
= n_args
;
1822 transact_ctx
.argv
= args
;
1823 ovs_cmdl_run_command(&transact_ctx
, do_transact_commands
);
1826 for (j
= 0; j
< n_args
; j
++) {
1830 json_destroy(command
);
1832 ovsdb_txn_abort(do_transact_txn
);
1833 ovsdb_destroy(do_transact_db
); /* Also destroys 'schema'. */
1837 compare_link1(const void *a_
, const void *b_
)
1839 const struct idltest_link1
*const *ap
= a_
;
1840 const struct idltest_link1
*const *bp
= b_
;
1841 const struct idltest_link1
*a
= *ap
;
1842 const struct idltest_link1
*b
= *bp
;
1844 return a
->i
< b
->i
? -1 : a
->i
> b
->i
;
1848 print_idl_row_updated_simple(const struct idltest_simple
*s
, int step
)
1851 bool updated
= false;
1853 for (i
= 0; i
< IDLTEST_SIMPLE_N_COLUMNS
; i
++) {
1854 if (idltest_simple_is_updated(s
, i
)) {
1856 printf("%03d: updated columns:", step
);
1859 printf(" %s", idltest_simple_columns
[i
].name
);
1868 print_idl_row_updated_link1(const struct idltest_link1
*l1
, int step
)
1871 bool updated
= false;
1873 for (i
= 0; i
< IDLTEST_LINK1_N_COLUMNS
; i
++) {
1874 if (idltest_link1_is_updated(l1
, i
)) {
1876 printf("%03d: updated columns:", step
);
1879 printf(" %s", idltest_link1_columns
[i
].name
);
1888 print_idl_row_updated_link2(const struct idltest_link2
*l2
, int step
)
1891 bool updated
= false;
1893 for (i
= 0; i
< IDLTEST_LINK2_N_COLUMNS
; i
++) {
1894 if (idltest_link2_is_updated(l2
, i
)) {
1896 printf("%03d: updated columns:", step
);
1899 printf(" %s", idltest_link2_columns
[i
].name
);
1908 print_idl_row_updated_singleton(const struct idltest_singleton
*sng
, int step
)
1911 bool updated
= false;
1913 for (i
= 0; i
< IDLTEST_SINGLETON_N_COLUMNS
; i
++) {
1914 if (idltest_singleton_is_updated(sng
, i
)) {
1916 printf("%03d: updated columns:", step
);
1919 printf(" %s", idltest_singleton_columns
[i
].name
);
1928 print_idl_row_simple(const struct idltest_simple
*s
, int step
)
1932 printf("%03d: i=%"PRId64
" r=%g b=%s s=%s u="UUID_FMT
" ia=[",
1933 step
, s
->i
, s
->r
, s
->b
? "true" : "false",
1934 s
->s
, UUID_ARGS(&s
->u
));
1935 for (i
= 0; i
< s
->n_ia
; i
++) {
1936 printf("%s%"PRId64
, i
? " " : "", s
->ia
[i
]);
1939 for (i
= 0; i
< s
->n_ra
; i
++) {
1940 printf("%s%g", i
? " " : "", s
->ra
[i
]);
1943 for (i
= 0; i
< s
->n_ba
; i
++) {
1944 printf("%s%s", i
? " " : "", s
->ba
[i
] ? "true" : "false");
1947 for (i
= 0; i
< s
->n_sa
; i
++) {
1948 printf("%s%s", i
? " " : "", s
->sa
[i
]);
1951 for (i
= 0; i
< s
->n_ua
; i
++) {
1952 printf("%s"UUID_FMT
, i
? " " : "", UUID_ARGS(&s
->ua
[i
]));
1954 printf("] uuid="UUID_FMT
"\n", UUID_ARGS(&s
->header_
.uuid
));
1955 print_idl_row_updated_simple(s
, step
);
1959 print_idl_row_link1(const struct idltest_link1
*l1
, int step
)
1961 struct idltest_link1
**links
;
1964 printf("%03d: i=%"PRId64
" k=", step
, l1
->i
);
1966 printf("%"PRId64
, l1
->k
->i
);
1969 links
= xmemdup(l1
->ka
, l1
->n_ka
* sizeof *l1
->ka
);
1970 qsort(links
, l1
->n_ka
, sizeof *links
, compare_link1
);
1971 for (i
= 0; i
< l1
->n_ka
; i
++) {
1972 printf("%s%"PRId64
, i
? " " : "", links
[i
]->i
);
1977 printf("%"PRId64
, l1
->l2
->i
);
1979 printf(" uuid="UUID_FMT
"\n", UUID_ARGS(&l1
->header_
.uuid
));
1980 print_idl_row_updated_link1(l1
, step
);
1984 print_idl_row_link2(const struct idltest_link2
*l2
, int step
)
1986 printf("%03d: i=%"PRId64
" l1=", step
, l2
->i
);
1988 printf("%"PRId64
, l2
->l1
->i
);
1990 printf(" uuid="UUID_FMT
"\n", UUID_ARGS(&l2
->header_
.uuid
));
1991 print_idl_row_updated_link2(l2
, step
);
1995 print_idl_row_singleton(const struct idltest_singleton
*sng
, int step
)
1997 printf("%03d: name=%s", step
, sng
->name
);
1998 printf(" uuid="UUID_FMT
"\n", UUID_ARGS(&sng
->header_
.uuid
));
1999 print_idl_row_updated_singleton(sng
, step
);
2003 print_idl(struct ovsdb_idl
*idl
, int step
)
2005 const struct idltest_simple
*s
;
2006 const struct idltest_link1
*l1
;
2007 const struct idltest_link2
*l2
;
2008 const struct idltest_singleton
*sng
;
2011 IDLTEST_SIMPLE_FOR_EACH (s
, idl
) {
2012 print_idl_row_simple(s
, step
);
2015 IDLTEST_LINK1_FOR_EACH (l1
, idl
) {
2016 print_idl_row_link1(l1
, step
);
2019 IDLTEST_LINK2_FOR_EACH (l2
, idl
) {
2020 print_idl_row_link2(l2
, step
);
2023 IDLTEST_SINGLETON_FOR_EACH (sng
, idl
) {
2024 print_idl_row_singleton(sng
, step
);
2028 printf("%03d: empty\n", step
);
2033 print_idl_track(struct ovsdb_idl
*idl
, int step
, unsigned int seqno
)
2035 const struct idltest_simple
*s
;
2036 const struct idltest_link1
*l1
;
2037 const struct idltest_link2
*l2
;
2040 IDLTEST_SIMPLE_FOR_EACH_TRACKED (s
, idl
) {
2041 if (idltest_simple_row_get_seqno(s
, OVSDB_IDL_CHANGE_DELETE
) >= seqno
) {
2042 printf("%03d: ##deleted## uuid="UUID_FMT
"\n", step
, UUID_ARGS(&s
->header_
.uuid
));
2044 print_idl_row_simple(s
, step
);
2048 IDLTEST_LINK1_FOR_EACH_TRACKED (l1
, idl
) {
2049 if (idltest_simple_row_get_seqno(s
, OVSDB_IDL_CHANGE_DELETE
) >= seqno
) {
2050 printf("%03d: ##deleted## uuid="UUID_FMT
"\n", step
, UUID_ARGS(&s
->header_
.uuid
));
2052 print_idl_row_link1(l1
, step
);
2056 IDLTEST_LINK2_FOR_EACH_TRACKED (l2
, idl
) {
2057 if (idltest_simple_row_get_seqno(s
, OVSDB_IDL_CHANGE_DELETE
) >= seqno
) {
2058 printf("%03d: ##deleted## uuid="UUID_FMT
"\n", step
, UUID_ARGS(&s
->header_
.uuid
));
2060 print_idl_row_link2(l2
, step
);
2065 printf("%03d: empty\n", step
);
2070 parse_uuids(const struct json
*json
, struct ovsdb_symbol_table
*symtab
,
2075 if (json
->type
== JSON_STRING
&& uuid_from_string(&uuid
, json
->string
)) {
2076 char *name
= xasprintf("#%"PRIuSIZE
"#", *n
);
2077 fprintf(stderr
, "%s = "UUID_FMT
"\n", name
, UUID_ARGS(&uuid
));
2078 ovsdb_symbol_table_put(symtab
, name
, &uuid
, false);
2081 } else if (json
->type
== JSON_ARRAY
) {
2084 for (i
= 0; i
< json
->array
.n
; i
++) {
2085 parse_uuids(json
->array
.elems
[i
], symtab
, n
);
2087 } else if (json
->type
== JSON_OBJECT
) {
2088 const struct shash_node
*node
;
2090 SHASH_FOR_EACH (node
, json_object(json
)) {
2091 parse_uuids(node
->data
, symtab
, n
);
2097 substitute_uuids(struct json
*json
, const struct ovsdb_symbol_table
*symtab
)
2099 if (json
->type
== JSON_STRING
) {
2100 const struct ovsdb_symbol
*symbol
;
2102 symbol
= ovsdb_symbol_table_get(symtab
, json
->string
);
2105 json
->string
= xasprintf(UUID_FMT
, UUID_ARGS(&symbol
->uuid
));
2107 } else if (json
->type
== JSON_ARRAY
) {
2110 for (i
= 0; i
< json
->array
.n
; i
++) {
2111 substitute_uuids(json
->array
.elems
[i
], symtab
);
2113 } else if (json
->type
== JSON_OBJECT
) {
2114 const struct shash_node
*node
;
2116 SHASH_FOR_EACH (node
, json_object(json
)) {
2117 substitute_uuids(node
->data
, symtab
);
2122 static const struct idltest_simple
*
2123 idltest_find_simple(struct ovsdb_idl
*idl
, int i
)
2125 const struct idltest_simple
*s
;
2127 IDLTEST_SIMPLE_FOR_EACH (s
, idl
) {
2136 idl_set(struct ovsdb_idl
*idl
, char *commands
, int step
)
2138 char *cmd
, *save_ptr1
= NULL
;
2139 struct ovsdb_idl_txn
*txn
;
2140 enum ovsdb_idl_txn_status status
;
2141 bool increment
= false;
2143 txn
= ovsdb_idl_txn_create(idl
);
2144 ovsdb_idl_check_consistency(idl
);
2145 for (cmd
= strtok_r(commands
, ",", &save_ptr1
); cmd
;
2146 cmd
= strtok_r(NULL
, ",", &save_ptr1
)) {
2147 char *save_ptr2
= NULL
;
2148 char *name
, *arg1
, *arg2
, *arg3
;
2150 name
= strtok_r(cmd
, " ", &save_ptr2
);
2151 arg1
= strtok_r(NULL
, " ", &save_ptr2
);
2152 arg2
= strtok_r(NULL
, " ", &save_ptr2
);
2153 arg3
= strtok_r(NULL
, " ", &save_ptr2
);
2155 if (!strcmp(name
, "set")) {
2156 const struct idltest_simple
*s
;
2159 ovs_fatal(0, "\"set\" command requires 3 arguments");
2162 s
= idltest_find_simple(idl
, atoi(arg1
));
2164 ovs_fatal(0, "\"set\" command asks for nonexistent "
2165 "i=%d", atoi(arg1
));
2168 if (!strcmp(arg2
, "b")) {
2169 idltest_simple_set_b(s
, atoi(arg3
));
2170 } else if (!strcmp(arg2
, "s")) {
2171 idltest_simple_set_s(s
, arg3
);
2172 } else if (!strcmp(arg2
, "u")) {
2174 if (!uuid_from_string(&uuid
, arg3
)) {
2175 ovs_fatal(0, "\"%s\" is not a valid UUID", arg3
);
2177 idltest_simple_set_u(s
, uuid
);
2178 } else if (!strcmp(arg2
, "r")) {
2179 idltest_simple_set_r(s
, atof(arg3
));
2181 ovs_fatal(0, "\"set\" command asks for unknown column %s",
2184 } else if (!strcmp(name
, "insert")) {
2185 struct idltest_simple
*s
;
2187 if (!arg1
|| arg2
) {
2188 ovs_fatal(0, "\"insert\" command requires 1 argument");
2191 s
= idltest_simple_insert(txn
);
2192 idltest_simple_set_i(s
, atoi(arg1
));
2193 } else if (!strcmp(name
, "delete")) {
2194 const struct idltest_simple
*s
;
2196 if (!arg1
|| arg2
) {
2197 ovs_fatal(0, "\"delete\" command requires 1 argument");
2200 s
= idltest_find_simple(idl
, atoi(arg1
));
2202 ovs_fatal(0, "\"delete\" command asks for nonexistent "
2203 "i=%d", atoi(arg1
));
2205 idltest_simple_delete(s
);
2206 } else if (!strcmp(name
, "verify")) {
2207 const struct idltest_simple
*s
;
2209 if (!arg2
|| arg3
) {
2210 ovs_fatal(0, "\"verify\" command requires 2 arguments");
2213 s
= idltest_find_simple(idl
, atoi(arg1
));
2215 ovs_fatal(0, "\"verify\" command asks for nonexistent "
2216 "i=%d", atoi(arg1
));
2219 if (!strcmp(arg2
, "i")) {
2220 idltest_simple_verify_i(s
);
2221 } else if (!strcmp(arg2
, "b")) {
2222 idltest_simple_verify_b(s
);
2223 } else if (!strcmp(arg2
, "s")) {
2224 idltest_simple_verify_s(s
);
2225 } else if (!strcmp(arg2
, "u")) {
2226 idltest_simple_verify_s(s
);
2227 } else if (!strcmp(arg2
, "r")) {
2228 idltest_simple_verify_r(s
);
2230 ovs_fatal(0, "\"verify\" command asks for unknown column %s",
2233 } else if (!strcmp(name
, "increment")) {
2234 const struct idltest_simple
*s
;
2236 if (!arg1
|| arg2
) {
2237 ovs_fatal(0, "\"increment\" command requires 1 argument");
2240 s
= idltest_find_simple(idl
, atoi(arg1
));
2242 ovs_fatal(0, "\"set\" command asks for nonexistent "
2243 "i=%d", atoi(arg1
));
2246 ovsdb_idl_txn_increment(txn
, &s
->header_
, &idltest_simple_col_i
,
2249 } else if (!strcmp(name
, "abort")) {
2250 ovsdb_idl_txn_abort(txn
);
2251 ovsdb_idl_check_consistency(idl
);
2253 } else if (!strcmp(name
, "destroy")) {
2254 printf("%03d: destroy\n", step
);
2255 ovsdb_idl_txn_destroy(txn
);
2256 ovsdb_idl_check_consistency(idl
);
2259 ovs_fatal(0, "unknown command %s", name
);
2261 ovsdb_idl_check_consistency(idl
);
2264 status
= ovsdb_idl_txn_commit_block(txn
);
2265 printf("%03d: commit, status=%s",
2266 step
, ovsdb_idl_txn_status_to_string(status
));
2268 printf(", increment=%"PRId64
,
2269 ovsdb_idl_txn_get_increment_new_value(txn
));
2272 ovsdb_idl_txn_destroy(txn
);
2273 ovsdb_idl_check_consistency(idl
);
2276 static const struct ovsdb_idl_table_class
*
2277 find_table_class(const char *name
)
2279 if (!strcmp(name
, "simple")) {
2280 return &idltest_table_simple
;
2281 } else if (!strcmp(name
, "link1")) {
2282 return &idltest_table_link1
;
2283 } else if (!strcmp(name
, "link2")) {
2284 return &idltest_table_link2
;
2290 parse_simple_json_clause(struct ovsdb_idl_condition
*cond
,
2291 enum ovsdb_function function
,
2292 const char *column
, const struct json
*arg
)
2294 if (!strcmp(column
, "b")) {
2295 idltest_simple_add_clause_b(cond
, function
, json_boolean(arg
));
2296 } else if (!strcmp(column
, "i")) {
2297 idltest_simple_add_clause_i(cond
, function
, json_integer(arg
));
2298 } else if (!strcmp(column
, "s")) {
2299 idltest_simple_add_clause_s(cond
, function
, json_string(arg
));
2300 } else if (!strcmp(column
, "u")) {
2302 if (!uuid_from_string(&uuid
, json_string(arg
))) {
2303 ovs_fatal(0, "\"%s\" is not a valid UUID", json_string(arg
));
2305 idltest_simple_add_clause_u(cond
, function
, uuid
);
2306 } else if (!strcmp(column
, "r")) {
2307 idltest_simple_add_clause_r(cond
, function
, json_real(arg
));
2309 ovs_fatal(0, "Unsupported columns name %s", column
);
2314 parse_link1_json_clause(struct ovsdb_idl_condition
*cond
,
2315 enum ovsdb_function function
,
2316 const char *column
, const struct json
*arg
)
2318 if (!strcmp(column
, "i")) {
2319 idltest_link1_add_clause_i(cond
, function
, json_integer(arg
));
2321 ovs_fatal(0, "Unsupported columns name %s", column
);
2326 parse_link2_json_clause(struct ovsdb_idl_condition
*cond
,
2327 enum ovsdb_function function
,
2328 const char *column
, const struct json
*arg
)
2330 if (!strcmp(column
, "i")) {
2331 idltest_link2_add_clause_i(cond
, function
, json_integer(arg
));
2333 ovs_fatal(0, "Unsupported columns name %s", column
);
2338 update_conditions(struct ovsdb_idl
*idl
, char *commands
)
2340 char *cmd
, *save_ptr1
= NULL
;
2341 const struct ovsdb_idl_table_class
*tc
;
2343 for (cmd
= strtok_r(commands
, ";", &save_ptr1
); cmd
;
2344 cmd
= strtok_r(NULL
, ";", &save_ptr1
)) {
2345 char *save_ptr2
= NULL
;
2346 char *table_name
= strtok_r(cmd
, " ", &save_ptr2
);
2347 struct json
*json
= parse_json(save_ptr2
);
2350 if (json
->type
!= JSON_ARRAY
) {
2351 ovs_fatal(0, "condition should be an array");
2354 tc
= find_table_class(table_name
);
2356 ovs_fatal(0, "Table %s does not exist", table_name
);
2359 struct ovsdb_idl_condition cond
= OVSDB_IDL_CONDITION_INIT(&cond
);
2360 for (i
= 0; i
< json
->array
.n
; i
++) {
2361 const struct json
*clause
= json
->array
.elems
[i
];
2362 if (clause
->type
== JSON_TRUE
) {
2363 ovsdb_idl_condition_add_clause_true(&cond
);
2364 } else if (clause
->type
!= JSON_ARRAY
|| clause
->array
.n
!= 3
2365 || clause
->array
.elems
[0]->type
!= JSON_STRING
2366 || clause
->array
.elems
[1]->type
!= JSON_STRING
) {
2367 ovs_fatal(0, "Error parsing condition");
2369 enum ovsdb_function function
;
2370 const char *function_s
= json_string(clause
->array
.elems
[1]);
2371 struct ovsdb_error
*error
= ovsdb_function_from_string(
2372 function_s
, &function
);
2374 ovs_fatal(0, "unknown clause function %s", function_s
);
2377 const char *column
= json_string(clause
->array
.elems
[0]);
2378 const struct json
*arg
= clause
->array
.elems
[2];
2379 if (!strcmp(table_name
, "simple")) {
2380 parse_simple_json_clause(&cond
, function
, column
, arg
);
2381 } else if (!strcmp(table_name
, "link1")) {
2382 parse_link1_json_clause(&cond
, function
, column
, arg
);
2383 } else if (!strcmp(table_name
, "link2")) {
2384 parse_link2_json_clause(&cond
, function
, column
, arg
);
2389 unsigned int seqno
= ovsdb_idl_get_condition_seqno(idl
);
2390 unsigned int next_seqno
= ovsdb_idl_set_condition(idl
, tc
, &cond
);
2391 if (seqno
== next_seqno
) {
2392 ovs_fatal(0, "condition unchanged");
2394 ovsdb_idl_condition_destroy(&cond
);
2400 do_idl(struct ovs_cmdl_context
*ctx
)
2402 struct jsonrpc
*rpc
;
2403 struct ovsdb_idl
*idl
;
2404 unsigned int seqno
= 0;
2405 struct ovsdb_symbol_table
*symtab
;
2412 track
= ((struct test_ovsdb_pvt_context
*)(ctx
->pvt
))->track
;
2414 idl
= ovsdb_idl_create(ctx
->argv
[1], &idltest_idl_class
, true, true);
2415 ovsdb_idl_set_leader_only(idl
, false);
2416 if (ctx
->argc
> 2) {
2417 struct stream
*stream
;
2419 error
= stream_open_block(jsonrpc_stream_open(ctx
->argv
[1], &stream
,
2420 DSCP_DEFAULT
), -1, &stream
);
2422 ovs_fatal(error
, "failed to connect to \"%s\"", ctx
->argv
[1]);
2424 rpc
= jsonrpc_open(stream
);
2430 ovsdb_idl_track_add_all(idl
);
2433 setvbuf(stdout
, NULL
, _IONBF
, 0);
2435 symtab
= ovsdb_symbol_table_create();
2436 const char cond_s
[] = "condition ";
2437 if (ctx
->argc
> 2 && strstr(ctx
->argv
[2], cond_s
)) {
2438 update_conditions(idl
, ctx
->argv
[2] + strlen(cond_s
));
2439 printf("%03d: change conditions\n", step
++);
2444 for (; i
< ctx
->argc
; i
++) {
2445 char *arg
= ctx
->argv
[i
];
2446 struct jsonrpc_msg
*request
, *reply
;
2449 /* The previous transaction didn't change anything. */
2452 /* Wait for update. */
2455 ovsdb_idl_check_consistency(idl
);
2456 if (ovsdb_idl_get_seqno(idl
) != seqno
) {
2461 ovsdb_idl_wait(idl
);
2468 print_idl_track(idl
, step
++, ovsdb_idl_get_seqno(idl
));
2469 ovsdb_idl_track_clear(idl
);
2471 print_idl(idl
, step
++);
2474 seqno
= ovsdb_idl_get_seqno(idl
);
2476 if (!strcmp(arg
, "reconnect")) {
2477 printf("%03d: reconnect\n", step
++);
2478 ovsdb_idl_force_reconnect(idl
);
2479 } else if (!strncmp(arg
, cond_s
, strlen(cond_s
))) {
2480 update_conditions(idl
, arg
+ strlen(cond_s
));
2481 printf("%03d: change conditions\n", step
++);
2482 } else if (arg
[0] != '[') {
2483 idl_set(idl
, arg
, step
++);
2485 struct json
*json
= parse_json(arg
);
2486 substitute_uuids(json
, symtab
);
2487 request
= jsonrpc_create_request("transact", json
, NULL
);
2488 error
= jsonrpc_transact_block(rpc
, request
, &reply
);
2489 if (error
|| reply
->error
) {
2490 ovs_fatal(error
, "jsonrpc transaction failed");
2492 printf("%03d: ", step
++);
2493 if (reply
->result
) {
2494 parse_uuids(reply
->result
, symtab
, &n_uuids
);
2496 json_destroy(reply
->id
);
2498 print_and_free_json(jsonrpc_msg_to_json(reply
));
2501 ovsdb_symbol_table_destroy(symtab
);
2508 ovsdb_idl_check_consistency(idl
);
2509 if (ovsdb_idl_get_seqno(idl
) != seqno
) {
2512 ovsdb_idl_wait(idl
);
2515 print_idl(idl
, step
++);
2516 ovsdb_idl_track_clear(idl
);
2517 ovsdb_idl_destroy(idl
);
2518 printf("%03d: done\n", step
);
2522 print_idl_row_simple2(const struct idltest_simple2
*s
, int step
)
2525 const struct ovsdb_datum
*smap
, *imap
;
2527 smap
= idltest_simple2_get_smap(s
, OVSDB_TYPE_STRING
, OVSDB_TYPE_STRING
);
2528 imap
= idltest_simple2_get_imap(s
, OVSDB_TYPE_INTEGER
, OVSDB_TYPE_STRING
);
2529 printf("%03d: name=%s smap=[",
2531 for (i
= 0; i
< smap
->n
; i
++) {
2532 printf("[%s : %s]%s", smap
->keys
[i
].string
, smap
->values
[i
].string
,
2533 i
< smap
->n
-1? ",": "");
2536 for (i
= 0; i
< imap
->n
; i
++) {
2537 printf("[%"PRId64
" : %s]%s", imap
->keys
[i
].integer
, imap
->values
[i
].string
,
2538 i
< imap
->n
-1? ",":"");
2544 dump_simple2(struct ovsdb_idl
*idl
,
2545 const struct idltest_simple2
*myRow
,
2548 IDLTEST_SIMPLE2_FOR_EACH(myRow
, idl
) {
2549 print_idl_row_simple2(myRow
, step
);
2554 do_idl_partial_update_map_column(struct ovs_cmdl_context
*ctx
)
2556 struct ovsdb_idl
*idl
;
2557 struct ovsdb_idl_txn
*myTxn
;
2558 const struct idltest_simple2
*myRow
;
2559 const struct ovsdb_datum
*smap
, *imap OVS_UNUSED
;
2561 char key_to_delete
[100];
2563 idl
= ovsdb_idl_create(ctx
->argv
[1], &idltest_idl_class
, false, true);
2564 ovsdb_idl_add_table(idl
, &idltest_table_simple2
);
2565 ovsdb_idl_add_column(idl
, &idltest_simple2_col_name
);
2566 ovsdb_idl_add_column(idl
, &idltest_simple2_col_smap
);
2567 ovsdb_idl_add_column(idl
, &idltest_simple2_col_imap
);
2568 ovsdb_idl_get_initial_snapshot(idl
);
2569 setvbuf(stdout
, NULL
, _IONBF
, 0);
2572 /* Display original data in table. */
2574 printf("%03d: Getting records\n", step
++);
2575 dump_simple2(idl
, myRow
, step
++);
2577 /* Insert new elements in different map columns. */
2578 myRow
= idltest_simple2_first(idl
);
2579 myTxn
= ovsdb_idl_txn_create(idl
);
2580 idltest_simple2_get_smap(myRow
, OVSDB_TYPE_STRING
,
2582 idltest_simple2_update_smap_setkey(myRow
, "key1", "myList1");
2583 imap
= idltest_simple2_get_imap(myRow
, OVSDB_TYPE_INTEGER
,
2585 idltest_simple2_update_imap_setkey(myRow
, 3, "myids2");
2586 idltest_simple2_set_name(myRow
, "String2");
2587 ovsdb_idl_txn_commit_block(myTxn
);
2588 ovsdb_idl_txn_destroy(myTxn
);
2589 ovsdb_idl_get_initial_snapshot(idl
);
2590 printf("%03d: After insert element\n", step
++);
2591 dump_simple2(idl
, myRow
, step
++);
2593 /* Insert duplicate element. */
2594 myTxn
= ovsdb_idl_txn_create(idl
);
2595 idltest_simple2_update_smap_setkey(myRow
, "key1", "myList1");
2596 ovsdb_idl_txn_commit_block(myTxn
);
2597 ovsdb_idl_txn_destroy(myTxn
);
2598 ovsdb_idl_get_initial_snapshot(idl
);
2599 printf("%03d: After insert duplicated element\n", step
++);
2600 dump_simple2(idl
, myRow
, step
++);
2602 /* Deletes an element of a map column. */
2603 myRow
= idltest_simple2_first(idl
);
2604 myTxn
= ovsdb_idl_txn_create(idl
);
2605 smap
= idltest_simple2_get_smap(myRow
, OVSDB_TYPE_STRING
,
2607 strcpy(key_to_delete
, smap
->keys
[0].string
);
2608 idltest_simple2_update_smap_delkey(myRow
, smap
->keys
[0].string
);
2609 ovsdb_idl_txn_commit_block(myTxn
);
2610 ovsdb_idl_txn_destroy(myTxn
);
2611 ovsdb_idl_get_initial_snapshot(idl
);
2612 printf("%03d: After delete element\n", step
++);
2613 dump_simple2(idl
, myRow
, step
++);
2615 /* Try to delete a deleted element of a map column. */
2616 myTxn
= ovsdb_idl_txn_create(idl
);
2617 idltest_simple2_update_smap_delkey(myRow
, key_to_delete
);
2618 ovsdb_idl_txn_commit_block(myTxn
);
2619 ovsdb_idl_txn_destroy(myTxn
);
2620 ovsdb_idl_get_initial_snapshot(idl
);
2621 printf("%03d: After trying to delete a deleted element\n", step
++);
2622 dump_simple2(idl
, myRow
, step
++);
2624 ovsdb_idl_destroy(idl
);
2625 printf("%03d: End test\n", step
);
2629 print_idl_row_simple3(const struct idltest_simple3
*s
, int step
)
2632 const struct ovsdb_datum
*uset
;
2633 const struct ovsdb_datum
*uref
;
2635 uset
= idltest_simple3_get_uset(s
, OVSDB_TYPE_UUID
);
2636 printf("%03d: name=%s uset=[",
2638 for (i
= 0; i
< uset
->n
; i
++) {
2639 printf("["UUID_FMT
"]%s", UUID_ARGS(&(uset
->keys
[i
].uuid
)), i
< uset
->n
-1? ",": "");
2641 uref
= idltest_simple3_get_uref(s
, OVSDB_TYPE_UUID
);
2643 for (i
= 0; i
< uref
->n
; i
++) {
2644 printf("["UUID_FMT
"]%s", UUID_ARGS(&(uref
->keys
[i
].uuid
)), i
< uref
->n
-1? ",": "");
2650 dump_simple3(struct ovsdb_idl
*idl
,
2651 const struct idltest_simple3
*myRow
,
2654 IDLTEST_SIMPLE3_FOR_EACH(myRow
, idl
) {
2655 print_idl_row_simple3(myRow
, step
);
2660 do_idl_partial_update_set_column(struct ovs_cmdl_context
*ctx
)
2662 struct ovsdb_idl
*idl
;
2663 struct ovsdb_idl_txn
*myTxn
;
2664 const struct idltest_simple3
*myRow
;
2665 struct idltest_simple4
*myRow2
;
2666 const struct ovsdb_datum
*uset OVS_UNUSED
;
2667 const struct ovsdb_datum
*uref OVS_UNUSED
;
2670 idl
= ovsdb_idl_create(ctx
->argv
[1], &idltest_idl_class
, false, true);
2671 ovsdb_idl_add_table(idl
, &idltest_table_simple3
);
2672 ovsdb_idl_add_column(idl
, &idltest_simple3_col_name
);
2673 ovsdb_idl_add_column(idl
, &idltest_simple3_col_uset
);
2674 ovsdb_idl_add_column(idl
, &idltest_simple3_col_uref
);
2675 ovsdb_idl_add_table(idl
, &idltest_table_simple4
);
2676 ovsdb_idl_add_column(idl
, &idltest_simple4_col_name
);
2677 ovsdb_idl_get_initial_snapshot(idl
);
2678 setvbuf(stdout
, NULL
, _IONBF
, 0);
2681 /* Display original data in table. */
2683 printf("%03d: Getting records\n", step
++);
2684 dump_simple3(idl
, myRow
, step
++);
2686 /* Insert new elements in different map columns. */
2687 myRow
= idltest_simple3_first(idl
);
2688 myTxn
= ovsdb_idl_txn_create(idl
);
2689 idltest_simple3_get_uset(myRow
, OVSDB_TYPE_UUID
);
2690 struct uuid uuid_to_add
;
2691 uuid_from_string(&uuid_to_add
, "001e43d2-dd3f-4616-ab6a-83a490bb0991");
2692 idltest_simple3_update_uset_addvalue(myRow
, uuid_to_add
);
2693 idltest_simple3_set_name(myRow
, "String2");
2694 ovsdb_idl_txn_commit_block(myTxn
);
2695 ovsdb_idl_txn_destroy(myTxn
);
2696 ovsdb_idl_get_initial_snapshot(idl
);
2697 printf("%03d: After rename+add new value\n", step
++);
2698 dump_simple3(idl
, myRow
, step
++);
2700 /* Insert duplicate element. */
2701 myTxn
= ovsdb_idl_txn_create(idl
);
2702 struct uuid uuid_to_add2
;
2703 uuid_from_string(&uuid_to_add2
, "0026b3ba-571b-4729-8227-d860a5210ab8");
2704 idltest_simple3_update_uset_addvalue(myRow
, uuid_to_add2
);
2705 ovsdb_idl_txn_commit_block(myTxn
);
2706 ovsdb_idl_txn_destroy(myTxn
);
2707 ovsdb_idl_get_initial_snapshot(idl
);
2708 printf("%03d: After add new value\n", step
++);
2709 dump_simple3(idl
, myRow
, step
++);
2711 /* Deletes an element of a set column. */
2712 myRow
= idltest_simple3_first(idl
);
2713 myTxn
= ovsdb_idl_txn_create(idl
);
2714 uset
= idltest_simple3_get_uset(myRow
, OVSDB_TYPE_UUID
);
2715 idltest_simple3_update_uset_delvalue(myRow
, uuid_to_add
);
2716 ovsdb_idl_txn_commit_block(myTxn
);
2717 ovsdb_idl_txn_destroy(myTxn
);
2718 ovsdb_idl_get_initial_snapshot(idl
);
2719 printf("%03d: After delete value\n", step
++);
2720 dump_simple3(idl
, myRow
, step
++);
2722 /* Try to delete a deleted element of a map column. */
2723 myRow
= idltest_simple3_first(idl
);
2724 myTxn
= ovsdb_idl_txn_create(idl
);
2725 idltest_simple3_update_uset_delvalue(myRow
, uuid_to_add
);
2726 ovsdb_idl_txn_commit_block(myTxn
);
2727 ovsdb_idl_txn_destroy(myTxn
);
2728 ovsdb_idl_get_initial_snapshot(idl
);
2729 printf("%03d: After trying to delete a deleted value\n", step
++);
2730 dump_simple3(idl
, myRow
, step
++);
2732 /* Adds to a table and update a strong reference in another table. */
2733 myRow
= idltest_simple3_first(idl
);
2734 myTxn
= ovsdb_idl_txn_create(idl
);
2735 myRow2
= idltest_simple4_insert(myTxn
);
2736 idltest_simple4_set_name(myRow2
, "test");
2737 idltest_simple3_update_uref_addvalue(myRow
, myRow2
);
2738 ovsdb_idl_txn_commit_block(myTxn
);
2739 ovsdb_idl_txn_destroy(myTxn
);
2740 ovsdb_idl_get_initial_snapshot(idl
);
2741 printf("%03d: After add to other table + set of strong ref\n", step
++);
2742 dump_simple3(idl
, myRow
, step
++);
2743 ovsdb_idl_destroy(idl
);
2744 printf("%03d: End test\n", step
);
2748 do_idl_compound_index_with_ref(struct ovs_cmdl_context
*ctx
)
2750 struct ovsdb_idl
*idl
;
2751 struct ovsdb_idl_txn
*myTxn
;
2752 const struct idltest_simple3
*myRow
;
2753 struct idltest_simple4
*myRow2
;
2754 const struct ovsdb_datum
*uset OVS_UNUSED
;
2755 const struct ovsdb_datum
*uref OVS_UNUSED
;
2758 idl
= ovsdb_idl_create(ctx
->argv
[1], &idltest_idl_class
, false, true);
2759 ovsdb_idl_add_table(idl
, &idltest_table_simple3
);
2760 ovsdb_idl_add_column(idl
, &idltest_simple3_col_name
);
2761 ovsdb_idl_add_column(idl
, &idltest_simple3_col_uset
);
2762 ovsdb_idl_add_column(idl
, &idltest_simple3_col_uref
);
2763 ovsdb_idl_add_table(idl
, &idltest_table_simple4
);
2764 ovsdb_idl_add_column(idl
, &idltest_simple4_col_name
);
2766 struct ovsdb_idl_index
*index
= ovsdb_idl_index_create1(
2767 idl
, &idltest_simple3_col_uref
);
2769 ovsdb_idl_get_initial_snapshot(idl
);
2771 setvbuf(stdout
, NULL
, _IONBF
, 0);
2774 /* Adds to a table and update a strong reference in another table. */
2775 myTxn
= ovsdb_idl_txn_create(idl
);
2776 myRow
= idltest_simple3_insert(myTxn
);
2777 myRow2
= idltest_simple4_insert(myTxn
);
2778 idltest_simple4_set_name(myRow2
, "test");
2779 idltest_simple3_update_uref_addvalue(myRow
, myRow2
);
2780 ovsdb_idl_txn_commit_block(myTxn
);
2781 ovsdb_idl_txn_destroy(myTxn
);
2782 ovsdb_idl_get_initial_snapshot(idl
);
2783 printf("%03d: After add to other table + set of strong ref\n", step
++);
2784 dump_simple3(idl
, myRow
, step
++);
2786 myRow2
= (struct idltest_simple4
*) idltest_simple4_first(idl
);
2787 printf("%03d: check simple4: %s\n", step
++,
2788 myRow2
? "not empty" : "empty");
2790 /* Use index to query the row with reference */
2792 struct idltest_simple3
*equal
= idltest_simple3_index_init_row(index
);
2793 myRow2
= (struct idltest_simple4
*) idltest_simple4_first(idl
);
2794 idltest_simple3_index_set_uref(equal
, &myRow2
, 1);
2795 printf("%03d: Query using index with reference\n", step
++);
2796 IDLTEST_SIMPLE3_FOR_EACH_EQUAL (myRow
, equal
, index
) {
2797 print_idl_row_simple3(myRow
, step
++);
2799 idltest_simple3_index_destroy_row(equal
);
2801 /* Delete the row with reference */
2802 myTxn
= ovsdb_idl_txn_create(idl
);
2803 myRow
= idltest_simple3_first(idl
);
2804 idltest_simple3_delete(myRow
);
2805 ovsdb_idl_txn_commit_block(myTxn
);
2806 ovsdb_idl_txn_destroy(myTxn
);
2807 ovsdb_idl_get_initial_snapshot(idl
);
2808 printf("%03d: After delete\n", step
++);
2809 dump_simple3(idl
, myRow
, step
++);
2811 myRow2
= (struct idltest_simple4
*) idltest_simple4_first(idl
);
2812 printf("%03d: check simple4: %s\n", step
++,
2813 myRow2
? "not empty" : "empty");
2815 ovsdb_idl_destroy(idl
);
2816 printf("%03d: End test\n", step
);
2821 test_idl_compound_index_single_column(struct ovsdb_idl
*idl
,
2822 struct ovsdb_idl_index
*s_index
,
2823 struct ovsdb_idl_index
*i_index
)
2825 const struct idltest_simple
*myRow
;
2826 struct ovsdb_idl_txn
*txn
;
2829 /* Display records by string index. */
2831 IDLTEST_SIMPLE_FOR_EACH_BYINDEX (myRow
, s_index
) {
2832 printf("%03d: s=%s i=%"PRId64
" b=%s r=%f\n", step
, myRow
->s
,
2833 myRow
->i
, myRow
->b
?"True":"False", myRow
->r
);
2835 /* Display records by integer index. */
2837 IDLTEST_SIMPLE_FOR_EACH_BYINDEX (myRow
, i_index
) {
2838 printf("%03d: i=%"PRId64
" s=%s b=%s r=%f\n", step
, myRow
->i
,
2839 myRow
->s
, myRow
->b
?"True":"False", myRow
->r
);
2841 /* Display records by string index -> s_index with filtering
2842 * where s=\"List001\
2845 struct idltest_simple
*equal
= idltest_simple_index_init_row(s_index
);
2846 idltest_simple_index_set_s(equal
, "List001");
2847 ovs_assert(strcmp(equal
->s
, "List001") == 0);
2848 IDLTEST_SIMPLE_FOR_EACH_EQUAL (myRow
, equal
, s_index
) {
2849 printf("%03d: s=%s i=%"PRId64
" b=%s r=%f\n", step
, myRow
->s
,
2850 myRow
->i
, myRow
->b
?"True":"False", myRow
->r
);
2852 /* Display records by integer index -> i_index with filtering where i=5 */
2854 idltest_simple_index_set_i(equal
, 5);
2855 ovs_assert(equal
->i
== 5);
2856 IDLTEST_SIMPLE_FOR_EACH_EQUAL (myRow
, equal
, i_index
) {
2857 printf("%03d: i=%"PRId64
" s=%s b=%s r=%f\n", step
, myRow
->i
,
2858 myRow
->s
, myRow
->b
?"True":"False", myRow
->r
);
2860 /* Display records by integer index -> i_index in range i=[3,7] */
2862 struct idltest_simple
*from
, *to
;
2863 from
= idltest_simple_index_init_row(i_index
);
2864 idltest_simple_index_set_i(from
, 3);
2865 ovs_assert(from
->i
== 3);
2866 to
= idltest_simple_index_init_row(i_index
);
2867 idltest_simple_index_set_i(to
, 7);
2868 ovs_assert(to
->i
== 7);
2869 IDLTEST_SIMPLE_FOR_EACH_RANGE (myRow
, from
, to
, i_index
) {
2870 printf("%03d: i=%"PRId64
" s=%s b=%s r=%f\n", step
, myRow
->i
,
2871 myRow
->s
, myRow
->b
?"True":"False", myRow
->r
);
2873 /* Delete record i=4 and insert i=54 by integer index -> i_index */
2875 struct idltest_simple
*toDelete
, *toInsert
;
2876 toDelete
= idltest_simple_index_init_row(i_index
);
2877 idltest_simple_index_set_i(toDelete
, 4);
2878 ovs_assert(toDelete
->i
== 4);
2879 myRow
= idltest_simple_index_find(i_index
, toDelete
);
2881 ovs_assert(myRow
->i
== 4);
2882 txn
= ovsdb_idl_txn_create(idl
);
2883 idltest_simple_delete(myRow
);
2884 myRow
= idltest_simple_index_find(i_index
, toDelete
);
2886 myRow
= idltest_simple_insert(txn
);
2887 idltest_simple_set_i(myRow
, 54);
2888 idltest_simple_set_s(myRow
, "Lista054");
2889 toInsert
= idltest_simple_index_init_row(i_index
);
2890 idltest_simple_index_set_i(toInsert
, 54);
2891 myRow
= idltest_simple_index_find(i_index
, toInsert
);
2893 ovs_assert(myRow
->i
== 54);
2894 ovs_assert(!strcmp(myRow
->s
, "Lista054"));
2895 ovsdb_idl_txn_commit_block(txn
);
2896 ovsdb_idl_txn_destroy(txn
);
2897 idltest_simple_index_set_i(to
, 60);
2898 printf("Expected 60, stored %"PRId64
"\n", to
->i
);
2899 ovs_assert(to
->i
== 60);
2900 IDLTEST_SIMPLE_FOR_EACH_RANGE (myRow
, from
, to
, i_index
) {
2901 printf("%03d: i=%"PRId64
" s=%s b=%s r=%f\n", step
, myRow
->i
,
2902 myRow
->s
, myRow
->b
?"True":"False", myRow
->r
);
2905 /* Update record i=10 to i=30, make sure index is updated accordingly */
2907 struct idltest_simple
*toUpdate
;
2908 toUpdate
= idltest_simple_index_init_row(i_index
);
2909 idltest_simple_index_set_i(toUpdate
, 10);
2910 ovs_assert(toUpdate
->i
== 10);
2911 myRow
= idltest_simple_index_find(i_index
, toUpdate
);
2913 ovs_assert(myRow
->i
== 10);
2914 txn
= ovsdb_idl_txn_create(idl
);
2915 idltest_simple_set_i(myRow
, 30);
2916 myRow
= idltest_simple_index_find(i_index
, toUpdate
);
2918 ovsdb_idl_txn_commit_block(txn
);
2919 ovsdb_idl_txn_destroy(txn
);
2920 idltest_simple_index_set_i(to
, 60);
2921 printf("Expected 60, stored %"PRId64
"\n", to
->i
);
2922 ovs_assert(to
->i
== 60);
2923 IDLTEST_SIMPLE_FOR_EACH_RANGE (myRow
, from
, to
, i_index
) {
2924 printf("%03d: i=%"PRId64
" s=%s b=%s r=%f\n", step
, myRow
->i
,
2925 myRow
->s
, myRow
->b
?"True":"False", myRow
->r
);
2928 /* Test special-case range, "from" and "to" are both NULL,
2929 * which is interpreted as the range from -infinity to +infinity. */
2931 IDLTEST_SIMPLE_FOR_EACH_RANGE (myRow
, NULL
, NULL
, i_index
) {
2932 printf("%03d: i=%"PRId64
" s=%s b=%s r=%f\n", step
, myRow
->i
,
2933 myRow
->s
, myRow
->b
?"True":"False", myRow
->r
);
2936 /* Free the temporal rows */
2937 idltest_simple_index_destroy_row(from
);
2938 idltest_simple_index_destroy_row(to
);
2939 idltest_simple_index_destroy_row(equal
);
2940 idltest_simple_index_destroy_row(toDelete
);
2941 idltest_simple_index_destroy_row(toInsert
);
2942 idltest_simple_index_destroy_row(toUpdate
);
2947 test_idl_compound_index_double_column(struct ovsdb_idl_index
*si_index
,
2948 struct ovsdb_idl_index
*sid_index
,
2949 struct ovsdb_idl_index
*is_index
,
2950 struct ovsdb_idl_index
*ids_index
)
2952 const struct idltest_simple
*myRow
;
2955 /* Display records by string-integer index -> si_index */
2957 IDLTEST_SIMPLE_FOR_EACH_BYINDEX (myRow
, si_index
) {
2958 printf("%03d: s=%s i=%"PRId64
" b=%s r=%f\n", step
, myRow
->s
, myRow
->i
,
2959 myRow
->b
?"True":"False", myRow
->r
);
2961 /* Display records by string-integer(down order) index -> sid_index */
2963 IDLTEST_SIMPLE_FOR_EACH_BYINDEX (myRow
, sid_index
) {
2964 printf("%03d: s=%s i=%"PRId64
" b=%s r=%f\n", step
, myRow
->s
, myRow
->i
,
2965 myRow
->b
?"True":"False", myRow
->r
);
2967 /* Display records by string-integer index -> si_index with filtering
2968 * where s="List000" and i=10
2971 struct idltest_simple
*equal
= idltest_simple_index_init_row(si_index
);
2972 idltest_simple_index_set_s(equal
, "List000");
2973 ovs_assert(strcmp(equal
->s
, "List000") == 0);
2974 idltest_simple_index_set_i(equal
, 10);
2975 ovs_assert(equal
->i
== 10);
2976 IDLTEST_SIMPLE_FOR_EACH_EQUAL (myRow
, equal
, si_index
) {
2977 printf("%03d: s=%s i=%"PRId64
" b=%s r=%f\n", step
, myRow
->s
, myRow
->i
,
2978 myRow
->b
?"True":"False", myRow
->r
);
2980 /* Display records by string-integer index -> si_index in range i=[0,100]
2981 * and s=[\"List002\",\"List003\"]
2984 struct idltest_simple
*from
= idltest_simple_index_init_row(si_index
);
2985 struct idltest_simple
*to
= idltest_simple_index_init_row(si_index
);
2986 idltest_simple_index_set_i(from
, 0);
2987 ovs_assert(from
->i
== 0);
2988 idltest_simple_index_set_s(from
, "List001");
2989 ovs_assert(strcmp(from
->s
, "List001") == 0);
2990 idltest_simple_index_set_i(to
, 100);
2991 ovs_assert(to
->i
== 100);
2992 idltest_simple_index_set_s(to
, "List005");
2993 ovs_assert(strcmp(to
->s
, "List005")==0);
2994 IDLTEST_SIMPLE_FOR_EACH_RANGE (myRow
, from
, to
, si_index
) {
2995 printf("%03d: s=%s i=%"PRId64
" b=%s r=%f\n", step
, myRow
->s
, myRow
->i
,
2996 myRow
->b
?"True":"False", myRow
->r
);
2998 /* Display records using integer-string index. */
3000 IDLTEST_SIMPLE_FOR_EACH_BYINDEX (myRow
, is_index
) {
3001 printf("%03d: i=%"PRId64
" s=%s b=%s r=%f\n", step
, myRow
->i
, myRow
->s
,
3002 myRow
->b
?"True":"False", myRow
->r
);
3004 /* Display records using integer(descend)-string index. */
3006 IDLTEST_SIMPLE_FOR_EACH_BYINDEX (myRow
, ids_index
) {
3007 printf("%03d: i=%"PRId64
" s=%s b=%s r=%f\n", step
, myRow
->i
, myRow
->s
,
3008 myRow
->b
?"True":"False", myRow
->r
);
3011 idltest_simple_index_destroy_row(to
);
3012 idltest_simple_index_destroy_row(from
);
3013 idltest_simple_index_destroy_row(equal
);
3018 do_idl_compound_index(struct ovs_cmdl_context
*ctx
)
3020 struct ovsdb_idl
*idl
;
3021 enum TESTS
{ IDL_COMPOUND_INDEX_WITH_SINGLE_COLUMN
,
3022 IDL_COMPOUND_INDEX_WITH_DOUBLE_COLUMN
3027 idl
= ovsdb_idl_create(ctx
->argv
[1], &idltest_idl_class
, false, true);
3029 /* Add tables/columns and initialize index data needed for tests */
3030 ovsdb_idl_add_table(idl
, &idltest_table_simple
);
3031 ovsdb_idl_add_column(idl
, &idltest_simple_col_s
);
3032 ovsdb_idl_add_column(idl
, &idltest_simple_col_i
);
3033 ovsdb_idl_add_column(idl
, &idltest_simple_col_r
);
3034 ovsdb_idl_add_column(idl
, &idltest_simple_col_b
);
3036 struct ovsdb_idl_index
*s_index
3037 = ovsdb_idl_index_create1(idl
, &idltest_simple_col_s
);
3039 struct ovsdb_idl_index
*i_index
3040 = ovsdb_idl_index_create1(idl
, &idltest_simple_col_i
);
3042 struct ovsdb_idl_index
*si_index
3043 = ovsdb_idl_index_create2(idl
, &idltest_simple_col_s
,
3044 &idltest_simple_col_i
);
3046 const struct ovsdb_idl_index_column sid_columns
[] = {
3047 { .column
= &idltest_simple_col_s
},
3048 { .column
= &idltest_simple_col_i
, .order
= OVSDB_INDEX_DESC
},
3050 struct ovsdb_idl_index
*sid_index
3051 = ovsdb_idl_index_create(idl
, sid_columns
, ARRAY_SIZE(sid_columns
));
3053 struct ovsdb_idl_index
*is_index
3054 = ovsdb_idl_index_create2(idl
, &idltest_simple_col_i
,
3055 &idltest_simple_col_s
);
3057 const struct ovsdb_idl_index_column ids_columns
[] = {
3058 { .column
= &idltest_simple_col_i
, .order
= OVSDB_INDEX_DESC
},
3059 { .column
= &idltest_simple_col_s
},
3061 struct ovsdb_idl_index
*ids_index
3062 = ovsdb_idl_index_create(idl
, ids_columns
, ARRAY_SIZE(sid_columns
));
3064 /* wait for replica to be updated */
3065 ovsdb_idl_get_initial_snapshot(idl
);
3067 setvbuf(stdout
, NULL
, _IONBF
, 0);
3068 int test_to_run
= -1;
3069 for (i
= 2; i
< ctx
->argc
; i
++) {
3070 char *arg
= ctx
->argv
[i
];
3072 if (strcmp(arg
,"idl_compound_index_single_column") == 0) {
3073 test_to_run
= IDL_COMPOUND_INDEX_WITH_SINGLE_COLUMN
;
3074 } else if (strcmp(arg
, "idl_compound_index_double_column") == 0) {
3075 test_to_run
= IDL_COMPOUND_INDEX_WITH_DOUBLE_COLUMN
;
3078 switch (test_to_run
) {
3079 case IDL_COMPOUND_INDEX_WITH_SINGLE_COLUMN
:
3080 test_idl_compound_index_single_column(idl
, s_index
, i_index
);
3082 case IDL_COMPOUND_INDEX_WITH_DOUBLE_COLUMN
:
3083 test_idl_compound_index_double_column(si_index
, sid_index
,
3084 is_index
, ids_index
);
3087 printf("%03d: Test %s not implemented.\n", step
++, arg
);
3090 ovsdb_idl_destroy(idl
);
3091 printf("%03d: done\n", step
);
3094 static struct ovs_cmdl_command all_commands
[] = {
3095 { "log-io", NULL
, 2, INT_MAX
, do_log_io
, OVS_RO
},
3096 { "default-atoms", NULL
, 0, 0, do_default_atoms
, OVS_RO
},
3097 { "default-data", NULL
, 0, 0, do_default_data
, OVS_RO
},
3098 { "diff-data", NULL
, 3, INT_MAX
, do_diff_data
, OVS_RO
},
3099 { "parse-atomic-type", NULL
, 1, 1, do_parse_atomic_type
, OVS_RO
},
3100 { "parse-base-type", NULL
, 1, 1, do_parse_base_type
, OVS_RO
},
3101 { "parse-type", NULL
, 1, 1, do_parse_type
, OVS_RO
},
3102 { "parse-atoms", NULL
, 2, INT_MAX
, do_parse_atoms
, OVS_RO
},
3103 { "parse-atom-strings", NULL
, 2, INT_MAX
, do_parse_atom_strings
, OVS_RO
},
3104 { "parse-data", NULL
, 2, INT_MAX
, do_parse_data
, OVS_RO
},
3105 { "parse-data-strings", NULL
, 2, INT_MAX
, do_parse_data_strings
, OVS_RO
},
3106 { "sort-atoms", NULL
, 2, 2, do_sort_atoms
, OVS_RO
},
3107 { "parse-column", NULL
, 2, 2, do_parse_column
, OVS_RO
},
3108 { "parse-table", NULL
, 2, 3, do_parse_table
, OVS_RO
},
3109 { "parse-rows", NULL
, 2, INT_MAX
, do_parse_rows
, OVS_RO
},
3110 { "compare-rows", NULL
, 2, INT_MAX
, do_compare_rows
, OVS_RO
},
3111 { "parse-conditions", NULL
, 2, INT_MAX
, do_parse_conditions
, OVS_RO
},
3112 { "evaluate-conditions", NULL
, 3, 3, do_evaluate_conditions
, OVS_RO
},
3113 { "evaluate-conditions-any", NULL
, 3, 3, do_evaluate_conditions_any
, OVS_RO
},
3114 { "compare-conditions", NULL
, 2, 2, do_compare_conditions
, OVS_RO
},
3115 { "parse-mutations", NULL
, 2, INT_MAX
, do_parse_mutations
, OVS_RO
},
3116 { "execute-mutations", NULL
, 3, 3, do_execute_mutations
, OVS_RO
},
3117 { "query", NULL
, 3, 3, do_query
, OVS_RO
},
3118 { "query-distinct", NULL
, 4, 4, do_query_distinct
, OVS_RO
},
3119 { "transact", NULL
, 1, INT_MAX
, do_transact
, OVS_RO
},
3120 { "parse-schema", NULL
, 1, 1, do_parse_schema
, OVS_RO
},
3121 { "execute", NULL
, 2, INT_MAX
, do_execute
, OVS_RO
},
3122 { "execute-readonly", NULL
, 2, INT_MAX
, do_execute_ro
, OVS_RO
},
3123 { "trigger", NULL
, 2, INT_MAX
, do_trigger
, OVS_RO
},
3124 { "idl", NULL
, 1, INT_MAX
, do_idl
, OVS_RO
},
3125 { "idl-compound-index", NULL
, 2, 2, do_idl_compound_index
, OVS_RW
},
3126 { "idl-compound-index-with-ref", NULL
, 1, INT_MAX
,
3127 do_idl_compound_index_with_ref
, OVS_RO
},
3128 { "idl-partial-update-map-column", NULL
, 1, INT_MAX
,
3129 do_idl_partial_update_map_column
, OVS_RO
},
3130 { "idl-partial-update-set-column", NULL
, 1, INT_MAX
,
3131 do_idl_partial_update_set_column
, OVS_RO
},
3132 { "help", NULL
, 0, INT_MAX
, do_help
, OVS_RO
},
3133 { NULL
, NULL
, 0, 0, NULL
, OVS_RO
},
3136 static struct ovs_cmdl_command
*
3137 get_all_commands(void)
3139 return all_commands
;