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
);
99 unsigned long int timeout
;
102 c
= getopt_long(argc
, argv
, short_options
, long_options
, NULL
);
109 timeout
= strtoul(optarg
, NULL
, 10);
111 ovs_fatal(0, "value %s on -t or --timeout is not at least 1",
122 vlog_set_verbosity(optarg
);
133 case OPT_NO_RENAME_OPEN_FILES
:
134 ovsdb_log_disable_renaming_open_files();
150 printf("%s: Open vSwitch database test utility\n"
151 "usage: %s [OPTIONS] COMMAND [ARG...]\n\n"
152 " [--magic=MAGIC] [--no-rename-open-files] "
153 " log-io FILE FLAGS COMMAND...\n"
154 " open FILE with FLAGS (and MAGIC), run COMMANDs\n"
156 " test ovsdb_atom_default()\n"
158 " test ovsdb_datum_default()\n"
159 " parse-atomic-type TYPE\n"
160 " parse TYPE as OVSDB atomic type, and re-serialize\n"
161 " parse-base-type TYPE\n"
162 " parse TYPE as OVSDB base type, and re-serialize\n"
164 " parse JSON as OVSDB type, and re-serialize\n"
165 " parse-atoms TYPE ATOM...\n"
166 " parse JSON ATOMs as atoms of TYPE, and re-serialize\n"
167 " parse-atom-strings TYPE ATOM...\n"
168 " parse string ATOMs as atoms of given TYPE, and re-serialize\n"
169 " sort-atoms TYPE ATOM...\n"
170 " print JSON ATOMs in sorted order\n"
171 " parse-data TYPE DATUM...\n"
172 " parse JSON DATUMs as data of given TYPE, and re-serialize\n"
173 " parse-data-strings TYPE DATUM...\n"
174 " parse string DATUMs as data of given TYPE, and re-serialize\n"
175 " parse-column NAME OBJECT\n"
176 " parse column NAME with info OBJECT, and re-serialize\n"
177 " parse-table NAME OBJECT [DEFAULT-IS-ROOT]\n"
178 " parse table NAME with info OBJECT\n"
179 " parse-row TABLE ROW..., and re-serialize\n"
180 " parse each ROW of defined TABLE\n"
181 " compare-row TABLE ROW...\n"
182 " mutually compare all of the ROWs, print those that are equal\n"
183 " parse-conditions TABLE CONDITION...\n"
184 " parse each CONDITION on TABLE, and re-serialize\n"
185 " evaluate-conditions TABLE [CONDITION,...] [ROW,...]\n"
186 " test CONDITIONS on TABLE against each ROW, print results\n"
187 " evaluate-conditions-any TABLE [CONDITION,...] [ROW,...]\n"
188 " test CONDITIONS to match any of the CONDITONS on TABLE\n"
189 " against each ROW, print results\n"
190 " compare-conditions TABLE [CONDITION,...]\n"
191 " mutually compare all of the CONDITION, print results for\n"
193 " parse-mutations TABLE MUTATION...\n"
194 " parse each MUTATION on TABLE, and re-serialize\n"
195 " execute-mutations TABLE [MUTATION,...] [ROW,...]\n"
196 " execute MUTATIONS on TABLE on each ROW, print results\n"
197 " query TABLE [ROW,...] [CONDITION,...]\n"
198 " add each ROW to TABLE, then query and print the rows that\n"
199 " satisfy each CONDITION.\n"
200 " query-distinct TABLE [ROW,...] [CONDITION,...] COLUMNS\n"
201 " add each ROW to TABLE, then query and print the rows that\n"
202 " satisfy each CONDITION and have distinct COLUMNS.\n"
203 " parse-schema JSON\n"
204 " parse JSON as an OVSDB schema, and re-serialize\n"
205 " transact COMMAND\n"
206 " execute each specified transactional COMMAND:\n"
213 " execute SCHEMA TRANSACTION...\n"
214 " executes each TRANSACTION on an initially empty database\n"
215 " the specified SCHEMA\n"
216 " execute-readonly SCHEMA TRANSACTION...\n"
217 " same as execute, except the TRANSACTION will be executed\n"
218 " against the database server that is in read only mode\n"
219 " trigger SCHEMA TRANSACTION...\n"
220 " executes each TRANSACTION on an initially empty database\n"
221 " the specified SCHEMA. A TRANSACTION of the form\n"
222 " [\"advance\", NUMBER] advances NUMBER milliseconds in\n"
223 " simulated time, for causing triggers to time out.\n"
224 " idl SERVER [TRANSACTION...]\n"
225 " connect to SERVER and dump the contents of the database\n"
226 " as seen initially by the IDL implementation and after\n"
227 " executing each TRANSACTION. (Each TRANSACTION must modify\n"
228 " the database or this command will hang.)\n"
229 " idl-partial-update-map-column SERVER \n"
230 " connect to SERVER and executes different operations to\n"
231 " test the capacity of updating elements inside a map column\n"
232 " displaying the table information after each operation.\n"
233 " idl-partial-update-set-column SERVER \n"
234 " connect to SERVER and executes different operations to\n"
235 " test the capacity of updating elements inside a set column\n"
236 " displaying the table information after each operation.\n"
237 " idl-compound-index TEST_TO_EXECUTE\n"
238 " Execute the tests to verify compound-index feature.\n"
239 " The TEST_TO_EXECUTE are:\n"
240 " idl_compound_index_single_column:\n"
241 " test for indexes using one column.\n"
242 " idl_compound_index_double_column:\n"
243 " test for indexes using two columns.\n",
244 program_name
, program_name
);
246 printf("\nOther options:\n"
247 " -t, --timeout=SECS give up after SECS seconds\n"
248 " -h, --help display this help message\n"
249 " -c, --change-track used with the 'idl' command to\n"
250 " enable tracking of IDL changes\n");
254 /* Command helper functions. */
257 parse_json(const char *s
)
259 struct json
*json
= json_from_string(s
);
260 if (json
->type
== JSON_STRING
) {
261 ovs_fatal(0, "\"%s\": %s", s
, json
->string
);
267 unbox_json(struct json
*json
)
269 if (json
->type
== JSON_ARRAY
&& json
->array
.n
== 1) {
270 struct json
*inner
= json
->array
.elems
[0];
271 json
->array
.elems
[0] = NULL
;
280 print_and_free_json(struct json
*json
)
282 char *string
= json_to_string(json
, JSSF_SORT
);
289 print_and_free_ovsdb_error(struct ovsdb_error
*error
)
291 char *string
= ovsdb_error_to_string_free(error
);
297 check_ovsdb_error(struct ovsdb_error
*error
)
300 char *s
= ovsdb_error_to_string_free(error
);
301 ovs_fatal(0, "%s", s
);
306 die_if_error(char *error
)
309 ovs_fatal(0, "%s", error
);
313 /* Command implementations. */
316 do_log_io(struct ovs_cmdl_context
*ctx
)
318 const char *name
= ctx
->argv
[1];
319 char *mode_string
= ctx
->argv
[2];
321 struct ovsdb_error
*error
;
322 enum ovsdb_log_open_mode mode
;
325 if (!strcmp(mode_string
, "read-only")) {
326 mode
= OVSDB_LOG_READ_ONLY
;
327 } else if (!strcmp(mode_string
, "read/write")) {
328 mode
= OVSDB_LOG_READ_WRITE
;
329 } else if (!strcmp(mode_string
, "create")) {
330 mode
= OVSDB_LOG_CREATE
;
331 } else if (!strcmp(mode_string
, "create-excl")) {
332 mode
= OVSDB_LOG_CREATE_EXCL
;
334 ovs_fatal(0, "unknown log-io open mode \"%s\"", mode_string
);
337 struct ovsdb_log
*log
;
338 check_ovsdb_error(ovsdb_log_open(name
, magic
, mode
, -1, &log
));
339 printf("%s: open successful\n", name
);
341 struct ovsdb_log
*replacement
= NULL
;
343 for (i
= 3; i
< ctx
->argc
; i
++) {
344 const char *command
= ctx
->argv
[i
];
346 struct ovsdb_log
*target
;
347 const char *target_name
;
348 if (!strncmp(command
, "old-", 4)) {
352 } else if (!strncmp(command
, "new-", 4)) {
354 ovs_fatal(0, "%s: can't execute command without "
355 "replacement log", command
);
359 target
= replacement
;
360 target_name
= "(temp)";
366 if (!strcmp(command
, "read")) {
369 error
= ovsdb_log_read(target
, &json
);
371 printf("%s: read: ", target_name
);
373 print_and_free_json(json
);
375 printf("end of log\n");
379 } else if (!strncmp(command
, "write:", 6)) {
380 struct json
*json
= parse_json(command
+ 6);
381 error
= ovsdb_log_write_and_free(target
, json
);
382 } else if (!strcmp(command
, "commit")) {
383 error
= ovsdb_log_commit_block(target
);
384 } else if (!strcmp(command
, "replace_start")) {
385 ovs_assert(!replacement
);
386 error
= ovsdb_log_replace_start(log
, &replacement
);
387 } else if (!strcmp(command
, "replace_commit")) {
388 ovs_assert(replacement
);
389 error
= ovsdb_log_replace_commit(log
, replacement
);
391 } else if (!strcmp(command
, "replace_abort")) {
392 ovs_assert(replacement
);
393 ovsdb_log_replace_abort(replacement
);
397 ovs_fatal(0, "unknown log-io command \"%s\"", command
);
400 char *s
= ovsdb_error_to_string_free(error
);
401 printf("%s: %s failed: %s\n", target_name
, command
, s
);
404 printf("%s: %s successful\n", target_name
, command
);
408 ovsdb_log_close(log
);
412 do_default_atoms(struct ovs_cmdl_context
*ctx OVS_UNUSED
)
416 for (type
= 0; type
< OVSDB_N_TYPES
; type
++) {
417 union ovsdb_atom atom
;
419 if (type
== OVSDB_TYPE_VOID
) {
423 printf("%s: ", ovsdb_atomic_type_to_string(type
));
425 ovsdb_atom_init_default(&atom
, type
);
426 if (!ovsdb_atom_equals(&atom
, ovsdb_atom_default(type
), type
)) {
430 ovsdb_atom_destroy(&atom
, type
);
437 do_default_data(struct ovs_cmdl_context
*ctx OVS_UNUSED
)
442 for (n_min
= 0; n_min
<= 1; n_min
++) {
443 for (key
= 0; key
< OVSDB_N_TYPES
; key
++) {
444 if (key
== OVSDB_TYPE_VOID
) {
447 for (value
= 0; value
< OVSDB_N_TYPES
; value
++) {
448 struct ovsdb_datum datum
;
449 struct ovsdb_type type
;
451 ovsdb_base_type_init(&type
.key
, key
);
452 ovsdb_base_type_init(&type
.value
, value
);
455 ovs_assert(ovsdb_type_is_valid(&type
));
457 printf("key %s, value %s, n_min %u: ",
458 ovsdb_atomic_type_to_string(key
),
459 ovsdb_atomic_type_to_string(value
), n_min
);
461 ovsdb_datum_init_default(&datum
, &type
);
462 if (!ovsdb_datum_equals(&datum
, ovsdb_datum_default(&type
),
467 ovsdb_datum_destroy(&datum
, &type
);
468 ovsdb_type_destroy(&type
);
477 do_diff_data(struct ovs_cmdl_context
*ctx
)
479 struct ovsdb_type type
;
481 struct ovsdb_datum
new, old
, diff
, reincarnation
;
483 json
= unbox_json(parse_json(ctx
->argv
[1]));
484 check_ovsdb_error(ovsdb_type_from_json(&type
, json
));
487 /* Arguments in pairs of 'old' and 'new'. */
488 for (int i
= 2; i
< ctx
->argc
- 1; i
+=2) {
489 struct ovsdb_error
*error
;
491 json
= unbox_json(parse_json(ctx
->argv
[i
]));
492 check_ovsdb_error(ovsdb_datum_from_json(&old
, &type
, json
, NULL
));
495 json
= unbox_json(parse_json(ctx
->argv
[i
+1]));
496 check_ovsdb_error(ovsdb_transient_datum_from_json(&new, &type
, json
));
499 /* Generate the diff. */
500 ovsdb_datum_diff(&diff
, &old
, &new, &type
);
502 /* Apply diff to 'old' to create'reincarnation'. */
503 error
= ovsdb_datum_apply_diff(&reincarnation
, &old
, &diff
, &type
);
505 char *string
= ovsdb_error_to_string_free(error
);
506 ovs_fatal(0, "%s", string
);
509 /* Test to make sure 'new' equals 'reincarnation'. */
510 if (!ovsdb_datum_equals(&new, &reincarnation
, &type
)) {
511 ovs_fatal(0, "failed to apply diff");
515 json
= ovsdb_datum_to_json(&diff
, &type
);
517 print_and_free_json(json
);
519 /* Print reincarnation */
520 json
= ovsdb_datum_to_json(&reincarnation
, &type
);
521 printf ("apply diff: ");
522 print_and_free_json(json
);
524 ovsdb_datum_destroy(&new, &type
);
525 ovsdb_datum_destroy(&old
, &type
);
526 ovsdb_datum_destroy(&diff
, &type
);
527 ovsdb_datum_destroy(&reincarnation
, &type
);
532 ovsdb_type_destroy(&type
);
536 do_parse_atomic_type(struct ovs_cmdl_context
*ctx
)
538 enum ovsdb_atomic_type type
;
541 json
= unbox_json(parse_json(ctx
->argv
[1]));
542 check_ovsdb_error(ovsdb_atomic_type_from_json(&type
, json
));
544 print_and_free_json(ovsdb_atomic_type_to_json(type
));
548 do_parse_base_type(struct ovs_cmdl_context
*ctx
)
550 struct ovsdb_base_type base
;
553 json
= unbox_json(parse_json(ctx
->argv
[1]));
554 check_ovsdb_error(ovsdb_base_type_from_json(&base
, json
));
556 print_and_free_json(ovsdb_base_type_to_json(&base
));
557 ovsdb_base_type_destroy(&base
);
561 do_parse_type(struct ovs_cmdl_context
*ctx
)
563 struct ovsdb_type type
;
566 json
= unbox_json(parse_json(ctx
->argv
[1]));
567 check_ovsdb_error(ovsdb_type_from_json(&type
, json
));
569 print_and_free_json(ovsdb_type_to_json(&type
));
570 ovsdb_type_destroy(&type
);
574 do_parse_atoms(struct ovs_cmdl_context
*ctx
)
576 struct ovsdb_base_type base
;
580 json
= unbox_json(parse_json(ctx
->argv
[1]));
581 check_ovsdb_error(ovsdb_base_type_from_json(&base
, json
));
584 for (i
= 2; i
< ctx
->argc
; i
++) {
585 struct ovsdb_error
*error
;
586 union ovsdb_atom atom
;
588 json
= unbox_json(parse_json(ctx
->argv
[i
]));
589 error
= ovsdb_atom_from_json(&atom
, &base
, json
, NULL
);
593 print_and_free_ovsdb_error(error
);
595 print_and_free_json(ovsdb_atom_to_json(&atom
, base
.type
));
596 ovsdb_atom_destroy(&atom
, base
.type
);
599 ovsdb_base_type_destroy(&base
);
603 do_parse_atom_strings(struct ovs_cmdl_context
*ctx
)
605 struct ovsdb_base_type base
;
609 json
= unbox_json(parse_json(ctx
->argv
[1]));
610 check_ovsdb_error(ovsdb_base_type_from_json(&base
, json
));
613 for (i
= 2; i
< ctx
->argc
; i
++) {
614 union ovsdb_atom atom
, *range_end_atom
= NULL
;
617 die_if_error(ovsdb_atom_from_string(&atom
, &range_end_atom
, &base
,
618 ctx
->argv
[i
], NULL
));
621 ovsdb_atom_to_string(&atom
, base
.type
, &out
);
622 if (range_end_atom
) {
623 struct ds range_end_ds
;
624 ds_init(&range_end_ds
);
625 ovsdb_atom_to_string(range_end_atom
, base
.type
, &range_end_ds
);
626 ds_put_char(&out
, '-');
627 ds_put_cstr(&out
, ds_cstr(&range_end_ds
));;
628 ds_destroy(&range_end_ds
);
633 ovsdb_atom_destroy(&atom
, base
.type
);
634 if (range_end_atom
) {
635 ovsdb_atom_destroy(range_end_atom
, base
.type
);
636 free(range_end_atom
);
639 ovsdb_base_type_destroy(&base
);
643 do_parse_data__(int argc
, char *argv
[],
645 (*parse
)(struct ovsdb_datum
*datum
,
646 const struct ovsdb_type
*type
,
647 const struct json
*json
,
648 struct ovsdb_symbol_table
*symtab
))
650 struct ovsdb_type type
;
654 json
= unbox_json(parse_json(argv
[1]));
655 check_ovsdb_error(ovsdb_type_from_json(&type
, json
));
658 for (i
= 2; i
< argc
; i
++) {
659 struct ovsdb_datum datum
;
661 json
= unbox_json(parse_json(argv
[i
]));
662 check_ovsdb_error(parse(&datum
, &type
, json
, NULL
));
665 print_and_free_json(ovsdb_datum_to_json(&datum
, &type
));
667 ovsdb_datum_destroy(&datum
, &type
);
669 ovsdb_type_destroy(&type
);
673 do_parse_data(struct ovs_cmdl_context
*ctx
)
675 do_parse_data__(ctx
->argc
, ctx
->argv
, ovsdb_datum_from_json
);
679 do_parse_data_strings(struct ovs_cmdl_context
*ctx
)
681 struct ovsdb_type type
;
685 json
= unbox_json(parse_json(ctx
->argv
[1]));
686 check_ovsdb_error(ovsdb_type_from_json(&type
, json
));
689 for (i
= 2; i
< ctx
->argc
; i
++) {
690 struct ovsdb_datum datum
;
693 die_if_error(ovsdb_datum_from_string(&datum
, &type
, ctx
->argv
[i
], NULL
));
696 ovsdb_datum_to_string(&datum
, &type
, &out
);
700 ovsdb_datum_destroy(&datum
, &type
);
702 ovsdb_type_destroy(&type
);
705 static enum ovsdb_atomic_type compare_atoms_atomic_type
;
708 compare_atoms(const void *a_
, const void *b_
)
710 const union ovsdb_atom
*a
= a_
;
711 const union ovsdb_atom
*b
= b_
;
713 return ovsdb_atom_compare_3way(a
, b
, compare_atoms_atomic_type
);
717 do_sort_atoms(struct ovs_cmdl_context
*ctx
)
719 struct ovsdb_base_type base
;
720 union ovsdb_atom
*atoms
;
721 struct json
*json
, **json_atoms
;
725 json
= unbox_json(parse_json(ctx
->argv
[1]));
726 check_ovsdb_error(ovsdb_base_type_from_json(&base
, json
));
729 json
= unbox_json(parse_json(ctx
->argv
[2]));
730 if (json
->type
!= JSON_ARRAY
) {
731 ovs_fatal(0, "second argument must be array");
734 /* Convert JSON atoms to internal representation. */
735 n_atoms
= json
->array
.n
;
736 atoms
= xmalloc(n_atoms
* sizeof *atoms
);
737 for (i
= 0; i
< n_atoms
; i
++) {
738 check_ovsdb_error(ovsdb_atom_from_json(&atoms
[i
], &base
,
739 json
->array
.elems
[i
], NULL
));
744 compare_atoms_atomic_type
= base
.type
;
745 qsort(atoms
, n_atoms
, sizeof *atoms
, compare_atoms
);
747 /* Convert internal representation back to JSON. */
748 json_atoms
= xmalloc(n_atoms
* sizeof *json_atoms
);
749 for (i
= 0; i
< n_atoms
; i
++) {
750 json_atoms
[i
] = ovsdb_atom_to_json(&atoms
[i
], base
.type
);
751 ovsdb_atom_destroy(&atoms
[i
], base
.type
);
753 print_and_free_json(json_array_create(json_atoms
, n_atoms
));
755 ovsdb_base_type_destroy(&base
);
759 do_parse_column(struct ovs_cmdl_context
*ctx
)
761 struct ovsdb_column
*column
;
764 json
= parse_json(ctx
->argv
[2]);
765 check_ovsdb_error(ovsdb_column_from_json(json
, ctx
->argv
[1], &column
));
767 print_and_free_json(ovsdb_column_to_json(column
));
768 ovsdb_column_destroy(column
);
772 do_parse_table(struct ovs_cmdl_context
*ctx
)
774 struct ovsdb_table_schema
*ts
;
775 bool default_is_root
;
778 default_is_root
= ctx
->argc
> 3 && !strcmp(ctx
->argv
[3], "true");
780 json
= parse_json(ctx
->argv
[2]);
781 check_ovsdb_error(ovsdb_table_schema_from_json(json
, ctx
->argv
[1], &ts
));
783 print_and_free_json(ovsdb_table_schema_to_json(ts
, default_is_root
));
784 ovsdb_table_schema_destroy(ts
);
788 do_parse_rows(struct ovs_cmdl_context
*ctx
)
790 struct ovsdb_column_set all_columns
;
791 struct ovsdb_table_schema
*ts
;
792 struct ovsdb_table
*table
;
796 json
= unbox_json(parse_json(ctx
->argv
[1]));
797 check_ovsdb_error(ovsdb_table_schema_from_json(json
, "mytable", &ts
));
800 table
= ovsdb_table_create(ts
);
801 ovsdb_column_set_init(&all_columns
);
802 ovsdb_column_set_add_all(&all_columns
, table
);
804 for (i
= 2; i
< ctx
->argc
; i
++) {
805 struct ovsdb_column_set columns
;
806 struct ovsdb_row
*row
;
808 ovsdb_column_set_init(&columns
);
809 row
= ovsdb_row_create(table
);
811 json
= unbox_json(parse_json(ctx
->argv
[i
]));
812 check_ovsdb_error(ovsdb_row_from_json(row
, json
, NULL
, &columns
));
815 print_and_free_json(ovsdb_row_to_json(row
, &all_columns
));
817 if (columns
.n_columns
) {
823 for (j
= 0; j
< columns
.n_columns
; j
++) {
824 svec_add(&names
, columns
.columns
[j
]->name
);
827 s
= svec_join(&names
, ", ", "");
830 svec_destroy(&names
);
835 ovsdb_column_set_destroy(&columns
);
836 ovsdb_row_destroy(row
);
839 ovsdb_column_set_destroy(&all_columns
);
840 ovsdb_table_destroy(table
); /* Also destroys 'ts'. */
844 do_compare_rows(struct ovs_cmdl_context
*ctx
)
846 struct ovsdb_column_set all_columns
;
847 struct ovsdb_table_schema
*ts
;
848 struct ovsdb_table
*table
;
849 struct ovsdb_row
**rows
;
855 json
= unbox_json(parse_json(ctx
->argv
[1]));
856 check_ovsdb_error(ovsdb_table_schema_from_json(json
, "mytable", &ts
));
859 table
= ovsdb_table_create(ts
);
860 ovsdb_column_set_init(&all_columns
);
861 ovsdb_column_set_add_all(&all_columns
, table
);
863 n_rows
= ctx
->argc
- 2;
864 rows
= xmalloc(sizeof *rows
* n_rows
);
865 names
= xmalloc(sizeof *names
* n_rows
);
866 for (i
= 0; i
< n_rows
; i
++) {
867 rows
[i
] = ovsdb_row_create(table
);
869 json
= parse_json(ctx
->argv
[i
+ 2]);
870 if (json
->type
!= JSON_ARRAY
|| json
->array
.n
!= 2
871 || json
->array
.elems
[0]->type
!= JSON_STRING
) {
872 ovs_fatal(0, "\"%s\" does not have expected form "
873 "[\"name\", {data}]", ctx
->argv
[i
]);
875 names
[i
] = xstrdup(json
->array
.elems
[0]->string
);
876 check_ovsdb_error(ovsdb_row_from_json(rows
[i
], json
->array
.elems
[1],
880 for (i
= 0; i
< n_rows
; i
++) {
881 uint32_t i_hash
= ovsdb_row_hash_columns(rows
[i
], &all_columns
, 0);
882 for (j
= i
+ 1; j
< n_rows
; j
++) {
883 uint32_t j_hash
= ovsdb_row_hash_columns(rows
[j
], &all_columns
, 0);
884 if (ovsdb_row_equal_columns(rows
[i
], rows
[j
], &all_columns
)) {
885 printf("%s == %s\n", names
[i
], names
[j
]);
886 if (i_hash
!= j_hash
) {
887 printf("but hash(%s) != hash(%s)\n", names
[i
], names
[j
]);
890 } else if (i_hash
== j_hash
) {
891 printf("hash(%s) == hash(%s)\n", names
[i
], names
[j
]);
895 for (i
= 0; i
< n_rows
; i
++) {
896 ovsdb_row_destroy(rows
[i
]);
902 ovsdb_column_set_destroy(&all_columns
);
903 ovsdb_table_destroy(table
); /* Also destroys 'ts'. */
907 do_parse_conditions(struct ovs_cmdl_context
*ctx
)
909 struct ovsdb_table_schema
*ts
;
914 json
= unbox_json(parse_json(ctx
->argv
[1]));
915 check_ovsdb_error(ovsdb_table_schema_from_json(json
, "mytable", &ts
));
918 for (i
= 2; i
< ctx
->argc
; i
++) {
919 struct ovsdb_condition cnd
;
920 struct ovsdb_error
*error
;
922 json
= parse_json(ctx
->argv
[i
]);
923 error
= ovsdb_condition_from_json(ts
, json
, NULL
, &cnd
);
925 print_and_free_json(ovsdb_condition_to_json(&cnd
));
927 char *s
= ovsdb_error_to_string_free(error
);
928 ovs_error(0, "%s", s
);
934 ovsdb_condition_destroy(&cnd
);
936 ovsdb_table_schema_destroy(ts
);
941 #define OVSDB_CONDITION_EVERY 0
942 #define OVSDB_CONDITION_ANY 1
945 do_evaluate_condition__(struct ovs_cmdl_context
*ctx
, int mode
)
947 struct ovsdb_table_schema
*ts
;
948 struct ovsdb_table
*table
;
949 struct ovsdb_condition
*conditions
;
951 struct ovsdb_row
**rows
;
956 /* Parse table schema, create table. */
957 json
= unbox_json(parse_json(ctx
->argv
[1]));
958 check_ovsdb_error(ovsdb_table_schema_from_json(json
, "mytable", &ts
));
961 table
= ovsdb_table_create(ts
);
963 /* Parse conditions. */
964 json
= parse_json(ctx
->argv
[2]);
965 if (json
->type
!= JSON_ARRAY
) {
966 ovs_fatal(0, "CONDITION argument is not JSON array");
968 n_conditions
= json
->array
.n
;
969 conditions
= xmalloc(n_conditions
* sizeof *conditions
);
970 for (i
= 0; i
< n_conditions
; i
++) {
971 check_ovsdb_error(ovsdb_condition_from_json(ts
, json
->array
.elems
[i
],
972 NULL
, &conditions
[i
]));
977 json
= parse_json(ctx
->argv
[3]);
978 if (json
->type
!= JSON_ARRAY
) {
979 ovs_fatal(0, "ROW argument is not JSON array");
981 n_rows
= json
->array
.n
;
982 rows
= xmalloc(n_rows
* sizeof *rows
);
983 for (i
= 0; i
< n_rows
; i
++) {
984 rows
[i
] = ovsdb_row_create(table
);
985 check_ovsdb_error(ovsdb_row_from_json(rows
[i
], json
->array
.elems
[i
],
990 for (i
= 0; i
< n_conditions
; i
++) {
991 printf("condition %2"PRIuSIZE
":", i
);
992 for (j
= 0; j
< n_rows
; j
++) {
994 if (mode
== OVSDB_CONDITION_EVERY
) {
995 result
= ovsdb_condition_match_every_clause(rows
[j
],
998 result
= ovsdb_condition_match_any_clause(rows
[j
]->fields
,
1005 putchar(result
? 'T' : '-');
1010 for (i
= 0; i
< n_conditions
; i
++) {
1011 ovsdb_condition_destroy(&conditions
[i
]);
1014 for (i
= 0; i
< n_rows
; i
++) {
1015 ovsdb_row_destroy(rows
[i
]);
1018 ovsdb_table_destroy(table
); /* Also destroys 'ts'. */
1022 do_evaluate_conditions(struct ovs_cmdl_context
*ctx
)
1024 do_evaluate_condition__(ctx
, OVSDB_CONDITION_EVERY
);
1028 do_evaluate_conditions_any(struct ovs_cmdl_context
*ctx
)
1030 do_evaluate_condition__(ctx
, OVSDB_CONDITION_ANY
);
1034 do_compare_conditions(struct ovs_cmdl_context
*ctx
)
1036 struct ovsdb_table_schema
*ts
;
1037 struct ovsdb_table
*table
;
1038 struct ovsdb_condition
*conditions
;
1039 size_t n_conditions
;
1043 /* Parse table schema, create table. */
1044 json
= unbox_json(parse_json(ctx
->argv
[1]));
1045 check_ovsdb_error(ovsdb_table_schema_from_json(json
, "mytable", &ts
));
1048 table
= ovsdb_table_create(ts
);
1050 /* Parse conditions. */
1051 json
= parse_json(ctx
->argv
[2]);
1052 if (json
->type
!= JSON_ARRAY
) {
1053 ovs_fatal(0, "CONDITION argument is not JSON array");
1055 n_conditions
= json
->array
.n
;
1056 conditions
= xmalloc(n_conditions
* sizeof *conditions
);
1058 for (i
= 0; i
< n_conditions
; i
++) {
1059 check_ovsdb_error(ovsdb_condition_from_json(ts
, json
->array
.elems
[i
],
1060 NULL
, &conditions
[i
]));
1064 for (i
= 0; i
< n_conditions
- 1; i
++) {
1065 int res
= ovsdb_condition_cmp_3way(&conditions
[i
], &conditions
[i
+ 1]);
1066 printf("condition %"PRIuSIZE
"-%"PRIuSIZE
": %d\n", i
, i
+ 1, res
);
1069 for (i
= 0; i
< n_conditions
; i
++) {
1070 ovsdb_condition_destroy(&conditions
[i
]);
1073 ovsdb_table_destroy(table
); /* Also destroys 'ts'. */
1077 do_parse_mutations(struct ovs_cmdl_context
*ctx
)
1079 struct ovsdb_table_schema
*ts
;
1084 json
= unbox_json(parse_json(ctx
->argv
[1]));
1085 check_ovsdb_error(ovsdb_table_schema_from_json(json
, "mytable", &ts
));
1088 for (i
= 2; i
< ctx
->argc
; i
++) {
1089 struct ovsdb_mutation_set set
;
1090 struct ovsdb_error
*error
;
1092 json
= parse_json(ctx
->argv
[i
]);
1093 error
= ovsdb_mutation_set_from_json(ts
, json
, NULL
, &set
);
1095 print_and_free_json(ovsdb_mutation_set_to_json(&set
));
1097 char *s
= ovsdb_error_to_string_free(error
);
1098 ovs_error(0, "%s", s
);
1104 ovsdb_mutation_set_destroy(&set
);
1106 ovsdb_table_schema_destroy(ts
);
1112 do_execute_mutations(struct ovs_cmdl_context
*ctx
)
1114 struct ovsdb_table_schema
*ts
;
1115 struct ovsdb_table
*table
;
1116 struct ovsdb_mutation_set
*sets
;
1118 struct ovsdb_row
**rows
;
1123 /* Parse table schema, create table. */
1124 json
= unbox_json(parse_json(ctx
->argv
[1]));
1125 check_ovsdb_error(ovsdb_table_schema_from_json(json
, "mytable", &ts
));
1128 table
= ovsdb_table_create(ts
);
1130 /* Parse mutations. */
1131 json
= parse_json(ctx
->argv
[2]);
1132 if (json
->type
!= JSON_ARRAY
) {
1133 ovs_fatal(0, "MUTATION argument is not JSON array");
1135 n_sets
= json
->array
.n
;
1136 sets
= xmalloc(n_sets
* sizeof *sets
);
1137 for (i
= 0; i
< n_sets
; i
++) {
1138 check_ovsdb_error(ovsdb_mutation_set_from_json(ts
,
1139 json
->array
.elems
[i
],
1145 json
= parse_json(ctx
->argv
[3]);
1146 if (json
->type
!= JSON_ARRAY
) {
1147 ovs_fatal(0, "ROW argument is not JSON array");
1149 n_rows
= json
->array
.n
;
1150 rows
= xmalloc(n_rows
* sizeof *rows
);
1151 for (i
= 0; i
< n_rows
; i
++) {
1152 rows
[i
] = ovsdb_row_create(table
);
1153 check_ovsdb_error(ovsdb_row_from_json(rows
[i
], json
->array
.elems
[i
],
1158 for (i
= 0; i
< n_sets
; i
++) {
1159 printf("mutation %2"PRIuSIZE
":\n", i
);
1160 for (j
= 0; j
< n_rows
; j
++) {
1161 struct ovsdb_error
*error
;
1162 struct ovsdb_row
*row
;
1164 row
= ovsdb_row_clone(rows
[j
]);
1165 error
= ovsdb_mutation_set_execute(row
, &sets
[i
]);
1167 printf("row %"PRIuSIZE
": ", j
);
1169 print_and_free_ovsdb_error(error
);
1171 struct ovsdb_column_set columns
;
1172 struct shash_node
*node
;
1174 ovsdb_column_set_init(&columns
);
1175 SHASH_FOR_EACH (node
, &ts
->columns
) {
1176 struct ovsdb_column
*c
= node
->data
;
1177 if (!ovsdb_datum_equals(&row
->fields
[c
->index
],
1178 &rows
[j
]->fields
[c
->index
],
1180 ovsdb_column_set_add(&columns
, c
);
1183 if (columns
.n_columns
) {
1184 print_and_free_json(ovsdb_row_to_json(row
, &columns
));
1186 printf("no change\n");
1188 ovsdb_column_set_destroy(&columns
);
1190 ovsdb_row_destroy(row
);
1195 for (i
= 0; i
< n_sets
; i
++) {
1196 ovsdb_mutation_set_destroy(&sets
[i
]);
1199 for (i
= 0; i
< n_rows
; i
++) {
1200 ovsdb_row_destroy(rows
[i
]);
1203 ovsdb_table_destroy(table
); /* Also destroys 'ts'. */
1206 /* Inserts a row, without bothering to update metadata such as refcounts. */
1208 put_row(struct ovsdb_table
*table
, struct ovsdb_row
*row
)
1210 const struct uuid
*uuid
= ovsdb_row_get_uuid(row
);
1211 if (!ovsdb_table_get_row(table
, uuid
)) {
1212 hmap_insert(&table
->rows
, &row
->hmap_node
, uuid_hash(uuid
));
1216 struct do_query_cbdata
{
1217 struct uuid
*row_uuids
;
1223 do_query_cb(const struct ovsdb_row
*row
, void *cbdata_
)
1225 struct do_query_cbdata
*cbdata
= cbdata_
;
1228 for (i
= 0; i
< cbdata
->n_rows
; i
++) {
1229 if (uuid_equals(ovsdb_row_get_uuid(row
), &cbdata
->row_uuids
[i
])) {
1230 cbdata
->counts
[i
]++;
1238 do_query(struct ovs_cmdl_context
*ctx
)
1240 struct do_query_cbdata cbdata
;
1241 struct ovsdb_table_schema
*ts
;
1242 struct ovsdb_table
*table
;
1247 /* Parse table schema, create table. */
1248 json
= unbox_json(parse_json(ctx
->argv
[1]));
1249 check_ovsdb_error(ovsdb_table_schema_from_json(json
, "mytable", &ts
));
1252 table
= ovsdb_table_create(ts
);
1254 /* Parse rows, add to table. */
1255 json
= parse_json(ctx
->argv
[2]);
1256 if (json
->type
!= JSON_ARRAY
) {
1257 ovs_fatal(0, "ROW argument is not JSON array");
1259 cbdata
.n_rows
= json
->array
.n
;
1260 cbdata
.row_uuids
= xmalloc(cbdata
.n_rows
* sizeof *cbdata
.row_uuids
);
1261 cbdata
.counts
= xmalloc(cbdata
.n_rows
* sizeof *cbdata
.counts
);
1262 for (i
= 0; i
< cbdata
.n_rows
; i
++) {
1263 struct ovsdb_row
*row
= ovsdb_row_create(table
);
1264 uuid_generate(ovsdb_row_get_uuid_rw(row
));
1265 check_ovsdb_error(ovsdb_row_from_json(row
, json
->array
.elems
[i
],
1267 if (ovsdb_table_get_row(table
, ovsdb_row_get_uuid(row
))) {
1268 ovs_fatal(0, "duplicate UUID "UUID_FMT
" in table",
1269 UUID_ARGS(ovsdb_row_get_uuid(row
)));
1271 cbdata
.row_uuids
[i
] = *ovsdb_row_get_uuid(row
);
1272 put_row(table
, row
);
1276 /* Parse conditions and execute queries. */
1277 json
= parse_json(ctx
->argv
[3]);
1278 if (json
->type
!= JSON_ARRAY
) {
1279 ovs_fatal(0, "CONDITION argument is not JSON array");
1281 for (i
= 0; i
< json
->array
.n
; i
++) {
1282 struct ovsdb_condition cnd
;
1285 check_ovsdb_error(ovsdb_condition_from_json(ts
, json
->array
.elems
[i
],
1288 memset(cbdata
.counts
, 0, cbdata
.n_rows
* sizeof *cbdata
.counts
);
1289 ovsdb_query(table
, &cnd
, do_query_cb
, &cbdata
);
1291 printf("query %2"PRIuSIZE
":", i
);
1292 for (j
= 0; j
< cbdata
.n_rows
; j
++) {
1296 if (cbdata
.counts
[j
]) {
1297 printf("%d", cbdata
.counts
[j
]);
1298 if (cbdata
.counts
[j
] > 1) {
1308 ovsdb_condition_destroy(&cnd
);
1312 ovsdb_table_destroy(table
); /* Also destroys 'ts'. */
1317 struct do_query_distinct_class
{
1318 struct ovsdb_row
*example
;
1322 struct do_query_distinct_row
{
1324 struct do_query_distinct_class
*class;
1328 do_query_distinct(struct ovs_cmdl_context
*ctx
)
1330 struct ovsdb_column_set columns
;
1331 struct ovsdb_table_schema
*ts
;
1332 struct ovsdb_table
*table
;
1333 struct do_query_distinct_row
*rows
;
1335 struct do_query_distinct_class
*classes
;
1341 /* Parse table schema, create table. */
1342 json
= unbox_json(parse_json(ctx
->argv
[1]));
1343 check_ovsdb_error(ovsdb_table_schema_from_json(json
, "mytable", &ts
));
1346 table
= ovsdb_table_create(ts
);
1348 /* Parse column set. */
1349 json
= parse_json(ctx
->argv
[4]);
1350 check_ovsdb_error(ovsdb_column_set_from_json(json
, table
->schema
,
1354 /* Parse rows, add to table. */
1355 json
= parse_json(ctx
->argv
[2]);
1356 if (json
->type
!= JSON_ARRAY
) {
1357 ovs_fatal(0, "ROW argument is not JSON array");
1359 n_rows
= json
->array
.n
;
1360 rows
= xmalloc(n_rows
* sizeof *rows
);
1361 classes
= xmalloc(n_rows
* sizeof *classes
);
1363 for (i
= 0; i
< n_rows
; i
++) {
1364 struct ovsdb_row
*row
;
1368 row
= ovsdb_row_create(table
);
1369 uuid_generate(ovsdb_row_get_uuid_rw(row
));
1370 check_ovsdb_error(ovsdb_row_from_json(row
, json
->array
.elems
[i
],
1373 /* Initialize row and find equivalence class. */
1374 rows
[i
].uuid
= *ovsdb_row_get_uuid(row
);
1375 rows
[i
].class = NULL
;
1376 for (j
= 0; j
< n_classes
; j
++) {
1377 if (ovsdb_row_equal_columns(row
, classes
[j
].example
, &columns
)) {
1378 rows
[i
].class = &classes
[j
];
1382 if (!rows
[i
].class) {
1383 rows
[i
].class = &classes
[n_classes
];
1384 classes
[n_classes
].example
= ovsdb_row_clone(row
);
1388 /* Add row to table. */
1389 if (ovsdb_table_get_row(table
, ovsdb_row_get_uuid(row
))) {
1390 ovs_fatal(0, "duplicate UUID "UUID_FMT
" in table",
1391 UUID_ARGS(ovsdb_row_get_uuid(row
)));
1393 put_row(table
, row
);
1398 /* Parse conditions and execute queries. */
1399 json
= parse_json(ctx
->argv
[3]);
1400 if (json
->type
!= JSON_ARRAY
) {
1401 ovs_fatal(0, "CONDITION argument is not JSON array");
1403 for (i
= 0; i
< json
->array
.n
; i
++) {
1404 struct ovsdb_row_set results
;
1405 struct ovsdb_condition cnd
;
1408 check_ovsdb_error(ovsdb_condition_from_json(ts
, json
->array
.elems
[i
],
1411 for (j
= 0; j
< n_classes
; j
++) {
1412 classes
[j
].count
= 0;
1414 ovsdb_row_set_init(&results
);
1415 ovsdb_query_distinct(table
, &cnd
, &columns
, &results
);
1416 for (j
= 0; j
< results
.n_rows
; j
++) {
1419 for (k
= 0; k
< n_rows
; k
++) {
1420 if (uuid_equals(ovsdb_row_get_uuid(results
.rows
[j
]),
1422 rows
[k
].class->count
++;
1426 ovsdb_row_set_destroy(&results
);
1428 printf("query %2"PRIuSIZE
":", i
);
1429 for (j
= 0; j
< n_rows
; j
++) {
1430 int count
= rows
[j
].class->count
;
1437 printf("%d", count
);
1439 } else if (count
== 1) {
1440 putchar("abcdefghijklmnopqrstuvwxyz"[rows
[j
].class - classes
]);
1447 ovsdb_condition_destroy(&cnd
);
1451 for (i
= 0; i
< n_classes
; i
++) {
1452 ovsdb_row_destroy(classes
[i
].example
);
1455 ovsdb_table_destroy(table
); /* Also destroys 'ts'. */
1463 do_parse_schema(struct ovs_cmdl_context
*ctx
)
1465 struct ovsdb_schema
*schema
;
1468 json
= parse_json(ctx
->argv
[1]);
1469 check_ovsdb_error(ovsdb_schema_from_json(json
, &schema
));
1471 print_and_free_json(ovsdb_schema_to_json(schema
));
1472 ovsdb_schema_destroy(schema
);
1476 do_execute__(struct ovs_cmdl_context
*ctx
, bool ro
)
1478 struct ovsdb_schema
*schema
;
1483 /* Create database. */
1484 json
= parse_json(ctx
->argv
[1]);
1485 check_ovsdb_error(ovsdb_schema_from_json(json
, &schema
));
1487 db
= ovsdb_create(schema
, ovsdb_storage_create_unbacked());
1489 for (i
= 2; i
< ctx
->argc
; i
++) {
1490 struct json
*params
, *result
;
1493 params
= parse_json(ctx
->argv
[i
]);
1494 result
= ovsdb_execute(db
, NULL
, params
, ro
, NULL
, NULL
, 0, NULL
);
1495 s
= json_to_string(result
, JSSF_SORT
);
1498 json_destroy(params
);
1499 json_destroy(result
);
1506 do_execute_ro(struct ovs_cmdl_context
*ctx
)
1508 do_execute__(ctx
, true);
1512 do_execute(struct ovs_cmdl_context
*ctx
)
1514 do_execute__(ctx
, false);
1517 struct test_trigger
{
1518 struct ovsdb_trigger trigger
;
1523 do_trigger_dump(struct test_trigger
*t
, long long int now
, const char *title
)
1525 struct jsonrpc_msg
*reply
;
1528 reply
= ovsdb_trigger_steal_reply(&t
->trigger
);
1529 s
= json_to_string(reply
->result
, JSSF_SORT
);
1530 printf("t=%lld: trigger %d (%s): %s\n", now
, t
->number
, title
, s
);
1532 jsonrpc_msg_destroy(reply
);
1533 ovsdb_trigger_destroy(&t
->trigger
);
1538 do_trigger(struct ovs_cmdl_context
*ctx
)
1540 struct ovsdb_schema
*schema
;
1541 struct ovsdb_session session
;
1542 struct ovsdb_server server
;
1549 /* Create database. */
1550 json
= parse_json(ctx
->argv
[1]);
1551 check_ovsdb_error(ovsdb_schema_from_json(json
, &schema
));
1553 db
= ovsdb_create(schema
, ovsdb_storage_create_unbacked());
1555 ovsdb_server_init(&server
);
1556 ovsdb_server_add_db(&server
, db
);
1557 ovsdb_session_init(&session
, &server
);
1561 for (i
= 2; i
< ctx
->argc
; i
++) {
1562 struct json
*params
= parse_json(ctx
->argv
[i
]);
1563 if (params
->type
== JSON_ARRAY
1564 && json_array(params
)->n
== 2
1565 && json_array(params
)->elems
[0]->type
== JSON_STRING
1566 && !strcmp(json_string(json_array(params
)->elems
[0]), "advance")
1567 && json_array(params
)->elems
[1]->type
== JSON_INTEGER
) {
1568 now
+= json_integer(json_array(params
)->elems
[1]);
1569 json_destroy(params
);
1571 struct test_trigger
*t
= xmalloc(sizeof *t
);
1572 ovsdb_trigger_init(&session
, db
, &t
->trigger
,
1573 jsonrpc_create_request("transact", params
,
1575 now
, false, NULL
, NULL
);
1576 t
->number
= number
++;
1577 if (ovsdb_trigger_is_complete(&t
->trigger
)) {
1578 do_trigger_dump(t
, now
, "immediate");
1580 printf("t=%lld: new trigger %d\n", now
, t
->number
);
1584 ovsdb_trigger_run(db
, now
);
1586 struct test_trigger
*t
;
1587 LIST_FOR_EACH_POP (t
, trigger
.node
, &session
.completions
) {
1588 do_trigger_dump(t
, now
, "delayed");
1589 ovsdb_trigger_run(db
, now
);
1592 ovsdb_trigger_wait(db
, now
);
1593 poll_immediate_wake();
1597 ovsdb_server_destroy(&server
);
1602 do_help(struct ovs_cmdl_context
*ctx OVS_UNUSED
)
1607 /* "transact" command. */
1609 static struct ovsdb
*do_transact_db
;
1610 static struct ovsdb_txn
*do_transact_txn
;
1611 static struct ovsdb_table
*do_transact_table
;
1614 do_transact_commit(struct ovs_cmdl_context
*ctx OVS_UNUSED
)
1616 ovsdb_error_destroy(ovsdb_txn_replay_commit(do_transact_txn
));
1617 do_transact_txn
= NULL
;
1621 do_transact_abort(struct ovs_cmdl_context
*ctx OVS_UNUSED
)
1623 ovsdb_txn_abort(do_transact_txn
);
1624 do_transact_txn
= NULL
;
1628 uuid_from_integer(int integer
, struct uuid
*uuid
)
1631 uuid
->parts
[3] = integer
;
1634 static const struct ovsdb_row
*
1635 do_transact_find_row(const char *uuid_string
)
1637 const struct ovsdb_row
*row
;
1640 uuid_from_integer(atoi(uuid_string
), &uuid
);
1641 row
= ovsdb_table_get_row(do_transact_table
, &uuid
);
1643 ovs_fatal(0, "table does not contain row with UUID "UUID_FMT
,
1650 do_transact_set_integer(struct ovsdb_row
*row
, const char *column_name
,
1653 if (integer
!= -1) {
1654 const struct ovsdb_column
*column
;
1656 column
= ovsdb_table_schema_get_column(do_transact_table
->schema
,
1658 row
->fields
[column
->index
].keys
[0].integer
= integer
;
1663 do_transact_get_integer(const struct ovsdb_row
*row
, const char *column_name
)
1665 const struct ovsdb_column
*column
;
1667 column
= ovsdb_table_schema_get_column(do_transact_table
->schema
,
1669 return row
->fields
[column
->index
].keys
[0].integer
;
1673 do_transact_set_i_j(struct ovsdb_row
*row
,
1674 const char *i_string
, const char *j_string
)
1676 do_transact_set_integer(row
, "i", atoi(i_string
));
1677 do_transact_set_integer(row
, "j", atoi(j_string
));
1681 do_transact_insert(struct ovs_cmdl_context
*ctx
)
1683 struct ovsdb_row
*row
;
1686 row
= ovsdb_row_create(do_transact_table
);
1689 uuid
= ovsdb_row_get_uuid_rw(row
);
1690 uuid_from_integer(atoi(ctx
->argv
[1]), uuid
);
1691 if (ovsdb_table_get_row(do_transact_table
, uuid
)) {
1692 ovs_fatal(0, "table already contains row with UUID "UUID_FMT
,
1696 do_transact_set_i_j(row
, ctx
->argv
[2], ctx
->argv
[3]);
1699 ovsdb_txn_row_insert(do_transact_txn
, row
);
1703 do_transact_delete(struct ovs_cmdl_context
*ctx
)
1705 const struct ovsdb_row
*row
= do_transact_find_row(ctx
->argv
[1]);
1706 ovsdb_txn_row_delete(do_transact_txn
, row
);
1710 do_transact_modify(struct ovs_cmdl_context
*ctx
)
1712 const struct ovsdb_row
*row_ro
;
1713 struct ovsdb_row
*row_rw
;
1715 row_ro
= do_transact_find_row(ctx
->argv
[1]);
1716 row_rw
= ovsdb_txn_row_modify(do_transact_txn
, row_ro
);
1717 do_transact_set_i_j(row_rw
, ctx
->argv
[2], ctx
->argv
[3]);
1721 compare_rows_by_uuid(const void *a_
, const void *b_
)
1723 struct ovsdb_row
*const *ap
= a_
;
1724 struct ovsdb_row
*const *bp
= b_
;
1726 return uuid_compare_3way(ovsdb_row_get_uuid(*ap
), ovsdb_row_get_uuid(*bp
));
1730 do_transact_print(struct ovs_cmdl_context
*ctx OVS_UNUSED
)
1732 const struct ovsdb_row
**rows
;
1733 const struct ovsdb_row
*row
;
1737 n_rows
= hmap_count(&do_transact_table
->rows
);
1738 rows
= xmalloc(n_rows
* sizeof *rows
);
1740 HMAP_FOR_EACH (row
, hmap_node
, &do_transact_table
->rows
) {
1743 ovs_assert(i
== n_rows
);
1745 qsort(rows
, n_rows
, sizeof *rows
, compare_rows_by_uuid
);
1747 for (i
= 0; i
< n_rows
; i
++) {
1748 printf("\n%"PRId32
": i=%d, j=%d",
1749 ovsdb_row_get_uuid(rows
[i
])->parts
[3],
1750 do_transact_get_integer(rows
[i
], "i"),
1751 do_transact_get_integer(rows
[i
], "j"));
1758 do_transact(struct ovs_cmdl_context
*ctx
)
1760 static const struct ovs_cmdl_command do_transact_commands
[] = {
1761 { "commit", NULL
, 0, 0, do_transact_commit
, OVS_RO
},
1762 { "abort", NULL
, 0, 0, do_transact_abort
, OVS_RO
},
1763 { "insert", NULL
, 2, 3, do_transact_insert
, OVS_RO
},
1764 { "delete", NULL
, 1, 1, do_transact_delete
, OVS_RO
},
1765 { "modify", NULL
, 2, 3, do_transact_modify
, OVS_RO
},
1766 { "print", NULL
, 0, 0, do_transact_print
, OVS_RO
},
1767 { NULL
, NULL
, 0, 0, NULL
, OVS_RO
},
1770 struct ovsdb_schema
*schema
;
1775 json
= parse_json("{\"name\": \"testdb\", "
1779 " {\"i\": {\"type\": \"integer\"}, "
1780 " \"j\": {\"type\": \"integer\"}}}}}");
1781 check_ovsdb_error(ovsdb_schema_from_json(json
, &schema
));
1783 do_transact_db
= ovsdb_create(schema
, ovsdb_storage_create_unbacked());
1784 do_transact_table
= ovsdb_get_table(do_transact_db
, "mytable");
1785 ovs_assert(do_transact_table
!= NULL
);
1787 for (i
= 1; i
< ctx
->argc
; i
++) {
1788 struct json
*command
;
1792 struct ovs_cmdl_context transact_ctx
= { .argc
= 0, };
1794 command
= parse_json(ctx
->argv
[i
]);
1795 if (command
->type
!= JSON_ARRAY
) {
1796 ovs_fatal(0, "transaction %d must be JSON array "
1797 "with at least 1 element", i
);
1800 n_args
= command
->array
.n
;
1801 args
= xmalloc((n_args
+ 1) * sizeof *args
);
1802 for (j
= 0; j
< n_args
; j
++) {
1803 struct json
*s
= command
->array
.elems
[j
];
1804 if (s
->type
!= JSON_STRING
) {
1805 ovs_fatal(0, "transaction %d argument %d must be JSON string",
1808 args
[j
] = xstrdup(json_string(s
));
1810 args
[n_args
] = NULL
;
1812 if (!do_transact_txn
) {
1813 do_transact_txn
= ovsdb_txn_create(do_transact_db
);
1816 for (j
= 0; j
< n_args
; j
++) {
1820 fputs(args
[j
], stdout
);
1823 transact_ctx
.argc
= n_args
;
1824 transact_ctx
.argv
= args
;
1825 ovs_cmdl_run_command(&transact_ctx
, do_transact_commands
);
1828 for (j
= 0; j
< n_args
; j
++) {
1832 json_destroy(command
);
1834 ovsdb_txn_abort(do_transact_txn
);
1835 ovsdb_destroy(do_transact_db
); /* Also destroys 'schema'. */
1839 compare_link1(const void *a_
, const void *b_
)
1841 const struct idltest_link1
*const *ap
= a_
;
1842 const struct idltest_link1
*const *bp
= b_
;
1843 const struct idltest_link1
*a
= *ap
;
1844 const struct idltest_link1
*b
= *bp
;
1846 return a
->i
< b
->i
? -1 : a
->i
> b
->i
;
1850 print_idl_row_updated_simple(const struct idltest_simple
*s
, int step
)
1853 bool updated
= false;
1855 for (i
= 0; i
< IDLTEST_SIMPLE_N_COLUMNS
; i
++) {
1856 if (idltest_simple_is_updated(s
, i
)) {
1858 printf("%03d: updated columns:", step
);
1861 printf(" %s", idltest_simple_columns
[i
].name
);
1870 print_idl_row_updated_link1(const struct idltest_link1
*l1
, int step
)
1873 bool updated
= false;
1875 for (i
= 0; i
< IDLTEST_LINK1_N_COLUMNS
; i
++) {
1876 if (idltest_link1_is_updated(l1
, i
)) {
1878 printf("%03d: updated columns:", step
);
1881 printf(" %s", idltest_link1_columns
[i
].name
);
1890 print_idl_row_updated_link2(const struct idltest_link2
*l2
, int step
)
1893 bool updated
= false;
1895 for (i
= 0; i
< IDLTEST_LINK2_N_COLUMNS
; i
++) {
1896 if (idltest_link2_is_updated(l2
, i
)) {
1898 printf("%03d: updated columns:", step
);
1901 printf(" %s", idltest_link2_columns
[i
].name
);
1910 print_idl_row_updated_singleton(const struct idltest_singleton
*sng
, int step
)
1913 bool updated
= false;
1915 for (i
= 0; i
< IDLTEST_SINGLETON_N_COLUMNS
; i
++) {
1916 if (idltest_singleton_is_updated(sng
, i
)) {
1918 printf("%03d: updated columns:", step
);
1921 printf(" %s", idltest_singleton_columns
[i
].name
);
1930 print_idl_row_simple(const struct idltest_simple
*s
, int step
)
1934 printf("%03d: i=%"PRId64
" r=%g b=%s s=%s u="UUID_FMT
" ia=[",
1935 step
, s
->i
, s
->r
, s
->b
? "true" : "false",
1936 s
->s
, UUID_ARGS(&s
->u
));
1937 for (i
= 0; i
< s
->n_ia
; i
++) {
1938 printf("%s%"PRId64
, i
? " " : "", s
->ia
[i
]);
1941 for (i
= 0; i
< s
->n_ra
; i
++) {
1942 printf("%s%g", i
? " " : "", s
->ra
[i
]);
1945 for (i
= 0; i
< s
->n_ba
; i
++) {
1946 printf("%s%s", i
? " " : "", s
->ba
[i
] ? "true" : "false");
1949 for (i
= 0; i
< s
->n_sa
; i
++) {
1950 printf("%s%s", i
? " " : "", s
->sa
[i
]);
1953 for (i
= 0; i
< s
->n_ua
; i
++) {
1954 printf("%s"UUID_FMT
, i
? " " : "", UUID_ARGS(&s
->ua
[i
]));
1956 printf("] uuid="UUID_FMT
"\n", UUID_ARGS(&s
->header_
.uuid
));
1957 print_idl_row_updated_simple(s
, step
);
1961 print_idl_row_link1(const struct idltest_link1
*l1
, int step
)
1963 struct idltest_link1
**links
;
1966 printf("%03d: i=%"PRId64
" k=", step
, l1
->i
);
1968 printf("%"PRId64
, l1
->k
->i
);
1971 links
= xmemdup(l1
->ka
, l1
->n_ka
* sizeof *l1
->ka
);
1972 qsort(links
, l1
->n_ka
, sizeof *links
, compare_link1
);
1973 for (i
= 0; i
< l1
->n_ka
; i
++) {
1974 printf("%s%"PRId64
, i
? " " : "", links
[i
]->i
);
1979 printf("%"PRId64
, l1
->l2
->i
);
1981 printf(" uuid="UUID_FMT
"\n", UUID_ARGS(&l1
->header_
.uuid
));
1982 print_idl_row_updated_link1(l1
, step
);
1986 print_idl_row_link2(const struct idltest_link2
*l2
, int step
)
1988 printf("%03d: i=%"PRId64
" l1=", step
, l2
->i
);
1990 printf("%"PRId64
, l2
->l1
->i
);
1992 printf(" uuid="UUID_FMT
"\n", UUID_ARGS(&l2
->header_
.uuid
));
1993 print_idl_row_updated_link2(l2
, step
);
1997 print_idl_row_singleton(const struct idltest_singleton
*sng
, int step
)
1999 printf("%03d: name=%s", step
, sng
->name
);
2000 printf(" uuid="UUID_FMT
"\n", UUID_ARGS(&sng
->header_
.uuid
));
2001 print_idl_row_updated_singleton(sng
, step
);
2005 print_idl(struct ovsdb_idl
*idl
, int step
)
2007 const struct idltest_simple
*s
;
2008 const struct idltest_link1
*l1
;
2009 const struct idltest_link2
*l2
;
2010 const struct idltest_singleton
*sng
;
2013 IDLTEST_SIMPLE_FOR_EACH (s
, idl
) {
2014 print_idl_row_simple(s
, step
);
2017 IDLTEST_LINK1_FOR_EACH (l1
, idl
) {
2018 print_idl_row_link1(l1
, step
);
2021 IDLTEST_LINK2_FOR_EACH (l2
, idl
) {
2022 print_idl_row_link2(l2
, step
);
2025 IDLTEST_SINGLETON_FOR_EACH (sng
, idl
) {
2026 print_idl_row_singleton(sng
, step
);
2030 printf("%03d: empty\n", step
);
2035 print_idl_track(struct ovsdb_idl
*idl
, int step
, unsigned int seqno
)
2037 const struct idltest_simple
*s
;
2038 const struct idltest_link1
*l1
;
2039 const struct idltest_link2
*l2
;
2042 IDLTEST_SIMPLE_FOR_EACH_TRACKED (s
, idl
) {
2043 if (idltest_simple_row_get_seqno(s
, OVSDB_IDL_CHANGE_DELETE
) >= seqno
) {
2044 printf("%03d: ##deleted## uuid="UUID_FMT
"\n", step
, UUID_ARGS(&s
->header_
.uuid
));
2046 print_idl_row_simple(s
, step
);
2050 IDLTEST_LINK1_FOR_EACH_TRACKED (l1
, idl
) {
2051 if (idltest_simple_row_get_seqno(s
, OVSDB_IDL_CHANGE_DELETE
) >= seqno
) {
2052 printf("%03d: ##deleted## uuid="UUID_FMT
"\n", step
, UUID_ARGS(&s
->header_
.uuid
));
2054 print_idl_row_link1(l1
, step
);
2058 IDLTEST_LINK2_FOR_EACH_TRACKED (l2
, idl
) {
2059 if (idltest_simple_row_get_seqno(s
, OVSDB_IDL_CHANGE_DELETE
) >= seqno
) {
2060 printf("%03d: ##deleted## uuid="UUID_FMT
"\n", step
, UUID_ARGS(&s
->header_
.uuid
));
2062 print_idl_row_link2(l2
, step
);
2067 printf("%03d: empty\n", step
);
2072 parse_uuids(const struct json
*json
, struct ovsdb_symbol_table
*symtab
,
2077 if (json
->type
== JSON_STRING
&& uuid_from_string(&uuid
, json
->string
)) {
2078 char *name
= xasprintf("#%"PRIuSIZE
"#", *n
);
2079 fprintf(stderr
, "%s = "UUID_FMT
"\n", name
, UUID_ARGS(&uuid
));
2080 ovsdb_symbol_table_put(symtab
, name
, &uuid
, false);
2083 } else if (json
->type
== JSON_ARRAY
) {
2086 for (i
= 0; i
< json
->array
.n
; i
++) {
2087 parse_uuids(json
->array
.elems
[i
], symtab
, n
);
2089 } else if (json
->type
== JSON_OBJECT
) {
2090 const struct shash_node
*node
;
2092 SHASH_FOR_EACH (node
, json_object(json
)) {
2093 parse_uuids(node
->data
, symtab
, n
);
2099 substitute_uuids(struct json
*json
, const struct ovsdb_symbol_table
*symtab
)
2101 if (json
->type
== JSON_STRING
) {
2102 const struct ovsdb_symbol
*symbol
;
2104 symbol
= ovsdb_symbol_table_get(symtab
, json
->string
);
2107 json
->string
= xasprintf(UUID_FMT
, UUID_ARGS(&symbol
->uuid
));
2109 } else if (json
->type
== JSON_ARRAY
) {
2112 for (i
= 0; i
< json
->array
.n
; i
++) {
2113 substitute_uuids(json
->array
.elems
[i
], symtab
);
2115 } else if (json
->type
== JSON_OBJECT
) {
2116 const struct shash_node
*node
;
2118 SHASH_FOR_EACH (node
, json_object(json
)) {
2119 substitute_uuids(node
->data
, symtab
);
2124 static const struct idltest_simple
*
2125 idltest_find_simple(struct ovsdb_idl
*idl
, int i
)
2127 const struct idltest_simple
*s
;
2129 IDLTEST_SIMPLE_FOR_EACH (s
, idl
) {
2138 idl_set(struct ovsdb_idl
*idl
, char *commands
, int step
)
2140 char *cmd
, *save_ptr1
= NULL
;
2141 struct ovsdb_idl_txn
*txn
;
2142 enum ovsdb_idl_txn_status status
;
2143 bool increment
= false;
2145 txn
= ovsdb_idl_txn_create(idl
);
2146 ovsdb_idl_check_consistency(idl
);
2147 for (cmd
= strtok_r(commands
, ",", &save_ptr1
); cmd
;
2148 cmd
= strtok_r(NULL
, ",", &save_ptr1
)) {
2149 char *save_ptr2
= NULL
;
2150 char *name
, *arg1
, *arg2
, *arg3
;
2152 name
= strtok_r(cmd
, " ", &save_ptr2
);
2153 arg1
= strtok_r(NULL
, " ", &save_ptr2
);
2154 arg2
= strtok_r(NULL
, " ", &save_ptr2
);
2155 arg3
= strtok_r(NULL
, " ", &save_ptr2
);
2157 if (!strcmp(name
, "set")) {
2158 const struct idltest_simple
*s
;
2161 ovs_fatal(0, "\"set\" command requires 3 arguments");
2164 s
= idltest_find_simple(idl
, atoi(arg1
));
2166 ovs_fatal(0, "\"set\" command asks for nonexistent "
2167 "i=%d", atoi(arg1
));
2170 if (!strcmp(arg2
, "b")) {
2171 idltest_simple_set_b(s
, atoi(arg3
));
2172 } else if (!strcmp(arg2
, "s")) {
2173 idltest_simple_set_s(s
, arg3
);
2174 } else if (!strcmp(arg2
, "u")) {
2176 if (!uuid_from_string(&uuid
, arg3
)) {
2177 ovs_fatal(0, "\"%s\" is not a valid UUID", arg3
);
2179 idltest_simple_set_u(s
, uuid
);
2180 } else if (!strcmp(arg2
, "r")) {
2181 idltest_simple_set_r(s
, atof(arg3
));
2183 ovs_fatal(0, "\"set\" command asks for unknown column %s",
2186 } else if (!strcmp(name
, "insert")) {
2187 struct idltest_simple
*s
;
2189 if (!arg1
|| arg2
) {
2190 ovs_fatal(0, "\"insert\" command requires 1 argument");
2193 s
= idltest_simple_insert(txn
);
2194 idltest_simple_set_i(s
, atoi(arg1
));
2195 } else if (!strcmp(name
, "delete")) {
2196 const struct idltest_simple
*s
;
2198 if (!arg1
|| arg2
) {
2199 ovs_fatal(0, "\"delete\" command requires 1 argument");
2202 s
= idltest_find_simple(idl
, atoi(arg1
));
2204 ovs_fatal(0, "\"delete\" command asks for nonexistent "
2205 "i=%d", atoi(arg1
));
2207 idltest_simple_delete(s
);
2208 } else if (!strcmp(name
, "verify")) {
2209 const struct idltest_simple
*s
;
2211 if (!arg2
|| arg3
) {
2212 ovs_fatal(0, "\"verify\" command requires 2 arguments");
2215 s
= idltest_find_simple(idl
, atoi(arg1
));
2217 ovs_fatal(0, "\"verify\" command asks for nonexistent "
2218 "i=%d", atoi(arg1
));
2221 if (!strcmp(arg2
, "i")) {
2222 idltest_simple_verify_i(s
);
2223 } else if (!strcmp(arg2
, "b")) {
2224 idltest_simple_verify_b(s
);
2225 } else if (!strcmp(arg2
, "s")) {
2226 idltest_simple_verify_s(s
);
2227 } else if (!strcmp(arg2
, "u")) {
2228 idltest_simple_verify_s(s
);
2229 } else if (!strcmp(arg2
, "r")) {
2230 idltest_simple_verify_r(s
);
2232 ovs_fatal(0, "\"verify\" command asks for unknown column %s",
2235 } else if (!strcmp(name
, "increment")) {
2236 const struct idltest_simple
*s
;
2238 if (!arg1
|| arg2
) {
2239 ovs_fatal(0, "\"increment\" command requires 1 argument");
2242 s
= idltest_find_simple(idl
, atoi(arg1
));
2244 ovs_fatal(0, "\"set\" command asks for nonexistent "
2245 "i=%d", atoi(arg1
));
2248 ovsdb_idl_txn_increment(txn
, &s
->header_
, &idltest_simple_col_i
,
2251 } else if (!strcmp(name
, "abort")) {
2252 ovsdb_idl_txn_abort(txn
);
2253 ovsdb_idl_check_consistency(idl
);
2255 } else if (!strcmp(name
, "destroy")) {
2256 printf("%03d: destroy\n", step
);
2257 ovsdb_idl_txn_destroy(txn
);
2258 ovsdb_idl_check_consistency(idl
);
2261 ovs_fatal(0, "unknown command %s", name
);
2263 ovsdb_idl_check_consistency(idl
);
2266 status
= ovsdb_idl_txn_commit_block(txn
);
2267 printf("%03d: commit, status=%s",
2268 step
, ovsdb_idl_txn_status_to_string(status
));
2270 printf(", increment=%"PRId64
,
2271 ovsdb_idl_txn_get_increment_new_value(txn
));
2274 ovsdb_idl_txn_destroy(txn
);
2275 ovsdb_idl_check_consistency(idl
);
2278 static const struct ovsdb_idl_table_class
*
2279 find_table_class(const char *name
)
2281 if (!strcmp(name
, "simple")) {
2282 return &idltest_table_simple
;
2283 } else if (!strcmp(name
, "link1")) {
2284 return &idltest_table_link1
;
2285 } else if (!strcmp(name
, "link2")) {
2286 return &idltest_table_link2
;
2292 parse_simple_json_clause(struct ovsdb_idl_condition
*cond
,
2293 enum ovsdb_function function
,
2294 const char *column
, const struct json
*arg
)
2296 if (!strcmp(column
, "b")) {
2297 idltest_simple_add_clause_b(cond
, function
, json_boolean(arg
));
2298 } else if (!strcmp(column
, "i")) {
2299 idltest_simple_add_clause_i(cond
, function
, json_integer(arg
));
2300 } else if (!strcmp(column
, "s")) {
2301 idltest_simple_add_clause_s(cond
, function
, json_string(arg
));
2302 } else if (!strcmp(column
, "u")) {
2304 if (!uuid_from_string(&uuid
, json_string(arg
))) {
2305 ovs_fatal(0, "\"%s\" is not a valid UUID", json_string(arg
));
2307 idltest_simple_add_clause_u(cond
, function
, uuid
);
2308 } else if (!strcmp(column
, "r")) {
2309 idltest_simple_add_clause_r(cond
, function
, json_real(arg
));
2311 ovs_fatal(0, "Unsupported columns name %s", column
);
2316 parse_link1_json_clause(struct ovsdb_idl_condition
*cond
,
2317 enum ovsdb_function function
,
2318 const char *column
, const struct json
*arg
)
2320 if (!strcmp(column
, "i")) {
2321 idltest_link1_add_clause_i(cond
, function
, json_integer(arg
));
2323 ovs_fatal(0, "Unsupported columns name %s", column
);
2328 parse_link2_json_clause(struct ovsdb_idl_condition
*cond
,
2329 enum ovsdb_function function
,
2330 const char *column
, const struct json
*arg
)
2332 if (!strcmp(column
, "i")) {
2333 idltest_link2_add_clause_i(cond
, function
, json_integer(arg
));
2335 ovs_fatal(0, "Unsupported columns name %s", column
);
2340 update_conditions(struct ovsdb_idl
*idl
, char *commands
)
2342 char *cmd
, *save_ptr1
= NULL
;
2343 const struct ovsdb_idl_table_class
*tc
;
2345 for (cmd
= strtok_r(commands
, ";", &save_ptr1
); cmd
;
2346 cmd
= strtok_r(NULL
, ";", &save_ptr1
)) {
2347 char *save_ptr2
= NULL
;
2348 char *table_name
= strtok_r(cmd
, " ", &save_ptr2
);
2349 struct json
*json
= parse_json(save_ptr2
);
2352 if (json
->type
!= JSON_ARRAY
) {
2353 ovs_fatal(0, "condition should be an array");
2356 tc
= find_table_class(table_name
);
2358 ovs_fatal(0, "Table %s does not exist", table_name
);
2361 struct ovsdb_idl_condition cond
= OVSDB_IDL_CONDITION_INIT(&cond
);
2362 for (i
= 0; i
< json
->array
.n
; i
++) {
2363 const struct json
*clause
= json
->array
.elems
[i
];
2364 if (clause
->type
== JSON_TRUE
) {
2365 ovsdb_idl_condition_add_clause_true(&cond
);
2366 } else if (clause
->type
!= JSON_ARRAY
|| clause
->array
.n
!= 3
2367 || clause
->array
.elems
[0]->type
!= JSON_STRING
2368 || clause
->array
.elems
[1]->type
!= JSON_STRING
) {
2369 ovs_fatal(0, "Error parsing condition");
2371 enum ovsdb_function function
;
2372 const char *function_s
= json_string(clause
->array
.elems
[1]);
2373 struct ovsdb_error
*error
= ovsdb_function_from_string(
2374 function_s
, &function
);
2376 ovs_fatal(0, "unknown clause function %s", function_s
);
2379 const char *column
= json_string(clause
->array
.elems
[0]);
2380 const struct json
*arg
= clause
->array
.elems
[2];
2381 if (!strcmp(table_name
, "simple")) {
2382 parse_simple_json_clause(&cond
, function
, column
, arg
);
2383 } else if (!strcmp(table_name
, "link1")) {
2384 parse_link1_json_clause(&cond
, function
, column
, arg
);
2385 } else if (!strcmp(table_name
, "link2")) {
2386 parse_link2_json_clause(&cond
, function
, column
, arg
);
2391 unsigned int seqno
= ovsdb_idl_get_condition_seqno(idl
);
2392 unsigned int next_seqno
= ovsdb_idl_set_condition(idl
, tc
, &cond
);
2393 if (seqno
== next_seqno
) {
2394 ovs_fatal(0, "condition unchanged");
2396 ovsdb_idl_condition_destroy(&cond
);
2402 do_idl(struct ovs_cmdl_context
*ctx
)
2404 struct jsonrpc
*rpc
;
2405 struct ovsdb_idl
*idl
;
2406 unsigned int seqno
= 0;
2407 struct ovsdb_symbol_table
*symtab
;
2414 track
= ((struct test_ovsdb_pvt_context
*)(ctx
->pvt
))->track
;
2416 idl
= ovsdb_idl_create(ctx
->argv
[1], &idltest_idl_class
, true, true);
2417 if (ctx
->argc
> 2) {
2418 struct stream
*stream
;
2420 error
= stream_open_block(jsonrpc_stream_open(ctx
->argv
[1], &stream
,
2421 DSCP_DEFAULT
), &stream
);
2423 ovs_fatal(error
, "failed to connect to \"%s\"", ctx
->argv
[1]);
2425 rpc
= jsonrpc_open(stream
);
2431 ovsdb_idl_track_add_all(idl
);
2434 setvbuf(stdout
, NULL
, _IONBF
, 0);
2436 symtab
= ovsdb_symbol_table_create();
2437 const char cond_s
[] = "condition ";
2438 if (ctx
->argc
> 2 && strstr(ctx
->argv
[2], cond_s
)) {
2439 update_conditions(idl
, ctx
->argv
[2] + strlen(cond_s
));
2440 printf("%03d: change conditions\n", step
++);
2445 for (; i
< ctx
->argc
; i
++) {
2446 char *arg
= ctx
->argv
[i
];
2447 struct jsonrpc_msg
*request
, *reply
;
2450 /* The previous transaction didn't change anything. */
2453 /* Wait for update. */
2456 ovsdb_idl_check_consistency(idl
);
2457 if (ovsdb_idl_get_seqno(idl
) != seqno
) {
2462 ovsdb_idl_wait(idl
);
2469 print_idl_track(idl
, step
++, ovsdb_idl_get_seqno(idl
));
2470 ovsdb_idl_track_clear(idl
);
2472 print_idl(idl
, step
++);
2475 seqno
= ovsdb_idl_get_seqno(idl
);
2477 if (!strcmp(arg
, "reconnect")) {
2478 printf("%03d: reconnect\n", step
++);
2479 ovsdb_idl_force_reconnect(idl
);
2480 } else if (!strncmp(arg
, cond_s
, strlen(cond_s
))) {
2481 update_conditions(idl
, arg
+ strlen(cond_s
));
2482 printf("%03d: change conditions\n", step
++);
2483 } else if (arg
[0] != '[') {
2484 idl_set(idl
, arg
, step
++);
2486 struct json
*json
= parse_json(arg
);
2487 substitute_uuids(json
, symtab
);
2488 request
= jsonrpc_create_request("transact", json
, NULL
);
2489 error
= jsonrpc_transact_block(rpc
, request
, &reply
);
2490 if (error
|| reply
->error
) {
2491 ovs_fatal(error
, "jsonrpc transaction failed");
2493 printf("%03d: ", step
++);
2494 if (reply
->result
) {
2495 parse_uuids(reply
->result
, symtab
, &n_uuids
);
2497 json_destroy(reply
->id
);
2499 print_and_free_json(jsonrpc_msg_to_json(reply
));
2502 ovsdb_symbol_table_destroy(symtab
);
2509 ovsdb_idl_check_consistency(idl
);
2510 if (ovsdb_idl_get_seqno(idl
) != seqno
) {
2513 ovsdb_idl_wait(idl
);
2516 print_idl(idl
, step
++);
2517 ovsdb_idl_track_clear(idl
);
2518 ovsdb_idl_destroy(idl
);
2519 printf("%03d: done\n", step
);
2523 print_idl_row_simple2(const struct idltest_simple2
*s
, int step
)
2526 const struct ovsdb_datum
*smap
, *imap
;
2528 smap
= idltest_simple2_get_smap(s
, OVSDB_TYPE_STRING
, OVSDB_TYPE_STRING
);
2529 imap
= idltest_simple2_get_imap(s
, OVSDB_TYPE_INTEGER
, OVSDB_TYPE_STRING
);
2530 printf("%03d: name=%s smap=[",
2532 for (i
= 0; i
< smap
->n
; i
++) {
2533 printf("[%s : %s]%s", smap
->keys
[i
].string
, smap
->values
[i
].string
,
2534 i
< smap
->n
-1? ",": "");
2537 for (i
= 0; i
< imap
->n
; i
++) {
2538 printf("[%"PRId64
" : %s]%s", imap
->keys
[i
].integer
, imap
->values
[i
].string
,
2539 i
< imap
->n
-1? ",":"");
2545 dump_simple2(struct ovsdb_idl
*idl
,
2546 const struct idltest_simple2
*myRow
,
2549 IDLTEST_SIMPLE2_FOR_EACH(myRow
, idl
) {
2550 print_idl_row_simple2(myRow
, step
);
2555 do_idl_partial_update_map_column(struct ovs_cmdl_context
*ctx
)
2557 struct ovsdb_idl
*idl
;
2558 struct ovsdb_idl_txn
*myTxn
;
2559 const struct idltest_simple2
*myRow
;
2560 const struct ovsdb_datum
*smap
, *imap OVS_UNUSED
;
2562 char key_to_delete
[100];
2564 idl
= ovsdb_idl_create(ctx
->argv
[1], &idltest_idl_class
, false, true);
2565 ovsdb_idl_add_table(idl
, &idltest_table_simple2
);
2566 ovsdb_idl_add_column(idl
, &idltest_simple2_col_name
);
2567 ovsdb_idl_add_column(idl
, &idltest_simple2_col_smap
);
2568 ovsdb_idl_add_column(idl
, &idltest_simple2_col_imap
);
2569 ovsdb_idl_get_initial_snapshot(idl
);
2570 setvbuf(stdout
, NULL
, _IONBF
, 0);
2573 /* Display original data in table. */
2575 printf("%03d: Getting records\n", step
++);
2576 dump_simple2(idl
, myRow
, step
++);
2578 /* Insert new elements in different map columns. */
2579 myRow
= idltest_simple2_first(idl
);
2580 myTxn
= ovsdb_idl_txn_create(idl
);
2581 idltest_simple2_get_smap(myRow
, OVSDB_TYPE_STRING
,
2583 idltest_simple2_update_smap_setkey(myRow
, "key1", "myList1");
2584 imap
= idltest_simple2_get_imap(myRow
, OVSDB_TYPE_INTEGER
,
2586 idltest_simple2_update_imap_setkey(myRow
, 3, "myids2");
2587 idltest_simple2_set_name(myRow
, "String2");
2588 ovsdb_idl_txn_commit_block(myTxn
);
2589 ovsdb_idl_txn_destroy(myTxn
);
2590 ovsdb_idl_get_initial_snapshot(idl
);
2591 printf("%03d: After insert element\n", step
++);
2592 dump_simple2(idl
, myRow
, step
++);
2594 /* Insert duplicate element. */
2595 myTxn
= ovsdb_idl_txn_create(idl
);
2596 idltest_simple2_update_smap_setkey(myRow
, "key1", "myList1");
2597 ovsdb_idl_txn_commit_block(myTxn
);
2598 ovsdb_idl_txn_destroy(myTxn
);
2599 ovsdb_idl_get_initial_snapshot(idl
);
2600 printf("%03d: After insert duplicated element\n", step
++);
2601 dump_simple2(idl
, myRow
, step
++);
2603 /* Deletes an element of a map column. */
2604 myRow
= idltest_simple2_first(idl
);
2605 myTxn
= ovsdb_idl_txn_create(idl
);
2606 smap
= idltest_simple2_get_smap(myRow
, OVSDB_TYPE_STRING
,
2608 strcpy(key_to_delete
, smap
->keys
[0].string
);
2609 idltest_simple2_update_smap_delkey(myRow
, smap
->keys
[0].string
);
2610 ovsdb_idl_txn_commit_block(myTxn
);
2611 ovsdb_idl_txn_destroy(myTxn
);
2612 ovsdb_idl_get_initial_snapshot(idl
);
2613 printf("%03d: After delete element\n", step
++);
2614 dump_simple2(idl
, myRow
, step
++);
2616 /* Try to delete a deleted element of a map column. */
2617 myTxn
= ovsdb_idl_txn_create(idl
);
2618 idltest_simple2_update_smap_delkey(myRow
, key_to_delete
);
2619 ovsdb_idl_txn_commit_block(myTxn
);
2620 ovsdb_idl_txn_destroy(myTxn
);
2621 ovsdb_idl_get_initial_snapshot(idl
);
2622 printf("%03d: After trying to delete a deleted element\n", step
++);
2623 dump_simple2(idl
, myRow
, step
++);
2625 ovsdb_idl_destroy(idl
);
2626 printf("%03d: End test\n", step
);
2630 print_idl_row_simple3(const struct idltest_simple3
*s
, int step
)
2633 const struct ovsdb_datum
*uset
;
2634 const struct ovsdb_datum
*uref
;
2636 uset
= idltest_simple3_get_uset(s
, OVSDB_TYPE_UUID
);
2637 printf("%03d: name=%s uset=[",
2639 for (i
= 0; i
< uset
->n
; i
++) {
2640 printf("["UUID_FMT
"]%s", UUID_ARGS(&(uset
->keys
[i
].uuid
)), i
< uset
->n
-1? ",": "");
2642 uref
= idltest_simple3_get_uref(s
, OVSDB_TYPE_UUID
);
2644 for (i
= 0; i
< uref
->n
; i
++) {
2645 printf("["UUID_FMT
"]%s", UUID_ARGS(&(uref
->keys
[i
].uuid
)), i
< uref
->n
-1? ",": "");
2651 dump_simple3(struct ovsdb_idl
*idl
,
2652 const struct idltest_simple3
*myRow
,
2655 IDLTEST_SIMPLE3_FOR_EACH(myRow
, idl
) {
2656 print_idl_row_simple3(myRow
, step
);
2661 do_idl_partial_update_set_column(struct ovs_cmdl_context
*ctx
)
2663 struct ovsdb_idl
*idl
;
2664 struct ovsdb_idl_txn
*myTxn
;
2665 const struct idltest_simple3
*myRow
;
2666 struct idltest_simple4
*myRow2
;
2667 const struct ovsdb_datum
*uset OVS_UNUSED
;
2668 const struct ovsdb_datum
*uref OVS_UNUSED
;
2671 idl
= ovsdb_idl_create(ctx
->argv
[1], &idltest_idl_class
, false, true);
2672 ovsdb_idl_add_table(idl
, &idltest_table_simple3
);
2673 ovsdb_idl_add_column(idl
, &idltest_simple3_col_name
);
2674 ovsdb_idl_add_column(idl
, &idltest_simple3_col_uset
);
2675 ovsdb_idl_add_column(idl
, &idltest_simple3_col_uref
);
2676 ovsdb_idl_add_table(idl
, &idltest_table_simple4
);
2677 ovsdb_idl_add_column(idl
, &idltest_simple4_col_name
);
2678 ovsdb_idl_get_initial_snapshot(idl
);
2679 setvbuf(stdout
, NULL
, _IONBF
, 0);
2682 /* Display original data in table. */
2684 printf("%03d: Getting records\n", step
++);
2685 dump_simple3(idl
, myRow
, step
++);
2687 /* Insert new elements in different map columns. */
2688 myRow
= idltest_simple3_first(idl
);
2689 myTxn
= ovsdb_idl_txn_create(idl
);
2690 idltest_simple3_get_uset(myRow
, OVSDB_TYPE_UUID
);
2691 struct uuid uuid_to_add
;
2692 uuid_from_string(&uuid_to_add
, "001e43d2-dd3f-4616-ab6a-83a490bb0991");
2693 idltest_simple3_update_uset_addvalue(myRow
, uuid_to_add
);
2694 idltest_simple3_set_name(myRow
, "String2");
2695 ovsdb_idl_txn_commit_block(myTxn
);
2696 ovsdb_idl_txn_destroy(myTxn
);
2697 ovsdb_idl_get_initial_snapshot(idl
);
2698 printf("%03d: After rename+add new value\n", step
++);
2699 dump_simple3(idl
, myRow
, step
++);
2701 /* Insert duplicate element. */
2702 myTxn
= ovsdb_idl_txn_create(idl
);
2703 struct uuid uuid_to_add2
;
2704 uuid_from_string(&uuid_to_add2
, "0026b3ba-571b-4729-8227-d860a5210ab8");
2705 idltest_simple3_update_uset_addvalue(myRow
, uuid_to_add2
);
2706 ovsdb_idl_txn_commit_block(myTxn
);
2707 ovsdb_idl_txn_destroy(myTxn
);
2708 ovsdb_idl_get_initial_snapshot(idl
);
2709 printf("%03d: After add new value\n", step
++);
2710 dump_simple3(idl
, myRow
, step
++);
2712 /* Deletes an element of a set column. */
2713 myRow
= idltest_simple3_first(idl
);
2714 myTxn
= ovsdb_idl_txn_create(idl
);
2715 uset
= idltest_simple3_get_uset(myRow
, OVSDB_TYPE_UUID
);
2716 idltest_simple3_update_uset_delvalue(myRow
, uuid_to_add
);
2717 ovsdb_idl_txn_commit_block(myTxn
);
2718 ovsdb_idl_txn_destroy(myTxn
);
2719 ovsdb_idl_get_initial_snapshot(idl
);
2720 printf("%03d: After delete value\n", step
++);
2721 dump_simple3(idl
, myRow
, step
++);
2723 /* Try to delete a deleted element of a map column. */
2724 myRow
= idltest_simple3_first(idl
);
2725 myTxn
= ovsdb_idl_txn_create(idl
);
2726 idltest_simple3_update_uset_delvalue(myRow
, uuid_to_add
);
2727 ovsdb_idl_txn_commit_block(myTxn
);
2728 ovsdb_idl_txn_destroy(myTxn
);
2729 ovsdb_idl_get_initial_snapshot(idl
);
2730 printf("%03d: After trying to delete a deleted value\n", step
++);
2731 dump_simple3(idl
, myRow
, step
++);
2733 /* Adds to a table and update a strong reference in another table. */
2734 myRow
= idltest_simple3_first(idl
);
2735 myTxn
= ovsdb_idl_txn_create(idl
);
2736 myRow2
= idltest_simple4_insert(myTxn
);
2737 idltest_simple4_set_name(myRow2
, "test");
2738 idltest_simple3_update_uref_addvalue(myRow
, myRow2
);
2739 ovsdb_idl_txn_commit_block(myTxn
);
2740 ovsdb_idl_txn_destroy(myTxn
);
2741 ovsdb_idl_get_initial_snapshot(idl
);
2742 printf("%03d: After add to other table + set of strong ref\n", step
++);
2743 dump_simple3(idl
, myRow
, step
++);
2744 ovsdb_idl_destroy(idl
);
2745 printf("%03d: End test\n", step
);
2749 do_idl_compound_index_with_ref(struct ovs_cmdl_context
*ctx
)
2751 struct ovsdb_idl
*idl
;
2752 struct ovsdb_idl_txn
*myTxn
;
2753 const struct idltest_simple3
*myRow
;
2754 struct idltest_simple4
*myRow2
;
2755 const struct ovsdb_datum
*uset OVS_UNUSED
;
2756 const struct ovsdb_datum
*uref OVS_UNUSED
;
2759 idl
= ovsdb_idl_create(ctx
->argv
[1], &idltest_idl_class
, false, true);
2760 ovsdb_idl_add_table(idl
, &idltest_table_simple3
);
2761 ovsdb_idl_add_column(idl
, &idltest_simple3_col_name
);
2762 ovsdb_idl_add_column(idl
, &idltest_simple3_col_uset
);
2763 ovsdb_idl_add_column(idl
, &idltest_simple3_col_uref
);
2764 ovsdb_idl_add_table(idl
, &idltest_table_simple4
);
2765 ovsdb_idl_add_column(idl
, &idltest_simple4_col_name
);
2767 struct ovsdb_idl_index
*index
= ovsdb_idl_index_create1(
2768 idl
, &idltest_simple3_col_uref
);
2770 ovsdb_idl_get_initial_snapshot(idl
);
2772 setvbuf(stdout
, NULL
, _IONBF
, 0);
2775 /* Adds to a table and update a strong reference in another table. */
2776 myTxn
= ovsdb_idl_txn_create(idl
);
2777 myRow
= idltest_simple3_insert(myTxn
);
2778 myRow2
= idltest_simple4_insert(myTxn
);
2779 idltest_simple4_set_name(myRow2
, "test");
2780 idltest_simple3_update_uref_addvalue(myRow
, myRow2
);
2781 ovsdb_idl_txn_commit_block(myTxn
);
2782 ovsdb_idl_txn_destroy(myTxn
);
2783 ovsdb_idl_get_initial_snapshot(idl
);
2784 printf("%03d: After add to other table + set of strong ref\n", step
++);
2785 dump_simple3(idl
, myRow
, step
++);
2787 myRow2
= (struct idltest_simple4
*) idltest_simple4_first(idl
);
2788 printf("%03d: check simple4: %s\n", step
++,
2789 myRow2
? "not empty" : "empty");
2791 /* Use index to query the row with reference */
2793 struct idltest_simple3
*equal
= idltest_simple3_index_init_row(index
);
2794 myRow2
= (struct idltest_simple4
*) idltest_simple4_first(idl
);
2795 idltest_simple3_index_set_uref(equal
, &myRow2
, 1);
2796 printf("%03d: Query using index with reference\n", step
++);
2797 IDLTEST_SIMPLE3_FOR_EACH_EQUAL (myRow
, equal
, index
) {
2798 print_idl_row_simple3(myRow
, step
++);
2800 idltest_simple3_index_destroy_row(equal
);
2802 /* Delete the row with reference */
2803 myTxn
= ovsdb_idl_txn_create(idl
);
2804 myRow
= idltest_simple3_first(idl
);
2805 idltest_simple3_delete(myRow
);
2806 ovsdb_idl_txn_commit_block(myTxn
);
2807 ovsdb_idl_txn_destroy(myTxn
);
2808 ovsdb_idl_get_initial_snapshot(idl
);
2809 printf("%03d: After delete\n", step
++);
2810 dump_simple3(idl
, myRow
, step
++);
2812 myRow2
= (struct idltest_simple4
*) idltest_simple4_first(idl
);
2813 printf("%03d: check simple4: %s\n", step
++,
2814 myRow2
? "not empty" : "empty");
2816 ovsdb_idl_destroy(idl
);
2817 printf("%03d: End test\n", step
);
2822 test_idl_compound_index_single_column(struct ovsdb_idl
*idl
,
2823 struct ovsdb_idl_index
*s_index
,
2824 struct ovsdb_idl_index
*i_index
)
2826 const struct idltest_simple
*myRow
;
2827 struct ovsdb_idl_txn
*txn
;
2830 /* Display records by string index. */
2832 IDLTEST_SIMPLE_FOR_EACH_BYINDEX (myRow
, s_index
) {
2833 printf("%03d: s=%s i=%"PRId64
" b=%s r=%f\n", step
, myRow
->s
,
2834 myRow
->i
, myRow
->b
?"True":"False", myRow
->r
);
2836 /* Display records by integer index. */
2838 IDLTEST_SIMPLE_FOR_EACH_BYINDEX (myRow
, i_index
) {
2839 printf("%03d: i=%"PRId64
" s=%s b=%s r=%f\n", step
, myRow
->i
,
2840 myRow
->s
, myRow
->b
?"True":"False", myRow
->r
);
2842 /* Display records by string index -> s_index with filtering
2843 * where s=\"List001\
2846 struct idltest_simple
*equal
= idltest_simple_index_init_row(s_index
);
2847 idltest_simple_index_set_s(equal
, "List001");
2848 ovs_assert(strcmp(equal
->s
, "List001") == 0);
2849 IDLTEST_SIMPLE_FOR_EACH_EQUAL (myRow
, equal
, s_index
) {
2850 printf("%03d: s=%s i=%"PRId64
" b=%s r=%f\n", step
, myRow
->s
,
2851 myRow
->i
, myRow
->b
?"True":"False", myRow
->r
);
2853 /* Display records by integer index -> i_index with filtering where i=5 */
2855 idltest_simple_index_set_i(equal
, 5);
2856 ovs_assert(equal
->i
== 5);
2857 IDLTEST_SIMPLE_FOR_EACH_EQUAL (myRow
, equal
, i_index
) {
2858 printf("%03d: i=%"PRId64
" s=%s b=%s r=%f\n", step
, myRow
->i
,
2859 myRow
->s
, myRow
->b
?"True":"False", myRow
->r
);
2861 /* Display records by integer index -> i_index in range i=[3,7] */
2863 struct idltest_simple
*from
, *to
;
2864 from
= idltest_simple_index_init_row(i_index
);
2865 idltest_simple_index_set_i(from
, 3);
2866 ovs_assert(from
->i
== 3);
2867 to
= idltest_simple_index_init_row(i_index
);
2868 idltest_simple_index_set_i(to
, 7);
2869 ovs_assert(to
->i
== 7);
2870 IDLTEST_SIMPLE_FOR_EACH_RANGE (myRow
, from
, to
, i_index
) {
2871 printf("%03d: i=%"PRId64
" s=%s b=%s r=%f\n", step
, myRow
->i
,
2872 myRow
->s
, myRow
->b
?"True":"False", myRow
->r
);
2874 /* Delete record i=4 and insert i=54 by integer index -> i_index */
2876 struct idltest_simple
*toDelete
, *toInsert
;
2877 toDelete
= idltest_simple_index_init_row(i_index
);
2878 idltest_simple_index_set_i(toDelete
, 4);
2879 ovs_assert(toDelete
->i
== 4);
2880 myRow
= idltest_simple_index_find(i_index
, toDelete
);
2882 ovs_assert(myRow
->i
== 4);
2883 txn
= ovsdb_idl_txn_create(idl
);
2884 idltest_simple_delete(myRow
);
2885 toInsert
= idltest_simple_insert(txn
);
2886 idltest_simple_set_i(toInsert
, 54);
2887 idltest_simple_set_s(toInsert
, "Lista054");
2888 ovsdb_idl_txn_commit_block(txn
);
2889 ovsdb_idl_txn_destroy(txn
);
2890 idltest_simple_index_set_i(to
, 60);
2891 printf("Expected 60, stored %"PRId64
"\n", to
->i
);
2892 ovs_assert(to
->i
== 60);
2893 IDLTEST_SIMPLE_FOR_EACH_RANGE (myRow
, from
, to
, i_index
) {
2894 printf("%03d: i=%"PRId64
" s=%s b=%s r=%f\n", step
, myRow
->i
,
2895 myRow
->s
, myRow
->b
?"True":"False", myRow
->r
);
2898 /* Test special-case range, "from" and "to" are both NULL,
2899 * which is interpreted as the range from -infinity to +infinity. */
2901 IDLTEST_SIMPLE_FOR_EACH_RANGE (myRow
, NULL
, NULL
, i_index
) {
2902 printf("%03d: i=%"PRId64
" s=%s b=%s r=%f\n", step
, myRow
->i
,
2903 myRow
->s
, myRow
->b
?"True":"False", myRow
->r
);
2906 /* Free the temporal rows */
2907 idltest_simple_index_destroy_row(from
);
2908 idltest_simple_index_destroy_row(to
);
2909 idltest_simple_index_destroy_row(equal
);
2910 idltest_simple_index_destroy_row(toDelete
);
2915 test_idl_compound_index_double_column(struct ovsdb_idl_index
*si_index
,
2916 struct ovsdb_idl_index
*sid_index
,
2917 struct ovsdb_idl_index
*is_index
,
2918 struct ovsdb_idl_index
*ids_index
)
2920 const struct idltest_simple
*myRow
;
2923 /* Display records by string-integer index -> si_index */
2925 IDLTEST_SIMPLE_FOR_EACH_BYINDEX (myRow
, si_index
) {
2926 printf("%03d: s=%s i=%"PRId64
" b=%s r=%f\n", step
, myRow
->s
, myRow
->i
,
2927 myRow
->b
?"True":"False", myRow
->r
);
2929 /* Display records by string-integer(down order) index -> sid_index */
2931 IDLTEST_SIMPLE_FOR_EACH_BYINDEX (myRow
, sid_index
) {
2932 printf("%03d: s=%s i=%"PRId64
" b=%s r=%f\n", step
, myRow
->s
, myRow
->i
,
2933 myRow
->b
?"True":"False", myRow
->r
);
2935 /* Display records by string-integer index -> si_index with filtering
2936 * where s="List000" and i=10
2939 struct idltest_simple
*equal
= idltest_simple_index_init_row(si_index
);
2940 idltest_simple_index_set_s(equal
, "List000");
2941 ovs_assert(strcmp(equal
->s
, "List000") == 0);
2942 idltest_simple_index_set_i(equal
, 10);
2943 ovs_assert(equal
->i
== 10);
2944 IDLTEST_SIMPLE_FOR_EACH_EQUAL (myRow
, equal
, si_index
) {
2945 printf("%03d: s=%s i=%"PRId64
" b=%s r=%f\n", step
, myRow
->s
, myRow
->i
,
2946 myRow
->b
?"True":"False", myRow
->r
);
2948 /* Display records by string-integer index -> si_index in range i=[0,100]
2949 * and s=[\"List002\",\"List003\"]
2952 struct idltest_simple
*from
= idltest_simple_index_init_row(si_index
);
2953 struct idltest_simple
*to
= idltest_simple_index_init_row(si_index
);
2954 idltest_simple_index_set_i(from
, 0);
2955 ovs_assert(from
->i
== 0);
2956 idltest_simple_index_set_s(from
, "List001");
2957 ovs_assert(strcmp(from
->s
, "List001") == 0);
2958 idltest_simple_index_set_i(to
, 100);
2959 ovs_assert(to
->i
== 100);
2960 idltest_simple_index_set_s(to
, "List005");
2961 ovs_assert(strcmp(to
->s
, "List005")==0);
2962 IDLTEST_SIMPLE_FOR_EACH_RANGE (myRow
, from
, to
, si_index
) {
2963 printf("%03d: s=%s i=%"PRId64
" b=%s r=%f\n", step
, myRow
->s
, myRow
->i
,
2964 myRow
->b
?"True":"False", myRow
->r
);
2966 /* Display records using integer-string index. */
2968 IDLTEST_SIMPLE_FOR_EACH_BYINDEX (myRow
, is_index
) {
2969 printf("%03d: i=%"PRId64
" s=%s b=%s r=%f\n", step
, myRow
->i
, myRow
->s
,
2970 myRow
->b
?"True":"False", myRow
->r
);
2972 /* Display records using integer(descend)-string index. */
2974 IDLTEST_SIMPLE_FOR_EACH_BYINDEX (myRow
, ids_index
) {
2975 printf("%03d: i=%"PRId64
" s=%s b=%s r=%f\n", step
, myRow
->i
, myRow
->s
,
2976 myRow
->b
?"True":"False", myRow
->r
);
2979 idltest_simple_index_destroy_row(to
);
2980 idltest_simple_index_destroy_row(from
);
2981 idltest_simple_index_destroy_row(equal
);
2986 do_idl_compound_index(struct ovs_cmdl_context
*ctx
)
2988 struct ovsdb_idl
*idl
;
2989 enum TESTS
{ IDL_COMPOUND_INDEX_WITH_SINGLE_COLUMN
,
2990 IDL_COMPOUND_INDEX_WITH_DOUBLE_COLUMN
2995 idl
= ovsdb_idl_create(ctx
->argv
[1], &idltest_idl_class
, false, true);
2997 /* Add tables/columns and initialize index data needed for tests */
2998 ovsdb_idl_add_table(idl
, &idltest_table_simple
);
2999 ovsdb_idl_add_column(idl
, &idltest_simple_col_s
);
3000 ovsdb_idl_add_column(idl
, &idltest_simple_col_i
);
3001 ovsdb_idl_add_column(idl
, &idltest_simple_col_r
);
3002 ovsdb_idl_add_column(idl
, &idltest_simple_col_b
);
3004 struct ovsdb_idl_index
*s_index
3005 = ovsdb_idl_index_create1(idl
, &idltest_simple_col_s
);
3007 struct ovsdb_idl_index
*i_index
3008 = ovsdb_idl_index_create1(idl
, &idltest_simple_col_i
);
3010 struct ovsdb_idl_index
*si_index
3011 = ovsdb_idl_index_create2(idl
, &idltest_simple_col_s
,
3012 &idltest_simple_col_i
);
3014 const struct ovsdb_idl_index_column sid_columns
[] = {
3015 { .column
= &idltest_simple_col_s
},
3016 { .column
= &idltest_simple_col_i
, .order
= OVSDB_INDEX_DESC
},
3018 struct ovsdb_idl_index
*sid_index
3019 = ovsdb_idl_index_create(idl
, sid_columns
, ARRAY_SIZE(sid_columns
));
3021 struct ovsdb_idl_index
*is_index
3022 = ovsdb_idl_index_create2(idl
, &idltest_simple_col_i
,
3023 &idltest_simple_col_s
);
3025 const struct ovsdb_idl_index_column ids_columns
[] = {
3026 { .column
= &idltest_simple_col_i
, .order
= OVSDB_INDEX_DESC
},
3027 { .column
= &idltest_simple_col_s
},
3029 struct ovsdb_idl_index
*ids_index
3030 = ovsdb_idl_index_create(idl
, ids_columns
, ARRAY_SIZE(sid_columns
));
3032 /* wait for replica to be updated */
3033 ovsdb_idl_get_initial_snapshot(idl
);
3035 setvbuf(stdout
, NULL
, _IONBF
, 0);
3036 int test_to_run
= -1;
3037 for (i
= 2; i
< ctx
->argc
; i
++) {
3038 char *arg
= ctx
->argv
[i
];
3040 if (strcmp(arg
,"idl_compound_index_single_column") == 0) {
3041 test_to_run
= IDL_COMPOUND_INDEX_WITH_SINGLE_COLUMN
;
3042 } else if (strcmp(arg
, "idl_compound_index_double_column") == 0) {
3043 test_to_run
= IDL_COMPOUND_INDEX_WITH_DOUBLE_COLUMN
;
3046 switch (test_to_run
) {
3047 case IDL_COMPOUND_INDEX_WITH_SINGLE_COLUMN
:
3048 test_idl_compound_index_single_column(idl
, s_index
, i_index
);
3050 case IDL_COMPOUND_INDEX_WITH_DOUBLE_COLUMN
:
3051 test_idl_compound_index_double_column(si_index
, sid_index
,
3052 is_index
, ids_index
);
3055 printf("%03d: Test %s not implemented.\n", step
++, arg
);
3058 ovsdb_idl_destroy(idl
);
3059 printf("%03d: done\n", step
);
3062 static struct ovs_cmdl_command all_commands
[] = {
3063 { "log-io", NULL
, 2, INT_MAX
, do_log_io
, OVS_RO
},
3064 { "default-atoms", NULL
, 0, 0, do_default_atoms
, OVS_RO
},
3065 { "default-data", NULL
, 0, 0, do_default_data
, OVS_RO
},
3066 { "diff-data", NULL
, 3, INT_MAX
, do_diff_data
, OVS_RO
},
3067 { "parse-atomic-type", NULL
, 1, 1, do_parse_atomic_type
, OVS_RO
},
3068 { "parse-base-type", NULL
, 1, 1, do_parse_base_type
, OVS_RO
},
3069 { "parse-type", NULL
, 1, 1, do_parse_type
, OVS_RO
},
3070 { "parse-atoms", NULL
, 2, INT_MAX
, do_parse_atoms
, OVS_RO
},
3071 { "parse-atom-strings", NULL
, 2, INT_MAX
, do_parse_atom_strings
, OVS_RO
},
3072 { "parse-data", NULL
, 2, INT_MAX
, do_parse_data
, OVS_RO
},
3073 { "parse-data-strings", NULL
, 2, INT_MAX
, do_parse_data_strings
, OVS_RO
},
3074 { "sort-atoms", NULL
, 2, 2, do_sort_atoms
, OVS_RO
},
3075 { "parse-column", NULL
, 2, 2, do_parse_column
, OVS_RO
},
3076 { "parse-table", NULL
, 2, 3, do_parse_table
, OVS_RO
},
3077 { "parse-rows", NULL
, 2, INT_MAX
, do_parse_rows
, OVS_RO
},
3078 { "compare-rows", NULL
, 2, INT_MAX
, do_compare_rows
, OVS_RO
},
3079 { "parse-conditions", NULL
, 2, INT_MAX
, do_parse_conditions
, OVS_RO
},
3080 { "evaluate-conditions", NULL
, 3, 3, do_evaluate_conditions
, OVS_RO
},
3081 { "evaluate-conditions-any", NULL
, 3, 3, do_evaluate_conditions_any
, OVS_RO
},
3082 { "compare-conditions", NULL
, 2, 2, do_compare_conditions
, OVS_RO
},
3083 { "parse-mutations", NULL
, 2, INT_MAX
, do_parse_mutations
, OVS_RO
},
3084 { "execute-mutations", NULL
, 3, 3, do_execute_mutations
, OVS_RO
},
3085 { "query", NULL
, 3, 3, do_query
, OVS_RO
},
3086 { "query-distinct", NULL
, 4, 4, do_query_distinct
, OVS_RO
},
3087 { "transact", NULL
, 1, INT_MAX
, do_transact
, OVS_RO
},
3088 { "parse-schema", NULL
, 1, 1, do_parse_schema
, OVS_RO
},
3089 { "execute", NULL
, 2, INT_MAX
, do_execute
, OVS_RO
},
3090 { "execute-readonly", NULL
, 2, INT_MAX
, do_execute_ro
, OVS_RO
},
3091 { "trigger", NULL
, 2, INT_MAX
, do_trigger
, OVS_RO
},
3092 { "idl", NULL
, 1, INT_MAX
, do_idl
, OVS_RO
},
3093 { "idl-compound-index", NULL
, 2, 2, do_idl_compound_index
, OVS_RW
},
3094 { "idl-compound-index-with-ref", NULL
, 1, INT_MAX
,
3095 do_idl_compound_index_with_ref
, OVS_RO
},
3096 { "idl-partial-update-map-column", NULL
, 1, INT_MAX
,
3097 do_idl_partial_update_map_column
, OVS_RO
},
3098 { "idl-partial-update-set-column", NULL
, 1, INT_MAX
,
3099 do_idl_partial_update_set_column
, OVS_RO
},
3100 { "help", NULL
, 0, INT_MAX
, do_help
, OVS_RO
},
3101 { NULL
, NULL
, 0, 0, NULL
, OVS_RO
},
3104 static struct ovs_cmdl_command
*
3105 get_all_commands(void)
3107 return all_commands
;