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.
26 #include "byte-order.h"
27 #include "command-line.h"
28 #include "openvswitch/dynamic-string.h"
29 #include "openvswitch/json.h"
31 #include "ovsdb-data.h"
32 #include "ovsdb-error.h"
33 #include "ovsdb-idl.h"
34 #include "ovsdb-types.h"
35 #include "ovsdb/column.h"
36 #include "ovsdb/condition.h"
37 #include "ovsdb/file.h"
38 #include "ovsdb/log.h"
39 #include "ovsdb/mutation.h"
40 #include "ovsdb/ovsdb.h"
41 #include "ovsdb/query.h"
42 #include "ovsdb/row.h"
43 #include "ovsdb/server.h"
44 #include "ovsdb/table.h"
45 #include "ovsdb/transaction.h"
46 #include "ovsdb/trigger.h"
47 #include "poll-loop.h"
50 #include "tests/idltest.h"
53 #include "openvswitch/vlog.h"
55 struct test_ovsdb_pvt_context
{
59 OVS_NO_RETURN
static void usage(void);
60 static void parse_options(int argc
, char *argv
[],
61 struct test_ovsdb_pvt_context
*pvt
);
62 static struct ovs_cmdl_command
*get_all_commands(void);
65 main(int argc
, char *argv
[])
67 struct test_ovsdb_pvt_context pvt
= {.track
= false};
68 struct ovs_cmdl_context ctx
= { .argc
= 0, .pvt
= &pvt
};
69 set_program_name(argv
[0]);
70 parse_options(argc
, argv
, &pvt
);
71 ctx
.argc
= argc
- optind
;
72 ctx
.argv
= argv
+ optind
;
73 ovs_cmdl_run_command(&ctx
, get_all_commands());
78 parse_options(int argc
, char *argv
[], struct test_ovsdb_pvt_context
*pvt
)
80 static const struct option long_options
[] = {
81 {"timeout", required_argument
, NULL
, 't'},
82 {"verbose", optional_argument
, NULL
, 'v'},
83 {"change-track", optional_argument
, NULL
, 'c'},
84 {"help", no_argument
, NULL
, 'h'},
87 char *short_options
= ovs_cmdl_long_options_to_short_options(long_options
);
90 unsigned long int timeout
;
93 c
= getopt_long(argc
, argv
, short_options
, long_options
, NULL
);
100 timeout
= strtoul(optarg
, NULL
, 10);
102 ovs_fatal(0, "value %s on -t or --timeout is not at least 1",
113 vlog_set_verbosity(optarg
);
133 printf("%s: Open vSwitch database test utility\n"
134 "usage: %s [OPTIONS] COMMAND [ARG...]\n\n"
135 " log-io FILE FLAGS COMMAND...\n"
136 " open FILE with FLAGS, run COMMANDs\n"
138 " test ovsdb_atom_default()\n"
140 " test ovsdb_datum_default()\n"
141 " parse-atomic-type TYPE\n"
142 " parse TYPE as OVSDB atomic type, and re-serialize\n"
143 " parse-base-type TYPE\n"
144 " parse TYPE as OVSDB base type, and re-serialize\n"
146 " parse JSON as OVSDB type, and re-serialize\n"
147 " parse-atoms TYPE ATOM...\n"
148 " parse JSON ATOMs as atoms of TYPE, and re-serialize\n"
149 " parse-atom-strings TYPE ATOM...\n"
150 " parse string ATOMs as atoms of given TYPE, and re-serialize\n"
151 " sort-atoms TYPE ATOM...\n"
152 " print JSON ATOMs in sorted order\n"
153 " parse-data TYPE DATUM...\n"
154 " parse JSON DATUMs as data of given TYPE, and re-serialize\n"
155 " parse-data-strings TYPE DATUM...\n"
156 " parse string DATUMs as data of given TYPE, and re-serialize\n"
157 " parse-column NAME OBJECT\n"
158 " parse column NAME with info OBJECT, and re-serialize\n"
159 " parse-table NAME OBJECT [DEFAULT-IS-ROOT]\n"
160 " parse table NAME with info OBJECT\n"
161 " parse-row TABLE ROW..., and re-serialize\n"
162 " parse each ROW of defined TABLE\n"
163 " compare-row TABLE ROW...\n"
164 " mutually compare all of the ROWs, print those that are equal\n"
165 " parse-conditions TABLE CONDITION...\n"
166 " parse each CONDITION on TABLE, and re-serialize\n"
167 " evaluate-conditions TABLE [CONDITION,...] [ROW,...]\n"
168 " test CONDITIONS on TABLE against each ROW, print results\n"
169 " evaluate-conditions-any TABLE [CONDITION,...] [ROW,...]\n"
170 " test CONDITIONS to match any of the CONDITONS on TABLE\n"
171 " against each ROW, print results\n"
172 " compare-conditions TABLE [CONDITION,...]\n"
173 " mutually compare all of the CONDITION, print results for\n"
175 " parse-mutations TABLE MUTATION...\n"
176 " parse each MUTATION on TABLE, and re-serialize\n"
177 " execute-mutations TABLE [MUTATION,...] [ROW,...]\n"
178 " execute MUTATIONS on TABLE on each ROW, print results\n"
179 " query TABLE [ROW,...] [CONDITION,...]\n"
180 " add each ROW to TABLE, then query and print the rows that\n"
181 " satisfy each CONDITION.\n"
182 " query-distinct TABLE [ROW,...] [CONDITION,...] COLUMNS\n"
183 " add each ROW to TABLE, then query and print the rows that\n"
184 " satisfy each CONDITION and have distinct COLUMNS.\n"
185 " parse-schema JSON\n"
186 " parse JSON as an OVSDB schema, and re-serialize\n"
187 " transact COMMAND\n"
188 " execute each specified transactional COMMAND:\n"
195 " execute SCHEMA TRANSACTION...\n"
196 " executes each TRANSACTION on an initially empty database\n"
197 " the specified SCHEMA\n"
198 " execute-readonly SCHEMA TRANSACTION...\n"
199 " same as execute, except the TRANSACTION will be executed\n"
200 " against the database server that is in read only mode\n"
201 " trigger SCHEMA TRANSACTION...\n"
202 " executes each TRANSACTION on an initially empty database\n"
203 " the specified SCHEMA. A TRANSACTION of the form\n"
204 " [\"advance\", NUMBER] advances NUMBER milliseconds in\n"
205 " simulated time, for causing triggers to time out.\n"
206 " idl SERVER [TRANSACTION...]\n"
207 " connect to SERVER and dump the contents of the database\n"
208 " as seen initially by the IDL implementation and after\n"
209 " executing each TRANSACTION. (Each TRANSACTION must modify\n"
210 " the database or this command will hang.)\n"
211 " idl-partial-update-map-column SERVER \n"
212 " connect to SERVER and executes different operations to\n"
213 " test the capacity of updating elements inside a map column\n"
214 " displaying the table information after each operation.\n"
215 " idl-partial-update-set-column SERVER \n"
216 " connect to SERVER and executes different operations to\n"
217 " test the capacity of updating elements inside a set column\n"
218 " displaying the table information after each operation.\n",
219 program_name
, program_name
);
221 printf("\nOther options:\n"
222 " -t, --timeout=SECS give up after SECS seconds\n"
223 " -h, --help display this help message\n"
224 " -c, --change-track used with the 'idl' command to\n"
225 " enable tracking of IDL changes\n");
229 /* Command helper functions. */
232 parse_json(const char *s
)
234 struct json
*json
= json_from_string(s
);
235 if (json
->type
== JSON_STRING
) {
236 ovs_fatal(0, "\"%s\": %s", s
, json
->u
.string
);
242 unbox_json(struct json
*json
)
244 if (json
->type
== JSON_ARRAY
&& json
->u
.array
.n
== 1) {
245 struct json
*inner
= json
->u
.array
.elems
[0];
246 json
->u
.array
.elems
[0] = NULL
;
255 print_and_free_json(struct json
*json
)
257 char *string
= json_to_string(json
, JSSF_SORT
);
264 print_and_free_ovsdb_error(struct ovsdb_error
*error
)
266 char *string
= ovsdb_error_to_string(error
);
267 ovsdb_error_destroy(error
);
273 check_ovsdb_error(struct ovsdb_error
*error
)
276 char *s
= ovsdb_error_to_string(error
);
277 ovsdb_error_destroy(error
);
278 ovs_fatal(0, "%s", s
);
283 die_if_error(char *error
)
286 ovs_fatal(0, "%s", error
);
290 /* Command implementations. */
293 do_log_io(struct ovs_cmdl_context
*ctx
)
295 const char *name
= ctx
->argv
[1];
296 char *mode_string
= ctx
->argv
[2];
298 struct ovsdb_error
*error
;
299 enum ovsdb_log_open_mode mode
;
300 struct ovsdb_log
*log
;
303 if (!strcmp(mode_string
, "read-only")) {
304 mode
= OVSDB_LOG_READ_ONLY
;
305 } else if (!strcmp(mode_string
, "read/write")) {
306 mode
= OVSDB_LOG_READ_WRITE
;
307 } else if (!strcmp(mode_string
, "create")) {
308 mode
= OVSDB_LOG_CREATE
;
310 ovs_fatal(0, "unknown log-io open mode \"%s\"", mode_string
);
313 check_ovsdb_error(ovsdb_log_open(name
, mode
, -1, &log
));
314 printf("%s: open successful\n", name
);
316 for (i
= 3; i
< ctx
->argc
; i
++) {
317 const char *command
= ctx
->argv
[i
];
318 if (!strcmp(command
, "read")) {
321 error
= ovsdb_log_read(log
, &json
);
323 printf("%s: read: ", name
);
325 print_and_free_json(json
);
327 printf("end of log\n");
331 } else if (!strncmp(command
, "write:", 6)) {
332 struct json
*json
= parse_json(command
+ 6);
333 error
= ovsdb_log_write(log
, json
);
335 } else if (!strcmp(command
, "commit")) {
336 error
= ovsdb_log_commit(log
);
338 ovs_fatal(0, "unknown log-io command \"%s\"", command
);
341 char *s
= ovsdb_error_to_string(error
);
342 printf("%s: %s failed: %s\n", name
, command
, s
);
344 ovsdb_error_destroy(error
);
346 printf("%s: %s successful\n", name
, command
);
350 ovsdb_log_close(log
);
354 do_default_atoms(struct ovs_cmdl_context
*ctx OVS_UNUSED
)
358 for (type
= 0; type
< OVSDB_N_TYPES
; type
++) {
359 union ovsdb_atom atom
;
361 if (type
== OVSDB_TYPE_VOID
) {
365 printf("%s: ", ovsdb_atomic_type_to_string(type
));
367 ovsdb_atom_init_default(&atom
, type
);
368 if (!ovsdb_atom_equals(&atom
, ovsdb_atom_default(type
), type
)) {
372 ovsdb_atom_destroy(&atom
, type
);
379 do_default_data(struct ovs_cmdl_context
*ctx OVS_UNUSED
)
384 for (n_min
= 0; n_min
<= 1; n_min
++) {
385 for (key
= 0; key
< OVSDB_N_TYPES
; key
++) {
386 if (key
== OVSDB_TYPE_VOID
) {
389 for (value
= 0; value
< OVSDB_N_TYPES
; value
++) {
390 struct ovsdb_datum datum
;
391 struct ovsdb_type type
;
393 ovsdb_base_type_init(&type
.key
, key
);
394 ovsdb_base_type_init(&type
.value
, value
);
397 assert(ovsdb_type_is_valid(&type
));
399 printf("key %s, value %s, n_min %u: ",
400 ovsdb_atomic_type_to_string(key
),
401 ovsdb_atomic_type_to_string(value
), n_min
);
403 ovsdb_datum_init_default(&datum
, &type
);
404 if (!ovsdb_datum_equals(&datum
, ovsdb_datum_default(&type
),
409 ovsdb_datum_destroy(&datum
, &type
);
410 ovsdb_type_destroy(&type
);
419 do_diff_data(struct ovs_cmdl_context
*ctx
)
421 struct ovsdb_type type
;
423 struct ovsdb_datum
new, old
, diff
, reincarnation
;
425 json
= unbox_json(parse_json(ctx
->argv
[1]));
426 check_ovsdb_error(ovsdb_type_from_json(&type
, json
));
429 /* Arguments in pairs of 'old' and 'new'. */
430 for (int i
= 2; i
< ctx
->argc
- 1; i
+=2) {
431 struct ovsdb_error
*error
;
433 json
= unbox_json(parse_json(ctx
->argv
[i
]));
434 check_ovsdb_error(ovsdb_datum_from_json(&old
, &type
, json
, NULL
));
437 json
= unbox_json(parse_json(ctx
->argv
[i
+1]));
438 check_ovsdb_error(ovsdb_transient_datum_from_json(&new, &type
, json
));
441 /* Generate the diff. */
442 ovsdb_datum_diff(&diff
, &old
, &new, &type
);
444 /* Apply diff to 'old' to create'reincarnation'. */
445 error
= ovsdb_datum_apply_diff(&reincarnation
, &old
, &diff
, &type
);
447 char *string
= ovsdb_error_to_string(error
);
448 ovsdb_error_destroy(error
);
449 ovs_fatal(0, "%s", string
);
452 /* Test to make sure 'new' equals 'reincarnation'. */
453 if (!ovsdb_datum_equals(&new, &reincarnation
, &type
)) {
454 ovs_fatal(0, "failed to apply diff");
458 json
= ovsdb_datum_to_json(&diff
, &type
);
460 print_and_free_json(json
);
462 /* Print reincarnation */
463 json
= ovsdb_datum_to_json(&reincarnation
, &type
);
464 printf ("apply diff: ");
465 print_and_free_json(json
);
467 ovsdb_datum_destroy(&new, &type
);
468 ovsdb_datum_destroy(&old
, &type
);
469 ovsdb_datum_destroy(&diff
, &type
);
470 ovsdb_datum_destroy(&reincarnation
, &type
);
475 ovsdb_type_destroy(&type
);
479 do_parse_atomic_type(struct ovs_cmdl_context
*ctx
)
481 enum ovsdb_atomic_type type
;
484 json
= unbox_json(parse_json(ctx
->argv
[1]));
485 check_ovsdb_error(ovsdb_atomic_type_from_json(&type
, json
));
487 print_and_free_json(ovsdb_atomic_type_to_json(type
));
491 do_parse_base_type(struct ovs_cmdl_context
*ctx
)
493 struct ovsdb_base_type base
;
496 json
= unbox_json(parse_json(ctx
->argv
[1]));
497 check_ovsdb_error(ovsdb_base_type_from_json(&base
, json
));
499 print_and_free_json(ovsdb_base_type_to_json(&base
));
500 ovsdb_base_type_destroy(&base
);
504 do_parse_type(struct ovs_cmdl_context
*ctx
)
506 struct ovsdb_type type
;
509 json
= unbox_json(parse_json(ctx
->argv
[1]));
510 check_ovsdb_error(ovsdb_type_from_json(&type
, json
));
512 print_and_free_json(ovsdb_type_to_json(&type
));
513 ovsdb_type_destroy(&type
);
517 do_parse_atoms(struct ovs_cmdl_context
*ctx
)
519 struct ovsdb_base_type base
;
523 json
= unbox_json(parse_json(ctx
->argv
[1]));
524 check_ovsdb_error(ovsdb_base_type_from_json(&base
, json
));
527 for (i
= 2; i
< ctx
->argc
; i
++) {
528 struct ovsdb_error
*error
;
529 union ovsdb_atom atom
;
531 json
= unbox_json(parse_json(ctx
->argv
[i
]));
532 error
= ovsdb_atom_from_json(&atom
, &base
, json
, NULL
);
536 print_and_free_ovsdb_error(error
);
538 print_and_free_json(ovsdb_atom_to_json(&atom
, base
.type
));
539 ovsdb_atom_destroy(&atom
, base
.type
);
542 ovsdb_base_type_destroy(&base
);
546 do_parse_atom_strings(struct ovs_cmdl_context
*ctx
)
548 struct ovsdb_base_type base
;
552 json
= unbox_json(parse_json(ctx
->argv
[1]));
553 check_ovsdb_error(ovsdb_base_type_from_json(&base
, json
));
556 for (i
= 2; i
< ctx
->argc
; i
++) {
557 union ovsdb_atom atom
, *range_end_atom
= NULL
;
560 die_if_error(ovsdb_atom_from_string(&atom
, &range_end_atom
, &base
,
561 ctx
->argv
[i
], NULL
));
564 ovsdb_atom_to_string(&atom
, base
.type
, &out
);
565 if (range_end_atom
) {
566 struct ds range_end_ds
;
567 ds_init(&range_end_ds
);
568 ovsdb_atom_to_string(range_end_atom
, base
.type
, &range_end_ds
);
569 ds_put_char(&out
, '-');
570 ds_put_cstr(&out
, ds_cstr(&range_end_ds
));;
571 ds_destroy(&range_end_ds
);
576 ovsdb_atom_destroy(&atom
, base
.type
);
577 if (range_end_atom
) {
578 ovsdb_atom_destroy(range_end_atom
, base
.type
);
581 ovsdb_base_type_destroy(&base
);
585 do_parse_data__(int argc
, char *argv
[],
587 (*parse
)(struct ovsdb_datum
*datum
,
588 const struct ovsdb_type
*type
,
589 const struct json
*json
,
590 struct ovsdb_symbol_table
*symtab
))
592 struct ovsdb_type type
;
596 json
= unbox_json(parse_json(argv
[1]));
597 check_ovsdb_error(ovsdb_type_from_json(&type
, json
));
600 for (i
= 2; i
< argc
; i
++) {
601 struct ovsdb_datum datum
;
603 json
= unbox_json(parse_json(argv
[i
]));
604 check_ovsdb_error(parse(&datum
, &type
, json
, NULL
));
607 print_and_free_json(ovsdb_datum_to_json(&datum
, &type
));
609 ovsdb_datum_destroy(&datum
, &type
);
611 ovsdb_type_destroy(&type
);
615 do_parse_data(struct ovs_cmdl_context
*ctx
)
617 do_parse_data__(ctx
->argc
, ctx
->argv
, ovsdb_datum_from_json
);
621 do_parse_data_strings(struct ovs_cmdl_context
*ctx
)
623 struct ovsdb_type type
;
627 json
= unbox_json(parse_json(ctx
->argv
[1]));
628 check_ovsdb_error(ovsdb_type_from_json(&type
, json
));
631 for (i
= 2; i
< ctx
->argc
; i
++) {
632 struct ovsdb_datum datum
;
635 die_if_error(ovsdb_datum_from_string(&datum
, &type
, ctx
->argv
[i
], NULL
));
638 ovsdb_datum_to_string(&datum
, &type
, &out
);
642 ovsdb_datum_destroy(&datum
, &type
);
644 ovsdb_type_destroy(&type
);
647 static enum ovsdb_atomic_type compare_atoms_atomic_type
;
650 compare_atoms(const void *a_
, const void *b_
)
652 const union ovsdb_atom
*a
= a_
;
653 const union ovsdb_atom
*b
= b_
;
655 return ovsdb_atom_compare_3way(a
, b
, compare_atoms_atomic_type
);
659 do_sort_atoms(struct ovs_cmdl_context
*ctx
)
661 struct ovsdb_base_type base
;
662 union ovsdb_atom
*atoms
;
663 struct json
*json
, **json_atoms
;
667 json
= unbox_json(parse_json(ctx
->argv
[1]));
668 check_ovsdb_error(ovsdb_base_type_from_json(&base
, json
));
671 json
= unbox_json(parse_json(ctx
->argv
[2]));
672 if (json
->type
!= JSON_ARRAY
) {
673 ovs_fatal(0, "second argument must be array");
676 /* Convert JSON atoms to internal representation. */
677 n_atoms
= json
->u
.array
.n
;
678 atoms
= xmalloc(n_atoms
* sizeof *atoms
);
679 for (i
= 0; i
< n_atoms
; i
++) {
680 check_ovsdb_error(ovsdb_atom_from_json(&atoms
[i
], &base
,
681 json
->u
.array
.elems
[i
], NULL
));
686 compare_atoms_atomic_type
= base
.type
;
687 qsort(atoms
, n_atoms
, sizeof *atoms
, compare_atoms
);
689 /* Convert internal representation back to JSON. */
690 json_atoms
= xmalloc(n_atoms
* sizeof *json_atoms
);
691 for (i
= 0; i
< n_atoms
; i
++) {
692 json_atoms
[i
] = ovsdb_atom_to_json(&atoms
[i
], base
.type
);
693 ovsdb_atom_destroy(&atoms
[i
], base
.type
);
695 print_and_free_json(json_array_create(json_atoms
, n_atoms
));
697 ovsdb_base_type_destroy(&base
);
701 do_parse_column(struct ovs_cmdl_context
*ctx
)
703 struct ovsdb_column
*column
;
706 json
= parse_json(ctx
->argv
[2]);
707 check_ovsdb_error(ovsdb_column_from_json(json
, ctx
->argv
[1], &column
));
709 print_and_free_json(ovsdb_column_to_json(column
));
710 ovsdb_column_destroy(column
);
714 do_parse_table(struct ovs_cmdl_context
*ctx
)
716 struct ovsdb_table_schema
*ts
;
717 bool default_is_root
;
720 default_is_root
= ctx
->argc
> 3 && !strcmp(ctx
->argv
[3], "true");
722 json
= parse_json(ctx
->argv
[2]);
723 check_ovsdb_error(ovsdb_table_schema_from_json(json
, ctx
->argv
[1], &ts
));
725 print_and_free_json(ovsdb_table_schema_to_json(ts
, default_is_root
));
726 ovsdb_table_schema_destroy(ts
);
730 do_parse_rows(struct ovs_cmdl_context
*ctx
)
732 struct ovsdb_column_set all_columns
;
733 struct ovsdb_table_schema
*ts
;
734 struct ovsdb_table
*table
;
738 json
= unbox_json(parse_json(ctx
->argv
[1]));
739 check_ovsdb_error(ovsdb_table_schema_from_json(json
, "mytable", &ts
));
742 table
= ovsdb_table_create(ts
);
743 ovsdb_column_set_init(&all_columns
);
744 ovsdb_column_set_add_all(&all_columns
, table
);
746 for (i
= 2; i
< ctx
->argc
; i
++) {
747 struct ovsdb_column_set columns
;
748 struct ovsdb_row
*row
;
750 ovsdb_column_set_init(&columns
);
751 row
= ovsdb_row_create(table
);
753 json
= unbox_json(parse_json(ctx
->argv
[i
]));
754 check_ovsdb_error(ovsdb_row_from_json(row
, json
, NULL
, &columns
));
757 print_and_free_json(ovsdb_row_to_json(row
, &all_columns
));
759 if (columns
.n_columns
) {
765 for (j
= 0; j
< columns
.n_columns
; j
++) {
766 svec_add(&names
, columns
.columns
[j
]->name
);
769 s
= svec_join(&names
, ", ", "");
772 svec_destroy(&names
);
777 ovsdb_column_set_destroy(&columns
);
778 ovsdb_row_destroy(row
);
781 ovsdb_column_set_destroy(&all_columns
);
782 ovsdb_table_destroy(table
); /* Also destroys 'ts'. */
786 do_compare_rows(struct ovs_cmdl_context
*ctx
)
788 struct ovsdb_column_set all_columns
;
789 struct ovsdb_table_schema
*ts
;
790 struct ovsdb_table
*table
;
791 struct ovsdb_row
**rows
;
797 json
= unbox_json(parse_json(ctx
->argv
[1]));
798 check_ovsdb_error(ovsdb_table_schema_from_json(json
, "mytable", &ts
));
801 table
= ovsdb_table_create(ts
);
802 ovsdb_column_set_init(&all_columns
);
803 ovsdb_column_set_add_all(&all_columns
, table
);
805 n_rows
= ctx
->argc
- 2;
806 rows
= xmalloc(sizeof *rows
* n_rows
);
807 names
= xmalloc(sizeof *names
* n_rows
);
808 for (i
= 0; i
< n_rows
; i
++) {
809 rows
[i
] = ovsdb_row_create(table
);
811 json
= parse_json(ctx
->argv
[i
+ 2]);
812 if (json
->type
!= JSON_ARRAY
|| json
->u
.array
.n
!= 2
813 || json
->u
.array
.elems
[0]->type
!= JSON_STRING
) {
814 ovs_fatal(0, "\"%s\" does not have expected form "
815 "[\"name\", {data}]", ctx
->argv
[i
]);
817 names
[i
] = xstrdup(json
->u
.array
.elems
[0]->u
.string
);
818 check_ovsdb_error(ovsdb_row_from_json(rows
[i
], json
->u
.array
.elems
[1],
822 for (i
= 0; i
< n_rows
; i
++) {
823 uint32_t i_hash
= ovsdb_row_hash_columns(rows
[i
], &all_columns
, 0);
824 for (j
= i
+ 1; j
< n_rows
; j
++) {
825 uint32_t j_hash
= ovsdb_row_hash_columns(rows
[j
], &all_columns
, 0);
826 if (ovsdb_row_equal_columns(rows
[i
], rows
[j
], &all_columns
)) {
827 printf("%s == %s\n", names
[i
], names
[j
]);
828 if (i_hash
!= j_hash
) {
829 printf("but hash(%s) != hash(%s)\n", names
[i
], names
[j
]);
832 } else if (i_hash
== j_hash
) {
833 printf("hash(%s) == hash(%s)\n", names
[i
], names
[j
]);
837 for (i
= 0; i
< n_rows
; i
++) {
838 ovsdb_row_destroy(rows
[i
]);
844 ovsdb_column_set_destroy(&all_columns
);
845 ovsdb_table_destroy(table
); /* Also destroys 'ts'. */
849 do_parse_conditions(struct ovs_cmdl_context
*ctx
)
851 struct ovsdb_table_schema
*ts
;
856 json
= unbox_json(parse_json(ctx
->argv
[1]));
857 check_ovsdb_error(ovsdb_table_schema_from_json(json
, "mytable", &ts
));
860 for (i
= 2; i
< ctx
->argc
; i
++) {
861 struct ovsdb_condition cnd
;
862 struct ovsdb_error
*error
;
864 json
= parse_json(ctx
->argv
[i
]);
865 error
= ovsdb_condition_from_json(ts
, json
, NULL
, &cnd
);
867 print_and_free_json(ovsdb_condition_to_json(&cnd
));
869 char *s
= ovsdb_error_to_string(error
);
870 ovs_error(0, "%s", s
);
872 ovsdb_error_destroy(error
);
877 ovsdb_condition_destroy(&cnd
);
879 ovsdb_table_schema_destroy(ts
);
884 #define OVSDB_CONDITION_EVERY 0
885 #define OVSDB_CONDITION_ANY 1
888 do_evaluate_condition__(struct ovs_cmdl_context
*ctx
, int mode
)
890 struct ovsdb_table_schema
*ts
;
891 struct ovsdb_table
*table
;
892 struct ovsdb_condition
*conditions
;
894 struct ovsdb_row
**rows
;
899 /* Parse table schema, create table. */
900 json
= unbox_json(parse_json(ctx
->argv
[1]));
901 check_ovsdb_error(ovsdb_table_schema_from_json(json
, "mytable", &ts
));
904 table
= ovsdb_table_create(ts
);
906 /* Parse conditions. */
907 json
= parse_json(ctx
->argv
[2]);
908 if (json
->type
!= JSON_ARRAY
) {
909 ovs_fatal(0, "CONDITION argument is not JSON array");
911 n_conditions
= json
->u
.array
.n
;
912 conditions
= xmalloc(n_conditions
* sizeof *conditions
);
913 for (i
= 0; i
< n_conditions
; i
++) {
914 check_ovsdb_error(ovsdb_condition_from_json(ts
, json
->u
.array
.elems
[i
],
915 NULL
, &conditions
[i
]));
920 json
= parse_json(ctx
->argv
[3]);
921 if (json
->type
!= JSON_ARRAY
) {
922 ovs_fatal(0, "ROW argument is not JSON array");
924 n_rows
= json
->u
.array
.n
;
925 rows
= xmalloc(n_rows
* sizeof *rows
);
926 for (i
= 0; i
< n_rows
; i
++) {
927 rows
[i
] = ovsdb_row_create(table
);
928 check_ovsdb_error(ovsdb_row_from_json(rows
[i
], json
->u
.array
.elems
[i
],
933 for (i
= 0; i
< n_conditions
; i
++) {
934 printf("condition %2"PRIuSIZE
":", i
);
935 for (j
= 0; j
< n_rows
; j
++) {
937 if (mode
== OVSDB_CONDITION_EVERY
) {
938 result
= ovsdb_condition_match_every_clause(rows
[j
],
941 result
= ovsdb_condition_match_any_clause(rows
[j
]->fields
,
948 putchar(result
? 'T' : '-');
953 for (i
= 0; i
< n_conditions
; i
++) {
954 ovsdb_condition_destroy(&conditions
[i
]);
957 for (i
= 0; i
< n_rows
; i
++) {
958 ovsdb_row_destroy(rows
[i
]);
961 ovsdb_table_destroy(table
); /* Also destroys 'ts'. */
965 do_evaluate_conditions(struct ovs_cmdl_context
*ctx
)
967 do_evaluate_condition__(ctx
, OVSDB_CONDITION_EVERY
);
971 do_evaluate_conditions_any(struct ovs_cmdl_context
*ctx
)
973 do_evaluate_condition__(ctx
, OVSDB_CONDITION_ANY
);
977 do_compare_conditions(struct ovs_cmdl_context
*ctx
)
979 struct ovsdb_table_schema
*ts
;
980 struct ovsdb_table
*table
;
981 struct ovsdb_condition
*conditions
;
986 /* Parse table schema, create table. */
987 json
= unbox_json(parse_json(ctx
->argv
[1]));
988 check_ovsdb_error(ovsdb_table_schema_from_json(json
, "mytable", &ts
));
991 table
= ovsdb_table_create(ts
);
993 /* Parse conditions. */
994 json
= parse_json(ctx
->argv
[2]);
995 if (json
->type
!= JSON_ARRAY
) {
996 ovs_fatal(0, "CONDITION argument is not JSON array");
998 n_conditions
= json
->u
.array
.n
;
999 conditions
= xmalloc(n_conditions
* sizeof *conditions
);
1001 for (i
= 0; i
< n_conditions
; i
++) {
1002 check_ovsdb_error(ovsdb_condition_from_json(ts
, json
->u
.array
.elems
[i
],
1003 NULL
, &conditions
[i
]));
1007 for (i
= 0; i
< n_conditions
- 1; i
++) {
1008 int res
= ovsdb_condition_cmp_3way(&conditions
[i
], &conditions
[i
+ 1]);
1009 printf("condition %"PRIuSIZE
"-%"PRIuSIZE
": %d\n", i
, i
+ 1, res
);
1012 for (i
= 0; i
< n_conditions
; i
++) {
1013 ovsdb_condition_destroy(&conditions
[i
]);
1016 ovsdb_table_destroy(table
); /* Also destroys 'ts'. */
1020 do_parse_mutations(struct ovs_cmdl_context
*ctx
)
1022 struct ovsdb_table_schema
*ts
;
1027 json
= unbox_json(parse_json(ctx
->argv
[1]));
1028 check_ovsdb_error(ovsdb_table_schema_from_json(json
, "mytable", &ts
));
1031 for (i
= 2; i
< ctx
->argc
; i
++) {
1032 struct ovsdb_mutation_set set
;
1033 struct ovsdb_error
*error
;
1035 json
= parse_json(ctx
->argv
[i
]);
1036 error
= ovsdb_mutation_set_from_json(ts
, json
, NULL
, &set
);
1038 print_and_free_json(ovsdb_mutation_set_to_json(&set
));
1040 char *s
= ovsdb_error_to_string(error
);
1041 ovs_error(0, "%s", s
);
1043 ovsdb_error_destroy(error
);
1048 ovsdb_mutation_set_destroy(&set
);
1050 ovsdb_table_schema_destroy(ts
);
1056 do_execute_mutations(struct ovs_cmdl_context
*ctx
)
1058 struct ovsdb_table_schema
*ts
;
1059 struct ovsdb_table
*table
;
1060 struct ovsdb_mutation_set
*sets
;
1062 struct ovsdb_row
**rows
;
1067 /* Parse table schema, create table. */
1068 json
= unbox_json(parse_json(ctx
->argv
[1]));
1069 check_ovsdb_error(ovsdb_table_schema_from_json(json
, "mytable", &ts
));
1072 table
= ovsdb_table_create(ts
);
1074 /* Parse mutations. */
1075 json
= parse_json(ctx
->argv
[2]);
1076 if (json
->type
!= JSON_ARRAY
) {
1077 ovs_fatal(0, "MUTATION argument is not JSON array");
1079 n_sets
= json
->u
.array
.n
;
1080 sets
= xmalloc(n_sets
* sizeof *sets
);
1081 for (i
= 0; i
< n_sets
; i
++) {
1082 check_ovsdb_error(ovsdb_mutation_set_from_json(ts
,
1083 json
->u
.array
.elems
[i
],
1089 json
= parse_json(ctx
->argv
[3]);
1090 if (json
->type
!= JSON_ARRAY
) {
1091 ovs_fatal(0, "ROW argument is not JSON array");
1093 n_rows
= json
->u
.array
.n
;
1094 rows
= xmalloc(n_rows
* sizeof *rows
);
1095 for (i
= 0; i
< n_rows
; i
++) {
1096 rows
[i
] = ovsdb_row_create(table
);
1097 check_ovsdb_error(ovsdb_row_from_json(rows
[i
], json
->u
.array
.elems
[i
],
1102 for (i
= 0; i
< n_sets
; i
++) {
1103 printf("mutation %2"PRIuSIZE
":\n", i
);
1104 for (j
= 0; j
< n_rows
; j
++) {
1105 struct ovsdb_error
*error
;
1106 struct ovsdb_row
*row
;
1108 row
= ovsdb_row_clone(rows
[j
]);
1109 error
= ovsdb_mutation_set_execute(row
, &sets
[i
]);
1111 printf("row %"PRIuSIZE
": ", j
);
1113 print_and_free_ovsdb_error(error
);
1115 struct ovsdb_column_set columns
;
1116 struct shash_node
*node
;
1118 ovsdb_column_set_init(&columns
);
1119 SHASH_FOR_EACH (node
, &ts
->columns
) {
1120 struct ovsdb_column
*c
= node
->data
;
1121 if (!ovsdb_datum_equals(&row
->fields
[c
->index
],
1122 &rows
[j
]->fields
[c
->index
],
1124 ovsdb_column_set_add(&columns
, c
);
1127 if (columns
.n_columns
) {
1128 print_and_free_json(ovsdb_row_to_json(row
, &columns
));
1130 printf("no change\n");
1132 ovsdb_column_set_destroy(&columns
);
1134 ovsdb_row_destroy(row
);
1139 for (i
= 0; i
< n_sets
; i
++) {
1140 ovsdb_mutation_set_destroy(&sets
[i
]);
1143 for (i
= 0; i
< n_rows
; i
++) {
1144 ovsdb_row_destroy(rows
[i
]);
1147 ovsdb_table_destroy(table
); /* Also destroys 'ts'. */
1150 /* Inserts a row, without bothering to update metadata such as refcounts. */
1152 put_row(struct ovsdb_table
*table
, struct ovsdb_row
*row
)
1154 const struct uuid
*uuid
= ovsdb_row_get_uuid(row
);
1155 if (!ovsdb_table_get_row(table
, uuid
)) {
1156 hmap_insert(&table
->rows
, &row
->hmap_node
, uuid_hash(uuid
));
1160 struct do_query_cbdata
{
1161 struct uuid
*row_uuids
;
1167 do_query_cb(const struct ovsdb_row
*row
, void *cbdata_
)
1169 struct do_query_cbdata
*cbdata
= cbdata_
;
1172 for (i
= 0; i
< cbdata
->n_rows
; i
++) {
1173 if (uuid_equals(ovsdb_row_get_uuid(row
), &cbdata
->row_uuids
[i
])) {
1174 cbdata
->counts
[i
]++;
1182 do_query(struct ovs_cmdl_context
*ctx
)
1184 struct do_query_cbdata cbdata
;
1185 struct ovsdb_table_schema
*ts
;
1186 struct ovsdb_table
*table
;
1191 /* Parse table schema, create table. */
1192 json
= unbox_json(parse_json(ctx
->argv
[1]));
1193 check_ovsdb_error(ovsdb_table_schema_from_json(json
, "mytable", &ts
));
1196 table
= ovsdb_table_create(ts
);
1198 /* Parse rows, add to table. */
1199 json
= parse_json(ctx
->argv
[2]);
1200 if (json
->type
!= JSON_ARRAY
) {
1201 ovs_fatal(0, "ROW argument is not JSON array");
1203 cbdata
.n_rows
= json
->u
.array
.n
;
1204 cbdata
.row_uuids
= xmalloc(cbdata
.n_rows
* sizeof *cbdata
.row_uuids
);
1205 cbdata
.counts
= xmalloc(cbdata
.n_rows
* sizeof *cbdata
.counts
);
1206 for (i
= 0; i
< cbdata
.n_rows
; i
++) {
1207 struct ovsdb_row
*row
= ovsdb_row_create(table
);
1208 uuid_generate(ovsdb_row_get_uuid_rw(row
));
1209 check_ovsdb_error(ovsdb_row_from_json(row
, json
->u
.array
.elems
[i
],
1211 if (ovsdb_table_get_row(table
, ovsdb_row_get_uuid(row
))) {
1212 ovs_fatal(0, "duplicate UUID "UUID_FMT
" in table",
1213 UUID_ARGS(ovsdb_row_get_uuid(row
)));
1215 cbdata
.row_uuids
[i
] = *ovsdb_row_get_uuid(row
);
1216 put_row(table
, row
);
1220 /* Parse conditions and execute queries. */
1221 json
= parse_json(ctx
->argv
[3]);
1222 if (json
->type
!= JSON_ARRAY
) {
1223 ovs_fatal(0, "CONDITION argument is not JSON array");
1225 for (i
= 0; i
< json
->u
.array
.n
; i
++) {
1226 struct ovsdb_condition cnd
;
1229 check_ovsdb_error(ovsdb_condition_from_json(ts
, json
->u
.array
.elems
[i
],
1232 memset(cbdata
.counts
, 0, cbdata
.n_rows
* sizeof *cbdata
.counts
);
1233 ovsdb_query(table
, &cnd
, do_query_cb
, &cbdata
);
1235 printf("query %2"PRIuSIZE
":", i
);
1236 for (j
= 0; j
< cbdata
.n_rows
; j
++) {
1240 if (cbdata
.counts
[j
]) {
1241 printf("%d", cbdata
.counts
[j
]);
1242 if (cbdata
.counts
[j
] > 1) {
1252 ovsdb_condition_destroy(&cnd
);
1256 ovsdb_table_destroy(table
); /* Also destroys 'ts'. */
1261 struct do_query_distinct_class
{
1262 struct ovsdb_row
*example
;
1266 struct do_query_distinct_row
{
1268 struct do_query_distinct_class
*class;
1272 do_query_distinct(struct ovs_cmdl_context
*ctx
)
1274 struct ovsdb_column_set columns
;
1275 struct ovsdb_table_schema
*ts
;
1276 struct ovsdb_table
*table
;
1277 struct do_query_distinct_row
*rows
;
1279 struct do_query_distinct_class
*classes
;
1285 /* Parse table schema, create table. */
1286 json
= unbox_json(parse_json(ctx
->argv
[1]));
1287 check_ovsdb_error(ovsdb_table_schema_from_json(json
, "mytable", &ts
));
1290 table
= ovsdb_table_create(ts
);
1292 /* Parse column set. */
1293 json
= parse_json(ctx
->argv
[4]);
1294 check_ovsdb_error(ovsdb_column_set_from_json(json
, table
->schema
,
1298 /* Parse rows, add to table. */
1299 json
= parse_json(ctx
->argv
[2]);
1300 if (json
->type
!= JSON_ARRAY
) {
1301 ovs_fatal(0, "ROW argument is not JSON array");
1303 n_rows
= json
->u
.array
.n
;
1304 rows
= xmalloc(n_rows
* sizeof *rows
);
1305 classes
= xmalloc(n_rows
* sizeof *classes
);
1307 for (i
= 0; i
< n_rows
; i
++) {
1308 struct ovsdb_row
*row
;
1312 row
= ovsdb_row_create(table
);
1313 uuid_generate(ovsdb_row_get_uuid_rw(row
));
1314 check_ovsdb_error(ovsdb_row_from_json(row
, json
->u
.array
.elems
[i
],
1317 /* Initialize row and find equivalence class. */
1318 rows
[i
].uuid
= *ovsdb_row_get_uuid(row
);
1319 rows
[i
].class = NULL
;
1320 for (j
= 0; j
< n_classes
; j
++) {
1321 if (ovsdb_row_equal_columns(row
, classes
[j
].example
, &columns
)) {
1322 rows
[i
].class = &classes
[j
];
1326 if (!rows
[i
].class) {
1327 rows
[i
].class = &classes
[n_classes
];
1328 classes
[n_classes
].example
= ovsdb_row_clone(row
);
1332 /* Add row to table. */
1333 if (ovsdb_table_get_row(table
, ovsdb_row_get_uuid(row
))) {
1334 ovs_fatal(0, "duplicate UUID "UUID_FMT
" in table",
1335 UUID_ARGS(ovsdb_row_get_uuid(row
)));
1337 put_row(table
, row
);
1342 /* Parse conditions and execute queries. */
1343 json
= parse_json(ctx
->argv
[3]);
1344 if (json
->type
!= JSON_ARRAY
) {
1345 ovs_fatal(0, "CONDITION argument is not JSON array");
1347 for (i
= 0; i
< json
->u
.array
.n
; i
++) {
1348 struct ovsdb_row_set results
;
1349 struct ovsdb_condition cnd
;
1352 check_ovsdb_error(ovsdb_condition_from_json(ts
, json
->u
.array
.elems
[i
],
1355 for (j
= 0; j
< n_classes
; j
++) {
1356 classes
[j
].count
= 0;
1358 ovsdb_row_set_init(&results
);
1359 ovsdb_query_distinct(table
, &cnd
, &columns
, &results
);
1360 for (j
= 0; j
< results
.n_rows
; j
++) {
1363 for (k
= 0; k
< n_rows
; k
++) {
1364 if (uuid_equals(ovsdb_row_get_uuid(results
.rows
[j
]),
1366 rows
[k
].class->count
++;
1370 ovsdb_row_set_destroy(&results
);
1372 printf("query %2"PRIuSIZE
":", i
);
1373 for (j
= 0; j
< n_rows
; j
++) {
1374 int count
= rows
[j
].class->count
;
1381 printf("%d", count
);
1383 } else if (count
== 1) {
1384 putchar("abcdefghijklmnopqrstuvwxyz"[rows
[j
].class - classes
]);
1391 ovsdb_condition_destroy(&cnd
);
1395 for (i
= 0; i
< n_classes
; i
++) {
1396 ovsdb_row_destroy(classes
[i
].example
);
1399 ovsdb_table_destroy(table
); /* Also destroys 'ts'. */
1407 do_parse_schema(struct ovs_cmdl_context
*ctx
)
1409 struct ovsdb_schema
*schema
;
1412 json
= parse_json(ctx
->argv
[1]);
1413 check_ovsdb_error(ovsdb_schema_from_json(json
, &schema
));
1415 print_and_free_json(ovsdb_schema_to_json(schema
));
1416 ovsdb_schema_destroy(schema
);
1420 do_execute__(struct ovs_cmdl_context
*ctx
, bool ro
)
1422 struct ovsdb_schema
*schema
;
1427 /* Create database. */
1428 json
= parse_json(ctx
->argv
[1]);
1429 check_ovsdb_error(ovsdb_schema_from_json(json
, &schema
));
1431 db
= ovsdb_create(schema
);
1433 for (i
= 2; i
< ctx
->argc
; i
++) {
1434 struct json
*params
, *result
;
1437 params
= parse_json(ctx
->argv
[i
]);
1438 result
= ovsdb_execute(db
, NULL
, params
, ro
, 0, NULL
);
1439 s
= json_to_string(result
, JSSF_SORT
);
1442 json_destroy(params
);
1443 json_destroy(result
);
1450 do_execute_ro(struct ovs_cmdl_context
*ctx
)
1452 do_execute__(ctx
, true);
1456 do_execute(struct ovs_cmdl_context
*ctx
)
1458 do_execute__(ctx
, false);
1461 struct test_trigger
{
1462 struct ovsdb_trigger trigger
;
1467 do_trigger_dump(struct test_trigger
*t
, long long int now
, const char *title
)
1469 struct json
*result
;
1472 result
= ovsdb_trigger_steal_result(&t
->trigger
);
1473 s
= json_to_string(result
, JSSF_SORT
);
1474 printf("t=%lld: trigger %d (%s): %s\n", now
, t
->number
, title
, s
);
1476 json_destroy(result
);
1477 ovsdb_trigger_destroy(&t
->trigger
);
1482 do_trigger(struct ovs_cmdl_context
*ctx
)
1484 struct ovsdb_schema
*schema
;
1485 struct ovsdb_session session
;
1486 struct ovsdb_server server
;
1493 /* Create database. */
1494 json
= parse_json(ctx
->argv
[1]);
1495 check_ovsdb_error(ovsdb_schema_from_json(json
, &schema
));
1497 db
= ovsdb_create(schema
);
1499 ovsdb_server_init(&server
);
1500 ovsdb_server_add_db(&server
, db
);
1501 ovsdb_session_init(&session
, &server
);
1505 for (i
= 2; i
< ctx
->argc
; i
++) {
1506 struct json
*params
= parse_json(ctx
->argv
[i
]);
1507 if (params
->type
== JSON_ARRAY
1508 && json_array(params
)->n
== 2
1509 && json_array(params
)->elems
[0]->type
== JSON_STRING
1510 && !strcmp(json_string(json_array(params
)->elems
[0]), "advance")
1511 && json_array(params
)->elems
[1]->type
== JSON_INTEGER
) {
1512 now
+= json_integer(json_array(params
)->elems
[1]);
1513 json_destroy(params
);
1515 struct test_trigger
*t
= xmalloc(sizeof *t
);
1516 ovsdb_trigger_init(&session
, db
, &t
->trigger
, params
, now
, false);
1517 t
->number
= number
++;
1518 if (ovsdb_trigger_is_complete(&t
->trigger
)) {
1519 do_trigger_dump(t
, now
, "immediate");
1521 printf("t=%lld: new trigger %d\n", now
, t
->number
);
1525 ovsdb_trigger_run(db
, now
);
1526 while (!ovs_list_is_empty(&session
.completions
)) {
1527 do_trigger_dump(CONTAINER_OF(ovs_list_pop_front(&session
.completions
),
1528 struct test_trigger
, trigger
.node
),
1532 ovsdb_trigger_wait(db
, now
);
1533 poll_immediate_wake();
1537 ovsdb_server_destroy(&server
);
1542 do_help(struct ovs_cmdl_context
*ctx OVS_UNUSED
)
1547 /* "transact" command. */
1549 static struct ovsdb
*do_transact_db
;
1550 static struct ovsdb_txn
*do_transact_txn
;
1551 static struct ovsdb_table
*do_transact_table
;
1554 do_transact_commit(struct ovs_cmdl_context
*ctx OVS_UNUSED
)
1556 ovsdb_error_destroy(ovsdb_txn_commit(do_transact_txn
, false));
1557 do_transact_txn
= NULL
;
1561 do_transact_abort(struct ovs_cmdl_context
*ctx OVS_UNUSED
)
1563 ovsdb_txn_abort(do_transact_txn
);
1564 do_transact_txn
= NULL
;
1568 uuid_from_integer(int integer
, struct uuid
*uuid
)
1571 uuid
->parts
[3] = integer
;
1574 static const struct ovsdb_row
*
1575 do_transact_find_row(const char *uuid_string
)
1577 const struct ovsdb_row
*row
;
1580 uuid_from_integer(atoi(uuid_string
), &uuid
);
1581 row
= ovsdb_table_get_row(do_transact_table
, &uuid
);
1583 ovs_fatal(0, "table does not contain row with UUID "UUID_FMT
,
1590 do_transact_set_integer(struct ovsdb_row
*row
, const char *column_name
,
1593 if (integer
!= -1) {
1594 const struct ovsdb_column
*column
;
1596 column
= ovsdb_table_schema_get_column(do_transact_table
->schema
,
1598 row
->fields
[column
->index
].keys
[0].integer
= integer
;
1603 do_transact_get_integer(const struct ovsdb_row
*row
, const char *column_name
)
1605 const struct ovsdb_column
*column
;
1607 column
= ovsdb_table_schema_get_column(do_transact_table
->schema
,
1609 return row
->fields
[column
->index
].keys
[0].integer
;
1613 do_transact_set_i_j(struct ovsdb_row
*row
,
1614 const char *i_string
, const char *j_string
)
1616 do_transact_set_integer(row
, "i", atoi(i_string
));
1617 do_transact_set_integer(row
, "j", atoi(j_string
));
1621 do_transact_insert(struct ovs_cmdl_context
*ctx
)
1623 struct ovsdb_row
*row
;
1626 row
= ovsdb_row_create(do_transact_table
);
1629 uuid
= ovsdb_row_get_uuid_rw(row
);
1630 uuid_from_integer(atoi(ctx
->argv
[1]), uuid
);
1631 if (ovsdb_table_get_row(do_transact_table
, uuid
)) {
1632 ovs_fatal(0, "table already contains row with UUID "UUID_FMT
,
1636 do_transact_set_i_j(row
, ctx
->argv
[2], ctx
->argv
[3]);
1639 ovsdb_txn_row_insert(do_transact_txn
, row
);
1643 do_transact_delete(struct ovs_cmdl_context
*ctx
)
1645 const struct ovsdb_row
*row
= do_transact_find_row(ctx
->argv
[1]);
1646 ovsdb_txn_row_delete(do_transact_txn
, row
);
1650 do_transact_modify(struct ovs_cmdl_context
*ctx
)
1652 const struct ovsdb_row
*row_ro
;
1653 struct ovsdb_row
*row_rw
;
1655 row_ro
= do_transact_find_row(ctx
->argv
[1]);
1656 row_rw
= ovsdb_txn_row_modify(do_transact_txn
, row_ro
);
1657 do_transact_set_i_j(row_rw
, ctx
->argv
[2], ctx
->argv
[3]);
1661 compare_rows_by_uuid(const void *a_
, const void *b_
)
1663 struct ovsdb_row
*const *ap
= a_
;
1664 struct ovsdb_row
*const *bp
= b_
;
1666 return uuid_compare_3way(ovsdb_row_get_uuid(*ap
), ovsdb_row_get_uuid(*bp
));
1670 do_transact_print(struct ovs_cmdl_context
*ctx OVS_UNUSED
)
1672 const struct ovsdb_row
**rows
;
1673 const struct ovsdb_row
*row
;
1677 n_rows
= hmap_count(&do_transact_table
->rows
);
1678 rows
= xmalloc(n_rows
* sizeof *rows
);
1680 HMAP_FOR_EACH (row
, hmap_node
, &do_transact_table
->rows
) {
1683 assert(i
== n_rows
);
1685 qsort(rows
, n_rows
, sizeof *rows
, compare_rows_by_uuid
);
1687 for (i
= 0; i
< n_rows
; i
++) {
1688 printf("\n%"PRId32
": i=%d, j=%d",
1689 ovsdb_row_get_uuid(rows
[i
])->parts
[3],
1690 do_transact_get_integer(rows
[i
], "i"),
1691 do_transact_get_integer(rows
[i
], "j"));
1698 do_transact(struct ovs_cmdl_context
*ctx
)
1700 static const struct ovs_cmdl_command do_transact_commands
[] = {
1701 { "commit", NULL
, 0, 0, do_transact_commit
, OVS_RO
},
1702 { "abort", NULL
, 0, 0, do_transact_abort
, OVS_RO
},
1703 { "insert", NULL
, 2, 3, do_transact_insert
, OVS_RO
},
1704 { "delete", NULL
, 1, 1, do_transact_delete
, OVS_RO
},
1705 { "modify", NULL
, 2, 3, do_transact_modify
, OVS_RO
},
1706 { "print", NULL
, 0, 0, do_transact_print
, OVS_RO
},
1707 { NULL
, NULL
, 0, 0, NULL
, OVS_RO
},
1710 struct ovsdb_schema
*schema
;
1715 json
= parse_json("{\"name\": \"testdb\", "
1719 " {\"i\": {\"type\": \"integer\"}, "
1720 " \"j\": {\"type\": \"integer\"}}}}}");
1721 check_ovsdb_error(ovsdb_schema_from_json(json
, &schema
));
1723 do_transact_db
= ovsdb_create(schema
);
1724 do_transact_table
= ovsdb_get_table(do_transact_db
, "mytable");
1725 assert(do_transact_table
!= NULL
);
1727 for (i
= 1; i
< ctx
->argc
; i
++) {
1728 struct json
*command
;
1732 struct ovs_cmdl_context transact_ctx
= { .argc
= 0, };
1734 command
= parse_json(ctx
->argv
[i
]);
1735 if (command
->type
!= JSON_ARRAY
) {
1736 ovs_fatal(0, "transaction %d must be JSON array "
1737 "with at least 1 element", i
);
1740 n_args
= command
->u
.array
.n
;
1741 args
= xmalloc((n_args
+ 1) * sizeof *args
);
1742 for (j
= 0; j
< n_args
; j
++) {
1743 struct json
*s
= command
->u
.array
.elems
[j
];
1744 if (s
->type
!= JSON_STRING
) {
1745 ovs_fatal(0, "transaction %d argument %d must be JSON string",
1748 args
[j
] = xstrdup(json_string(s
));
1750 args
[n_args
] = NULL
;
1752 if (!do_transact_txn
) {
1753 do_transact_txn
= ovsdb_txn_create(do_transact_db
);
1756 for (j
= 0; j
< n_args
; j
++) {
1760 fputs(args
[j
], stdout
);
1763 transact_ctx
.argc
= n_args
;
1764 transact_ctx
.argv
= args
;
1765 ovs_cmdl_run_command(&transact_ctx
, do_transact_commands
);
1768 for (j
= 0; j
< n_args
; j
++) {
1772 json_destroy(command
);
1774 ovsdb_txn_abort(do_transact_txn
);
1775 ovsdb_destroy(do_transact_db
); /* Also destroys 'schema'. */
1779 compare_link1(const void *a_
, const void *b_
)
1781 const struct idltest_link1
*const *ap
= a_
;
1782 const struct idltest_link1
*const *bp
= b_
;
1783 const struct idltest_link1
*a
= *ap
;
1784 const struct idltest_link1
*b
= *bp
;
1786 return a
->i
< b
->i
? -1 : a
->i
> b
->i
;
1790 print_idl_row_updated_simple(const struct idltest_simple
*s
, int step
)
1793 bool updated
= false;
1795 for (i
= 0; i
< IDLTEST_SIMPLE_N_COLUMNS
; i
++) {
1796 if (idltest_simple_is_updated(s
, i
)) {
1798 printf("%03d: updated columns:", step
);
1801 printf(" %s", idltest_simple_columns
[i
].name
);
1810 print_idl_row_updated_link1(const struct idltest_link1
*l1
, int step
)
1813 bool updated
= false;
1815 for (i
= 0; i
< IDLTEST_LINK1_N_COLUMNS
; i
++) {
1816 if (idltest_link1_is_updated(l1
, i
)) {
1818 printf("%03d: updated columns:", step
);
1821 printf(" %s", idltest_link1_columns
[i
].name
);
1830 print_idl_row_updated_link2(const struct idltest_link2
*l2
, int step
)
1833 bool updated
= false;
1835 for (i
= 0; i
< IDLTEST_LINK2_N_COLUMNS
; i
++) {
1836 if (idltest_link2_is_updated(l2
, i
)) {
1838 printf("%03d: updated columns:", step
);
1841 printf(" %s", idltest_link2_columns
[i
].name
);
1850 print_idl_row_simple(const struct idltest_simple
*s
, int step
)
1854 printf("%03d: i=%"PRId64
" r=%g b=%s s=%s u="UUID_FMT
" ia=[",
1855 step
, s
->i
, s
->r
, s
->b
? "true" : "false",
1856 s
->s
, UUID_ARGS(&s
->u
));
1857 for (i
= 0; i
< s
->n_ia
; i
++) {
1858 printf("%s%"PRId64
, i
? " " : "", s
->ia
[i
]);
1861 for (i
= 0; i
< s
->n_ra
; i
++) {
1862 printf("%s%g", i
? " " : "", s
->ra
[i
]);
1865 for (i
= 0; i
< s
->n_ba
; i
++) {
1866 printf("%s%s", i
? " " : "", s
->ba
[i
] ? "true" : "false");
1869 for (i
= 0; i
< s
->n_sa
; i
++) {
1870 printf("%s%s", i
? " " : "", s
->sa
[i
]);
1873 for (i
= 0; i
< s
->n_ua
; i
++) {
1874 printf("%s"UUID_FMT
, i
? " " : "", UUID_ARGS(&s
->ua
[i
]));
1876 printf("] uuid="UUID_FMT
"\n", UUID_ARGS(&s
->header_
.uuid
));
1877 print_idl_row_updated_simple(s
, step
);
1881 print_idl_row_link1(const struct idltest_link1
*l1
, int step
)
1883 struct idltest_link1
**links
;
1886 printf("%03d: i=%"PRId64
" k=", step
, l1
->i
);
1888 printf("%"PRId64
, l1
->k
->i
);
1891 links
= xmemdup(l1
->ka
, l1
->n_ka
* sizeof *l1
->ka
);
1892 qsort(links
, l1
->n_ka
, sizeof *links
, compare_link1
);
1893 for (i
= 0; i
< l1
->n_ka
; i
++) {
1894 printf("%s%"PRId64
, i
? " " : "", links
[i
]->i
);
1899 printf("%"PRId64
, l1
->l2
->i
);
1901 printf(" uuid="UUID_FMT
"\n", UUID_ARGS(&l1
->header_
.uuid
));
1902 print_idl_row_updated_link1(l1
, step
);
1906 print_idl_row_link2(const struct idltest_link2
*l2
, int step
)
1908 printf("%03d: i=%"PRId64
" l1=", step
, l2
->i
);
1910 printf("%"PRId64
, l2
->l1
->i
);
1912 printf(" uuid="UUID_FMT
"\n", UUID_ARGS(&l2
->header_
.uuid
));
1913 print_idl_row_updated_link2(l2
, step
);
1917 print_idl(struct ovsdb_idl
*idl
, int step
)
1919 const struct idltest_simple
*s
;
1920 const struct idltest_link1
*l1
;
1921 const struct idltest_link2
*l2
;
1924 IDLTEST_SIMPLE_FOR_EACH (s
, idl
) {
1925 print_idl_row_simple(s
, step
);
1928 IDLTEST_LINK1_FOR_EACH (l1
, idl
) {
1929 print_idl_row_link1(l1
, step
);
1932 IDLTEST_LINK2_FOR_EACH (l2
, idl
) {
1933 print_idl_row_link2(l2
, step
);
1937 printf("%03d: empty\n", step
);
1942 print_idl_track(struct ovsdb_idl
*idl
, int step
, unsigned int seqno
)
1944 const struct idltest_simple
*s
;
1945 const struct idltest_link1
*l1
;
1946 const struct idltest_link2
*l2
;
1949 IDLTEST_SIMPLE_FOR_EACH_TRACKED (s
, idl
) {
1950 if (idltest_simple_row_get_seqno(s
, OVSDB_IDL_CHANGE_DELETE
) >= seqno
) {
1951 printf("%03d: ##deleted## uuid="UUID_FMT
"\n", step
, UUID_ARGS(&s
->header_
.uuid
));
1953 print_idl_row_simple(s
, step
);
1957 IDLTEST_LINK1_FOR_EACH_TRACKED (l1
, idl
) {
1958 if (idltest_simple_row_get_seqno(s
, OVSDB_IDL_CHANGE_DELETE
) >= seqno
) {
1959 printf("%03d: ##deleted## uuid="UUID_FMT
"\n", step
, UUID_ARGS(&s
->header_
.uuid
));
1961 print_idl_row_link1(l1
, step
);
1965 IDLTEST_LINK2_FOR_EACH_TRACKED (l2
, idl
) {
1966 if (idltest_simple_row_get_seqno(s
, OVSDB_IDL_CHANGE_DELETE
) >= seqno
) {
1967 printf("%03d: ##deleted## uuid="UUID_FMT
"\n", step
, UUID_ARGS(&s
->header_
.uuid
));
1969 print_idl_row_link2(l2
, step
);
1974 printf("%03d: empty\n", step
);
1979 parse_uuids(const struct json
*json
, struct ovsdb_symbol_table
*symtab
,
1984 if (json
->type
== JSON_STRING
&& uuid_from_string(&uuid
, json
->u
.string
)) {
1985 char *name
= xasprintf("#%"PRIuSIZE
"#", *n
);
1986 fprintf(stderr
, "%s = "UUID_FMT
"\n", name
, UUID_ARGS(&uuid
));
1987 ovsdb_symbol_table_put(symtab
, name
, &uuid
, false);
1990 } else if (json
->type
== JSON_ARRAY
) {
1993 for (i
= 0; i
< json
->u
.array
.n
; i
++) {
1994 parse_uuids(json
->u
.array
.elems
[i
], symtab
, n
);
1996 } else if (json
->type
== JSON_OBJECT
) {
1997 const struct shash_node
*node
;
1999 SHASH_FOR_EACH (node
, json_object(json
)) {
2000 parse_uuids(node
->data
, symtab
, n
);
2006 substitute_uuids(struct json
*json
, const struct ovsdb_symbol_table
*symtab
)
2008 if (json
->type
== JSON_STRING
) {
2009 const struct ovsdb_symbol
*symbol
;
2011 symbol
= ovsdb_symbol_table_get(symtab
, json
->u
.string
);
2013 free(json
->u
.string
);
2014 json
->u
.string
= xasprintf(UUID_FMT
, UUID_ARGS(&symbol
->uuid
));
2016 } else if (json
->type
== JSON_ARRAY
) {
2019 for (i
= 0; i
< json
->u
.array
.n
; i
++) {
2020 substitute_uuids(json
->u
.array
.elems
[i
], symtab
);
2022 } else if (json
->type
== JSON_OBJECT
) {
2023 const struct shash_node
*node
;
2025 SHASH_FOR_EACH (node
, json_object(json
)) {
2026 substitute_uuids(node
->data
, symtab
);
2031 static const struct idltest_simple
*
2032 idltest_find_simple(struct ovsdb_idl
*idl
, int i
)
2034 const struct idltest_simple
*s
;
2036 IDLTEST_SIMPLE_FOR_EACH (s
, idl
) {
2045 idl_set(struct ovsdb_idl
*idl
, char *commands
, int step
)
2047 char *cmd
, *save_ptr1
= NULL
;
2048 struct ovsdb_idl_txn
*txn
;
2049 enum ovsdb_idl_txn_status status
;
2050 bool increment
= false;
2052 txn
= ovsdb_idl_txn_create(idl
);
2053 ovsdb_idl_check_consistency(idl
);
2054 for (cmd
= strtok_r(commands
, ",", &save_ptr1
); cmd
;
2055 cmd
= strtok_r(NULL
, ",", &save_ptr1
)) {
2056 char *save_ptr2
= NULL
;
2057 char *name
, *arg1
, *arg2
, *arg3
;
2059 name
= strtok_r(cmd
, " ", &save_ptr2
);
2060 arg1
= strtok_r(NULL
, " ", &save_ptr2
);
2061 arg2
= strtok_r(NULL
, " ", &save_ptr2
);
2062 arg3
= strtok_r(NULL
, " ", &save_ptr2
);
2064 if (!strcmp(name
, "set")) {
2065 const struct idltest_simple
*s
;
2068 ovs_fatal(0, "\"set\" command requires 3 arguments");
2071 s
= idltest_find_simple(idl
, atoi(arg1
));
2073 ovs_fatal(0, "\"set\" command asks for nonexistent "
2074 "i=%d", atoi(arg1
));
2077 if (!strcmp(arg2
, "b")) {
2078 idltest_simple_set_b(s
, atoi(arg3
));
2079 } else if (!strcmp(arg2
, "s")) {
2080 idltest_simple_set_s(s
, arg3
);
2081 } else if (!strcmp(arg2
, "u")) {
2083 if (!uuid_from_string(&uuid
, arg3
)) {
2084 ovs_fatal(0, "\"%s\" is not a valid UUID", arg3
);
2086 idltest_simple_set_u(s
, uuid
);
2087 } else if (!strcmp(arg2
, "r")) {
2088 idltest_simple_set_r(s
, atof(arg3
));
2090 ovs_fatal(0, "\"set\" command asks for unknown column %s",
2093 } else if (!strcmp(name
, "insert")) {
2094 struct idltest_simple
*s
;
2096 if (!arg1
|| arg2
) {
2097 ovs_fatal(0, "\"insert\" command requires 1 argument");
2100 s
= idltest_simple_insert(txn
);
2101 idltest_simple_set_i(s
, atoi(arg1
));
2102 } else if (!strcmp(name
, "delete")) {
2103 const struct idltest_simple
*s
;
2105 if (!arg1
|| arg2
) {
2106 ovs_fatal(0, "\"delete\" command requires 1 argument");
2109 s
= idltest_find_simple(idl
, atoi(arg1
));
2111 ovs_fatal(0, "\"delete\" command asks for nonexistent "
2112 "i=%d", atoi(arg1
));
2114 idltest_simple_delete(s
);
2115 } else if (!strcmp(name
, "verify")) {
2116 const struct idltest_simple
*s
;
2118 if (!arg2
|| arg3
) {
2119 ovs_fatal(0, "\"verify\" command requires 2 arguments");
2122 s
= idltest_find_simple(idl
, atoi(arg1
));
2124 ovs_fatal(0, "\"verify\" command asks for nonexistent "
2125 "i=%d", atoi(arg1
));
2128 if (!strcmp(arg2
, "i")) {
2129 idltest_simple_verify_i(s
);
2130 } else if (!strcmp(arg2
, "b")) {
2131 idltest_simple_verify_b(s
);
2132 } else if (!strcmp(arg2
, "s")) {
2133 idltest_simple_verify_s(s
);
2134 } else if (!strcmp(arg2
, "u")) {
2135 idltest_simple_verify_s(s
);
2136 } else if (!strcmp(arg2
, "r")) {
2137 idltest_simple_verify_r(s
);
2139 ovs_fatal(0, "\"verify\" command asks for unknown column %s",
2142 } else if (!strcmp(name
, "increment")) {
2143 const struct idltest_simple
*s
;
2145 if (!arg1
|| arg2
) {
2146 ovs_fatal(0, "\"increment\" command requires 1 argument");
2149 s
= idltest_find_simple(idl
, atoi(arg1
));
2151 ovs_fatal(0, "\"set\" command asks for nonexistent "
2152 "i=%d", atoi(arg1
));
2155 ovsdb_idl_txn_increment(txn
, &s
->header_
, &idltest_simple_col_i
,
2158 } else if (!strcmp(name
, "abort")) {
2159 ovsdb_idl_txn_abort(txn
);
2160 ovsdb_idl_check_consistency(idl
);
2162 } else if (!strcmp(name
, "destroy")) {
2163 printf("%03d: destroy\n", step
);
2164 ovsdb_idl_txn_destroy(txn
);
2165 ovsdb_idl_check_consistency(idl
);
2168 ovs_fatal(0, "unknown command %s", name
);
2170 ovsdb_idl_check_consistency(idl
);
2173 status
= ovsdb_idl_txn_commit_block(txn
);
2174 printf("%03d: commit, status=%s",
2175 step
, ovsdb_idl_txn_status_to_string(status
));
2177 printf(", increment=%"PRId64
,
2178 ovsdb_idl_txn_get_increment_new_value(txn
));
2181 ovsdb_idl_txn_destroy(txn
);
2182 ovsdb_idl_check_consistency(idl
);
2185 static const struct ovsdb_idl_table_class
*
2186 find_table_class(const char *name
)
2188 if (!strcmp(name
, "simple")) {
2189 return &idltest_table_simple
;
2190 } else if (!strcmp(name
, "link1")) {
2191 return &idltest_table_link1
;
2192 } else if (!strcmp(name
, "link2")) {
2193 return &idltest_table_link2
;
2199 parse_simple_json_clause(struct ovsdb_idl_condition
*cond
,
2200 enum ovsdb_function function
,
2201 const char *column
, const struct json
*arg
)
2203 if (!strcmp(column
, "b")) {
2204 idltest_simple_add_clause_b(cond
, function
, json_boolean(arg
));
2205 } else if (!strcmp(column
, "i")) {
2206 idltest_simple_add_clause_i(cond
, function
, json_integer(arg
));
2207 } else if (!strcmp(column
, "s")) {
2208 idltest_simple_add_clause_s(cond
, function
, json_string(arg
));
2209 } else if (!strcmp(column
, "u")) {
2211 if (!uuid_from_string(&uuid
, json_string(arg
))) {
2212 ovs_fatal(0, "\"%s\" is not a valid UUID", json_string(arg
));
2214 idltest_simple_add_clause_u(cond
, function
, uuid
);
2215 } else if (!strcmp(column
, "r")) {
2216 idltest_simple_add_clause_r(cond
, function
, json_real(arg
));
2218 ovs_fatal(0, "Unsupported columns name %s", column
);
2223 parse_link1_json_clause(struct ovsdb_idl_condition
*cond
,
2224 enum ovsdb_function function
,
2225 const char *column
, const struct json
*arg
)
2227 if (!strcmp(column
, "i")) {
2228 idltest_link1_add_clause_i(cond
, function
, json_integer(arg
));
2230 ovs_fatal(0, "Unsupported columns name %s", column
);
2235 parse_link2_json_clause(struct ovsdb_idl_condition
*cond
,
2236 enum ovsdb_function function
,
2237 const char *column
, const struct json
*arg
)
2239 if (!strcmp(column
, "i")) {
2240 idltest_link2_add_clause_i(cond
, function
, json_integer(arg
));
2242 ovs_fatal(0, "Unsupported columns name %s", column
);
2247 update_conditions(struct ovsdb_idl
*idl
, char *commands
)
2249 char *cmd
, *save_ptr1
= NULL
;
2250 const struct ovsdb_idl_table_class
*tc
;
2252 for (cmd
= strtok_r(commands
, ";", &save_ptr1
); cmd
;
2253 cmd
= strtok_r(NULL
, ";", &save_ptr1
)) {
2254 char *save_ptr2
= NULL
;
2255 char *table_name
= strtok_r(cmd
, " ", &save_ptr2
);
2256 struct json
*json
= parse_json(save_ptr2
);
2259 if (json
->type
!= JSON_ARRAY
) {
2260 ovs_fatal(0, "condition should be an array");
2263 tc
= find_table_class(table_name
);
2265 ovs_fatal(0, "Table %s does not exist", table_name
);
2268 struct ovsdb_idl_condition cond
= OVSDB_IDL_CONDITION_INIT(&cond
);
2269 for (i
= 0; i
< json
->u
.array
.n
; i
++) {
2270 const struct json
*clause
= json
->u
.array
.elems
[i
];
2271 if (clause
->type
== JSON_TRUE
) {
2272 ovsdb_idl_condition_add_clause_true(&cond
);
2273 } else if (clause
->type
!= JSON_ARRAY
|| clause
->u
.array
.n
!= 3
2274 || clause
->u
.array
.elems
[0]->type
!= JSON_STRING
2275 || clause
->u
.array
.elems
[1]->type
!= JSON_STRING
) {
2276 ovs_fatal(0, "Error parsing condition");
2278 enum ovsdb_function function
;
2279 const char *function_s
= json_string(clause
->u
.array
.elems
[1]);
2280 struct ovsdb_error
*error
= ovsdb_function_from_string(
2281 function_s
, &function
);
2283 ovs_fatal(0, "unknown clause function %s", function_s
);
2286 const char *column
= json_string(clause
->u
.array
.elems
[0]);
2287 const struct json
*arg
= clause
->u
.array
.elems
[2];
2288 if (!strcmp(table_name
, "simple")) {
2289 parse_simple_json_clause(&cond
, function
, column
, arg
);
2290 } else if (!strcmp(table_name
, "link1")) {
2291 parse_link1_json_clause(&cond
, function
, column
, arg
);
2292 } else if (!strcmp(table_name
, "link2")) {
2293 parse_link2_json_clause(&cond
, function
, column
, arg
);
2298 unsigned int seqno
= ovsdb_idl_get_condition_seqno(idl
);
2299 unsigned int next_seqno
= ovsdb_idl_set_condition(idl
, tc
, &cond
);
2300 if (seqno
== next_seqno
) {
2301 ovs_fatal(0, "condition unchanged");
2303 ovsdb_idl_condition_destroy(&cond
);
2309 do_idl(struct ovs_cmdl_context
*ctx
)
2311 struct jsonrpc
*rpc
;
2312 struct ovsdb_idl
*idl
;
2313 unsigned int seqno
= 0;
2314 struct ovsdb_symbol_table
*symtab
;
2321 track
= ((struct test_ovsdb_pvt_context
*)(ctx
->pvt
))->track
;
2323 idl
= ovsdb_idl_create(ctx
->argv
[1], &idltest_idl_class
, true, true);
2324 if (ctx
->argc
> 2) {
2325 struct stream
*stream
;
2327 error
= stream_open_block(jsonrpc_stream_open(ctx
->argv
[1], &stream
,
2328 DSCP_DEFAULT
), &stream
);
2330 ovs_fatal(error
, "failed to connect to \"%s\"", ctx
->argv
[1]);
2332 rpc
= jsonrpc_open(stream
);
2338 ovsdb_idl_track_add_all(idl
);
2341 setvbuf(stdout
, NULL
, _IONBF
, 0);
2343 symtab
= ovsdb_symbol_table_create();
2344 const char cond_s
[] = "condition ";
2345 if (ctx
->argc
> 2 && strstr(ctx
->argv
[2], cond_s
)) {
2346 update_conditions(idl
, ctx
->argv
[2] + strlen(cond_s
));
2347 printf("%03d: change conditions\n", step
++);
2352 for (; i
< ctx
->argc
; i
++) {
2353 char *arg
= ctx
->argv
[i
];
2354 struct jsonrpc_msg
*request
, *reply
;
2357 /* The previous transaction didn't change anything. */
2360 /* Wait for update. */
2363 ovsdb_idl_check_consistency(idl
);
2364 if (ovsdb_idl_get_seqno(idl
) != seqno
) {
2369 ovsdb_idl_wait(idl
);
2376 print_idl_track(idl
, step
++, ovsdb_idl_get_seqno(idl
));
2377 ovsdb_idl_track_clear(idl
);
2379 print_idl(idl
, step
++);
2382 seqno
= ovsdb_idl_get_seqno(idl
);
2384 if (!strcmp(arg
, "reconnect")) {
2385 printf("%03d: reconnect\n", step
++);
2386 ovsdb_idl_force_reconnect(idl
);
2387 } else if (!strncmp(arg
, cond_s
, strlen(cond_s
))) {
2388 update_conditions(idl
, arg
+ strlen(cond_s
));
2389 printf("%03d: change conditions\n", step
++);
2390 } else if (arg
[0] != '[') {
2391 idl_set(idl
, arg
, step
++);
2393 struct json
*json
= parse_json(arg
);
2394 substitute_uuids(json
, symtab
);
2395 request
= jsonrpc_create_request("transact", json
, NULL
);
2396 error
= jsonrpc_transact_block(rpc
, request
, &reply
);
2397 if (error
|| reply
->error
) {
2398 ovs_fatal(error
, "jsonrpc transaction failed");
2400 printf("%03d: ", step
++);
2401 if (reply
->result
) {
2402 parse_uuids(reply
->result
, symtab
, &n_uuids
);
2404 json_destroy(reply
->id
);
2406 print_and_free_json(jsonrpc_msg_to_json(reply
));
2409 ovsdb_symbol_table_destroy(symtab
);
2416 ovsdb_idl_check_consistency(idl
);
2417 if (ovsdb_idl_get_seqno(idl
) != seqno
) {
2420 ovsdb_idl_wait(idl
);
2423 print_idl(idl
, step
++);
2424 ovsdb_idl_track_clear(idl
);
2425 ovsdb_idl_destroy(idl
);
2426 printf("%03d: done\n", step
);
2430 print_idl_row_simple2(const struct idltest_simple2
*s
, int step
)
2433 const struct ovsdb_datum
*smap
, *imap
;
2435 smap
= idltest_simple2_get_smap(s
, OVSDB_TYPE_STRING
, OVSDB_TYPE_STRING
);
2436 imap
= idltest_simple2_get_imap(s
, OVSDB_TYPE_INTEGER
, OVSDB_TYPE_STRING
);
2437 printf("%03d: name=%s smap=[",
2439 for (i
= 0; i
< smap
->n
; i
++) {
2440 printf("[%s : %s]%s", smap
->keys
[i
].string
, smap
->values
[i
].string
,
2441 i
< smap
->n
-1? ",": "");
2444 for (i
= 0; i
< imap
->n
; i
++) {
2445 printf("[%"PRId64
" : %s]%s", imap
->keys
[i
].integer
, imap
->values
[i
].string
,
2446 i
< imap
->n
-1? ",":"");
2452 dump_simple2(struct ovsdb_idl
*idl
,
2453 const struct idltest_simple2
*myRow
,
2456 IDLTEST_SIMPLE2_FOR_EACH(myRow
, idl
) {
2457 print_idl_row_simple2(myRow
, step
);
2462 do_idl_partial_update_map_column(struct ovs_cmdl_context
*ctx
)
2464 struct ovsdb_idl
*idl
;
2465 struct ovsdb_idl_txn
*myTxn
;
2466 const struct idltest_simple2
*myRow
;
2467 const struct ovsdb_datum
*smap
, *imap OVS_UNUSED
;
2469 char key_to_delete
[100];
2471 idl
= ovsdb_idl_create(ctx
->argv
[1], &idltest_idl_class
, false, true);
2472 ovsdb_idl_add_table(idl
, &idltest_table_simple2
);
2473 ovsdb_idl_add_column(idl
, &idltest_simple2_col_name
);
2474 ovsdb_idl_add_column(idl
, &idltest_simple2_col_smap
);
2475 ovsdb_idl_add_column(idl
, &idltest_simple2_col_imap
);
2476 ovsdb_idl_get_initial_snapshot(idl
);
2477 setvbuf(stdout
, NULL
, _IONBF
, 0);
2480 /* Display original data in table. */
2482 printf("%03d: Getting records\n", step
++);
2483 dump_simple2(idl
, myRow
, step
++);
2485 /* Insert new elements in different map columns. */
2486 myRow
= idltest_simple2_first(idl
);
2487 myTxn
= ovsdb_idl_txn_create(idl
);
2488 idltest_simple2_get_smap(myRow
, OVSDB_TYPE_STRING
,
2490 idltest_simple2_update_smap_setkey(myRow
, "key1", "myList1");
2491 imap
= idltest_simple2_get_imap(myRow
, OVSDB_TYPE_INTEGER
,
2493 idltest_simple2_update_imap_setkey(myRow
, 3, "myids2");
2494 idltest_simple2_set_name(myRow
, "String2");
2495 ovsdb_idl_txn_commit_block(myTxn
);
2496 ovsdb_idl_txn_destroy(myTxn
);
2497 ovsdb_idl_get_initial_snapshot(idl
);
2498 printf("%03d: After insert element\n", step
++);
2499 dump_simple2(idl
, myRow
, step
++);
2501 /* Insert duplicate element. */
2502 myTxn
= ovsdb_idl_txn_create(idl
);
2503 idltest_simple2_update_smap_setkey(myRow
, "key1", "myList1");
2504 ovsdb_idl_txn_commit_block(myTxn
);
2505 ovsdb_idl_txn_destroy(myTxn
);
2506 ovsdb_idl_get_initial_snapshot(idl
);
2507 printf("%03d: After insert duplicated element\n", step
++);
2508 dump_simple2(idl
, myRow
, step
++);
2510 /* Deletes an element of a map column. */
2511 myRow
= idltest_simple2_first(idl
);
2512 myTxn
= ovsdb_idl_txn_create(idl
);
2513 smap
= idltest_simple2_get_smap(myRow
, OVSDB_TYPE_STRING
,
2515 strcpy(key_to_delete
, smap
->keys
[0].string
);
2516 idltest_simple2_update_smap_delkey(myRow
, smap
->keys
[0].string
);
2517 ovsdb_idl_txn_commit_block(myTxn
);
2518 ovsdb_idl_txn_destroy(myTxn
);
2519 ovsdb_idl_get_initial_snapshot(idl
);
2520 printf("%03d: After delete element\n", step
++);
2521 dump_simple2(idl
, myRow
, step
++);
2523 /* Try to delete a deleted element of a map column. */
2524 myTxn
= ovsdb_idl_txn_create(idl
);
2525 idltest_simple2_update_smap_delkey(myRow
, key_to_delete
);
2526 ovsdb_idl_txn_commit_block(myTxn
);
2527 ovsdb_idl_txn_destroy(myTxn
);
2528 ovsdb_idl_get_initial_snapshot(idl
);
2529 printf("%03d: After trying to delete a deleted element\n", step
++);
2530 dump_simple2(idl
, myRow
, step
++);
2532 printf("%03d: End test\n", step
);
2537 print_idl_row_simple3(const struct idltest_simple3
*s
, int step
)
2540 const struct ovsdb_datum
*uset
;
2541 const struct ovsdb_datum
*uref
;
2543 uset
= idltest_simple3_get_uset(s
, OVSDB_TYPE_UUID
);
2544 printf("%03d: name=%s uset=[",
2546 for (i
= 0; i
< uset
->n
; i
++) {
2547 printf("["UUID_FMT
"]%s", UUID_ARGS(&(uset
->keys
[i
].uuid
)), i
< uset
->n
-1? ",": "");
2549 uref
= idltest_simple3_get_uref(s
, OVSDB_TYPE_UUID
);
2551 for (i
= 0; i
< uref
->n
; i
++) {
2552 printf("["UUID_FMT
"]%s", UUID_ARGS(&(uref
->keys
[i
].uuid
)), i
< uref
->n
-1? ",": "");
2558 dump_simple3(struct ovsdb_idl
*idl
,
2559 const struct idltest_simple3
*myRow
,
2562 IDLTEST_SIMPLE3_FOR_EACH(myRow
, idl
) {
2563 print_idl_row_simple3(myRow
, step
);
2568 do_idl_partial_update_set_column(struct ovs_cmdl_context
*ctx
)
2570 struct ovsdb_idl
*idl
;
2571 struct ovsdb_idl_txn
*myTxn
;
2572 const struct idltest_simple3
*myRow
;
2573 struct idltest_simple4
*myRow2
;
2574 const struct ovsdb_datum
*uset OVS_UNUSED
;
2575 const struct ovsdb_datum
*uref OVS_UNUSED
;
2578 idl
= ovsdb_idl_create(ctx
->argv
[1], &idltest_idl_class
, false, true);
2579 ovsdb_idl_add_table(idl
, &idltest_table_simple3
);
2580 ovsdb_idl_add_column(idl
, &idltest_simple3_col_name
);
2581 ovsdb_idl_add_column(idl
, &idltest_simple3_col_uset
);
2582 ovsdb_idl_add_column(idl
, &idltest_simple3_col_uref
);
2583 ovsdb_idl_add_table(idl
, &idltest_table_simple4
);
2584 ovsdb_idl_add_column(idl
, &idltest_simple4_col_name
);
2585 ovsdb_idl_get_initial_snapshot(idl
);
2586 setvbuf(stdout
, NULL
, _IONBF
, 0);
2589 /* Display original data in table. */
2591 printf("%03d: Getting records\n", step
++);
2592 dump_simple3(idl
, myRow
, step
++);
2594 /* Insert new elements in different map columns. */
2595 myRow
= idltest_simple3_first(idl
);
2596 myTxn
= ovsdb_idl_txn_create(idl
);
2597 idltest_simple3_get_uset(myRow
, OVSDB_TYPE_UUID
);
2598 struct uuid uuid_to_add
;
2599 uuid_from_string(&uuid_to_add
, "001e43d2-dd3f-4616-ab6a-83a490bb0991");
2600 idltest_simple3_update_uset_addvalue(myRow
, uuid_to_add
);
2601 idltest_simple3_set_name(myRow
, "String2");
2602 ovsdb_idl_txn_commit_block(myTxn
);
2603 ovsdb_idl_txn_destroy(myTxn
);
2604 ovsdb_idl_get_initial_snapshot(idl
);
2605 printf("%03d: After rename+add new value\n", step
++);
2606 dump_simple3(idl
, myRow
, step
++);
2608 /* Insert duplicate element. */
2609 myTxn
= ovsdb_idl_txn_create(idl
);
2610 struct uuid uuid_to_add2
;
2611 uuid_from_string(&uuid_to_add2
, "0026b3ba-571b-4729-8227-d860a5210ab8");
2612 idltest_simple3_update_uset_addvalue(myRow
, uuid_to_add2
);
2613 ovsdb_idl_txn_commit_block(myTxn
);
2614 ovsdb_idl_txn_destroy(myTxn
);
2615 ovsdb_idl_get_initial_snapshot(idl
);
2616 printf("%03d: After add new value\n", step
++);
2617 dump_simple3(idl
, myRow
, step
++);
2619 /* Deletes an element of a set column. */
2620 myRow
= idltest_simple3_first(idl
);
2621 myTxn
= ovsdb_idl_txn_create(idl
);
2622 uset
= idltest_simple3_get_uset(myRow
, OVSDB_TYPE_UUID
);
2623 idltest_simple3_update_uset_delvalue(myRow
, uuid_to_add
);
2624 ovsdb_idl_txn_commit_block(myTxn
);
2625 ovsdb_idl_txn_destroy(myTxn
);
2626 ovsdb_idl_get_initial_snapshot(idl
);
2627 printf("%03d: After delete value\n", step
++);
2628 dump_simple3(idl
, myRow
, step
++);
2630 /* Try to delete a deleted element of a map column. */
2631 myRow
= idltest_simple3_first(idl
);
2632 myTxn
= ovsdb_idl_txn_create(idl
);
2633 idltest_simple3_update_uset_delvalue(myRow
, uuid_to_add
);
2634 ovsdb_idl_txn_commit_block(myTxn
);
2635 ovsdb_idl_txn_destroy(myTxn
);
2636 ovsdb_idl_get_initial_snapshot(idl
);
2637 printf("%03d: After trying to delete a deleted value\n", step
++);
2638 dump_simple3(idl
, myRow
, step
++);
2640 /* Adds to a table and update a strong reference in another table. */
2641 myRow
= idltest_simple3_first(idl
);
2642 myTxn
= ovsdb_idl_txn_create(idl
);
2643 myRow2
= idltest_simple4_insert(myTxn
);
2644 idltest_simple4_set_name(myRow2
, "test");
2645 idltest_simple3_update_uref_addvalue(myRow
, myRow2
);
2646 ovsdb_idl_txn_commit_block(myTxn
);
2647 ovsdb_idl_txn_destroy(myTxn
);
2648 ovsdb_idl_get_initial_snapshot(idl
);
2649 printf("%03d: After add to other table + set of strong ref\n", step
++);
2650 dump_simple3(idl
, myRow
, step
++);
2651 printf("%03d: End test\n", step
);
2655 static struct ovs_cmdl_command all_commands
[] = {
2656 { "log-io", NULL
, 2, INT_MAX
, do_log_io
, OVS_RO
},
2657 { "default-atoms", NULL
, 0, 0, do_default_atoms
, OVS_RO
},
2658 { "default-data", NULL
, 0, 0, do_default_data
, OVS_RO
},
2659 { "diff-data", NULL
, 3, INT_MAX
, do_diff_data
, OVS_RO
},
2660 { "parse-atomic-type", NULL
, 1, 1, do_parse_atomic_type
, OVS_RO
},
2661 { "parse-base-type", NULL
, 1, 1, do_parse_base_type
, OVS_RO
},
2662 { "parse-type", NULL
, 1, 1, do_parse_type
, OVS_RO
},
2663 { "parse-atoms", NULL
, 2, INT_MAX
, do_parse_atoms
, OVS_RO
},
2664 { "parse-atom-strings", NULL
, 2, INT_MAX
, do_parse_atom_strings
, OVS_RO
},
2665 { "parse-data", NULL
, 2, INT_MAX
, do_parse_data
, OVS_RO
},
2666 { "parse-data-strings", NULL
, 2, INT_MAX
, do_parse_data_strings
, OVS_RO
},
2667 { "sort-atoms", NULL
, 2, 2, do_sort_atoms
, OVS_RO
},
2668 { "parse-column", NULL
, 2, 2, do_parse_column
, OVS_RO
},
2669 { "parse-table", NULL
, 2, 3, do_parse_table
, OVS_RO
},
2670 { "parse-rows", NULL
, 2, INT_MAX
, do_parse_rows
, OVS_RO
},
2671 { "compare-rows", NULL
, 2, INT_MAX
, do_compare_rows
, OVS_RO
},
2672 { "parse-conditions", NULL
, 2, INT_MAX
, do_parse_conditions
, OVS_RO
},
2673 { "evaluate-conditions", NULL
, 3, 3, do_evaluate_conditions
, OVS_RO
},
2674 { "evaluate-conditions-any", NULL
, 3, 3, do_evaluate_conditions_any
, OVS_RO
},
2675 { "compare-conditions", NULL
, 2, 2, do_compare_conditions
, OVS_RO
},
2676 { "parse-mutations", NULL
, 2, INT_MAX
, do_parse_mutations
, OVS_RO
},
2677 { "execute-mutations", NULL
, 3, 3, do_execute_mutations
, OVS_RO
},
2678 { "query", NULL
, 3, 3, do_query
, OVS_RO
},
2679 { "query-distinct", NULL
, 4, 4, do_query_distinct
, OVS_RO
},
2680 { "transact", NULL
, 1, INT_MAX
, do_transact
, OVS_RO
},
2681 { "parse-schema", NULL
, 1, 1, do_parse_schema
, OVS_RO
},
2682 { "execute", NULL
, 2, INT_MAX
, do_execute
, OVS_RO
},
2683 { "execute-readonly", NULL
, 2, INT_MAX
, do_execute_ro
, OVS_RO
},
2684 { "trigger", NULL
, 2, INT_MAX
, do_trigger
, OVS_RO
},
2685 { "idl", NULL
, 1, INT_MAX
, do_idl
, OVS_RO
},
2686 { "idl-partial-update-map-column", NULL
, 1, INT_MAX
,
2687 do_idl_partial_update_map_column
, OVS_RO
},
2688 { "idl-partial-update-set-column", NULL
, 1, INT_MAX
,
2689 do_idl_partial_update_set_column
, OVS_RO
},
2690 { "help", NULL
, 0, INT_MAX
, do_help
, OVS_RO
},
2691 { NULL
, NULL
, 0, 0, NULL
, OVS_RO
},
2694 static struct ovs_cmdl_command
*
2695 get_all_commands(void)
2697 return all_commands
;