2 * Copyright (c) 2009, 2010, 2011, 2012 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 "command-line.h"
27 #include "dynamic-string.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/table.h"
44 #include "ovsdb/transaction.h"
45 #include "ovsdb/trigger.h"
46 #include "poll-loop.h"
49 #include "tests/idltest.h"
54 static struct command all_commands
[];
56 static void usage(void) NO_RETURN
;
57 static void parse_options(int argc
, char *argv
[]);
60 main(int argc
, char *argv
[])
62 set_program_name(argv
[0]);
63 parse_options(argc
, argv
);
64 run_command(argc
- optind
, argv
+ optind
, all_commands
);
69 parse_options(int argc
, char *argv
[])
71 static struct option long_options
[] = {
72 {"timeout", required_argument
, NULL
, 't'},
73 {"verbose", optional_argument
, NULL
, 'v'},
74 {"help", no_argument
, NULL
, 'h'},
77 char *short_options
= long_options_to_short_options(long_options
);
80 unsigned long int timeout
;
83 c
= getopt_long(argc
, argv
, short_options
, long_options
, NULL
);
90 timeout
= strtoul(optarg
, NULL
, 10);
92 ovs_fatal(0, "value %s on -t or --timeout is not at least 1",
103 vlog_set_verbosity(optarg
);
119 printf("%s: Open vSwitch database test utility\n"
120 "usage: %s [OPTIONS] COMMAND [ARG...]\n\n"
121 " log-io FILE FLAGS COMMAND...\n"
122 " open FILE with FLAGS, run COMMANDs\n"
124 " test ovsdb_atom_default()\n"
126 " test ovsdb_datum_default()\n"
127 " parse-atomic-type TYPE\n"
128 " parse TYPE as OVSDB atomic type, and re-serialize\n"
129 " parse-base-type TYPE\n"
130 " parse TYPE as OVSDB base type, and re-serialize\n"
132 " parse JSON as OVSDB type, and re-serialize\n"
133 " parse-atoms TYPE ATOM...\n"
134 " parse JSON ATOMs as atoms of TYPE, and re-serialize\n"
135 " parse-atom-strings TYPE ATOM...\n"
136 " parse string ATOMs as atoms of given TYPE, and re-serialize\n"
137 " sort-atoms TYPE ATOM...\n"
138 " print JSON ATOMs in sorted order\n"
139 " parse-data TYPE DATUM...\n"
140 " parse JSON DATUMs as data of given TYPE, and re-serialize\n"
141 " parse-data-strings TYPE DATUM...\n"
142 " parse string DATUMs as data of given TYPE, and re-serialize\n"
143 " parse-column NAME OBJECT\n"
144 " parse column NAME with info OBJECT, and re-serialize\n"
145 " parse-table NAME OBJECT [DEFAULT-IS-ROOT]\n"
146 " parse table NAME with info OBJECT\n"
147 " parse-row TABLE ROW..., and re-serialize\n"
148 " parse each ROW of defined TABLE\n"
149 " compare-row TABLE ROW...\n"
150 " mutually compare all of the ROWs, print those that are equal\n"
151 " parse-conditions TABLE CONDITION...\n"
152 " parse each CONDITION on TABLE, and re-serialize\n"
153 " evaluate-conditions TABLE [CONDITION,...] [ROW,...]\n"
154 " test CONDITIONS on TABLE against each ROW, print results\n"
155 " parse-mutations TABLE MUTATION...\n"
156 " parse each MUTATION on TABLE, and re-serialize\n"
157 " execute-mutations TABLE [MUTATION,...] [ROW,...]\n"
158 " execute MUTATIONS on TABLE on each ROW, print results\n"
159 " query TABLE [ROW,...] [CONDITION,...]\n"
160 " add each ROW to TABLE, then query and print the rows that\n"
161 " satisfy each CONDITION.\n"
162 " query-distinct TABLE [ROW,...] [CONDITION,...] COLUMNS\n"
163 " add each ROW to TABLE, then query and print the rows that\n"
164 " satisfy each CONDITION and have distinct COLUMNS.\n"
165 " parse-schema JSON\n"
166 " parse JSON as an OVSDB schema, and re-serialize\n"
167 " transact COMMAND\n"
168 " execute each specified transactional COMMAND:\n"
175 " execute SCHEMA TRANSACTION...\n"
176 " executes each TRANSACTION on an initially empty database\n"
177 " the specified SCHEMA\n"
178 " trigger SCHEMA TRANSACTION...\n"
179 " executes each TRANSACTION on an initially empty database\n"
180 " the specified SCHEMA. A TRANSACTION of the form\n"
181 " [\"advance\", NUMBER] advances NUMBER milliseconds in\n"
182 " simulated time, for causing triggers to time out.\n"
183 " idl SERVER [TRANSACTION...]\n"
184 " connect to SERVER and dump the contents of the database\n"
185 " as seen initially by the IDL implementation and after\n"
186 " executing each TRANSACTION. (Each TRANSACTION must modify\n"
187 " the database or this command will hang.)\n",
188 program_name
, program_name
);
190 printf("\nOther options:\n"
191 " -t, --timeout=SECS give up after SECS seconds\n"
192 " -h, --help display this help message\n");
196 /* Command helper functions. */
199 parse_json(const char *s
)
201 struct json
*json
= json_from_string(s
);
202 if (json
->type
== JSON_STRING
) {
203 ovs_fatal(0, "\"%s\": %s", s
, json
->u
.string
);
209 unbox_json(struct json
*json
)
211 if (json
->type
== JSON_ARRAY
&& json
->u
.array
.n
== 1) {
212 struct json
*inner
= json
->u
.array
.elems
[0];
213 json
->u
.array
.elems
[0] = NULL
;
222 print_and_free_json(struct json
*json
)
224 char *string
= json_to_string(json
, JSSF_SORT
);
231 print_and_free_ovsdb_error(struct ovsdb_error
*error
)
233 char *string
= ovsdb_error_to_string(error
);
234 ovsdb_error_destroy(error
);
240 check_ovsdb_error(struct ovsdb_error
*error
)
243 char *s
= ovsdb_error_to_string(error
);
244 ovsdb_error_destroy(error
);
245 ovs_fatal(0, "%s", s
);
250 die_if_error(char *error
)
253 ovs_fatal(0, "%s", error
);
257 /* Command implementations. */
260 do_log_io(int argc
, char *argv
[])
262 const char *name
= argv
[1];
263 char *mode_string
= argv
[2];
265 struct ovsdb_error
*error
;
266 enum ovsdb_log_open_mode mode
;
267 struct ovsdb_log
*log
;
270 if (!strcmp(mode_string
, "read-only")) {
271 mode
= OVSDB_LOG_READ_ONLY
;
272 } else if (!strcmp(mode_string
, "read/write")) {
273 mode
= OVSDB_LOG_READ_WRITE
;
274 } else if (!strcmp(mode_string
, "create")) {
275 mode
= OVSDB_LOG_CREATE
;
277 ovs_fatal(0, "unknown log-io open mode \"%s\"", mode_string
);
280 check_ovsdb_error(ovsdb_log_open(name
, mode
, -1, &log
));
281 printf("%s: open successful\n", name
);
283 for (i
= 3; i
< argc
; i
++) {
284 const char *command
= argv
[i
];
285 if (!strcmp(command
, "read")) {
288 error
= ovsdb_log_read(log
, &json
);
290 printf("%s: read: ", name
);
292 print_and_free_json(json
);
294 printf("end of log\n");
298 } else if (!strncmp(command
, "write:", 6)) {
299 struct json
*json
= parse_json(command
+ 6);
300 error
= ovsdb_log_write(log
, json
);
302 } else if (!strcmp(command
, "commit")) {
303 error
= ovsdb_log_commit(log
);
305 ovs_fatal(0, "unknown log-io command \"%s\"", command
);
308 char *s
= ovsdb_error_to_string(error
);
309 printf("%s: %s failed: %s\n", name
, command
, s
);
311 ovsdb_error_destroy(error
);
313 printf("%s: %s successful\n", name
, command
);
317 ovsdb_log_close(log
);
321 do_default_atoms(int argc OVS_UNUSED
, char *argv
[] OVS_UNUSED
)
325 for (type
= 0; type
< OVSDB_N_TYPES
; type
++) {
326 union ovsdb_atom atom
;
328 if (type
== OVSDB_TYPE_VOID
) {
332 printf("%s: ", ovsdb_atomic_type_to_string(type
));
334 ovsdb_atom_init_default(&atom
, type
);
335 if (!ovsdb_atom_equals(&atom
, ovsdb_atom_default(type
), type
)) {
339 ovsdb_atom_destroy(&atom
, type
);
346 do_default_data(int argc OVS_UNUSED
, char *argv
[] OVS_UNUSED
)
351 for (n_min
= 0; n_min
<= 1; n_min
++) {
352 for (key
= 0; key
< OVSDB_N_TYPES
; key
++) {
353 if (key
== OVSDB_TYPE_VOID
) {
356 for (value
= 0; value
< OVSDB_N_TYPES
; value
++) {
357 struct ovsdb_datum datum
;
358 struct ovsdb_type type
;
360 ovsdb_base_type_init(&type
.key
, key
);
361 ovsdb_base_type_init(&type
.value
, value
);
364 assert(ovsdb_type_is_valid(&type
));
366 printf("key %s, value %s, n_min %u: ",
367 ovsdb_atomic_type_to_string(key
),
368 ovsdb_atomic_type_to_string(value
), n_min
);
370 ovsdb_datum_init_default(&datum
, &type
);
371 if (!ovsdb_datum_equals(&datum
, ovsdb_datum_default(&type
),
376 ovsdb_datum_destroy(&datum
, &type
);
377 ovsdb_type_destroy(&type
);
386 do_parse_atomic_type(int argc OVS_UNUSED
, char *argv
[])
388 enum ovsdb_atomic_type type
;
391 json
= unbox_json(parse_json(argv
[1]));
392 check_ovsdb_error(ovsdb_atomic_type_from_json(&type
, json
));
394 print_and_free_json(ovsdb_atomic_type_to_json(type
));
398 do_parse_base_type(int argc OVS_UNUSED
, char *argv
[])
400 struct ovsdb_base_type base
;
403 json
= unbox_json(parse_json(argv
[1]));
404 check_ovsdb_error(ovsdb_base_type_from_json(&base
, json
));
406 print_and_free_json(ovsdb_base_type_to_json(&base
));
407 ovsdb_base_type_destroy(&base
);
411 do_parse_type(int argc OVS_UNUSED
, char *argv
[])
413 struct ovsdb_type type
;
416 json
= unbox_json(parse_json(argv
[1]));
417 check_ovsdb_error(ovsdb_type_from_json(&type
, json
));
419 print_and_free_json(ovsdb_type_to_json(&type
));
420 ovsdb_type_destroy(&type
);
424 do_parse_atoms(int argc
, char *argv
[])
426 struct ovsdb_base_type base
;
430 json
= unbox_json(parse_json(argv
[1]));
431 check_ovsdb_error(ovsdb_base_type_from_json(&base
, json
));
434 for (i
= 2; i
< argc
; i
++) {
435 struct ovsdb_error
*error
;
436 union ovsdb_atom atom
;
438 json
= unbox_json(parse_json(argv
[i
]));
439 error
= ovsdb_atom_from_json(&atom
, &base
, json
, NULL
);
443 print_and_free_ovsdb_error(error
);
445 print_and_free_json(ovsdb_atom_to_json(&atom
, base
.type
));
446 ovsdb_atom_destroy(&atom
, base
.type
);
449 ovsdb_base_type_destroy(&base
);
453 do_parse_atom_strings(int argc
, char *argv
[])
455 struct ovsdb_base_type base
;
459 json
= unbox_json(parse_json(argv
[1]));
460 check_ovsdb_error(ovsdb_base_type_from_json(&base
, json
));
463 for (i
= 2; i
< argc
; i
++) {
464 union ovsdb_atom atom
;
467 die_if_error(ovsdb_atom_from_string(&atom
, &base
, argv
[i
], NULL
));
470 ovsdb_atom_to_string(&atom
, base
.type
, &out
);
474 ovsdb_atom_destroy(&atom
, base
.type
);
476 ovsdb_base_type_destroy(&base
);
480 do_parse_data__(int argc
, char *argv
[],
482 (*parse
)(struct ovsdb_datum
*datum
,
483 const struct ovsdb_type
*type
,
484 const struct json
*json
,
485 struct ovsdb_symbol_table
*symtab
))
487 struct ovsdb_type type
;
491 json
= unbox_json(parse_json(argv
[1]));
492 check_ovsdb_error(ovsdb_type_from_json(&type
, json
));
495 for (i
= 2; i
< argc
; i
++) {
496 struct ovsdb_datum datum
;
498 json
= unbox_json(parse_json(argv
[i
]));
499 check_ovsdb_error(parse(&datum
, &type
, json
, NULL
));
502 print_and_free_json(ovsdb_datum_to_json(&datum
, &type
));
504 ovsdb_datum_destroy(&datum
, &type
);
506 ovsdb_type_destroy(&type
);
510 do_parse_data(int argc
, char *argv
[])
512 do_parse_data__(argc
, argv
, ovsdb_datum_from_json
);
516 do_parse_data_strings(int argc
, char *argv
[])
518 struct ovsdb_type type
;
522 json
= unbox_json(parse_json(argv
[1]));
523 check_ovsdb_error(ovsdb_type_from_json(&type
, json
));
526 for (i
= 2; i
< argc
; i
++) {
527 struct ovsdb_datum datum
;
530 die_if_error(ovsdb_datum_from_string(&datum
, &type
, argv
[i
], NULL
));
533 ovsdb_datum_to_string(&datum
, &type
, &out
);
537 ovsdb_datum_destroy(&datum
, &type
);
539 ovsdb_type_destroy(&type
);
542 static enum ovsdb_atomic_type compare_atoms_atomic_type
;
545 compare_atoms(const void *a_
, const void *b_
)
547 const union ovsdb_atom
*a
= a_
;
548 const union ovsdb_atom
*b
= b_
;
550 return ovsdb_atom_compare_3way(a
, b
, compare_atoms_atomic_type
);
554 do_sort_atoms(int argc OVS_UNUSED
, char *argv
[])
556 struct ovsdb_base_type base
;
557 union ovsdb_atom
*atoms
;
558 struct json
*json
, **json_atoms
;
562 json
= unbox_json(parse_json(argv
[1]));
563 check_ovsdb_error(ovsdb_base_type_from_json(&base
, json
));
566 json
= unbox_json(parse_json(argv
[2]));
567 if (json
->type
!= JSON_ARRAY
) {
568 ovs_fatal(0, "second argument must be array");
571 /* Convert JSON atoms to internal representation. */
572 n_atoms
= json
->u
.array
.n
;
573 atoms
= xmalloc(n_atoms
* sizeof *atoms
);
574 for (i
= 0; i
< n_atoms
; i
++) {
575 check_ovsdb_error(ovsdb_atom_from_json(&atoms
[i
], &base
,
576 json
->u
.array
.elems
[i
], NULL
));
581 compare_atoms_atomic_type
= base
.type
;
582 qsort(atoms
, n_atoms
, sizeof *atoms
, compare_atoms
);
584 /* Convert internal representation back to JSON. */
585 json_atoms
= xmalloc(n_atoms
* sizeof *json_atoms
);
586 for (i
= 0; i
< n_atoms
; i
++) {
587 json_atoms
[i
] = ovsdb_atom_to_json(&atoms
[i
], base
.type
);
588 ovsdb_atom_destroy(&atoms
[i
], base
.type
);
590 print_and_free_json(json_array_create(json_atoms
, n_atoms
));
592 ovsdb_base_type_destroy(&base
);
596 do_parse_column(int argc OVS_UNUSED
, char *argv
[])
598 struct ovsdb_column
*column
;
601 json
= parse_json(argv
[2]);
602 check_ovsdb_error(ovsdb_column_from_json(json
, argv
[1], &column
));
604 print_and_free_json(ovsdb_column_to_json(column
));
605 ovsdb_column_destroy(column
);
609 do_parse_table(int argc OVS_UNUSED
, char *argv
[])
611 struct ovsdb_table_schema
*ts
;
612 bool default_is_root
;
615 default_is_root
= argc
> 3 && !strcmp(argv
[3], "true");
617 json
= parse_json(argv
[2]);
618 check_ovsdb_error(ovsdb_table_schema_from_json(json
, argv
[1], &ts
));
620 print_and_free_json(ovsdb_table_schema_to_json(ts
, default_is_root
));
621 ovsdb_table_schema_destroy(ts
);
625 do_parse_rows(int argc
, char *argv
[])
627 struct ovsdb_column_set all_columns
;
628 struct ovsdb_table_schema
*ts
;
629 struct ovsdb_table
*table
;
633 json
= unbox_json(parse_json(argv
[1]));
634 check_ovsdb_error(ovsdb_table_schema_from_json(json
, "mytable", &ts
));
637 table
= ovsdb_table_create(ts
);
638 ovsdb_column_set_init(&all_columns
);
639 ovsdb_column_set_add_all(&all_columns
, table
);
641 for (i
= 2; i
< argc
; i
++) {
642 struct ovsdb_column_set columns
;
643 struct ovsdb_row
*row
;
645 ovsdb_column_set_init(&columns
);
646 row
= ovsdb_row_create(table
);
648 json
= unbox_json(parse_json(argv
[i
]));
649 check_ovsdb_error(ovsdb_row_from_json(row
, json
, NULL
, &columns
));
652 print_and_free_json(ovsdb_row_to_json(row
, &all_columns
));
654 if (columns
.n_columns
) {
660 for (j
= 0; j
< columns
.n_columns
; j
++) {
661 svec_add(&names
, columns
.columns
[j
]->name
);
664 s
= svec_join(&names
, ", ", "");
667 svec_destroy(&names
);
672 ovsdb_column_set_destroy(&columns
);
673 ovsdb_row_destroy(row
);
676 ovsdb_column_set_destroy(&all_columns
);
677 ovsdb_table_destroy(table
); /* Also destroys 'ts'. */
681 do_compare_rows(int argc
, char *argv
[])
683 struct ovsdb_column_set all_columns
;
684 struct ovsdb_table_schema
*ts
;
685 struct ovsdb_table
*table
;
686 struct ovsdb_row
**rows
;
692 json
= unbox_json(parse_json(argv
[1]));
693 check_ovsdb_error(ovsdb_table_schema_from_json(json
, "mytable", &ts
));
696 table
= ovsdb_table_create(ts
);
697 ovsdb_column_set_init(&all_columns
);
698 ovsdb_column_set_add_all(&all_columns
, table
);
701 rows
= xmalloc(sizeof *rows
* n_rows
);
702 names
= xmalloc(sizeof *names
* n_rows
);
703 for (i
= 0; i
< n_rows
; i
++) {
704 rows
[i
] = ovsdb_row_create(table
);
706 json
= parse_json(argv
[i
+ 2]);
707 if (json
->type
!= JSON_ARRAY
|| json
->u
.array
.n
!= 2
708 || json
->u
.array
.elems
[0]->type
!= JSON_STRING
) {
709 ovs_fatal(0, "\"%s\" does not have expected form "
710 "[\"name\", {data}]", argv
[i
]);
712 names
[i
] = xstrdup(json
->u
.array
.elems
[0]->u
.string
);
713 check_ovsdb_error(ovsdb_row_from_json(rows
[i
], json
->u
.array
.elems
[1],
717 for (i
= 0; i
< n_rows
; i
++) {
718 uint32_t i_hash
= ovsdb_row_hash_columns(rows
[i
], &all_columns
, 0);
719 for (j
= i
+ 1; j
< n_rows
; j
++) {
720 uint32_t j_hash
= ovsdb_row_hash_columns(rows
[j
], &all_columns
, 0);
721 if (ovsdb_row_equal_columns(rows
[i
], rows
[j
], &all_columns
)) {
722 printf("%s == %s\n", names
[i
], names
[j
]);
723 if (i_hash
!= j_hash
) {
724 printf("but hash(%s) != hash(%s)\n", names
[i
], names
[j
]);
727 } else if (i_hash
== j_hash
) {
728 printf("hash(%s) == hash(%s)\n", names
[i
], names
[j
]);
732 for (i
= 0; i
< n_rows
; i
++) {
733 ovsdb_row_destroy(rows
[i
]);
739 ovsdb_column_set_destroy(&all_columns
);
740 ovsdb_table_destroy(table
); /* Also destroys 'ts'. */
744 do_parse_conditions(int argc
, char *argv
[])
746 struct ovsdb_table_schema
*ts
;
751 json
= unbox_json(parse_json(argv
[1]));
752 check_ovsdb_error(ovsdb_table_schema_from_json(json
, "mytable", &ts
));
755 for (i
= 2; i
< argc
; i
++) {
756 struct ovsdb_condition cnd
;
757 struct ovsdb_error
*error
;
759 json
= parse_json(argv
[i
]);
760 error
= ovsdb_condition_from_json(ts
, json
, NULL
, &cnd
);
762 print_and_free_json(ovsdb_condition_to_json(&cnd
));
764 char *s
= ovsdb_error_to_string(error
);
765 ovs_error(0, "%s", s
);
767 ovsdb_error_destroy(error
);
772 ovsdb_condition_destroy(&cnd
);
774 ovsdb_table_schema_destroy(ts
);
780 do_evaluate_conditions(int argc OVS_UNUSED
, char *argv
[])
782 struct ovsdb_table_schema
*ts
;
783 struct ovsdb_table
*table
;
784 struct ovsdb_condition
*conditions
;
786 struct ovsdb_row
**rows
;
791 /* Parse table schema, create table. */
792 json
= unbox_json(parse_json(argv
[1]));
793 check_ovsdb_error(ovsdb_table_schema_from_json(json
, "mytable", &ts
));
796 table
= ovsdb_table_create(ts
);
798 /* Parse conditions. */
799 json
= parse_json(argv
[2]);
800 if (json
->type
!= JSON_ARRAY
) {
801 ovs_fatal(0, "CONDITION argument is not JSON array");
803 n_conditions
= json
->u
.array
.n
;
804 conditions
= xmalloc(n_conditions
* sizeof *conditions
);
805 for (i
= 0; i
< n_conditions
; i
++) {
806 check_ovsdb_error(ovsdb_condition_from_json(ts
, json
->u
.array
.elems
[i
],
807 NULL
, &conditions
[i
]));
812 json
= parse_json(argv
[3]);
813 if (json
->type
!= JSON_ARRAY
) {
814 ovs_fatal(0, "ROW argument is not JSON array");
816 n_rows
= json
->u
.array
.n
;
817 rows
= xmalloc(n_rows
* sizeof *rows
);
818 for (i
= 0; i
< n_rows
; i
++) {
819 rows
[i
] = ovsdb_row_create(table
);
820 check_ovsdb_error(ovsdb_row_from_json(rows
[i
], json
->u
.array
.elems
[i
],
825 for (i
= 0; i
< n_conditions
; i
++) {
826 printf("condition %2zu:", i
);
827 for (j
= 0; j
< n_rows
; j
++) {
828 bool result
= ovsdb_condition_evaluate(rows
[j
], &conditions
[i
]);
832 putchar(result
? 'T' : '-');
837 for (i
= 0; i
< n_conditions
; i
++) {
838 ovsdb_condition_destroy(&conditions
[i
]);
841 for (i
= 0; i
< n_rows
; i
++) {
842 ovsdb_row_destroy(rows
[i
]);
845 ovsdb_table_destroy(table
); /* Also destroys 'ts'. */
849 do_parse_mutations(int argc
, char *argv
[])
851 struct ovsdb_table_schema
*ts
;
856 json
= unbox_json(parse_json(argv
[1]));
857 check_ovsdb_error(ovsdb_table_schema_from_json(json
, "mytable", &ts
));
860 for (i
= 2; i
< argc
; i
++) {
861 struct ovsdb_mutation_set set
;
862 struct ovsdb_error
*error
;
864 json
= parse_json(argv
[i
]);
865 error
= ovsdb_mutation_set_from_json(ts
, json
, NULL
, &set
);
867 print_and_free_json(ovsdb_mutation_set_to_json(&set
));
869 char *s
= ovsdb_error_to_string(error
);
870 ovs_error(0, "%s", s
);
872 ovsdb_error_destroy(error
);
877 ovsdb_mutation_set_destroy(&set
);
879 ovsdb_table_schema_destroy(ts
);
885 do_execute_mutations(int argc OVS_UNUSED
, char *argv
[])
887 struct ovsdb_table_schema
*ts
;
888 struct ovsdb_table
*table
;
889 struct ovsdb_mutation_set
*sets
;
891 struct ovsdb_row
**rows
;
896 /* Parse table schema, create table. */
897 json
= unbox_json(parse_json(argv
[1]));
898 check_ovsdb_error(ovsdb_table_schema_from_json(json
, "mytable", &ts
));
901 table
= ovsdb_table_create(ts
);
903 /* Parse mutations. */
904 json
= parse_json(argv
[2]);
905 if (json
->type
!= JSON_ARRAY
) {
906 ovs_fatal(0, "MUTATION argument is not JSON array");
908 n_sets
= json
->u
.array
.n
;
909 sets
= xmalloc(n_sets
* sizeof *sets
);
910 for (i
= 0; i
< n_sets
; i
++) {
911 check_ovsdb_error(ovsdb_mutation_set_from_json(ts
,
912 json
->u
.array
.elems
[i
],
918 json
= parse_json(argv
[3]);
919 if (json
->type
!= JSON_ARRAY
) {
920 ovs_fatal(0, "ROW argument is not JSON array");
922 n_rows
= json
->u
.array
.n
;
923 rows
= xmalloc(n_rows
* sizeof *rows
);
924 for (i
= 0; i
< n_rows
; i
++) {
925 rows
[i
] = ovsdb_row_create(table
);
926 check_ovsdb_error(ovsdb_row_from_json(rows
[i
], json
->u
.array
.elems
[i
],
931 for (i
= 0; i
< n_sets
; i
++) {
932 printf("mutation %2zu:\n", i
);
933 for (j
= 0; j
< n_rows
; j
++) {
934 struct ovsdb_error
*error
;
935 struct ovsdb_row
*row
;
937 row
= ovsdb_row_clone(rows
[j
]);
938 error
= ovsdb_mutation_set_execute(row
, &sets
[i
]);
940 printf("row %zu: ", j
);
942 print_and_free_ovsdb_error(error
);
944 struct ovsdb_column_set columns
;
945 struct shash_node
*node
;
947 ovsdb_column_set_init(&columns
);
948 SHASH_FOR_EACH (node
, &ts
->columns
) {
949 struct ovsdb_column
*c
= node
->data
;
950 if (!ovsdb_datum_equals(&row
->fields
[c
->index
],
951 &rows
[j
]->fields
[c
->index
],
953 ovsdb_column_set_add(&columns
, c
);
956 if (columns
.n_columns
) {
957 print_and_free_json(ovsdb_row_to_json(row
, &columns
));
959 printf("no change\n");
961 ovsdb_column_set_destroy(&columns
);
963 ovsdb_row_destroy(row
);
968 for (i
= 0; i
< n_sets
; i
++) {
969 ovsdb_mutation_set_destroy(&sets
[i
]);
972 for (i
= 0; i
< n_rows
; i
++) {
973 ovsdb_row_destroy(rows
[i
]);
976 ovsdb_table_destroy(table
); /* Also destroys 'ts'. */
979 /* Inserts a row, without bothering to update metadata such as refcounts. */
981 put_row(struct ovsdb_table
*table
, struct ovsdb_row
*row
)
983 const struct uuid
*uuid
= ovsdb_row_get_uuid(row
);
984 if (!ovsdb_table_get_row(table
, uuid
)) {
985 hmap_insert(&table
->rows
, &row
->hmap_node
, uuid_hash(uuid
));
989 struct do_query_cbdata
{
990 struct uuid
*row_uuids
;
996 do_query_cb(const struct ovsdb_row
*row
, void *cbdata_
)
998 struct do_query_cbdata
*cbdata
= cbdata_
;
1001 for (i
= 0; i
< cbdata
->n_rows
; i
++) {
1002 if (uuid_equals(ovsdb_row_get_uuid(row
), &cbdata
->row_uuids
[i
])) {
1003 cbdata
->counts
[i
]++;
1011 do_query(int argc OVS_UNUSED
, char *argv
[])
1013 struct do_query_cbdata cbdata
;
1014 struct ovsdb_table_schema
*ts
;
1015 struct ovsdb_table
*table
;
1020 /* Parse table schema, create table. */
1021 json
= unbox_json(parse_json(argv
[1]));
1022 check_ovsdb_error(ovsdb_table_schema_from_json(json
, "mytable", &ts
));
1025 table
= ovsdb_table_create(ts
);
1027 /* Parse rows, add to table. */
1028 json
= parse_json(argv
[2]);
1029 if (json
->type
!= JSON_ARRAY
) {
1030 ovs_fatal(0, "ROW argument is not JSON array");
1032 cbdata
.n_rows
= json
->u
.array
.n
;
1033 cbdata
.row_uuids
= xmalloc(cbdata
.n_rows
* sizeof *cbdata
.row_uuids
);
1034 cbdata
.counts
= xmalloc(cbdata
.n_rows
* sizeof *cbdata
.counts
);
1035 for (i
= 0; i
< cbdata
.n_rows
; i
++) {
1036 struct ovsdb_row
*row
= ovsdb_row_create(table
);
1037 uuid_generate(ovsdb_row_get_uuid_rw(row
));
1038 check_ovsdb_error(ovsdb_row_from_json(row
, json
->u
.array
.elems
[i
],
1040 if (ovsdb_table_get_row(table
, ovsdb_row_get_uuid(row
))) {
1041 ovs_fatal(0, "duplicate UUID "UUID_FMT
" in table",
1042 UUID_ARGS(ovsdb_row_get_uuid(row
)));
1044 cbdata
.row_uuids
[i
] = *ovsdb_row_get_uuid(row
);
1045 put_row(table
, row
);
1049 /* Parse conditions and execute queries. */
1050 json
= parse_json(argv
[3]);
1051 if (json
->type
!= JSON_ARRAY
) {
1052 ovs_fatal(0, "CONDITION argument is not JSON array");
1054 for (i
= 0; i
< json
->u
.array
.n
; i
++) {
1055 struct ovsdb_condition cnd
;
1058 check_ovsdb_error(ovsdb_condition_from_json(ts
, json
->u
.array
.elems
[i
],
1061 memset(cbdata
.counts
, 0, cbdata
.n_rows
* sizeof *cbdata
.counts
);
1062 ovsdb_query(table
, &cnd
, do_query_cb
, &cbdata
);
1064 printf("query %2zu:", i
);
1065 for (j
= 0; j
< cbdata
.n_rows
; j
++) {
1069 if (cbdata
.counts
[j
]) {
1070 printf("%d", cbdata
.counts
[j
]);
1071 if (cbdata
.counts
[j
] > 1) {
1081 ovsdb_condition_destroy(&cnd
);
1085 ovsdb_table_destroy(table
); /* Also destroys 'ts'. */
1090 struct do_query_distinct_class
{
1091 struct ovsdb_row
*example
;
1095 struct do_query_distinct_row
{
1097 struct do_query_distinct_class
*class;
1101 do_query_distinct(int argc OVS_UNUSED
, char *argv
[])
1103 struct ovsdb_column_set columns
;
1104 struct ovsdb_table_schema
*ts
;
1105 struct ovsdb_table
*table
;
1106 struct do_query_distinct_row
*rows
;
1108 struct do_query_distinct_class
*classes
;
1114 /* Parse table schema, create table. */
1115 json
= unbox_json(parse_json(argv
[1]));
1116 check_ovsdb_error(ovsdb_table_schema_from_json(json
, "mytable", &ts
));
1119 table
= ovsdb_table_create(ts
);
1121 /* Parse column set. */
1122 json
= parse_json(argv
[4]);
1123 check_ovsdb_error(ovsdb_column_set_from_json(json
, table
->schema
,
1127 /* Parse rows, add to table. */
1128 json
= parse_json(argv
[2]);
1129 if (json
->type
!= JSON_ARRAY
) {
1130 ovs_fatal(0, "ROW argument is not JSON array");
1132 n_rows
= json
->u
.array
.n
;
1133 rows
= xmalloc(n_rows
* sizeof *rows
);
1134 classes
= xmalloc(n_rows
* sizeof *classes
);
1136 for (i
= 0; i
< n_rows
; i
++) {
1137 struct ovsdb_row
*row
;
1141 row
= ovsdb_row_create(table
);
1142 uuid_generate(ovsdb_row_get_uuid_rw(row
));
1143 check_ovsdb_error(ovsdb_row_from_json(row
, json
->u
.array
.elems
[i
],
1146 /* Initialize row and find equivalence class. */
1147 rows
[i
].uuid
= *ovsdb_row_get_uuid(row
);
1148 rows
[i
].class = NULL
;
1149 for (j
= 0; j
< n_classes
; j
++) {
1150 if (ovsdb_row_equal_columns(row
, classes
[j
].example
, &columns
)) {
1151 rows
[i
].class = &classes
[j
];
1155 if (!rows
[i
].class) {
1156 rows
[i
].class = &classes
[n_classes
];
1157 classes
[n_classes
].example
= ovsdb_row_clone(row
);
1161 /* Add row to table. */
1162 if (ovsdb_table_get_row(table
, ovsdb_row_get_uuid(row
))) {
1163 ovs_fatal(0, "duplicate UUID "UUID_FMT
" in table",
1164 UUID_ARGS(ovsdb_row_get_uuid(row
)));
1166 put_row(table
, row
);
1171 /* Parse conditions and execute queries. */
1172 json
= parse_json(argv
[3]);
1173 if (json
->type
!= JSON_ARRAY
) {
1174 ovs_fatal(0, "CONDITION argument is not JSON array");
1176 for (i
= 0; i
< json
->u
.array
.n
; i
++) {
1177 struct ovsdb_row_set results
;
1178 struct ovsdb_condition cnd
;
1181 check_ovsdb_error(ovsdb_condition_from_json(ts
, json
->u
.array
.elems
[i
],
1184 for (j
= 0; j
< n_classes
; j
++) {
1185 classes
[j
].count
= 0;
1187 ovsdb_row_set_init(&results
);
1188 ovsdb_query_distinct(table
, &cnd
, &columns
, &results
);
1189 for (j
= 0; j
< results
.n_rows
; j
++) {
1192 for (k
= 0; k
< n_rows
; k
++) {
1193 if (uuid_equals(ovsdb_row_get_uuid(results
.rows
[j
]),
1195 rows
[k
].class->count
++;
1199 ovsdb_row_set_destroy(&results
);
1201 printf("query %2zu:", i
);
1202 for (j
= 0; j
< n_rows
; j
++) {
1203 int count
= rows
[j
].class->count
;
1210 printf("%d", count
);
1212 } else if (count
== 1) {
1213 putchar("abcdefghijklmnopqrstuvwxyz"[rows
[j
].class - classes
]);
1220 ovsdb_condition_destroy(&cnd
);
1224 ovsdb_table_destroy(table
); /* Also destroys 'ts'. */
1230 do_parse_schema(int argc OVS_UNUSED
, char *argv
[])
1232 struct ovsdb_schema
*schema
;
1235 json
= parse_json(argv
[1]);
1236 check_ovsdb_error(ovsdb_schema_from_json(json
, &schema
));
1238 print_and_free_json(ovsdb_schema_to_json(schema
));
1239 ovsdb_schema_destroy(schema
);
1243 do_execute(int argc OVS_UNUSED
, char *argv
[])
1245 struct ovsdb_schema
*schema
;
1250 /* Create database. */
1251 json
= parse_json(argv
[1]);
1252 check_ovsdb_error(ovsdb_schema_from_json(json
, &schema
));
1254 db
= ovsdb_create(schema
);
1256 for (i
= 2; i
< argc
; i
++) {
1257 struct json
*params
, *result
;
1260 params
= parse_json(argv
[i
]);
1261 result
= ovsdb_execute(db
, NULL
, params
, 0, NULL
);
1262 s
= json_to_string(result
, JSSF_SORT
);
1265 json_destroy(params
);
1266 json_destroy(result
);
1272 struct test_trigger
{
1273 struct ovsdb_trigger trigger
;
1278 do_trigger_dump(struct test_trigger
*t
, long long int now
, const char *title
)
1280 struct json
*result
;
1283 result
= ovsdb_trigger_steal_result(&t
->trigger
);
1284 s
= json_to_string(result
, JSSF_SORT
);
1285 printf("t=%lld: trigger %d (%s): %s\n", now
, t
->number
, title
, s
);
1287 json_destroy(result
);
1288 ovsdb_trigger_destroy(&t
->trigger
);
1293 do_trigger(int argc OVS_UNUSED
, char *argv
[])
1295 struct ovsdb_schema
*schema
;
1296 struct ovsdb_session session
;
1303 /* Create database. */
1304 json
= parse_json(argv
[1]);
1305 check_ovsdb_error(ovsdb_schema_from_json(json
, &schema
));
1307 db
= ovsdb_create(schema
);
1309 ovsdb_session_init(&session
, db
);
1313 for (i
= 2; i
< argc
; i
++) {
1314 struct json
*params
= parse_json(argv
[i
]);
1315 if (params
->type
== JSON_ARRAY
1316 && json_array(params
)->n
== 2
1317 && json_array(params
)->elems
[0]->type
== JSON_STRING
1318 && !strcmp(json_string(json_array(params
)->elems
[0]), "advance")
1319 && json_array(params
)->elems
[1]->type
== JSON_INTEGER
) {
1320 now
+= json_integer(json_array(params
)->elems
[1]);
1321 json_destroy(params
);
1323 struct test_trigger
*t
= xmalloc(sizeof *t
);
1324 ovsdb_trigger_init(&session
, &t
->trigger
, params
, now
);
1325 t
->number
= number
++;
1326 if (ovsdb_trigger_is_complete(&t
->trigger
)) {
1327 do_trigger_dump(t
, now
, "immediate");
1329 printf("t=%lld: new trigger %d\n", now
, t
->number
);
1333 ovsdb_trigger_run(db
, now
);
1334 while (!list_is_empty(&session
.completions
)) {
1335 do_trigger_dump(CONTAINER_OF(list_pop_front(&session
.completions
),
1336 struct test_trigger
, trigger
.node
),
1340 ovsdb_trigger_wait(db
, now
);
1341 poll_immediate_wake();
1349 do_help(int argc OVS_UNUSED
, char *argv
[] OVS_UNUSED
)
1354 /* "transact" command. */
1356 static struct ovsdb
*do_transact_db
;
1357 static struct ovsdb_txn
*do_transact_txn
;
1358 static struct ovsdb_table
*do_transact_table
;
1361 do_transact_commit(int argc OVS_UNUSED
, char *argv
[] OVS_UNUSED
)
1363 ovsdb_error_destroy(ovsdb_txn_commit(do_transact_txn
, false));
1364 do_transact_txn
= NULL
;
1368 do_transact_abort(int argc OVS_UNUSED
, char *argv
[] OVS_UNUSED
)
1370 ovsdb_txn_abort(do_transact_txn
);
1371 do_transact_txn
= NULL
;
1375 uuid_from_integer(int integer
, struct uuid
*uuid
)
1378 uuid
->parts
[3] = integer
;
1381 static const struct ovsdb_row
*
1382 do_transact_find_row(const char *uuid_string
)
1384 const struct ovsdb_row
*row
;
1387 uuid_from_integer(atoi(uuid_string
), &uuid
);
1388 row
= ovsdb_table_get_row(do_transact_table
, &uuid
);
1390 ovs_fatal(0, "table does not contain row with UUID "UUID_FMT
,
1397 do_transact_set_integer(struct ovsdb_row
*row
, const char *column_name
,
1400 if (integer
!= -1) {
1401 const struct ovsdb_column
*column
;
1403 column
= ovsdb_table_schema_get_column(do_transact_table
->schema
,
1405 row
->fields
[column
->index
].keys
[0].integer
= integer
;
1410 do_transact_get_integer(const struct ovsdb_row
*row
, const char *column_name
)
1412 const struct ovsdb_column
*column
;
1414 column
= ovsdb_table_schema_get_column(do_transact_table
->schema
,
1416 return row
->fields
[column
->index
].keys
[0].integer
;
1420 do_transact_set_i_j(struct ovsdb_row
*row
,
1421 const char *i_string
, const char *j_string
)
1423 do_transact_set_integer(row
, "i", atoi(i_string
));
1424 do_transact_set_integer(row
, "j", atoi(j_string
));
1428 do_transact_insert(int argc OVS_UNUSED
, char *argv
[] OVS_UNUSED
)
1430 struct ovsdb_row
*row
;
1433 row
= ovsdb_row_create(do_transact_table
);
1436 uuid
= ovsdb_row_get_uuid_rw(row
);
1437 uuid_from_integer(atoi(argv
[1]), uuid
);
1438 if (ovsdb_table_get_row(do_transact_table
, uuid
)) {
1439 ovs_fatal(0, "table already contains row with UUID "UUID_FMT
,
1443 do_transact_set_i_j(row
, argv
[2], argv
[3]);
1446 ovsdb_txn_row_insert(do_transact_txn
, row
);
1450 do_transact_delete(int argc OVS_UNUSED
, char *argv
[] OVS_UNUSED
)
1452 const struct ovsdb_row
*row
= do_transact_find_row(argv
[1]);
1453 ovsdb_txn_row_delete(do_transact_txn
, row
);
1457 do_transact_modify(int argc OVS_UNUSED
, char *argv
[] OVS_UNUSED
)
1459 const struct ovsdb_row
*row_ro
;
1460 struct ovsdb_row
*row_rw
;
1462 row_ro
= do_transact_find_row(argv
[1]);
1463 row_rw
= ovsdb_txn_row_modify(do_transact_txn
, row_ro
);
1464 do_transact_set_i_j(row_rw
, argv
[2], argv
[3]);
1468 compare_rows_by_uuid(const void *a_
, const void *b_
)
1470 struct ovsdb_row
*const *ap
= a_
;
1471 struct ovsdb_row
*const *bp
= b_
;
1473 return uuid_compare_3way(ovsdb_row_get_uuid(*ap
), ovsdb_row_get_uuid(*bp
));
1477 do_transact_print(int argc OVS_UNUSED
, char *argv
[] OVS_UNUSED
)
1479 const struct ovsdb_row
**rows
;
1480 const struct ovsdb_row
*row
;
1484 n_rows
= hmap_count(&do_transact_table
->rows
);
1485 rows
= xmalloc(n_rows
* sizeof *rows
);
1487 HMAP_FOR_EACH (row
, hmap_node
, &do_transact_table
->rows
) {
1490 assert(i
== n_rows
);
1492 qsort(rows
, n_rows
, sizeof *rows
, compare_rows_by_uuid
);
1494 for (i
= 0; i
< n_rows
; i
++) {
1495 printf("\n%"PRId32
": i=%d, j=%d",
1496 ovsdb_row_get_uuid(rows
[i
])->parts
[3],
1497 do_transact_get_integer(rows
[i
], "i"),
1498 do_transact_get_integer(rows
[i
], "j"));
1505 do_transact(int argc
, char *argv
[])
1507 static const struct command do_transact_commands
[] = {
1508 { "commit", 0, 0, do_transact_commit
},
1509 { "abort", 0, 0, do_transact_abort
},
1510 { "insert", 2, 3, do_transact_insert
},
1511 { "delete", 1, 1, do_transact_delete
},
1512 { "modify", 2, 3, do_transact_modify
},
1513 { "print", 0, 0, do_transact_print
},
1514 { NULL
, 0, 0, NULL
},
1517 struct ovsdb_schema
*schema
;
1522 json
= parse_json("{\"name\": \"testdb\", "
1526 " {\"i\": {\"type\": \"integer\"}, "
1527 " \"j\": {\"type\": \"integer\"}}}}}");
1528 check_ovsdb_error(ovsdb_schema_from_json(json
, &schema
));
1530 do_transact_db
= ovsdb_create(schema
);
1531 do_transact_table
= ovsdb_get_table(do_transact_db
, "mytable");
1532 assert(do_transact_table
!= NULL
);
1534 for (i
= 1; i
< argc
; i
++) {
1535 struct json
*command
;
1540 command
= parse_json(argv
[i
]);
1541 if (command
->type
!= JSON_ARRAY
) {
1542 ovs_fatal(0, "transaction %d must be JSON array "
1543 "with at least 1 element", i
);
1546 n_args
= command
->u
.array
.n
;
1547 args
= xmalloc((n_args
+ 1) * sizeof *args
);
1548 for (j
= 0; j
< n_args
; j
++) {
1549 struct json
*s
= command
->u
.array
.elems
[j
];
1550 if (s
->type
!= JSON_STRING
) {
1551 ovs_fatal(0, "transaction %d argument %d must be JSON string",
1554 args
[j
] = xstrdup(json_string(s
));
1556 args
[n_args
] = NULL
;
1558 if (!do_transact_txn
) {
1559 do_transact_txn
= ovsdb_txn_create(do_transact_db
);
1562 for (j
= 0; j
< n_args
; j
++) {
1566 fputs(args
[j
], stdout
);
1569 run_command(n_args
, args
, do_transact_commands
);
1572 for (j
= 0; j
< n_args
; j
++) {
1576 json_destroy(command
);
1578 ovsdb_txn_abort(do_transact_txn
);
1579 ovsdb_destroy(do_transact_db
); /* Also destroys 'schema'. */
1583 compare_link1(const void *a_
, const void *b_
)
1585 const struct idltest_link1
*const *ap
= a_
;
1586 const struct idltest_link1
*const *bp
= b_
;
1587 const struct idltest_link1
*a
= *ap
;
1588 const struct idltest_link1
*b
= *bp
;
1590 return a
->i
< b
->i
? -1 : a
->i
> b
->i
;
1594 print_idl(struct ovsdb_idl
*idl
, int step
)
1596 const struct idltest_simple
*s
;
1597 const struct idltest_link1
*l1
;
1598 const struct idltest_link2
*l2
;
1601 IDLTEST_SIMPLE_FOR_EACH (s
, idl
) {
1604 printf("%03d: i=%"PRId64
" r=%g b=%s s=%s u="UUID_FMT
" ia=[",
1605 step
, s
->i
, s
->r
, s
->b
? "true" : "false",
1606 s
->s
, UUID_ARGS(&s
->u
));
1607 for (i
= 0; i
< s
->n_ia
; i
++) {
1608 printf("%s%"PRId64
, i
? " " : "", s
->ia
[i
]);
1611 for (i
= 0; i
< s
->n_ra
; i
++) {
1612 printf("%s%g", i
? " " : "", s
->ra
[i
]);
1615 for (i
= 0; i
< s
->n_ba
; i
++) {
1616 printf("%s%s", i
? " " : "", s
->ba
[i
] ? "true" : "false");
1619 for (i
= 0; i
< s
->n_sa
; i
++) {
1620 printf("%s%s", i
? " " : "", s
->sa
[i
]);
1623 for (i
= 0; i
< s
->n_ua
; i
++) {
1624 printf("%s"UUID_FMT
, i
? " " : "", UUID_ARGS(&s
->ua
[i
]));
1626 printf("] uuid="UUID_FMT
"\n", UUID_ARGS(&s
->header_
.uuid
));
1629 IDLTEST_LINK1_FOR_EACH (l1
, idl
) {
1630 struct idltest_link1
**links
;
1633 printf("%03d: i=%"PRId64
" k=", step
, l1
->i
);
1635 printf("%"PRId64
, l1
->k
->i
);
1638 links
= xmemdup(l1
->ka
, l1
->n_ka
* sizeof *l1
->ka
);
1639 qsort(links
, l1
->n_ka
, sizeof *links
, compare_link1
);
1640 for (i
= 0; i
< l1
->n_ka
; i
++) {
1641 printf("%s%"PRId64
, i
? " " : "", links
[i
]->i
);
1646 printf("%"PRId64
, l1
->l2
->i
);
1648 printf(" uuid="UUID_FMT
"\n", UUID_ARGS(&l1
->header_
.uuid
));
1651 IDLTEST_LINK2_FOR_EACH (l2
, idl
) {
1652 printf("%03d: i=%"PRId64
" l1=", step
, l2
->i
);
1654 printf("%"PRId64
, l2
->l1
->i
);
1656 printf(" uuid="UUID_FMT
"\n", UUID_ARGS(&l2
->header_
.uuid
));
1660 printf("%03d: empty\n", step
);
1665 parse_uuids(const struct json
*json
, struct ovsdb_symbol_table
*symtab
,
1670 if (json
->type
== JSON_STRING
&& uuid_from_string(&uuid
, json
->u
.string
)) {
1671 char *name
= xasprintf("#%zu#", *n
);
1672 fprintf(stderr
, "%s = "UUID_FMT
"\n", name
, UUID_ARGS(&uuid
));
1673 ovsdb_symbol_table_put(symtab
, name
, &uuid
, false);
1676 } else if (json
->type
== JSON_ARRAY
) {
1679 for (i
= 0; i
< json
->u
.array
.n
; i
++) {
1680 parse_uuids(json
->u
.array
.elems
[i
], symtab
, n
);
1682 } else if (json
->type
== JSON_OBJECT
) {
1683 const struct shash_node
*node
;
1685 SHASH_FOR_EACH (node
, json_object(json
)) {
1686 parse_uuids(node
->data
, symtab
, n
);
1692 substitute_uuids(struct json
*json
, const struct ovsdb_symbol_table
*symtab
)
1694 if (json
->type
== JSON_STRING
) {
1695 const struct ovsdb_symbol
*symbol
;
1697 symbol
= ovsdb_symbol_table_get(symtab
, json
->u
.string
);
1699 free(json
->u
.string
);
1700 json
->u
.string
= xasprintf(UUID_FMT
, UUID_ARGS(&symbol
->uuid
));
1702 } else if (json
->type
== JSON_ARRAY
) {
1705 for (i
= 0; i
< json
->u
.array
.n
; i
++) {
1706 substitute_uuids(json
->u
.array
.elems
[i
], symtab
);
1708 } else if (json
->type
== JSON_OBJECT
) {
1709 const struct shash_node
*node
;
1711 SHASH_FOR_EACH (node
, json_object(json
)) {
1712 substitute_uuids(node
->data
, symtab
);
1717 static const struct idltest_simple
*
1718 idltest_find_simple(struct ovsdb_idl
*idl
, int i
)
1720 const struct idltest_simple
*s
;
1722 IDLTEST_SIMPLE_FOR_EACH (s
, idl
) {
1731 idl_set(struct ovsdb_idl
*idl
, char *commands
, int step
)
1733 char *cmd
, *save_ptr1
= NULL
;
1734 struct ovsdb_idl_txn
*txn
;
1735 enum ovsdb_idl_txn_status status
;
1736 bool increment
= false;
1738 txn
= ovsdb_idl_txn_create(idl
);
1739 for (cmd
= strtok_r(commands
, ",", &save_ptr1
); cmd
;
1740 cmd
= strtok_r(NULL
, ",", &save_ptr1
)) {
1741 char *save_ptr2
= NULL
;
1742 char *name
, *arg1
, *arg2
, *arg3
;
1744 name
= strtok_r(cmd
, " ", &save_ptr2
);
1745 arg1
= strtok_r(NULL
, " ", &save_ptr2
);
1746 arg2
= strtok_r(NULL
, " ", &save_ptr2
);
1747 arg3
= strtok_r(NULL
, " ", &save_ptr2
);
1749 if (!strcmp(name
, "set")) {
1750 const struct idltest_simple
*s
;
1753 ovs_fatal(0, "\"set\" command requires 3 arguments");
1756 s
= idltest_find_simple(idl
, atoi(arg1
));
1758 ovs_fatal(0, "\"set\" command asks for nonexistent "
1759 "i=%d", atoi(arg1
));
1762 if (!strcmp(arg2
, "b")) {
1763 idltest_simple_set_b(s
, atoi(arg3
));
1764 } else if (!strcmp(arg2
, "s")) {
1765 idltest_simple_set_s(s
, arg3
);
1766 } else if (!strcmp(arg2
, "u")) {
1768 if (!uuid_from_string(&uuid
, arg3
)) {
1769 ovs_fatal(0, "\"%s\" is not a valid UUID", arg3
);
1771 idltest_simple_set_u(s
, uuid
);
1772 } else if (!strcmp(arg2
, "r")) {
1773 idltest_simple_set_r(s
, atof(arg3
));
1775 ovs_fatal(0, "\"set\" command asks for unknown column %s",
1778 } else if (!strcmp(name
, "insert")) {
1779 struct idltest_simple
*s
;
1781 if (!arg1
|| arg2
) {
1782 ovs_fatal(0, "\"insert\" command requires 1 argument");
1785 s
= idltest_simple_insert(txn
);
1786 idltest_simple_set_i(s
, atoi(arg1
));
1787 } else if (!strcmp(name
, "delete")) {
1788 const struct idltest_simple
*s
;
1790 if (!arg1
|| arg2
) {
1791 ovs_fatal(0, "\"delete\" command requires 1 argument");
1794 s
= idltest_find_simple(idl
, atoi(arg1
));
1796 ovs_fatal(0, "\"delete\" command asks for nonexistent "
1797 "i=%d", atoi(arg1
));
1799 idltest_simple_delete(s
);
1800 } else if (!strcmp(name
, "verify")) {
1801 const struct idltest_simple
*s
;
1803 if (!arg2
|| arg3
) {
1804 ovs_fatal(0, "\"verify\" command requires 2 arguments");
1807 s
= idltest_find_simple(idl
, atoi(arg1
));
1809 ovs_fatal(0, "\"verify\" command asks for nonexistent "
1810 "i=%d", atoi(arg1
));
1813 if (!strcmp(arg2
, "i")) {
1814 idltest_simple_verify_i(s
);
1815 } else if (!strcmp(arg2
, "b")) {
1816 idltest_simple_verify_b(s
);
1817 } else if (!strcmp(arg2
, "s")) {
1818 idltest_simple_verify_s(s
);
1819 } else if (!strcmp(arg2
, "u")) {
1820 idltest_simple_verify_s(s
);
1821 } else if (!strcmp(arg2
, "r")) {
1822 idltest_simple_verify_r(s
);
1824 ovs_fatal(0, "\"verify\" command asks for unknown column %s",
1827 } else if (!strcmp(name
, "increment")) {
1828 const struct idltest_simple
*s
;
1830 if (!arg1
|| arg2
) {
1831 ovs_fatal(0, "\"increment\" command requires 1 argument");
1834 s
= idltest_find_simple(idl
, atoi(arg1
));
1836 ovs_fatal(0, "\"set\" command asks for nonexistent "
1837 "i=%d", atoi(arg1
));
1840 ovsdb_idl_txn_increment(txn
, &s
->header_
, &idltest_simple_col_i
);
1842 } else if (!strcmp(name
, "abort")) {
1843 ovsdb_idl_txn_abort(txn
);
1845 } else if (!strcmp(name
, "destroy")) {
1846 printf("%03d: destroy\n", step
);
1847 ovsdb_idl_txn_destroy(txn
);
1850 ovs_fatal(0, "unknown command %s", name
);
1854 status
= ovsdb_idl_txn_commit_block(txn
);
1855 printf("%03d: commit, status=%s",
1856 step
, ovsdb_idl_txn_status_to_string(status
));
1858 printf(", increment=%"PRId64
,
1859 ovsdb_idl_txn_get_increment_new_value(txn
));
1862 ovsdb_idl_txn_destroy(txn
);
1866 do_idl(int argc
, char *argv
[])
1868 struct jsonrpc
*rpc
;
1869 struct ovsdb_idl
*idl
;
1870 unsigned int seqno
= 0;
1871 struct ovsdb_symbol_table
*symtab
;
1879 idl
= ovsdb_idl_create(argv
[1], &idltest_idl_class
, true);
1881 struct stream
*stream
;
1883 error
= stream_open_block(jsonrpc_stream_open(argv
[1], &stream
,
1884 DSCP_DEFAULT
), &stream
);
1886 ovs_fatal(error
, "failed to connect to \"%s\"", argv
[1]);
1888 rpc
= jsonrpc_open(stream
);
1893 setvbuf(stdout
, NULL
, _IOLBF
, 0);
1895 symtab
= ovsdb_symbol_table_create();
1896 for (i
= 2; i
< argc
; i
++) {
1897 char *arg
= argv
[i
];
1898 struct jsonrpc_msg
*request
, *reply
;
1901 /* The previous transaction didn't change anything. */
1904 /* Wait for update. */
1907 if (ovsdb_idl_get_seqno(idl
) != seqno
) {
1912 ovsdb_idl_wait(idl
);
1918 print_idl(idl
, step
++);
1920 seqno
= ovsdb_idl_get_seqno(idl
);
1922 if (!strcmp(arg
, "reconnect")) {
1923 printf("%03d: reconnect\n", step
++);
1924 ovsdb_idl_force_reconnect(idl
);
1925 } else if (arg
[0] != '[') {
1926 idl_set(idl
, arg
, step
++);
1928 struct json
*json
= parse_json(arg
);
1929 substitute_uuids(json
, symtab
);
1930 request
= jsonrpc_create_request("transact", json
, NULL
);
1931 error
= jsonrpc_transact_block(rpc
, request
, &reply
);
1932 if (error
|| reply
->error
) {
1933 ovs_fatal(error
, "jsonrpc transaction failed");
1935 printf("%03d: ", step
++);
1936 if (reply
->result
) {
1937 parse_uuids(reply
->result
, symtab
, &n_uuids
);
1939 json_destroy(reply
->id
);
1941 print_and_free_json(jsonrpc_msg_to_json(reply
));
1944 ovsdb_symbol_table_destroy(symtab
);
1951 if (ovsdb_idl_get_seqno(idl
) != seqno
) {
1954 ovsdb_idl_wait(idl
);
1957 print_idl(idl
, step
++);
1958 ovsdb_idl_destroy(idl
);
1959 printf("%03d: done\n", step
);
1962 static struct command all_commands
[] = {
1963 { "log-io", 2, INT_MAX
, do_log_io
},
1964 { "default-atoms", 0, 0, do_default_atoms
},
1965 { "default-data", 0, 0, do_default_data
},
1966 { "parse-atomic-type", 1, 1, do_parse_atomic_type
},
1967 { "parse-base-type", 1, 1, do_parse_base_type
},
1968 { "parse-type", 1, 1, do_parse_type
},
1969 { "parse-atoms", 2, INT_MAX
, do_parse_atoms
},
1970 { "parse-atom-strings", 2, INT_MAX
, do_parse_atom_strings
},
1971 { "parse-data", 2, INT_MAX
, do_parse_data
},
1972 { "parse-data-strings", 2, INT_MAX
, do_parse_data_strings
},
1973 { "sort-atoms", 2, 2, do_sort_atoms
},
1974 { "parse-column", 2, 2, do_parse_column
},
1975 { "parse-table", 2, 3, do_parse_table
},
1976 { "parse-rows", 2, INT_MAX
, do_parse_rows
},
1977 { "compare-rows", 2, INT_MAX
, do_compare_rows
},
1978 { "parse-conditions", 2, INT_MAX
, do_parse_conditions
},
1979 { "evaluate-conditions", 3, 3, do_evaluate_conditions
},
1980 { "parse-mutations", 2, INT_MAX
, do_parse_mutations
},
1981 { "execute-mutations", 3, 3, do_execute_mutations
},
1982 { "query", 3, 3, do_query
},
1983 { "query-distinct", 4, 4, do_query_distinct
},
1984 { "transact", 1, INT_MAX
, do_transact
},
1985 { "parse-schema", 1, 1, do_parse_schema
},
1986 { "execute", 2, INT_MAX
, do_execute
},
1987 { "trigger", 2, INT_MAX
, do_trigger
},
1988 { "idl", 1, INT_MAX
, do_idl
},
1989 { "help", 0, INT_MAX
, do_help
},
1990 { NULL
, 0, 0, NULL
},