]> git.proxmox.com Git - ovs.git/blame - tests/test-ovsdb.c
System tests: Enable ALGs for userspace.
[ovs.git] / tests / test-ovsdb.c
CommitLineData
f85f8ebb 1/*
46437c52 2 * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2015, 2016, 2017 Nicira, Inc.
f85f8ebb
BP
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at:
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <config.h>
18
f85f8ebb
BP
19#include <fcntl.h>
20#include <getopt.h>
21#include <inttypes.h>
22#include <stdio.h>
23#include <stdlib.h>
24
f4248336 25#include "byte-order.h"
f85f8ebb 26#include "command-line.h"
3e8a2ad1 27#include "openvswitch/dynamic-string.h"
ee89ea7b 28#include "openvswitch/json.h"
c3bb4bd7 29#include "jsonrpc.h"
f85f8ebb
BP
30#include "ovsdb-data.h"
31#include "ovsdb-error.h"
c3bb4bd7 32#include "ovsdb-idl.h"
f85f8ebb
BP
33#include "ovsdb-types.h"
34#include "ovsdb/column.h"
35#include "ovsdb/condition.h"
bd06962a 36#include "ovsdb/file.h"
41709ccc 37#include "ovsdb/log.h"
e9f8f936 38#include "ovsdb/mutation.h"
f85f8ebb
BP
39#include "ovsdb/ovsdb.h"
40#include "ovsdb/query.h"
41#include "ovsdb/row.h"
e317253b 42#include "ovsdb/server.h"
f85f8ebb
BP
43#include "ovsdb/table.h"
44#include "ovsdb/transaction.h"
45#include "ovsdb/trigger.h"
46#include "poll-loop.h"
c3bb4bd7 47#include "stream.h"
f85f8ebb 48#include "svec.h"
c3bb4bd7 49#include "tests/idltest.h"
f85f8ebb
BP
50#include "timeval.h"
51#include "util.h"
e6211adc 52#include "openvswitch/vlog.h"
f85f8ebb 53
932104f4
SA
54struct test_ovsdb_pvt_context {
55 bool track;
56};
57
cab50449 58OVS_NO_RETURN static void usage(void);
932104f4
SA
59static void parse_options(int argc, char *argv[],
60 struct test_ovsdb_pvt_context *pvt);
5f383751 61static struct ovs_cmdl_command *get_all_commands(void);
f85f8ebb
BP
62
63int
64main(int argc, char *argv[])
65{
932104f4
SA
66 struct test_ovsdb_pvt_context pvt = {.track = false};
67 struct ovs_cmdl_context ctx = { .argc = 0, .pvt = &pvt};
f85f8ebb 68 set_program_name(argv[0]);
932104f4 69 parse_options(argc, argv, &pvt);
1636c761
RB
70 ctx.argc = argc - optind;
71 ctx.argv = argv + optind;
72 ovs_cmdl_run_command(&ctx, get_all_commands());
f85f8ebb
BP
73 return 0;
74}
75
76static void
932104f4 77parse_options(int argc, char *argv[], struct test_ovsdb_pvt_context *pvt)
f85f8ebb 78{
07fc4ed3 79 static const struct option long_options[] = {
e3c17733
BP
80 {"timeout", required_argument, NULL, 't'},
81 {"verbose", optional_argument, NULL, 'v'},
932104f4 82 {"change-track", optional_argument, NULL, 'c'},
e3c17733
BP
83 {"help", no_argument, NULL, 'h'},
84 {NULL, 0, NULL, 0},
f85f8ebb 85 };
5f383751 86 char *short_options = ovs_cmdl_long_options_to_short_options(long_options);
f85f8ebb
BP
87
88 for (;;) {
c3bb4bd7
BP
89 unsigned long int timeout;
90 int c;
91
92 c = getopt_long(argc, argv, short_options, long_options, NULL);
f85f8ebb
BP
93 if (c == -1) {
94 break;
95 }
96
97 switch (c) {
c3bb4bd7
BP
98 case 't':
99 timeout = strtoul(optarg, NULL, 10);
100 if (timeout <= 0) {
101 ovs_fatal(0, "value %s on -t or --timeout is not at least 1",
102 optarg);
103 } else {
104 time_alarm(timeout);
105 }
106 break;
107
f85f8ebb
BP
108 case 'h':
109 usage();
110
111 case 'v':
112 vlog_set_verbosity(optarg);
113 break;
114
932104f4
SA
115 case 'c':
116 pvt->track = true;
117 break;
118
f85f8ebb
BP
119 case '?':
120 exit(EXIT_FAILURE);
121
122 default:
123 abort();
124 }
125 }
126 free(short_options);
127}
128
129static void
130usage(void)
131{
132 printf("%s: Open vSwitch database test utility\n"
133 "usage: %s [OPTIONS] COMMAND [ARG...]\n\n"
41709ccc 134 " log-io FILE FLAGS COMMAND...\n"
f85f8ebb 135 " open FILE with FLAGS, run COMMANDs\n"
958ac03a
BP
136 " default-atoms\n"
137 " test ovsdb_atom_default()\n"
138 " default-data\n"
139 " test ovsdb_datum_default()\n"
f85f8ebb
BP
140 " parse-atomic-type TYPE\n"
141 " parse TYPE as OVSDB atomic type, and re-serialize\n"
bd76d25d
BP
142 " parse-base-type TYPE\n"
143 " parse TYPE as OVSDB base type, and re-serialize\n"
f85f8ebb
BP
144 " parse-type JSON\n"
145 " parse JSON as OVSDB type, and re-serialize\n"
146 " parse-atoms TYPE ATOM...\n"
5c414a2e
BP
147 " parse JSON ATOMs as atoms of TYPE, and re-serialize\n"
148 " parse-atom-strings TYPE ATOM...\n"
149 " parse string ATOMs as atoms of given TYPE, and re-serialize\n"
f85f8ebb 150 " sort-atoms TYPE ATOM...\n"
5c414a2e 151 " print JSON ATOMs in sorted order\n"
f85f8ebb 152 " parse-data TYPE DATUM...\n"
5c414a2e
BP
153 " parse JSON DATUMs as data of given TYPE, and re-serialize\n"
154 " parse-data-strings TYPE DATUM...\n"
155 " parse string DATUMs as data of given TYPE, and re-serialize\n"
f85f8ebb
BP
156 " parse-column NAME OBJECT\n"
157 " parse column NAME with info OBJECT, and re-serialize\n"
c5f341ab 158 " parse-table NAME OBJECT [DEFAULT-IS-ROOT]\n"
f85f8ebb
BP
159 " parse table NAME with info OBJECT\n"
160 " parse-row TABLE ROW..., and re-serialize\n"
161 " parse each ROW of defined TABLE\n"
162 " compare-row TABLE ROW...\n"
163 " mutually compare all of the ROWs, print those that are equal\n"
164 " parse-conditions TABLE CONDITION...\n"
165 " parse each CONDITION on TABLE, and re-serialize\n"
166 " evaluate-conditions TABLE [CONDITION,...] [ROW,...]\n"
167 " test CONDITIONS on TABLE against each ROW, print results\n"
ae9cab37
LS
168 " evaluate-conditions-any TABLE [CONDITION,...] [ROW,...]\n"
169 " test CONDITIONS to match any of the CONDITONS on TABLE\n"
170 " against each ROW, print results\n"
171 " compare-conditions TABLE [CONDITION,...]\n"
172 " mutually compare all of the CONDITION, print results for\n"
173 " each pair\n"
e9f8f936
BP
174 " parse-mutations TABLE MUTATION...\n"
175 " parse each MUTATION on TABLE, and re-serialize\n"
176 " execute-mutations TABLE [MUTATION,...] [ROW,...]\n"
177 " execute MUTATIONS on TABLE on each ROW, print results\n"
f85f8ebb
BP
178 " query TABLE [ROW,...] [CONDITION,...]\n"
179 " add each ROW to TABLE, then query and print the rows that\n"
180 " satisfy each CONDITION.\n"
181 " query-distinct TABLE [ROW,...] [CONDITION,...] COLUMNS\n"
182 " add each ROW to TABLE, then query and print the rows that\n"
183 " satisfy each CONDITION and have distinct COLUMNS.\n"
0d0f05b9
BP
184 " parse-schema JSON\n"
185 " parse JSON as an OVSDB schema, and re-serialize\n"
f85f8ebb
BP
186 " transact COMMAND\n"
187 " execute each specified transactional COMMAND:\n"
188 " commit\n"
189 " abort\n"
190 " insert UUID I J\n"
191 " delete UUID\n"
192 " modify UUID I J\n"
193 " print\n"
194 " execute SCHEMA TRANSACTION...\n"
195 " executes each TRANSACTION on an initially empty database\n"
196 " the specified SCHEMA\n"
e51879e9
AZ
197 " execute-readonly SCHEMA TRANSACTION...\n"
198 " same as execute, except the TRANSACTION will be executed\n"
199 " against the database server that is in read only mode\n"
f85f8ebb
BP
200 " trigger SCHEMA TRANSACTION...\n"
201 " executes each TRANSACTION on an initially empty database\n"
202 " the specified SCHEMA. A TRANSACTION of the form\n"
203 " [\"advance\", NUMBER] advances NUMBER milliseconds in\n"
c3bb4bd7
BP
204 " simulated time, for causing triggers to time out.\n"
205 " idl SERVER [TRANSACTION...]\n"
206 " connect to SERVER and dump the contents of the database\n"
207 " as seen initially by the IDL implementation and after\n"
208 " executing each TRANSACTION. (Each TRANSACTION must modify\n"
7251075c
EA
209 " the database or this command will hang.)\n"
210 " idl-partial-update-map-column SERVER \n"
211 " connect to SERVER and executes different operations to\n"
212 " test the capacity of updating elements inside a map column\n"
f1ab6e06
RM
213 " displaying the table information after each operation.\n"
214 " idl-partial-update-set-column SERVER \n"
215 " connect to SERVER and executes different operations to\n"
216 " test the capacity of updating elements inside a set column\n"
0a8606ee
LR
217 " displaying the table information after each operation.\n"
218 " idl-compound-index TEST_TO_EXECUTE\n"
219 " Execute the tests to verify compound-index feature.\n"
220 " The TEST_TO_EXECUTE are:\n"
221 " idl_compound_index_single_column:\n"
222 " test for indexes using one column.\n"
223 " idl_compound_index_double_column:\n"
224 " test for indexes using two columns.\n",
f85f8ebb
BP
225 program_name, program_name);
226 vlog_usage();
227 printf("\nOther options:\n"
c3bb4bd7 228 " -t, --timeout=SECS give up after SECS seconds\n"
932104f4
SA
229 " -h, --help display this help message\n"
230 " -c, --change-track used with the 'idl' command to\n"
231 " enable tracking of IDL changes\n");
f85f8ebb
BP
232 exit(EXIT_SUCCESS);
233}
234\f
235/* Command helper functions. */
236
237static struct json *
238parse_json(const char *s)
239{
240 struct json *json = json_from_string(s);
241 if (json->type == JSON_STRING) {
242 ovs_fatal(0, "\"%s\": %s", s, json->u.string);
243 }
244 return json;
245}
246
247static struct json *
248unbox_json(struct json *json)
249{
250 if (json->type == JSON_ARRAY && json->u.array.n == 1) {
251 struct json *inner = json->u.array.elems[0];
252 json->u.array.elems[0] = NULL;
253 json_destroy(json);
254 return inner;
255 } else {
256 return json;
257 }
258}
259
7bd02255 260static void
f85f8ebb
BP
261print_and_free_json(struct json *json)
262{
263 char *string = json_to_string(json, JSSF_SORT);
264 json_destroy(json);
265 puts(string);
266 free(string);
267}
268
e9f8f936
BP
269static void
270print_and_free_ovsdb_error(struct ovsdb_error *error)
271{
272 char *string = ovsdb_error_to_string(error);
273 ovsdb_error_destroy(error);
274 puts(string);
275 free(string);
276}
277
f85f8ebb
BP
278static void
279check_ovsdb_error(struct ovsdb_error *error)
280{
281 if (error) {
93ff0290
BP
282 char *s = ovsdb_error_to_string(error);
283 ovsdb_error_destroy(error);
284 ovs_fatal(0, "%s", s);
f85f8ebb
BP
285 }
286}
5c414a2e
BP
287
288static void
289die_if_error(char *error)
290{
291 if (error) {
292 ovs_fatal(0, "%s", error);
293 }
294}
f85f8ebb
BP
295\f
296/* Command implementations. */
297
298static void
1636c761 299do_log_io(struct ovs_cmdl_context *ctx)
f85f8ebb 300{
1636c761
RB
301 const char *name = ctx->argv[1];
302 char *mode_string = ctx->argv[2];
f85f8ebb
BP
303
304 struct ovsdb_error *error;
7446f148 305 enum ovsdb_log_open_mode mode;
41709ccc 306 struct ovsdb_log *log;
f85f8ebb
BP
307 int i;
308
7446f148
BP
309 if (!strcmp(mode_string, "read-only")) {
310 mode = OVSDB_LOG_READ_ONLY;
311 } else if (!strcmp(mode_string, "read/write")) {
312 mode = OVSDB_LOG_READ_WRITE;
313 } else if (!strcmp(mode_string, "create")) {
314 mode = OVSDB_LOG_CREATE;
315 } else {
316 ovs_fatal(0, "unknown log-io open mode \"%s\"", mode_string);
f85f8ebb
BP
317 }
318
7446f148 319 check_ovsdb_error(ovsdb_log_open(name, mode, -1, &log));
f85f8ebb
BP
320 printf("%s: open successful\n", name);
321
1636c761
RB
322 for (i = 3; i < ctx->argc; i++) {
323 const char *command = ctx->argv[i];
f85f8ebb
BP
324 if (!strcmp(command, "read")) {
325 struct json *json;
326
41709ccc 327 error = ovsdb_log_read(log, &json);
f85f8ebb
BP
328 if (!error) {
329 printf("%s: read: ", name);
330 if (json) {
331 print_and_free_json(json);
332 } else {
41709ccc 333 printf("end of log\n");
f85f8ebb
BP
334 }
335 continue;
336 }
337 } else if (!strncmp(command, "write:", 6)) {
338 struct json *json = parse_json(command + 6);
41709ccc 339 error = ovsdb_log_write(log, json);
f85f8ebb
BP
340 json_destroy(json);
341 } else if (!strcmp(command, "commit")) {
41709ccc 342 error = ovsdb_log_commit(log);
f85f8ebb 343 } else {
41709ccc 344 ovs_fatal(0, "unknown log-io command \"%s\"", command);
f85f8ebb
BP
345 }
346 if (error) {
347 char *s = ovsdb_error_to_string(error);
348 printf("%s: %s failed: %s\n", name, command, s);
349 free(s);
93ff0290 350 ovsdb_error_destroy(error);
f85f8ebb
BP
351 } else {
352 printf("%s: %s successful\n", name, command);
353 }
354 }
355
41709ccc 356 ovsdb_log_close(log);
f85f8ebb
BP
357}
358
958ac03a 359static void
1636c761 360do_default_atoms(struct ovs_cmdl_context *ctx OVS_UNUSED)
958ac03a
BP
361{
362 int type;
363
364 for (type = 0; type < OVSDB_N_TYPES; type++) {
365 union ovsdb_atom atom;
366
367 if (type == OVSDB_TYPE_VOID) {
368 continue;
369 }
370
371 printf("%s: ", ovsdb_atomic_type_to_string(type));
372
373 ovsdb_atom_init_default(&atom, type);
374 if (!ovsdb_atom_equals(&atom, ovsdb_atom_default(type), type)) {
375 printf("wrong\n");
376 exit(1);
377 }
378 ovsdb_atom_destroy(&atom, type);
379
380 printf("OK\n");
381 }
382}
383
384static void
1636c761 385do_default_data(struct ovs_cmdl_context *ctx OVS_UNUSED)
958ac03a
BP
386{
387 unsigned int n_min;
388 int key, value;
389
390 for (n_min = 0; n_min <= 1; n_min++) {
391 for (key = 0; key < OVSDB_N_TYPES; key++) {
392 if (key == OVSDB_TYPE_VOID) {
393 continue;
394 }
395 for (value = 0; value < OVSDB_N_TYPES; value++) {
396 struct ovsdb_datum datum;
397 struct ovsdb_type type;
398
399 ovsdb_base_type_init(&type.key, key);
400 ovsdb_base_type_init(&type.value, value);
401 type.n_min = n_min;
402 type.n_max = 1;
0a8606ee 403 ovs_assert(ovsdb_type_is_valid(&type));
958ac03a
BP
404
405 printf("key %s, value %s, n_min %u: ",
406 ovsdb_atomic_type_to_string(key),
407 ovsdb_atomic_type_to_string(value), n_min);
408
409 ovsdb_datum_init_default(&datum, &type);
410 if (!ovsdb_datum_equals(&datum, ovsdb_datum_default(&type),
411 &type)) {
412 printf("wrong\n");
413 exit(1);
414 }
415 ovsdb_datum_destroy(&datum, &type);
416 ovsdb_type_destroy(&type);
417
418 printf("OK\n");
419 }
420 }
421 }
422}
423
1a6f1cef
AZ
424static void
425do_diff_data(struct ovs_cmdl_context *ctx)
426{
427 struct ovsdb_type type;
428 struct json *json;
429 struct ovsdb_datum new, old, diff, reincarnation;
430
431 json = unbox_json(parse_json(ctx->argv[1]));
432 check_ovsdb_error(ovsdb_type_from_json(&type, json));
433 json_destroy(json);
434
435 /* Arguments in pairs of 'old' and 'new'. */
436 for (int i = 2; i < ctx->argc - 1; i+=2) {
437 struct ovsdb_error *error;
438
439 json = unbox_json(parse_json(ctx->argv[i]));
440 check_ovsdb_error(ovsdb_datum_from_json(&old, &type, json, NULL));
441 json_destroy(json);
442
443 json = unbox_json(parse_json(ctx->argv[i+1]));
444 check_ovsdb_error(ovsdb_transient_datum_from_json(&new, &type, json));
445 json_destroy(json);
446
447 /* Generate the diff. */
448 ovsdb_datum_diff(&diff, &old, &new, &type);
449
450 /* Apply diff to 'old' to create'reincarnation'. */
451 error = ovsdb_datum_apply_diff(&reincarnation, &old, &diff, &type);
452 if (error) {
cf2bc30c
WT
453 char *string = ovsdb_error_to_string(error);
454 ovsdb_error_destroy(error);
455 ovs_fatal(0, "%s", string);
1a6f1cef
AZ
456 }
457
458 /* Test to make sure 'new' equals 'reincarnation'. */
459 if (!ovsdb_datum_equals(&new, &reincarnation, &type)) {
460 ovs_fatal(0, "failed to apply diff");
461 }
462
463 /* Print diff */
464 json = ovsdb_datum_to_json(&diff, &type);
465 printf ("diff: ");
466 print_and_free_json(json);
467
468 /* Print reincarnation */
469 json = ovsdb_datum_to_json(&reincarnation, &type);
470 printf ("apply diff: ");
471 print_and_free_json(json);
472
473 ovsdb_datum_destroy(&new, &type);
474 ovsdb_datum_destroy(&old, &type);
475 ovsdb_datum_destroy(&diff, &type);
476 ovsdb_datum_destroy(&reincarnation, &type);
477
478 printf("OK\n");
479 }
480
481 ovsdb_type_destroy(&type);
482}
483
f85f8ebb 484static void
1636c761 485do_parse_atomic_type(struct ovs_cmdl_context *ctx)
f85f8ebb
BP
486{
487 enum ovsdb_atomic_type type;
488 struct json *json;
489
1636c761 490 json = unbox_json(parse_json(ctx->argv[1]));
f85f8ebb
BP
491 check_ovsdb_error(ovsdb_atomic_type_from_json(&type, json));
492 json_destroy(json);
493 print_and_free_json(ovsdb_atomic_type_to_json(type));
494}
495
bd76d25d 496static void
1636c761 497do_parse_base_type(struct ovs_cmdl_context *ctx)
bd76d25d
BP
498{
499 struct ovsdb_base_type base;
500 struct json *json;
501
1636c761 502 json = unbox_json(parse_json(ctx->argv[1]));
bd76d25d
BP
503 check_ovsdb_error(ovsdb_base_type_from_json(&base, json));
504 json_destroy(json);
505 print_and_free_json(ovsdb_base_type_to_json(&base));
506 ovsdb_base_type_destroy(&base);
507}
508
f85f8ebb 509static void
1636c761 510do_parse_type(struct ovs_cmdl_context *ctx)
f85f8ebb
BP
511{
512 struct ovsdb_type type;
513 struct json *json;
514
1636c761 515 json = unbox_json(parse_json(ctx->argv[1]));
f85f8ebb
BP
516 check_ovsdb_error(ovsdb_type_from_json(&type, json));
517 json_destroy(json);
518 print_and_free_json(ovsdb_type_to_json(&type));
bd76d25d 519 ovsdb_type_destroy(&type);
f85f8ebb
BP
520}
521
522static void
1636c761 523do_parse_atoms(struct ovs_cmdl_context *ctx)
f85f8ebb 524{
bd76d25d 525 struct ovsdb_base_type base;
f85f8ebb
BP
526 struct json *json;
527 int i;
528
1636c761 529 json = unbox_json(parse_json(ctx->argv[1]));
bd76d25d 530 check_ovsdb_error(ovsdb_base_type_from_json(&base, json));
f85f8ebb
BP
531 json_destroy(json);
532
1636c761 533 for (i = 2; i < ctx->argc; i++) {
bd76d25d 534 struct ovsdb_error *error;
f85f8ebb
BP
535 union ovsdb_atom atom;
536
1636c761 537 json = unbox_json(parse_json(ctx->argv[i]));
bd76d25d 538 error = ovsdb_atom_from_json(&atom, &base, json, NULL);
f85f8ebb
BP
539 json_destroy(json);
540
bd76d25d
BP
541 if (error) {
542 print_and_free_ovsdb_error(error);
543 } else {
7bd02255 544 print_and_free_json(ovsdb_atom_to_json(&atom, base.type));
bd76d25d
BP
545 ovsdb_atom_destroy(&atom, base.type);
546 }
f85f8ebb 547 }
bd76d25d 548 ovsdb_base_type_destroy(&base);
f85f8ebb
BP
549}
550
5c414a2e 551static void
1636c761 552do_parse_atom_strings(struct ovs_cmdl_context *ctx)
5c414a2e 553{
bd76d25d 554 struct ovsdb_base_type base;
5c414a2e
BP
555 struct json *json;
556 int i;
557
1636c761 558 json = unbox_json(parse_json(ctx->argv[1]));
bd76d25d 559 check_ovsdb_error(ovsdb_base_type_from_json(&base, json));
5c414a2e
BP
560 json_destroy(json);
561
1636c761 562 for (i = 2; i < ctx->argc; i++) {
1ab39058 563 union ovsdb_atom atom, *range_end_atom = NULL;
5c414a2e
BP
564 struct ds out;
565
1ab39058
LR
566 die_if_error(ovsdb_atom_from_string(&atom, &range_end_atom, &base,
567 ctx->argv[i], NULL));
5c414a2e
BP
568
569 ds_init(&out);
bd76d25d 570 ovsdb_atom_to_string(&atom, base.type, &out);
1ab39058
LR
571 if (range_end_atom) {
572 struct ds range_end_ds;
573 ds_init(&range_end_ds);
574 ovsdb_atom_to_string(range_end_atom, base.type, &range_end_ds);
575 ds_put_char(&out, '-');
576 ds_put_cstr(&out, ds_cstr(&range_end_ds));;
577 ds_destroy(&range_end_ds);
578 }
5c414a2e
BP
579 puts(ds_cstr(&out));
580 ds_destroy(&out);
581
bd76d25d 582 ovsdb_atom_destroy(&atom, base.type);
1ab39058
LR
583 if (range_end_atom) {
584 ovsdb_atom_destroy(range_end_atom, base.type);
585 }
5c414a2e 586 }
bd76d25d 587 ovsdb_base_type_destroy(&base);
5c414a2e
BP
588}
589
f85f8ebb 590static void
2b66469b
BP
591do_parse_data__(int argc, char *argv[],
592 struct ovsdb_error *
593 (*parse)(struct ovsdb_datum *datum,
594 const struct ovsdb_type *type,
595 const struct json *json,
596 struct ovsdb_symbol_table *symtab))
f85f8ebb
BP
597{
598 struct ovsdb_type type;
599 struct json *json;
600 int i;
601
602 json = unbox_json(parse_json(argv[1]));
603 check_ovsdb_error(ovsdb_type_from_json(&type, json));
604 json_destroy(json);
605
606 for (i = 2; i < argc; i++) {
607 struct ovsdb_datum datum;
608
609 json = unbox_json(parse_json(argv[i]));
2b66469b 610 check_ovsdb_error(parse(&datum, &type, json, NULL));
f85f8ebb
BP
611 json_destroy(json);
612
7bd02255 613 print_and_free_json(ovsdb_datum_to_json(&datum, &type));
f85f8ebb
BP
614
615 ovsdb_datum_destroy(&datum, &type);
616 }
bd76d25d 617 ovsdb_type_destroy(&type);
f85f8ebb
BP
618}
619
2b66469b 620static void
1636c761 621do_parse_data(struct ovs_cmdl_context *ctx)
2b66469b 622{
1636c761 623 do_parse_data__(ctx->argc, ctx->argv, ovsdb_datum_from_json);
2b66469b
BP
624}
625
5c414a2e 626static void
1636c761 627do_parse_data_strings(struct ovs_cmdl_context *ctx)
5c414a2e
BP
628{
629 struct ovsdb_type type;
630 struct json *json;
631 int i;
632
1636c761 633 json = unbox_json(parse_json(ctx->argv[1]));
5c414a2e
BP
634 check_ovsdb_error(ovsdb_type_from_json(&type, json));
635 json_destroy(json);
636
1636c761 637 for (i = 2; i < ctx->argc; i++) {
5c414a2e
BP
638 struct ovsdb_datum datum;
639 struct ds out;
640
1636c761 641 die_if_error(ovsdb_datum_from_string(&datum, &type, ctx->argv[i], NULL));
5c414a2e
BP
642
643 ds_init(&out);
644 ovsdb_datum_to_string(&datum, &type, &out);
645 puts(ds_cstr(&out));
646 ds_destroy(&out);
647
648 ovsdb_datum_destroy(&datum, &type);
649 }
bd76d25d 650 ovsdb_type_destroy(&type);
5c414a2e
BP
651}
652
f85f8ebb
BP
653static enum ovsdb_atomic_type compare_atoms_atomic_type;
654
655static int
656compare_atoms(const void *a_, const void *b_)
657{
658 const union ovsdb_atom *a = a_;
659 const union ovsdb_atom *b = b_;
660
661 return ovsdb_atom_compare_3way(a, b, compare_atoms_atomic_type);
662}
663
664static void
1636c761 665do_sort_atoms(struct ovs_cmdl_context *ctx)
f85f8ebb 666{
bd76d25d 667 struct ovsdb_base_type base;
f85f8ebb
BP
668 union ovsdb_atom *atoms;
669 struct json *json, **json_atoms;
670 size_t n_atoms;
671 int i;
672
1636c761 673 json = unbox_json(parse_json(ctx->argv[1]));
bd76d25d 674 check_ovsdb_error(ovsdb_base_type_from_json(&base, json));
f85f8ebb
BP
675 json_destroy(json);
676
1636c761 677 json = unbox_json(parse_json(ctx->argv[2]));
f85f8ebb
BP
678 if (json->type != JSON_ARRAY) {
679 ovs_fatal(0, "second argument must be array");
680 }
681
682 /* Convert JSON atoms to internal representation. */
683 n_atoms = json->u.array.n;
684 atoms = xmalloc(n_atoms * sizeof *atoms);
685 for (i = 0; i < n_atoms; i++) {
bd76d25d 686 check_ovsdb_error(ovsdb_atom_from_json(&atoms[i], &base,
f85f8ebb
BP
687 json->u.array.elems[i], NULL));
688 }
689 json_destroy(json);
690
691 /* Sort atoms. */
bd76d25d 692 compare_atoms_atomic_type = base.type;
f85f8ebb
BP
693 qsort(atoms, n_atoms, sizeof *atoms, compare_atoms);
694
695 /* Convert internal representation back to JSON. */
696 json_atoms = xmalloc(n_atoms * sizeof *json_atoms);
697 for (i = 0; i < n_atoms; i++) {
bd76d25d
BP
698 json_atoms[i] = ovsdb_atom_to_json(&atoms[i], base.type);
699 ovsdb_atom_destroy(&atoms[i], base.type);
f85f8ebb
BP
700 }
701 print_and_free_json(json_array_create(json_atoms, n_atoms));
93ff0290 702 free(atoms);
bd76d25d 703 ovsdb_base_type_destroy(&base);
f85f8ebb
BP
704}
705
706static void
1636c761 707do_parse_column(struct ovs_cmdl_context *ctx)
f85f8ebb
BP
708{
709 struct ovsdb_column *column;
710 struct json *json;
711
1636c761
RB
712 json = parse_json(ctx->argv[2]);
713 check_ovsdb_error(ovsdb_column_from_json(json, ctx->argv[1], &column));
f85f8ebb
BP
714 json_destroy(json);
715 print_and_free_json(ovsdb_column_to_json(column));
716 ovsdb_column_destroy(column);
717}
718
719static void
1636c761 720do_parse_table(struct ovs_cmdl_context *ctx)
f85f8ebb
BP
721{
722 struct ovsdb_table_schema *ts;
c5f341ab 723 bool default_is_root;
f85f8ebb
BP
724 struct json *json;
725
1636c761 726 default_is_root = ctx->argc > 3 && !strcmp(ctx->argv[3], "true");
c5f341ab 727
1636c761
RB
728 json = parse_json(ctx->argv[2]);
729 check_ovsdb_error(ovsdb_table_schema_from_json(json, ctx->argv[1], &ts));
f85f8ebb 730 json_destroy(json);
c5f341ab 731 print_and_free_json(ovsdb_table_schema_to_json(ts, default_is_root));
f85f8ebb
BP
732 ovsdb_table_schema_destroy(ts);
733}
734
735static void
1636c761 736do_parse_rows(struct ovs_cmdl_context *ctx)
f85f8ebb
BP
737{
738 struct ovsdb_column_set all_columns;
739 struct ovsdb_table_schema *ts;
740 struct ovsdb_table *table;
741 struct json *json;
742 int i;
743
1636c761 744 json = unbox_json(parse_json(ctx->argv[1]));
f85f8ebb
BP
745 check_ovsdb_error(ovsdb_table_schema_from_json(json, "mytable", &ts));
746 json_destroy(json);
747
748 table = ovsdb_table_create(ts);
749 ovsdb_column_set_init(&all_columns);
750 ovsdb_column_set_add_all(&all_columns, table);
751
1636c761 752 for (i = 2; i < ctx->argc; i++) {
f85f8ebb
BP
753 struct ovsdb_column_set columns;
754 struct ovsdb_row *row;
755
756 ovsdb_column_set_init(&columns);
757 row = ovsdb_row_create(table);
758
1636c761 759 json = unbox_json(parse_json(ctx->argv[i]));
f85f8ebb
BP
760 check_ovsdb_error(ovsdb_row_from_json(row, json, NULL, &columns));
761 json_destroy(json);
762
763 print_and_free_json(ovsdb_row_to_json(row, &all_columns));
764
765 if (columns.n_columns) {
766 struct svec names;
767 size_t j;
768 char *s;
769
770 svec_init(&names);
771 for (j = 0; j < columns.n_columns; j++) {
772 svec_add(&names, columns.columns[j]->name);
773 }
774 svec_sort(&names);
775 s = svec_join(&names, ", ", "");
776 puts(s);
777 free(s);
778 svec_destroy(&names);
779 } else {
780 printf("<none>\n");
781 }
782
783 ovsdb_column_set_destroy(&columns);
784 ovsdb_row_destroy(row);
785 }
786
787 ovsdb_column_set_destroy(&all_columns);
788 ovsdb_table_destroy(table); /* Also destroys 'ts'. */
789}
790
791static void
1636c761 792do_compare_rows(struct ovs_cmdl_context *ctx)
f85f8ebb
BP
793{
794 struct ovsdb_column_set all_columns;
795 struct ovsdb_table_schema *ts;
796 struct ovsdb_table *table;
797 struct ovsdb_row **rows;
798 struct json *json;
799 char **names;
800 int n_rows;
801 int i, j;
802
1636c761 803 json = unbox_json(parse_json(ctx->argv[1]));
f85f8ebb
BP
804 check_ovsdb_error(ovsdb_table_schema_from_json(json, "mytable", &ts));
805 json_destroy(json);
806
807 table = ovsdb_table_create(ts);
808 ovsdb_column_set_init(&all_columns);
809 ovsdb_column_set_add_all(&all_columns, table);
810
1636c761 811 n_rows = ctx->argc - 2;
f85f8ebb
BP
812 rows = xmalloc(sizeof *rows * n_rows);
813 names = xmalloc(sizeof *names * n_rows);
814 for (i = 0; i < n_rows; i++) {
815 rows[i] = ovsdb_row_create(table);
816
1636c761 817 json = parse_json(ctx->argv[i + 2]);
f85f8ebb
BP
818 if (json->type != JSON_ARRAY || json->u.array.n != 2
819 || json->u.array.elems[0]->type != JSON_STRING) {
820 ovs_fatal(0, "\"%s\" does not have expected form "
1636c761 821 "[\"name\", {data}]", ctx->argv[i]);
f85f8ebb
BP
822 }
823 names[i] = xstrdup(json->u.array.elems[0]->u.string);
824 check_ovsdb_error(ovsdb_row_from_json(rows[i], json->u.array.elems[1],
825 NULL, NULL));
826 json_destroy(json);
827 }
828 for (i = 0; i < n_rows; i++) {
829 uint32_t i_hash = ovsdb_row_hash_columns(rows[i], &all_columns, 0);
830 for (j = i + 1; j < n_rows; j++) {
831 uint32_t j_hash = ovsdb_row_hash_columns(rows[j], &all_columns, 0);
832 if (ovsdb_row_equal_columns(rows[i], rows[j], &all_columns)) {
833 printf("%s == %s\n", names[i], names[j]);
834 if (i_hash != j_hash) {
835 printf("but hash(%s) != hash(%s)\n", names[i], names[j]);
836 abort();
837 }
838 } else if (i_hash == j_hash) {
839 printf("hash(%s) == hash(%s)\n", names[i], names[j]);
840 }
841 }
842 }
93ff0290
BP
843 for (i = 0; i < n_rows; i++) {
844 ovsdb_row_destroy(rows[i]);
845 free(names[i]);
846 }
f85f8ebb
BP
847 free(rows);
848 free(names);
849
850 ovsdb_column_set_destroy(&all_columns);
851 ovsdb_table_destroy(table); /* Also destroys 'ts'. */
852}
853
854static void
1636c761 855do_parse_conditions(struct ovs_cmdl_context *ctx)
f85f8ebb
BP
856{
857 struct ovsdb_table_schema *ts;
858 struct json *json;
859 int exit_code = 0;
860 int i;
861
1636c761 862 json = unbox_json(parse_json(ctx->argv[1]));
f85f8ebb
BP
863 check_ovsdb_error(ovsdb_table_schema_from_json(json, "mytable", &ts));
864 json_destroy(json);
865
1636c761 866 for (i = 2; i < ctx->argc; i++) {
f85f8ebb
BP
867 struct ovsdb_condition cnd;
868 struct ovsdb_error *error;
869
1636c761 870 json = parse_json(ctx->argv[i]);
f85f8ebb
BP
871 error = ovsdb_condition_from_json(ts, json, NULL, &cnd);
872 if (!error) {
873 print_and_free_json(ovsdb_condition_to_json(&cnd));
874 } else {
875 char *s = ovsdb_error_to_string(error);
876 ovs_error(0, "%s", s);
877 free(s);
878 ovsdb_error_destroy(error);
879 exit_code = 1;
880 }
881 json_destroy(json);
882
883 ovsdb_condition_destroy(&cnd);
884 }
885 ovsdb_table_schema_destroy(ts);
886
887 exit(exit_code);
888}
889
ae9cab37
LS
890#define OVSDB_CONDITION_EVERY 0
891#define OVSDB_CONDITION_ANY 1
892
f85f8ebb 893static void
ae9cab37 894do_evaluate_condition__(struct ovs_cmdl_context *ctx, int mode)
f85f8ebb
BP
895{
896 struct ovsdb_table_schema *ts;
897 struct ovsdb_table *table;
898 struct ovsdb_condition *conditions;
899 size_t n_conditions;
900 struct ovsdb_row **rows;
901 size_t n_rows;
902 struct json *json;
903 size_t i, j;
904
905 /* Parse table schema, create table. */
1636c761 906 json = unbox_json(parse_json(ctx->argv[1]));
f85f8ebb
BP
907 check_ovsdb_error(ovsdb_table_schema_from_json(json, "mytable", &ts));
908 json_destroy(json);
909
910 table = ovsdb_table_create(ts);
911
912 /* Parse conditions. */
1636c761 913 json = parse_json(ctx->argv[2]);
f85f8ebb
BP
914 if (json->type != JSON_ARRAY) {
915 ovs_fatal(0, "CONDITION argument is not JSON array");
916 }
917 n_conditions = json->u.array.n;
918 conditions = xmalloc(n_conditions * sizeof *conditions);
919 for (i = 0; i < n_conditions; i++) {
920 check_ovsdb_error(ovsdb_condition_from_json(ts, json->u.array.elems[i],
921 NULL, &conditions[i]));
922 }
923 json_destroy(json);
924
925 /* Parse rows. */
1636c761 926 json = parse_json(ctx->argv[3]);
f85f8ebb
BP
927 if (json->type != JSON_ARRAY) {
928 ovs_fatal(0, "ROW argument is not JSON array");
929 }
930 n_rows = json->u.array.n;
931 rows = xmalloc(n_rows * sizeof *rows);
932 for (i = 0; i < n_rows; i++) {
933 rows[i] = ovsdb_row_create(table);
934 check_ovsdb_error(ovsdb_row_from_json(rows[i], json->u.array.elems[i],
935 NULL, NULL));
936 }
937 json_destroy(json);
938
939 for (i = 0; i < n_conditions; i++) {
34582733 940 printf("condition %2"PRIuSIZE":", i);
f85f8ebb 941 for (j = 0; j < n_rows; j++) {
ae9cab37
LS
942 bool result;
943 if (mode == OVSDB_CONDITION_EVERY) {
944 result = ovsdb_condition_match_every_clause(rows[j],
945 &conditions[i]);
946 } else {
947 result = ovsdb_condition_match_any_clause(rows[j]->fields,
948 &conditions[i],
949 NULL);
950 }
f85f8ebb
BP
951 if (j % 5 == 0) {
952 putchar(' ');
953 }
954 putchar(result ? 'T' : '-');
955 }
956 printf("\n");
957 }
958
959 for (i = 0; i < n_conditions; i++) {
960 ovsdb_condition_destroy(&conditions[i]);
961 }
93ff0290 962 free(conditions);
f85f8ebb
BP
963 for (i = 0; i < n_rows; i++) {
964 ovsdb_row_destroy(rows[i]);
965 }
93ff0290 966 free(rows);
f85f8ebb
BP
967 ovsdb_table_destroy(table); /* Also destroys 'ts'. */
968}
969
ae9cab37
LS
970static void
971do_evaluate_conditions(struct ovs_cmdl_context *ctx)
972{
973 do_evaluate_condition__(ctx, OVSDB_CONDITION_EVERY);
974}
975
976static void
977do_evaluate_conditions_any(struct ovs_cmdl_context *ctx)
978{
979 do_evaluate_condition__(ctx, OVSDB_CONDITION_ANY);
980}
981
982static void
983do_compare_conditions(struct ovs_cmdl_context *ctx)
984{
985 struct ovsdb_table_schema *ts;
986 struct ovsdb_table *table;
987 struct ovsdb_condition *conditions;
988 size_t n_conditions;
989 struct json *json;
990 size_t i;
991
992 /* Parse table schema, create table. */
993 json = unbox_json(parse_json(ctx->argv[1]));
994 check_ovsdb_error(ovsdb_table_schema_from_json(json, "mytable", &ts));
995 json_destroy(json);
996
997 table = ovsdb_table_create(ts);
998
999 /* Parse conditions. */
1000 json = parse_json(ctx->argv[2]);
1001 if (json->type != JSON_ARRAY) {
1002 ovs_fatal(0, "CONDITION argument is not JSON array");
1003 }
1004 n_conditions = json->u.array.n;
1005 conditions = xmalloc(n_conditions * sizeof *conditions);
1006
1007 for (i = 0; i < n_conditions; i++) {
1008 check_ovsdb_error(ovsdb_condition_from_json(ts, json->u.array.elems[i],
1009 NULL, &conditions[i]));
1010 }
1011 json_destroy(json);
1012
1013 for (i = 0; i < n_conditions - 1; i++) {
1014 int res = ovsdb_condition_cmp_3way(&conditions[i], &conditions[i + 1]);
1015 printf("condition %"PRIuSIZE"-%"PRIuSIZE": %d\n", i, i + 1, res);
1016 }
1017
1018 for (i = 0; i < n_conditions; i++) {
1019 ovsdb_condition_destroy(&conditions[i]);
1020 }
1021 free(conditions);
1022 ovsdb_table_destroy(table); /* Also destroys 'ts'. */
1023}
1024
e9f8f936 1025static void
1636c761 1026do_parse_mutations(struct ovs_cmdl_context *ctx)
e9f8f936
BP
1027{
1028 struct ovsdb_table_schema *ts;
1029 struct json *json;
1030 int exit_code = 0;
1031 int i;
1032
1636c761 1033 json = unbox_json(parse_json(ctx->argv[1]));
e9f8f936
BP
1034 check_ovsdb_error(ovsdb_table_schema_from_json(json, "mytable", &ts));
1035 json_destroy(json);
1036
1636c761 1037 for (i = 2; i < ctx->argc; i++) {
e9f8f936
BP
1038 struct ovsdb_mutation_set set;
1039 struct ovsdb_error *error;
1040
1636c761 1041 json = parse_json(ctx->argv[i]);
e9f8f936
BP
1042 error = ovsdb_mutation_set_from_json(ts, json, NULL, &set);
1043 if (!error) {
1044 print_and_free_json(ovsdb_mutation_set_to_json(&set));
1045 } else {
1046 char *s = ovsdb_error_to_string(error);
1047 ovs_error(0, "%s", s);
1048 free(s);
1049 ovsdb_error_destroy(error);
1050 exit_code = 1;
1051 }
1052 json_destroy(json);
1053
1054 ovsdb_mutation_set_destroy(&set);
1055 }
1056 ovsdb_table_schema_destroy(ts);
1057
1058 exit(exit_code);
1059}
1060
1061static void
1636c761 1062do_execute_mutations(struct ovs_cmdl_context *ctx)
e9f8f936
BP
1063{
1064 struct ovsdb_table_schema *ts;
1065 struct ovsdb_table *table;
1066 struct ovsdb_mutation_set *sets;
1067 size_t n_sets;
1068 struct ovsdb_row **rows;
1069 size_t n_rows;
1070 struct json *json;
1071 size_t i, j;
1072
1073 /* Parse table schema, create table. */
1636c761 1074 json = unbox_json(parse_json(ctx->argv[1]));
e9f8f936
BP
1075 check_ovsdb_error(ovsdb_table_schema_from_json(json, "mytable", &ts));
1076 json_destroy(json);
1077
1078 table = ovsdb_table_create(ts);
1079
1080 /* Parse mutations. */
1636c761 1081 json = parse_json(ctx->argv[2]);
e9f8f936
BP
1082 if (json->type != JSON_ARRAY) {
1083 ovs_fatal(0, "MUTATION argument is not JSON array");
1084 }
1085 n_sets = json->u.array.n;
1086 sets = xmalloc(n_sets * sizeof *sets);
1087 for (i = 0; i < n_sets; i++) {
1088 check_ovsdb_error(ovsdb_mutation_set_from_json(ts,
1089 json->u.array.elems[i],
1090 NULL, &sets[i]));
1091 }
1092 json_destroy(json);
1093
1094 /* Parse rows. */
1636c761 1095 json = parse_json(ctx->argv[3]);
e9f8f936
BP
1096 if (json->type != JSON_ARRAY) {
1097 ovs_fatal(0, "ROW argument is not JSON array");
1098 }
1099 n_rows = json->u.array.n;
1100 rows = xmalloc(n_rows * sizeof *rows);
1101 for (i = 0; i < n_rows; i++) {
1102 rows[i] = ovsdb_row_create(table);
1103 check_ovsdb_error(ovsdb_row_from_json(rows[i], json->u.array.elems[i],
1104 NULL, NULL));
1105 }
1106 json_destroy(json);
1107
1108 for (i = 0; i < n_sets; i++) {
34582733 1109 printf("mutation %2"PRIuSIZE":\n", i);
e9f8f936
BP
1110 for (j = 0; j < n_rows; j++) {
1111 struct ovsdb_error *error;
1112 struct ovsdb_row *row;
1113
1114 row = ovsdb_row_clone(rows[j]);
1115 error = ovsdb_mutation_set_execute(row, &sets[i]);
1116
34582733 1117 printf("row %"PRIuSIZE": ", j);
e9f8f936
BP
1118 if (error) {
1119 print_and_free_ovsdb_error(error);
1120 } else {
1121 struct ovsdb_column_set columns;
1122 struct shash_node *node;
1123
1124 ovsdb_column_set_init(&columns);
1125 SHASH_FOR_EACH (node, &ts->columns) {
1126 struct ovsdb_column *c = node->data;
1127 if (!ovsdb_datum_equals(&row->fields[c->index],
1128 &rows[j]->fields[c->index],
1129 &c->type)) {
1130 ovsdb_column_set_add(&columns, c);
1131 }
1132 }
1133 if (columns.n_columns) {
1134 print_and_free_json(ovsdb_row_to_json(row, &columns));
1135 } else {
1136 printf("no change\n");
1137 }
1138 ovsdb_column_set_destroy(&columns);
1139 }
1140 ovsdb_row_destroy(row);
1141 }
1142 printf("\n");
1143 }
1144
1145 for (i = 0; i < n_sets; i++) {
1146 ovsdb_mutation_set_destroy(&sets[i]);
1147 }
93ff0290 1148 free(sets);
e9f8f936
BP
1149 for (i = 0; i < n_rows; i++) {
1150 ovsdb_row_destroy(rows[i]);
1151 }
93ff0290 1152 free(rows);
e9f8f936
BP
1153 ovsdb_table_destroy(table); /* Also destroys 'ts'. */
1154}
1155
29d7226e
BP
1156/* Inserts a row, without bothering to update metadata such as refcounts. */
1157static void
1158put_row(struct ovsdb_table *table, struct ovsdb_row *row)
1159{
1160 const struct uuid *uuid = ovsdb_row_get_uuid(row);
1161 if (!ovsdb_table_get_row(table, uuid)) {
1162 hmap_insert(&table->rows, &row->hmap_node, uuid_hash(uuid));
1163 }
1164}
1165
f85f8ebb
BP
1166struct do_query_cbdata {
1167 struct uuid *row_uuids;
1168 int *counts;
1169 size_t n_rows;
1170};
1171
1172static bool
1173do_query_cb(const struct ovsdb_row *row, void *cbdata_)
1174{
1175 struct do_query_cbdata *cbdata = cbdata_;
1176 size_t i;
1177
1178 for (i = 0; i < cbdata->n_rows; i++) {
1179 if (uuid_equals(ovsdb_row_get_uuid(row), &cbdata->row_uuids[i])) {
1180 cbdata->counts[i]++;
1181 }
1182 }
1183
1184 return true;
1185}
1186
1187static void
1636c761 1188do_query(struct ovs_cmdl_context *ctx)
f85f8ebb
BP
1189{
1190 struct do_query_cbdata cbdata;
1191 struct ovsdb_table_schema *ts;
1192 struct ovsdb_table *table;
1193 struct json *json;
1194 int exit_code = 0;
1195 size_t i;
1196
1197 /* Parse table schema, create table. */
1636c761 1198 json = unbox_json(parse_json(ctx->argv[1]));
f85f8ebb
BP
1199 check_ovsdb_error(ovsdb_table_schema_from_json(json, "mytable", &ts));
1200 json_destroy(json);
1201
1202 table = ovsdb_table_create(ts);
1203
1204 /* Parse rows, add to table. */
1636c761 1205 json = parse_json(ctx->argv[2]);
f85f8ebb
BP
1206 if (json->type != JSON_ARRAY) {
1207 ovs_fatal(0, "ROW argument is not JSON array");
1208 }
1209 cbdata.n_rows = json->u.array.n;
1210 cbdata.row_uuids = xmalloc(cbdata.n_rows * sizeof *cbdata.row_uuids);
1211 cbdata.counts = xmalloc(cbdata.n_rows * sizeof *cbdata.counts);
1212 for (i = 0; i < cbdata.n_rows; i++) {
1213 struct ovsdb_row *row = ovsdb_row_create(table);
1214 uuid_generate(ovsdb_row_get_uuid_rw(row));
1215 check_ovsdb_error(ovsdb_row_from_json(row, json->u.array.elems[i],
1216 NULL, NULL));
1217 if (ovsdb_table_get_row(table, ovsdb_row_get_uuid(row))) {
1218 ovs_fatal(0, "duplicate UUID "UUID_FMT" in table",
1219 UUID_ARGS(ovsdb_row_get_uuid(row)));
1220 }
1221 cbdata.row_uuids[i] = *ovsdb_row_get_uuid(row);
29d7226e 1222 put_row(table, row);
f85f8ebb
BP
1223 }
1224 json_destroy(json);
1225
1226 /* Parse conditions and execute queries. */
1636c761 1227 json = parse_json(ctx->argv[3]);
f85f8ebb
BP
1228 if (json->type != JSON_ARRAY) {
1229 ovs_fatal(0, "CONDITION argument is not JSON array");
1230 }
1231 for (i = 0; i < json->u.array.n; i++) {
1232 struct ovsdb_condition cnd;
1233 size_t j;
1234
1235 check_ovsdb_error(ovsdb_condition_from_json(ts, json->u.array.elems[i],
1236 NULL, &cnd));
1237
1238 memset(cbdata.counts, 0, cbdata.n_rows * sizeof *cbdata.counts);
1239 ovsdb_query(table, &cnd, do_query_cb, &cbdata);
1240
34582733 1241 printf("query %2"PRIuSIZE":", i);
f85f8ebb
BP
1242 for (j = 0; j < cbdata.n_rows; j++) {
1243 if (j % 5 == 0) {
1244 putchar(' ');
1245 }
1246 if (cbdata.counts[j]) {
1247 printf("%d", cbdata.counts[j]);
1248 if (cbdata.counts[j] > 1) {
1249 /* Dup! */
1250 exit_code = 1;
1251 }
1252 } else {
1253 putchar('-');
1254 }
1255 }
1256 putchar('\n');
1257
1258 ovsdb_condition_destroy(&cnd);
1259 }
1260 json_destroy(json);
1261
1262 ovsdb_table_destroy(table); /* Also destroys 'ts'. */
1263
1264 exit(exit_code);
1265}
1266
1267struct do_query_distinct_class {
1268 struct ovsdb_row *example;
1269 int count;
1270};
1271
1272struct do_query_distinct_row {
1273 struct uuid uuid;
1274 struct do_query_distinct_class *class;
1275};
1276
1277static void
1636c761 1278do_query_distinct(struct ovs_cmdl_context *ctx)
f85f8ebb
BP
1279{
1280 struct ovsdb_column_set columns;
1281 struct ovsdb_table_schema *ts;
1282 struct ovsdb_table *table;
1283 struct do_query_distinct_row *rows;
1284 size_t n_rows;
1285 struct do_query_distinct_class *classes;
1286 size_t n_classes;
1287 struct json *json;
1288 int exit_code = 0;
2a022368 1289 size_t i;
f85f8ebb
BP
1290
1291 /* Parse table schema, create table. */
1636c761 1292 json = unbox_json(parse_json(ctx->argv[1]));
f85f8ebb
BP
1293 check_ovsdb_error(ovsdb_table_schema_from_json(json, "mytable", &ts));
1294 json_destroy(json);
1295
1296 table = ovsdb_table_create(ts);
1297
1298 /* Parse column set. */
1636c761 1299 json = parse_json(ctx->argv[4]);
1cb29ab0
BP
1300 check_ovsdb_error(ovsdb_column_set_from_json(json, table->schema,
1301 &columns));
f85f8ebb
BP
1302 json_destroy(json);
1303
1304 /* Parse rows, add to table. */
1636c761 1305 json = parse_json(ctx->argv[2]);
f85f8ebb
BP
1306 if (json->type != JSON_ARRAY) {
1307 ovs_fatal(0, "ROW argument is not JSON array");
1308 }
1309 n_rows = json->u.array.n;
1310 rows = xmalloc(n_rows * sizeof *rows);
1311 classes = xmalloc(n_rows * sizeof *classes);
1312 n_classes = 0;
1313 for (i = 0; i < n_rows; i++) {
1314 struct ovsdb_row *row;
1315 size_t j;
1316
1317 /* Parse row. */
1318 row = ovsdb_row_create(table);
1319 uuid_generate(ovsdb_row_get_uuid_rw(row));
1320 check_ovsdb_error(ovsdb_row_from_json(row, json->u.array.elems[i],
1321 NULL, NULL));
1322
1323 /* Initialize row and find equivalence class. */
1324 rows[i].uuid = *ovsdb_row_get_uuid(row);
1325 rows[i].class = NULL;
1326 for (j = 0; j < n_classes; j++) {
1327 if (ovsdb_row_equal_columns(row, classes[j].example, &columns)) {
1328 rows[i].class = &classes[j];
1329 break;
1330 }
1331 }
1332 if (!rows[i].class) {
1333 rows[i].class = &classes[n_classes];
1334 classes[n_classes].example = ovsdb_row_clone(row);
1335 n_classes++;
1336 }
1337
1338 /* Add row to table. */
1339 if (ovsdb_table_get_row(table, ovsdb_row_get_uuid(row))) {
1340 ovs_fatal(0, "duplicate UUID "UUID_FMT" in table",
1341 UUID_ARGS(ovsdb_row_get_uuid(row)));
1342 }
29d7226e 1343 put_row(table, row);
f85f8ebb
BP
1344
1345 }
1346 json_destroy(json);
1347
1348 /* Parse conditions and execute queries. */
1636c761 1349 json = parse_json(ctx->argv[3]);
f85f8ebb
BP
1350 if (json->type != JSON_ARRAY) {
1351 ovs_fatal(0, "CONDITION argument is not JSON array");
1352 }
1353 for (i = 0; i < json->u.array.n; i++) {
1354 struct ovsdb_row_set results;
1355 struct ovsdb_condition cnd;
2a022368 1356 size_t j;
f85f8ebb
BP
1357
1358 check_ovsdb_error(ovsdb_condition_from_json(ts, json->u.array.elems[i],
1359 NULL, &cnd));
1360
1361 for (j = 0; j < n_classes; j++) {
1362 classes[j].count = 0;
1363 }
1364 ovsdb_row_set_init(&results);
1365 ovsdb_query_distinct(table, &cnd, &columns, &results);
1366 for (j = 0; j < results.n_rows; j++) {
2a022368
BP
1367 size_t k;
1368
f85f8ebb
BP
1369 for (k = 0; k < n_rows; k++) {
1370 if (uuid_equals(ovsdb_row_get_uuid(results.rows[j]),
1371 &rows[k].uuid)) {
1372 rows[k].class->count++;
1373 }
1374 }
1375 }
1376 ovsdb_row_set_destroy(&results);
1377
34582733 1378 printf("query %2"PRIuSIZE":", i);
f85f8ebb
BP
1379 for (j = 0; j < n_rows; j++) {
1380 int count = rows[j].class->count;
1381
1382 if (j % 5 == 0) {
1383 putchar(' ');
1384 }
1385 if (count > 1) {
1386 /* Dup! */
1387 printf("%d", count);
1388 exit_code = 1;
1389 } else if (count == 1) {
1390 putchar("abcdefghijklmnopqrstuvwxyz"[rows[j].class - classes]);
1391 } else {
1392 putchar('-');
1393 }
1394 }
1395 putchar('\n');
1396
1397 ovsdb_condition_destroy(&cnd);
1398 }
1399 json_destroy(json);
1400
9ecd6449
WT
1401 for (i = 0; i < n_classes; i++) {
1402 ovsdb_row_destroy(classes[i].example);
1403 }
1404
f85f8ebb
BP
1405 ovsdb_table_destroy(table); /* Also destroys 'ts'. */
1406
dd7e1cbd
WT
1407 free(rows);
1408 free(classes);
f85f8ebb
BP
1409 exit(exit_code);
1410}
1411
0d0f05b9 1412static void
1636c761 1413do_parse_schema(struct ovs_cmdl_context *ctx)
0d0f05b9
BP
1414{
1415 struct ovsdb_schema *schema;
1416 struct json *json;
1417
1636c761 1418 json = parse_json(ctx->argv[1]);
0d0f05b9
BP
1419 check_ovsdb_error(ovsdb_schema_from_json(json, &schema));
1420 json_destroy(json);
1421 print_and_free_json(ovsdb_schema_to_json(schema));
1422 ovsdb_schema_destroy(schema);
1423}
1424
f85f8ebb 1425static void
e51879e9 1426do_execute__(struct ovs_cmdl_context *ctx, bool ro)
f85f8ebb
BP
1427{
1428 struct ovsdb_schema *schema;
1429 struct json *json;
1430 struct ovsdb *db;
1431 int i;
1432
1433 /* Create database. */
1636c761 1434 json = parse_json(ctx->argv[1]);
f85f8ebb
BP
1435 check_ovsdb_error(ovsdb_schema_from_json(json, &schema));
1436 json_destroy(json);
bd06962a 1437 db = ovsdb_create(schema);
f85f8ebb 1438
1636c761 1439 for (i = 2; i < ctx->argc; i++) {
f85f8ebb
BP
1440 struct json *params, *result;
1441 char *s;
1442
1636c761 1443 params = parse_json(ctx->argv[i]);
d6db7b3c 1444 result = ovsdb_execute(db, NULL, params, ro, NULL, NULL, 0, NULL);
f85f8ebb
BP
1445 s = json_to_string(result, JSSF_SORT);
1446 printf("%s\n", s);
93ff0290 1447 free(s);
f85f8ebb
BP
1448 json_destroy(params);
1449 json_destroy(result);
1450 }
1451
1452 ovsdb_destroy(db);
1453}
1454
e51879e9
AZ
1455static void
1456do_execute_ro(struct ovs_cmdl_context *ctx)
1457{
1458 do_execute__(ctx, true);
1459}
1460
1461static void
1462do_execute(struct ovs_cmdl_context *ctx)
1463{
1464 do_execute__(ctx, false);
1465}
1466
f85f8ebb
BP
1467struct test_trigger {
1468 struct ovsdb_trigger trigger;
1469 int number;
1470};
1471
1472static void
1473do_trigger_dump(struct test_trigger *t, long long int now, const char *title)
1474{
1475 struct json *result;
1476 char *s;
1477
1478 result = ovsdb_trigger_steal_result(&t->trigger);
1479 s = json_to_string(result, JSSF_SORT);
1480 printf("t=%lld: trigger %d (%s): %s\n", now, t->number, title, s);
93ff0290 1481 free(s);
f85f8ebb
BP
1482 json_destroy(result);
1483 ovsdb_trigger_destroy(&t->trigger);
1484 free(t);
1485}
1486
1487static void
1636c761 1488do_trigger(struct ovs_cmdl_context *ctx)
f85f8ebb
BP
1489{
1490 struct ovsdb_schema *schema;
e317253b 1491 struct ovsdb_session session;
b4e8d170 1492 struct ovsdb_server server;
f85f8ebb
BP
1493 struct json *json;
1494 struct ovsdb *db;
1495 long long int now;
1496 int number;
1497 int i;
1498
1499 /* Create database. */
1636c761 1500 json = parse_json(ctx->argv[1]);
f85f8ebb
BP
1501 check_ovsdb_error(ovsdb_schema_from_json(json, &schema));
1502 json_destroy(json);
bd06962a 1503 db = ovsdb_create(schema);
f85f8ebb 1504
b4e8d170
BP
1505 ovsdb_server_init(&server);
1506 ovsdb_server_add_db(&server, db);
1507 ovsdb_session_init(&session, &server);
e317253b 1508
f85f8ebb
BP
1509 now = 0;
1510 number = 0;
1636c761
RB
1511 for (i = 2; i < ctx->argc; i++) {
1512 struct json *params = parse_json(ctx->argv[i]);
f85f8ebb
BP
1513 if (params->type == JSON_ARRAY
1514 && json_array(params)->n == 2
1515 && json_array(params)->elems[0]->type == JSON_STRING
1516 && !strcmp(json_string(json_array(params)->elems[0]), "advance")
1517 && json_array(params)->elems[1]->type == JSON_INTEGER) {
1518 now += json_integer(json_array(params)->elems[1]);
1519 json_destroy(params);
1520 } else {
1521 struct test_trigger *t = xmalloc(sizeof *t);
d6db7b3c
LR
1522 ovsdb_trigger_init(&session, db, &t->trigger, params, now, false,
1523 NULL, NULL);
f85f8ebb
BP
1524 t->number = number++;
1525 if (ovsdb_trigger_is_complete(&t->trigger)) {
1526 do_trigger_dump(t, now, "immediate");
1527 } else {
1528 printf("t=%lld: new trigger %d\n", now, t->number);
1529 }
1530 }
1531
1532 ovsdb_trigger_run(db, now);
417e7e66
BW
1533 while (!ovs_list_is_empty(&session.completions)) {
1534 do_trigger_dump(CONTAINER_OF(ovs_list_pop_front(&session.completions),
f85f8ebb
BP
1535 struct test_trigger, trigger.node),
1536 now, "delayed");
1537 }
1538
1539 ovsdb_trigger_wait(db, now);
1540 poll_immediate_wake();
1541 poll_block();
1542 }
1543
b4e8d170 1544 ovsdb_server_destroy(&server);
f85f8ebb
BP
1545 ovsdb_destroy(db);
1546}
1547
1548static void
1636c761 1549do_help(struct ovs_cmdl_context *ctx OVS_UNUSED)
f85f8ebb
BP
1550{
1551 usage();
1552}
1553\f
1554/* "transact" command. */
1555
1556static struct ovsdb *do_transact_db;
1557static struct ovsdb_txn *do_transact_txn;
1558static struct ovsdb_table *do_transact_table;
1559
1560static void
1636c761 1561do_transact_commit(struct ovs_cmdl_context *ctx OVS_UNUSED)
f85f8ebb 1562{
85683160 1563 ovsdb_error_destroy(ovsdb_txn_commit(do_transact_txn, false));
f85f8ebb
BP
1564 do_transact_txn = NULL;
1565}
1566
1567static void
1636c761 1568do_transact_abort(struct ovs_cmdl_context *ctx OVS_UNUSED)
f85f8ebb
BP
1569{
1570 ovsdb_txn_abort(do_transact_txn);
1571 do_transact_txn = NULL;
1572}
1573
1574static void
1575uuid_from_integer(int integer, struct uuid *uuid)
1576{
1577 uuid_zero(uuid);
1578 uuid->parts[3] = integer;
1579}
1580
1581static const struct ovsdb_row *
1582do_transact_find_row(const char *uuid_string)
1583{
1584 const struct ovsdb_row *row;
1585 struct uuid uuid;
1586
1587 uuid_from_integer(atoi(uuid_string), &uuid);
1588 row = ovsdb_table_get_row(do_transact_table, &uuid);
1589 if (!row) {
1590 ovs_fatal(0, "table does not contain row with UUID "UUID_FMT,
1591 UUID_ARGS(&uuid));
1592 }
1593 return row;
1594}
1595
1596static void
1597do_transact_set_integer(struct ovsdb_row *row, const char *column_name,
1598 int integer)
1599{
1600 if (integer != -1) {
1601 const struct ovsdb_column *column;
1602
1603 column = ovsdb_table_schema_get_column(do_transact_table->schema,
1604 column_name);
1605 row->fields[column->index].keys[0].integer = integer;
1606 }
1607}
1608
1609static int
1610do_transact_get_integer(const struct ovsdb_row *row, const char *column_name)
1611{
1612 const struct ovsdb_column *column;
1613
1614 column = ovsdb_table_schema_get_column(do_transact_table->schema,
1615 column_name);
1616 return row->fields[column->index].keys[0].integer;
1617}
1618
1619static void
1620do_transact_set_i_j(struct ovsdb_row *row,
1621 const char *i_string, const char *j_string)
1622{
1623 do_transact_set_integer(row, "i", atoi(i_string));
1624 do_transact_set_integer(row, "j", atoi(j_string));
1625}
1626
1627static void
1636c761 1628do_transact_insert(struct ovs_cmdl_context *ctx)
f85f8ebb
BP
1629{
1630 struct ovsdb_row *row;
1631 struct uuid *uuid;
1632
1633 row = ovsdb_row_create(do_transact_table);
1634
1635 /* Set UUID. */
1636 uuid = ovsdb_row_get_uuid_rw(row);
1636c761 1637 uuid_from_integer(atoi(ctx->argv[1]), uuid);
f85f8ebb
BP
1638 if (ovsdb_table_get_row(do_transact_table, uuid)) {
1639 ovs_fatal(0, "table already contains row with UUID "UUID_FMT,
1640 UUID_ARGS(uuid));
1641 }
1642
1636c761 1643 do_transact_set_i_j(row, ctx->argv[2], ctx->argv[3]);
f85f8ebb
BP
1644
1645 /* Insert row. */
1646 ovsdb_txn_row_insert(do_transact_txn, row);
1647}
1648
1649static void
1636c761 1650do_transact_delete(struct ovs_cmdl_context *ctx)
f85f8ebb 1651{
1636c761 1652 const struct ovsdb_row *row = do_transact_find_row(ctx->argv[1]);
f85f8ebb
BP
1653 ovsdb_txn_row_delete(do_transact_txn, row);
1654}
1655
1656static void
1636c761 1657do_transact_modify(struct ovs_cmdl_context *ctx)
f85f8ebb
BP
1658{
1659 const struct ovsdb_row *row_ro;
1660 struct ovsdb_row *row_rw;
1661
1636c761 1662 row_ro = do_transact_find_row(ctx->argv[1]);
f85f8ebb 1663 row_rw = ovsdb_txn_row_modify(do_transact_txn, row_ro);
1636c761 1664 do_transact_set_i_j(row_rw, ctx->argv[2], ctx->argv[3]);
f85f8ebb
BP
1665}
1666
1667static int
1668compare_rows_by_uuid(const void *a_, const void *b_)
1669{
1670 struct ovsdb_row *const *ap = a_;
1671 struct ovsdb_row *const *bp = b_;
1672
1673 return uuid_compare_3way(ovsdb_row_get_uuid(*ap), ovsdb_row_get_uuid(*bp));
1674}
1675
1676static void
1636c761 1677do_transact_print(struct ovs_cmdl_context *ctx OVS_UNUSED)
f85f8ebb
BP
1678{
1679 const struct ovsdb_row **rows;
1680 const struct ovsdb_row *row;
1681 size_t n_rows;
1682 size_t i;
1683
1684 n_rows = hmap_count(&do_transact_table->rows);
1685 rows = xmalloc(n_rows * sizeof *rows);
1686 i = 0;
4e8e4213 1687 HMAP_FOR_EACH (row, hmap_node, &do_transact_table->rows) {
f85f8ebb
BP
1688 rows[i++] = row;
1689 }
0a8606ee 1690 ovs_assert(i == n_rows);
f85f8ebb
BP
1691
1692 qsort(rows, n_rows, sizeof *rows, compare_rows_by_uuid);
1693
1694 for (i = 0; i < n_rows; i++) {
1695 printf("\n%"PRId32": i=%d, j=%d",
1696 ovsdb_row_get_uuid(rows[i])->parts[3],
1697 do_transact_get_integer(rows[i], "i"),
1698 do_transact_get_integer(rows[i], "j"));
1699 }
1700
1701 free(rows);
1702}
1703
1704static void
1636c761 1705do_transact(struct ovs_cmdl_context *ctx)
f85f8ebb 1706{
5f383751 1707 static const struct ovs_cmdl_command do_transact_commands[] = {
1f4a7252
RM
1708 { "commit", NULL, 0, 0, do_transact_commit, OVS_RO },
1709 { "abort", NULL, 0, 0, do_transact_abort, OVS_RO },
1710 { "insert", NULL, 2, 3, do_transact_insert, OVS_RO },
1711 { "delete", NULL, 1, 1, do_transact_delete, OVS_RO },
1712 { "modify", NULL, 2, 3, do_transact_modify, OVS_RO },
1713 { "print", NULL, 0, 0, do_transact_print, OVS_RO },
1714 { NULL, NULL, 0, 0, NULL, OVS_RO },
f85f8ebb
BP
1715 };
1716
1717 struct ovsdb_schema *schema;
1718 struct json *json;
1719 int i;
1720
1721 /* Create table. */
1722 json = parse_json("{\"name\": \"testdb\", "
1723 " \"tables\": "
1724 " {\"mytable\": "
1725 " {\"columns\": "
1726 " {\"i\": {\"type\": \"integer\"}, "
1727 " \"j\": {\"type\": \"integer\"}}}}}");
1728 check_ovsdb_error(ovsdb_schema_from_json(json, &schema));
1729 json_destroy(json);
bd06962a 1730 do_transact_db = ovsdb_create(schema);
f85f8ebb 1731 do_transact_table = ovsdb_get_table(do_transact_db, "mytable");
0a8606ee 1732 ovs_assert(do_transact_table != NULL);
f85f8ebb 1733
1636c761 1734 for (i = 1; i < ctx->argc; i++) {
f85f8ebb
BP
1735 struct json *command;
1736 size_t n_args;
1737 char **args;
1738 int j;
1636c761 1739 struct ovs_cmdl_context transact_ctx = { .argc = 0, };
f85f8ebb 1740
1636c761 1741 command = parse_json(ctx->argv[i]);
f85f8ebb
BP
1742 if (command->type != JSON_ARRAY) {
1743 ovs_fatal(0, "transaction %d must be JSON array "
1744 "with at least 1 element", i);
1745 }
1746
1747 n_args = command->u.array.n;
1748 args = xmalloc((n_args + 1) * sizeof *args);
1749 for (j = 0; j < n_args; j++) {
1750 struct json *s = command->u.array.elems[j];
1751 if (s->type != JSON_STRING) {
1752 ovs_fatal(0, "transaction %d argument %d must be JSON string",
1753 i, j);
1754 }
1755 args[j] = xstrdup(json_string(s));
1756 }
1757 args[n_args] = NULL;
1758
1759 if (!do_transact_txn) {
1760 do_transact_txn = ovsdb_txn_create(do_transact_db);
1761 }
1762
1763 for (j = 0; j < n_args; j++) {
1764 if (j) {
1765 putchar(' ');
1766 }
1767 fputs(args[j], stdout);
1768 }
1769 fputs(":", stdout);
1636c761
RB
1770 transact_ctx.argc = n_args;
1771 transact_ctx.argv = args;
1772 ovs_cmdl_run_command(&transact_ctx, do_transact_commands);
f85f8ebb
BP
1773 putchar('\n');
1774
1775 for (j = 0; j < n_args; j++) {
1776 free(args[j]);
1777 }
1778 free(args);
1779 json_destroy(command);
1780 }
1781 ovsdb_txn_abort(do_transact_txn);
1782 ovsdb_destroy(do_transact_db); /* Also destroys 'schema'. */
1783}
1784
c3bb4bd7 1785static int
e9011ac8 1786compare_link1(const void *a_, const void *b_)
c3bb4bd7 1787{
e9011ac8
BP
1788 const struct idltest_link1 *const *ap = a_;
1789 const struct idltest_link1 *const *bp = b_;
1790 const struct idltest_link1 *a = *ap;
1791 const struct idltest_link1 *b = *bp;
c3bb4bd7
BP
1792
1793 return a->i < b->i ? -1 : a->i > b->i;
1794}
1795
32d37ce8
SA
1796static void
1797print_idl_row_updated_simple(const struct idltest_simple *s, int step)
1798{
1799 size_t i;
1800 bool updated = false;
1801
1802 for (i = 0; i < IDLTEST_SIMPLE_N_COLUMNS; i++) {
1803 if (idltest_simple_is_updated(s, i)) {
1804 if (!updated) {
1805 printf("%03d: updated columns:", step);
1806 updated = true;
1807 }
1808 printf(" %s", idltest_simple_columns[i].name);
1809 }
1810 }
1811 if (updated) {
1812 printf("\n");
1813 }
1814}
1815
1816static void
1817print_idl_row_updated_link1(const struct idltest_link1 *l1, int step)
1818{
1819 size_t i;
1820 bool updated = false;
1821
1822 for (i = 0; i < IDLTEST_LINK1_N_COLUMNS; i++) {
1823 if (idltest_link1_is_updated(l1, i)) {
1824 if (!updated) {
1825 printf("%03d: updated columns:", step);
1826 updated = true;
1827 }
1828 printf(" %s", idltest_link1_columns[i].name);
1829 }
1830 }
1831 if (updated) {
1832 printf("\n");
1833 }
1834}
1835
1836static void
1837print_idl_row_updated_link2(const struct idltest_link2 *l2, int step)
1838{
1839 size_t i;
1840 bool updated = false;
1841
1842 for (i = 0; i < IDLTEST_LINK2_N_COLUMNS; i++) {
1843 if (idltest_link2_is_updated(l2, i)) {
1844 if (!updated) {
1845 printf("%03d: updated columns:", step);
1846 updated = true;
1847 }
1848 printf(" %s", idltest_link2_columns[i].name);
1849 }
1850 }
1851 if (updated) {
1852 printf("\n");
1853 }
1854}
1855
932104f4
SA
1856static void
1857print_idl_row_simple(const struct idltest_simple *s, int step)
1858{
1859 size_t i;
1860
1861 printf("%03d: i=%"PRId64" r=%g b=%s s=%s u="UUID_FMT" ia=[",
1862 step, s->i, s->r, s->b ? "true" : "false",
1863 s->s, UUID_ARGS(&s->u));
1864 for (i = 0; i < s->n_ia; i++) {
1865 printf("%s%"PRId64, i ? " " : "", s->ia[i]);
1866 }
1867 printf("] ra=[");
1868 for (i = 0; i < s->n_ra; i++) {
1869 printf("%s%g", i ? " " : "", s->ra[i]);
1870 }
1871 printf("] ba=[");
1872 for (i = 0; i < s->n_ba; i++) {
1873 printf("%s%s", i ? " " : "", s->ba[i] ? "true" : "false");
1874 }
1875 printf("] sa=[");
1876 for (i = 0; i < s->n_sa; i++) {
1877 printf("%s%s", i ? " " : "", s->sa[i]);
1878 }
1879 printf("] ua=[");
1880 for (i = 0; i < s->n_ua; i++) {
1881 printf("%s"UUID_FMT, i ? " " : "", UUID_ARGS(&s->ua[i]));
1882 }
1883 printf("] uuid="UUID_FMT"\n", UUID_ARGS(&s->header_.uuid));
32d37ce8 1884 print_idl_row_updated_simple(s, step);
932104f4
SA
1885}
1886
1887static void
1888print_idl_row_link1(const struct idltest_link1 *l1, int step)
1889{
1890 struct idltest_link1 **links;
1891 size_t i;
1892
1893 printf("%03d: i=%"PRId64" k=", step, l1->i);
1894 if (l1->k) {
1895 printf("%"PRId64, l1->k->i);
1896 }
1897 printf(" ka=[");
1898 links = xmemdup(l1->ka, l1->n_ka * sizeof *l1->ka);
1899 qsort(links, l1->n_ka, sizeof *links, compare_link1);
1900 for (i = 0; i < l1->n_ka; i++) {
1901 printf("%s%"PRId64, i ? " " : "", links[i]->i);
1902 }
1903 free(links);
1904 printf("] l2=");
1905 if (l1->l2) {
1906 printf("%"PRId64, l1->l2->i);
1907 }
1908 printf(" uuid="UUID_FMT"\n", UUID_ARGS(&l1->header_.uuid));
32d37ce8 1909 print_idl_row_updated_link1(l1, step);
932104f4
SA
1910}
1911
1912static void
1913print_idl_row_link2(const struct idltest_link2 *l2, int step)
1914{
1915 printf("%03d: i=%"PRId64" l1=", step, l2->i);
1916 if (l2->l1) {
1917 printf("%"PRId64, l2->l1->i);
1918 }
1919 printf(" uuid="UUID_FMT"\n", UUID_ARGS(&l2->header_.uuid));
32d37ce8 1920 print_idl_row_updated_link2(l2, step);
932104f4
SA
1921}
1922
c3bb4bd7
BP
1923static void
1924print_idl(struct ovsdb_idl *idl, int step)
1925{
1926 const struct idltest_simple *s;
e9011ac8
BP
1927 const struct idltest_link1 *l1;
1928 const struct idltest_link2 *l2;
c3bb4bd7
BP
1929 int n = 0;
1930
1931 IDLTEST_SIMPLE_FOR_EACH (s, idl) {
932104f4 1932 print_idl_row_simple(s, step);
c3bb4bd7
BP
1933 n++;
1934 }
e9011ac8 1935 IDLTEST_LINK1_FOR_EACH (l1, idl) {
932104f4
SA
1936 print_idl_row_link1(l1, step);
1937 n++;
1938 }
1939 IDLTEST_LINK2_FOR_EACH (l2, idl) {
1940 print_idl_row_link2(l2, step);
1941 n++;
1942 }
1943 if (!n) {
1944 printf("%03d: empty\n", step);
1945 }
1946}
c3bb4bd7 1947
932104f4
SA
1948static void
1949print_idl_track(struct ovsdb_idl *idl, int step, unsigned int seqno)
1950{
1951 const struct idltest_simple *s;
1952 const struct idltest_link1 *l1;
1953 const struct idltest_link2 *l2;
1954 int n = 0;
1955
1956 IDLTEST_SIMPLE_FOR_EACH_TRACKED (s, idl) {
1957 if (idltest_simple_row_get_seqno(s, OVSDB_IDL_CHANGE_DELETE) >= seqno) {
1958 printf("%03d: ##deleted## uuid="UUID_FMT"\n", step, UUID_ARGS(&s->header_.uuid));
1959 } else {
1960 print_idl_row_simple(s, step);
c3bb4bd7 1961 }
932104f4
SA
1962 n++;
1963 }
1964 IDLTEST_LINK1_FOR_EACH_TRACKED (l1, idl) {
1965 if (idltest_simple_row_get_seqno(s, OVSDB_IDL_CHANGE_DELETE) >= seqno) {
1966 printf("%03d: ##deleted## uuid="UUID_FMT"\n", step, UUID_ARGS(&s->header_.uuid));
1967 } else {
1968 print_idl_row_link1(l1, step);
e9011ac8 1969 }
e9011ac8
BP
1970 n++;
1971 }
932104f4
SA
1972 IDLTEST_LINK2_FOR_EACH_TRACKED (l2, idl) {
1973 if (idltest_simple_row_get_seqno(s, OVSDB_IDL_CHANGE_DELETE) >= seqno) {
1974 printf("%03d: ##deleted## uuid="UUID_FMT"\n", step, UUID_ARGS(&s->header_.uuid));
1975 } else {
1976 print_idl_row_link2(l2, step);
e9011ac8 1977 }
c3bb4bd7
BP
1978 n++;
1979 }
1980 if (!n) {
1981 printf("%03d: empty\n", step);
1982 }
1983}
1984
c3bb4bd7
BP
1985static void
1986parse_uuids(const struct json *json, struct ovsdb_symbol_table *symtab,
1987 size_t *n)
1988{
1989 struct uuid uuid;
1990
1991 if (json->type == JSON_STRING && uuid_from_string(&uuid, json->u.string)) {
34582733 1992 char *name = xasprintf("#%"PRIuSIZE"#", *n);
2d2d6d4a
BP
1993 fprintf(stderr, "%s = "UUID_FMT"\n", name, UUID_ARGS(&uuid));
1994 ovsdb_symbol_table_put(symtab, name, &uuid, false);
c3bb4bd7
BP
1995 free(name);
1996 *n += 1;
1997 } else if (json->type == JSON_ARRAY) {
1998 size_t i;
1999
2000 for (i = 0; i < json->u.array.n; i++) {
2001 parse_uuids(json->u.array.elems[i], symtab, n);
2002 }
2003 } else if (json->type == JSON_OBJECT) {
2004 const struct shash_node *node;
2005
2006 SHASH_FOR_EACH (node, json_object(json)) {
2007 parse_uuids(node->data, symtab, n);
2008 }
2009 }
2010}
2011
2012static void
2013substitute_uuids(struct json *json, const struct ovsdb_symbol_table *symtab)
2014{
2015 if (json->type == JSON_STRING) {
2d2d6d4a 2016 const struct ovsdb_symbol *symbol;
c3bb4bd7 2017
2d2d6d4a
BP
2018 symbol = ovsdb_symbol_table_get(symtab, json->u.string);
2019 if (symbol) {
c3bb4bd7 2020 free(json->u.string);
2d2d6d4a 2021 json->u.string = xasprintf(UUID_FMT, UUID_ARGS(&symbol->uuid));
c3bb4bd7
BP
2022 }
2023 } else if (json->type == JSON_ARRAY) {
2024 size_t i;
2025
2026 for (i = 0; i < json->u.array.n; i++) {
2027 substitute_uuids(json->u.array.elems[i], symtab);
2028 }
2029 } else if (json->type == JSON_OBJECT) {
2030 const struct shash_node *node;
2031
2032 SHASH_FOR_EACH (node, json_object(json)) {
2033 substitute_uuids(node->data, symtab);
2034 }
2035 }
2036}
2037
475281c0
BP
2038static const struct idltest_simple *
2039idltest_find_simple(struct ovsdb_idl *idl, int i)
2040{
2041 const struct idltest_simple *s;
2042
2043 IDLTEST_SIMPLE_FOR_EACH (s, idl) {
2044 if (s->i == i) {
2045 return s;
2046 }
2047 }
2048 return NULL;
2049}
2050
2051static void
2052idl_set(struct ovsdb_idl *idl, char *commands, int step)
2053{
2054 char *cmd, *save_ptr1 = NULL;
2055 struct ovsdb_idl_txn *txn;
2056 enum ovsdb_idl_txn_status status;
b54e22e9 2057 bool increment = false;
475281c0
BP
2058
2059 txn = ovsdb_idl_txn_create(idl);
11990a52 2060 ovsdb_idl_check_consistency(idl);
475281c0
BP
2061 for (cmd = strtok_r(commands, ",", &save_ptr1); cmd;
2062 cmd = strtok_r(NULL, ",", &save_ptr1)) {
2063 char *save_ptr2 = NULL;
2064 char *name, *arg1, *arg2, *arg3;
2065
2066 name = strtok_r(cmd, " ", &save_ptr2);
2067 arg1 = strtok_r(NULL, " ", &save_ptr2);
2068 arg2 = strtok_r(NULL, " ", &save_ptr2);
2069 arg3 = strtok_r(NULL, " ", &save_ptr2);
2070
2071 if (!strcmp(name, "set")) {
2072 const struct idltest_simple *s;
2073
2074 if (!arg3) {
2075 ovs_fatal(0, "\"set\" command requires 3 arguments");
2076 }
2077
2078 s = idltest_find_simple(idl, atoi(arg1));
2079 if (!s) {
2080 ovs_fatal(0, "\"set\" command asks for nonexistent "
2081 "i=%d", atoi(arg1));
2082 }
2083
2084 if (!strcmp(arg2, "b")) {
2085 idltest_simple_set_b(s, atoi(arg3));
2086 } else if (!strcmp(arg2, "s")) {
2087 idltest_simple_set_s(s, arg3);
2088 } else if (!strcmp(arg2, "u")) {
2089 struct uuid uuid;
bca51200
BP
2090 if (!uuid_from_string(&uuid, arg3)) {
2091 ovs_fatal(0, "\"%s\" is not a valid UUID", arg3);
2092 }
475281c0
BP
2093 idltest_simple_set_u(s, uuid);
2094 } else if (!strcmp(arg2, "r")) {
2095 idltest_simple_set_r(s, atof(arg3));
2096 } else {
2097 ovs_fatal(0, "\"set\" command asks for unknown column %s",
2098 arg2);
2099 }
2100 } else if (!strcmp(name, "insert")) {
2101 struct idltest_simple *s;
2102
2103 if (!arg1 || arg2) {
6484e7cd 2104 ovs_fatal(0, "\"insert\" command requires 1 argument");
475281c0
BP
2105 }
2106
2107 s = idltest_simple_insert(txn);
2108 idltest_simple_set_i(s, atoi(arg1));
2109 } else if (!strcmp(name, "delete")) {
2110 const struct idltest_simple *s;
2111
2112 if (!arg1 || arg2) {
6484e7cd 2113 ovs_fatal(0, "\"delete\" command requires 1 argument");
475281c0
BP
2114 }
2115
2116 s = idltest_find_simple(idl, atoi(arg1));
2117 if (!s) {
6484e7cd 2118 ovs_fatal(0, "\"delete\" command asks for nonexistent "
475281c0
BP
2119 "i=%d", atoi(arg1));
2120 }
2121 idltest_simple_delete(s);
a91c6104
BP
2122 } else if (!strcmp(name, "verify")) {
2123 const struct idltest_simple *s;
2124
2125 if (!arg2 || arg3) {
2126 ovs_fatal(0, "\"verify\" command requires 2 arguments");
2127 }
2128
2129 s = idltest_find_simple(idl, atoi(arg1));
2130 if (!s) {
2131 ovs_fatal(0, "\"verify\" command asks for nonexistent "
2132 "i=%d", atoi(arg1));
2133 }
2134
2135 if (!strcmp(arg2, "i")) {
2136 idltest_simple_verify_i(s);
2137 } else if (!strcmp(arg2, "b")) {
2138 idltest_simple_verify_b(s);
2139 } else if (!strcmp(arg2, "s")) {
2140 idltest_simple_verify_s(s);
2141 } else if (!strcmp(arg2, "u")) {
2142 idltest_simple_verify_s(s);
2143 } else if (!strcmp(arg2, "r")) {
2144 idltest_simple_verify_r(s);
2145 } else {
2146 ovs_fatal(0, "\"verify\" command asks for unknown column %s",
2147 arg2);
2148 }
b54e22e9 2149 } else if (!strcmp(name, "increment")) {
94fbe1aa
BP
2150 const struct idltest_simple *s;
2151
2152 if (!arg1 || arg2) {
2153 ovs_fatal(0, "\"increment\" command requires 1 argument");
b54e22e9 2154 }
94fbe1aa
BP
2155
2156 s = idltest_find_simple(idl, atoi(arg1));
2157 if (!s) {
2158 ovs_fatal(0, "\"set\" command asks for nonexistent "
2159 "i=%d", atoi(arg1));
2160 }
2161
de32cec7
BP
2162 ovsdb_idl_txn_increment(txn, &s->header_, &idltest_simple_col_i,
2163 false);
b54e22e9 2164 increment = true;
2096903b
BP
2165 } else if (!strcmp(name, "abort")) {
2166 ovsdb_idl_txn_abort(txn);
11990a52 2167 ovsdb_idl_check_consistency(idl);
2096903b
BP
2168 break;
2169 } else if (!strcmp(name, "destroy")) {
2170 printf("%03d: destroy\n", step);
2171 ovsdb_idl_txn_destroy(txn);
11990a52 2172 ovsdb_idl_check_consistency(idl);
2096903b 2173 return;
475281c0
BP
2174 } else {
2175 ovs_fatal(0, "unknown command %s", name);
2176 }
11990a52 2177 ovsdb_idl_check_consistency(idl);
475281c0
BP
2178 }
2179
af96ccd2 2180 status = ovsdb_idl_txn_commit_block(txn);
b54e22e9 2181 printf("%03d: commit, status=%s",
475281c0 2182 step, ovsdb_idl_txn_status_to_string(status));
b54e22e9
BP
2183 if (increment) {
2184 printf(", increment=%"PRId64,
2185 ovsdb_idl_txn_get_increment_new_value(txn));
2186 }
2187 putchar('\n');
475281c0 2188 ovsdb_idl_txn_destroy(txn);
11990a52 2189 ovsdb_idl_check_consistency(idl);
475281c0
BP
2190}
2191
16ebb90e
LS
2192static const struct ovsdb_idl_table_class *
2193find_table_class(const char *name)
2194{
2195 if (!strcmp(name, "simple")) {
2196 return &idltest_table_simple;
2197 } else if (!strcmp(name, "link1")) {
2198 return &idltest_table_link1;
2199 } else if (!strcmp(name, "link2")) {
2200 return &idltest_table_link2;
2201 }
2202 return NULL;
2203}
2204
2205static void
0164e367
BP
2206parse_simple_json_clause(struct ovsdb_idl_condition *cond,
2207 enum ovsdb_function function,
2208 const char *column, const struct json *arg)
2209{
2210 if (!strcmp(column, "b")) {
2211 idltest_simple_add_clause_b(cond, function, json_boolean(arg));
2212 } else if (!strcmp(column, "i")) {
2213 idltest_simple_add_clause_i(cond, function, json_integer(arg));
2214 } else if (!strcmp(column, "s")) {
2215 idltest_simple_add_clause_s(cond, function, json_string(arg));
2216 } else if (!strcmp(column, "u")) {
16ebb90e 2217 struct uuid uuid;
0164e367
BP
2218 if (!uuid_from_string(&uuid, json_string(arg))) {
2219 ovs_fatal(0, "\"%s\" is not a valid UUID", json_string(arg));
16ebb90e 2220 }
0164e367
BP
2221 idltest_simple_add_clause_u(cond, function, uuid);
2222 } else if (!strcmp(column, "r")) {
2223 idltest_simple_add_clause_r(cond, function, json_real(arg));
16ebb90e 2224 } else {
0164e367 2225 ovs_fatal(0, "Unsupported columns name %s", column);
16ebb90e
LS
2226 }
2227}
2228
2229static void
0164e367
BP
2230parse_link1_json_clause(struct ovsdb_idl_condition *cond,
2231 enum ovsdb_function function,
2232 const char *column, const struct json *arg)
16ebb90e 2233{
0164e367
BP
2234 if (!strcmp(column, "i")) {
2235 idltest_link1_add_clause_i(cond, function, json_integer(arg));
16ebb90e 2236 } else {
0164e367 2237 ovs_fatal(0, "Unsupported columns name %s", column);
16ebb90e
LS
2238 }
2239}
2240
2241static void
0164e367
BP
2242parse_link2_json_clause(struct ovsdb_idl_condition *cond,
2243 enum ovsdb_function function,
2244 const char *column, const struct json *arg)
16ebb90e 2245{
0164e367
BP
2246 if (!strcmp(column, "i")) {
2247 idltest_link2_add_clause_i(cond, function, json_integer(arg));
16ebb90e 2248 } else {
0164e367 2249 ovs_fatal(0, "Unsupported columns name %s", column);
16ebb90e
LS
2250 }
2251}
2252
2253static void
2254update_conditions(struct ovsdb_idl *idl, char *commands)
2255{
2256 char *cmd, *save_ptr1 = NULL;
2257 const struct ovsdb_idl_table_class *tc;
16ebb90e
LS
2258
2259 for (cmd = strtok_r(commands, ";", &save_ptr1); cmd;
2260 cmd = strtok_r(NULL, ";", &save_ptr1)) {
16ebb90e
LS
2261 char *save_ptr2 = NULL;
2262 char *table_name = strtok_r(cmd, " ", &save_ptr2);
2263 struct json *json = parse_json(save_ptr2);
2264 int i;
2265
2266 if (json->type != JSON_ARRAY) {
2267 ovs_fatal(0, "condition should be an array");
2268 }
2269
2270 tc = find_table_class(table_name);
2271 if (!tc) {
2272 ovs_fatal(0, "Table %s does not exist", table_name);
2273 }
2274
0164e367 2275 struct ovsdb_idl_condition cond = OVSDB_IDL_CONDITION_INIT(&cond);
16ebb90e 2276 for (i = 0; i < json->u.array.n; i++) {
0164e367
BP
2277 const struct json *clause = json->u.array.elems[i];
2278 if (clause->type == JSON_TRUE) {
2279 ovsdb_idl_condition_add_clause_true(&cond);
2280 } else if (clause->type != JSON_ARRAY || clause->u.array.n != 3
2281 || clause->u.array.elems[0]->type != JSON_STRING
2282 || clause->u.array.elems[1]->type != JSON_STRING) {
2283 ovs_fatal(0, "Error parsing condition");
2284 } else {
2285 enum ovsdb_function function;
2286 const char *function_s = json_string(clause->u.array.elems[1]);
2287 struct ovsdb_error *error = ovsdb_function_from_string(
2288 function_s, &function);
2289 if (error) {
2290 ovs_fatal(0, "unknown clause function %s", function_s);
2291 }
2292
2293 const char *column = json_string(clause->u.array.elems[0]);
2294 const struct json *arg = clause->u.array.elems[2];
2295 if (!strcmp(table_name, "simple")) {
2296 parse_simple_json_clause(&cond, function, column, arg);
2297 } else if (!strcmp(table_name, "link1")) {
2298 parse_link1_json_clause(&cond, function, column, arg);
2299 } else if (!strcmp(table_name, "link2")) {
2300 parse_link2_json_clause(&cond, function, column, arg);
2301 }
16ebb90e
LS
2302 }
2303 }
46437c52
AZ
2304
2305 unsigned int seqno = ovsdb_idl_get_condition_seqno(idl);
2306 unsigned int next_seqno = ovsdb_idl_set_condition(idl, tc, &cond);
2307 if (seqno == next_seqno ) {
2308 ovs_fatal(0, "condition unchanged");
2309 }
0164e367 2310 ovsdb_idl_condition_destroy(&cond);
7e160f66 2311 json_destroy(json);
16ebb90e
LS
2312 }
2313}
2314
c3bb4bd7 2315static void
1636c761 2316do_idl(struct ovs_cmdl_context *ctx)
c3bb4bd7
BP
2317{
2318 struct jsonrpc *rpc;
2319 struct ovsdb_idl *idl;
2320 unsigned int seqno = 0;
2321 struct ovsdb_symbol_table *symtab;
2322 size_t n_uuids = 0;
2323 int step = 0;
2324 int error;
2325 int i;
932104f4 2326 bool track;
c3bb4bd7 2327
932104f4
SA
2328 track = ((struct test_ovsdb_pvt_context *)(ctx->pvt))->track;
2329
1636c761
RB
2330 idl = ovsdb_idl_create(ctx->argv[1], &idltest_idl_class, true, true);
2331 if (ctx->argc > 2) {
c3bb4bd7
BP
2332 struct stream *stream;
2333
1636c761 2334 error = stream_open_block(jsonrpc_stream_open(ctx->argv[1], &stream,
f125905c 2335 DSCP_DEFAULT), &stream);
c3bb4bd7 2336 if (error) {
1636c761 2337 ovs_fatal(error, "failed to connect to \"%s\"", ctx->argv[1]);
c3bb4bd7
BP
2338 }
2339 rpc = jsonrpc_open(stream);
2340 } else {
2341 rpc = NULL;
2342 }
2343
932104f4
SA
2344 if (track) {
2345 ovsdb_idl_track_add_all(idl);
2346 }
2347
76a6e630 2348 setvbuf(stdout, NULL, _IONBF, 0);
0d0f05b9 2349
c3bb4bd7 2350 symtab = ovsdb_symbol_table_create();
0164e367
BP
2351 const char cond_s[] = "condition ";
2352 if (ctx->argc > 2 && strstr(ctx->argv[2], cond_s)) {
2353 update_conditions(idl, ctx->argv[2] + strlen(cond_s));
16ebb90e
LS
2354 printf("%03d: change conditions\n", step++);
2355 i = 3;
2356 } else {
2357 i = 2;
2358 }
2359 for (; i < ctx->argc; i++) {
1636c761 2360 char *arg = ctx->argv[i];
c3bb4bd7 2361 struct jsonrpc_msg *request, *reply;
c3bb4bd7 2362
0d0f05b9
BP
2363 if (*arg == '+') {
2364 /* The previous transaction didn't change anything. */
2365 arg++;
2366 } else {
4ea21243 2367 /* Wait for update. */
854a94d9
BP
2368 for (;;) {
2369 ovsdb_idl_run(idl);
11990a52 2370 ovsdb_idl_check_consistency(idl);
854a94d9
BP
2371 if (ovsdb_idl_get_seqno(idl) != seqno) {
2372 break;
2373 }
4ea21243
BP
2374 jsonrpc_run(rpc);
2375
2376 ovsdb_idl_wait(idl);
2377 jsonrpc_wait(rpc);
2378 poll_block();
2379 }
2380
2381 /* Print update. */
932104f4
SA
2382 if (track) {
2383 print_idl_track(idl, step++, ovsdb_idl_get_seqno(idl));
2384 ovsdb_idl_track_clear(idl);
2385 } else {
2386 print_idl(idl, step++);
2387 }
0d0f05b9 2388 }
4ea21243 2389 seqno = ovsdb_idl_get_seqno(idl);
c3bb4bd7 2390
0d0f05b9 2391 if (!strcmp(arg, "reconnect")) {
c3bb4bd7
BP
2392 printf("%03d: reconnect\n", step++);
2393 ovsdb_idl_force_reconnect(idl);
0164e367
BP
2394 } else if (!strncmp(arg, cond_s, strlen(cond_s))) {
2395 update_conditions(idl, arg + strlen(cond_s));
16ebb90e 2396 printf("%03d: change conditions\n", step++);
0d0f05b9
BP
2397 } else if (arg[0] != '[') {
2398 idl_set(idl, arg, step++);
c3bb4bd7 2399 } else {
0d0f05b9 2400 struct json *json = parse_json(arg);
c3bb4bd7
BP
2401 substitute_uuids(json, symtab);
2402 request = jsonrpc_create_request("transact", json, NULL);
2403 error = jsonrpc_transact_block(rpc, request, &reply);
d35f8e72 2404 if (error || reply->error) {
c3bb4bd7
BP
2405 ovs_fatal(error, "jsonrpc transaction failed");
2406 }
2407 printf("%03d: ", step++);
2408 if (reply->result) {
2409 parse_uuids(reply->result, symtab, &n_uuids);
2410 }
2411 json_destroy(reply->id);
2412 reply->id = NULL;
2413 print_and_free_json(jsonrpc_msg_to_json(reply));
2414 }
2415 }
2416 ovsdb_symbol_table_destroy(symtab);
2417
2418 if (rpc) {
2419 jsonrpc_close(rpc);
2420 }
854a94d9
BP
2421 for (;;) {
2422 ovsdb_idl_run(idl);
11990a52 2423 ovsdb_idl_check_consistency(idl);
854a94d9
BP
2424 if (ovsdb_idl_get_seqno(idl) != seqno) {
2425 break;
2426 }
4ea21243
BP
2427 ovsdb_idl_wait(idl);
2428 poll_block();
2429 }
2430 print_idl(idl, step++);
932104f4 2431 ovsdb_idl_track_clear(idl);
c3bb4bd7
BP
2432 ovsdb_idl_destroy(idl);
2433 printf("%03d: done\n", step);
2434}
2435
7251075c
EA
2436static void
2437print_idl_row_simple2(const struct idltest_simple2 *s, int step)
2438{
2439 size_t i;
2440 const struct ovsdb_datum *smap, *imap;
2441
2442 smap = idltest_simple2_get_smap(s, OVSDB_TYPE_STRING, OVSDB_TYPE_STRING);
2443 imap = idltest_simple2_get_imap(s, OVSDB_TYPE_INTEGER, OVSDB_TYPE_STRING);
2444 printf("%03d: name=%s smap=[",
2445 step, s->name);
2446 for (i = 0; i < smap->n; i++) {
2447 printf("[%s : %s]%s", smap->keys[i].string, smap->values[i].string,
2448 i < smap->n-1? ",": "");
2449 }
2450 printf("] imap=[");
2451 for (i = 0; i < imap->n; i++) {
2452 printf("[%"PRId64" : %s]%s", imap->keys[i].integer, imap->values[i].string,
2453 i < imap->n-1? ",":"");
2454 }
2455 printf("]\n");
2456}
2457
2458static void
2459dump_simple2(struct ovsdb_idl *idl,
2460 const struct idltest_simple2 *myRow,
2461 int step)
2462{
2463 IDLTEST_SIMPLE2_FOR_EACH(myRow, idl) {
2464 print_idl_row_simple2(myRow, step);
2465 }
2466}
2467
7251075c
EA
2468static void
2469do_idl_partial_update_map_column(struct ovs_cmdl_context *ctx)
2470{
2471 struct ovsdb_idl *idl;
2472 struct ovsdb_idl_txn *myTxn;
2473 const struct idltest_simple2 *myRow;
2474 const struct ovsdb_datum *smap, *imap OVS_UNUSED;
2475 int step = 0;
2476 char key_to_delete[100];
2477
7251075c
EA
2478 idl = ovsdb_idl_create(ctx->argv[1], &idltest_idl_class, false, true);
2479 ovsdb_idl_add_table(idl, &idltest_table_simple2);
2480 ovsdb_idl_add_column(idl, &idltest_simple2_col_name);
2481 ovsdb_idl_add_column(idl, &idltest_simple2_col_smap);
2482 ovsdb_idl_add_column(idl, &idltest_simple2_col_imap);
2483 ovsdb_idl_get_initial_snapshot(idl);
2484 setvbuf(stdout, NULL, _IONBF, 0);
2485 ovsdb_idl_run(idl);
2486
f1ab6e06 2487 /* Display original data in table. */
7251075c
EA
2488 myRow = NULL;
2489 printf("%03d: Getting records\n", step++);
2490 dump_simple2(idl, myRow, step++);
2491
f1ab6e06 2492 /* Insert new elements in different map columns. */
7251075c
EA
2493 myRow = idltest_simple2_first(idl);
2494 myTxn = ovsdb_idl_txn_create(idl);
6ee95363 2495 idltest_simple2_get_smap(myRow, OVSDB_TYPE_STRING,
7251075c
EA
2496 OVSDB_TYPE_STRING);
2497 idltest_simple2_update_smap_setkey(myRow, "key1", "myList1");
2498 imap = idltest_simple2_get_imap(myRow, OVSDB_TYPE_INTEGER,
2499 OVSDB_TYPE_STRING);
2500 idltest_simple2_update_imap_setkey(myRow, 3, "myids2");
2501 idltest_simple2_set_name(myRow, "String2");
2502 ovsdb_idl_txn_commit_block(myTxn);
2503 ovsdb_idl_txn_destroy(myTxn);
2504 ovsdb_idl_get_initial_snapshot(idl);
2505 printf("%03d: After insert element\n", step++);
2506 dump_simple2(idl, myRow, step++);
2507
f1ab6e06 2508 /* Insert duplicate element. */
7251075c
EA
2509 myTxn = ovsdb_idl_txn_create(idl);
2510 idltest_simple2_update_smap_setkey(myRow, "key1", "myList1");
2511 ovsdb_idl_txn_commit_block(myTxn);
2512 ovsdb_idl_txn_destroy(myTxn);
2513 ovsdb_idl_get_initial_snapshot(idl);
2514 printf("%03d: After insert duplicated element\n", step++);
2515 dump_simple2(idl, myRow, step++);
2516
f1ab6e06 2517 /* Deletes an element of a map column. */
7251075c
EA
2518 myRow = idltest_simple2_first(idl);
2519 myTxn = ovsdb_idl_txn_create(idl);
2520 smap = idltest_simple2_get_smap(myRow, OVSDB_TYPE_STRING,
2521 OVSDB_TYPE_STRING);
2522 strcpy(key_to_delete, smap->keys[0].string);
2523 idltest_simple2_update_smap_delkey(myRow, smap->keys[0].string);
2524 ovsdb_idl_txn_commit_block(myTxn);
2525 ovsdb_idl_txn_destroy(myTxn);
2526 ovsdb_idl_get_initial_snapshot(idl);
2527 printf("%03d: After delete element\n", step++);
2528 dump_simple2(idl, myRow, step++);
2529
f1ab6e06 2530 /* Try to delete a deleted element of a map column. */
7251075c
EA
2531 myTxn = ovsdb_idl_txn_create(idl);
2532 idltest_simple2_update_smap_delkey(myRow, key_to_delete);
2533 ovsdb_idl_txn_commit_block(myTxn);
2534 ovsdb_idl_txn_destroy(myTxn);
2535 ovsdb_idl_get_initial_snapshot(idl);
2536 printf("%03d: After trying to delete a deleted element\n", step++);
2537 dump_simple2(idl, myRow, step++);
2538
98a1a320 2539 ovsdb_idl_destroy(idl);
7251075c
EA
2540 printf("%03d: End test\n", step);
2541 return;
2542}
2543
f1ab6e06
RM
2544static void
2545print_idl_row_simple3(const struct idltest_simple3 *s, int step)
2546{
2547 size_t i;
2548 const struct ovsdb_datum *uset;
2549 const struct ovsdb_datum *uref;
2550
2551 uset = idltest_simple3_get_uset(s, OVSDB_TYPE_UUID);
2552 printf("%03d: name=%s uset=[",
2553 step, s->name);
2554 for (i = 0; i < uset->n; i++) {
2555 printf("["UUID_FMT"]%s", UUID_ARGS(&(uset->keys[i].uuid)), i < uset->n-1? ",": "");
2556 }
2557 uref = idltest_simple3_get_uref(s, OVSDB_TYPE_UUID);
2558 printf("] uref=[");
2559 for (i = 0; i < uref->n; i++) {
2560 printf("["UUID_FMT"]%s", UUID_ARGS(&(uref->keys[i].uuid)), i < uref->n-1? ",": "");
2561 }
2562 printf("]\n");
2563}
2564
2565static void
2566dump_simple3(struct ovsdb_idl *idl,
2567 const struct idltest_simple3 *myRow,
2568 int step)
2569{
2570 IDLTEST_SIMPLE3_FOR_EACH(myRow, idl) {
2571 print_idl_row_simple3(myRow, step);
2572 }
2573}
2574
2575static void
2576do_idl_partial_update_set_column(struct ovs_cmdl_context *ctx)
2577{
2578 struct ovsdb_idl *idl;
2579 struct ovsdb_idl_txn *myTxn;
2580 const struct idltest_simple3 *myRow;
2581 struct idltest_simple4 *myRow2;
2582 const struct ovsdb_datum *uset OVS_UNUSED;
2583 const struct ovsdb_datum *uref OVS_UNUSED;
2584 int step = 0;
2585
f1ab6e06
RM
2586 idl = ovsdb_idl_create(ctx->argv[1], &idltest_idl_class, false, true);
2587 ovsdb_idl_add_table(idl, &idltest_table_simple3);
2588 ovsdb_idl_add_column(idl, &idltest_simple3_col_name);
2589 ovsdb_idl_add_column(idl, &idltest_simple3_col_uset);
2590 ovsdb_idl_add_column(idl, &idltest_simple3_col_uref);
2591 ovsdb_idl_add_table(idl, &idltest_table_simple4);
2592 ovsdb_idl_add_column(idl, &idltest_simple4_col_name);
2593 ovsdb_idl_get_initial_snapshot(idl);
2594 setvbuf(stdout, NULL, _IONBF, 0);
2595 ovsdb_idl_run(idl);
2596
2597 /* Display original data in table. */
2598 myRow = NULL;
2599 printf("%03d: Getting records\n", step++);
2600 dump_simple3(idl, myRow, step++);
2601
2602 /* Insert new elements in different map columns. */
2603 myRow = idltest_simple3_first(idl);
2604 myTxn = ovsdb_idl_txn_create(idl);
2605 idltest_simple3_get_uset(myRow, OVSDB_TYPE_UUID);
2606 struct uuid uuid_to_add;
2607 uuid_from_string(&uuid_to_add, "001e43d2-dd3f-4616-ab6a-83a490bb0991");
2608 idltest_simple3_update_uset_addvalue(myRow, uuid_to_add);
2609 idltest_simple3_set_name(myRow, "String2");
2610 ovsdb_idl_txn_commit_block(myTxn);
2611 ovsdb_idl_txn_destroy(myTxn);
2612 ovsdb_idl_get_initial_snapshot(idl);
2613 printf("%03d: After rename+add new value\n", step++);
2614 dump_simple3(idl, myRow, step++);
2615
2616 /* Insert duplicate element. */
2617 myTxn = ovsdb_idl_txn_create(idl);
2618 struct uuid uuid_to_add2;
2619 uuid_from_string(&uuid_to_add2, "0026b3ba-571b-4729-8227-d860a5210ab8");
2620 idltest_simple3_update_uset_addvalue(myRow, uuid_to_add2);
2621 ovsdb_idl_txn_commit_block(myTxn);
2622 ovsdb_idl_txn_destroy(myTxn);
2623 ovsdb_idl_get_initial_snapshot(idl);
2624 printf("%03d: After add new value\n", step++);
2625 dump_simple3(idl, myRow, step++);
2626
2627 /* Deletes an element of a set column. */
2628 myRow = idltest_simple3_first(idl);
2629 myTxn = ovsdb_idl_txn_create(idl);
2630 uset = idltest_simple3_get_uset(myRow, OVSDB_TYPE_UUID);
2631 idltest_simple3_update_uset_delvalue(myRow, uuid_to_add);
2632 ovsdb_idl_txn_commit_block(myTxn);
2633 ovsdb_idl_txn_destroy(myTxn);
2634 ovsdb_idl_get_initial_snapshot(idl);
2635 printf("%03d: After delete value\n", step++);
2636 dump_simple3(idl, myRow, step++);
2637
2638 /* Try to delete a deleted element of a map column. */
2639 myRow = idltest_simple3_first(idl);
2640 myTxn = ovsdb_idl_txn_create(idl);
2641 idltest_simple3_update_uset_delvalue(myRow, uuid_to_add);
2642 ovsdb_idl_txn_commit_block(myTxn);
2643 ovsdb_idl_txn_destroy(myTxn);
2644 ovsdb_idl_get_initial_snapshot(idl);
2645 printf("%03d: After trying to delete a deleted value\n", step++);
2646 dump_simple3(idl, myRow, step++);
2647
2648 /* Adds to a table and update a strong reference in another table. */
2649 myRow = idltest_simple3_first(idl);
2650 myTxn = ovsdb_idl_txn_create(idl);
2651 myRow2 = idltest_simple4_insert(myTxn);
2652 idltest_simple4_set_name(myRow2, "test");
2653 idltest_simple3_update_uref_addvalue(myRow, myRow2);
2654 ovsdb_idl_txn_commit_block(myTxn);
2655 ovsdb_idl_txn_destroy(myTxn);
2656 ovsdb_idl_get_initial_snapshot(idl);
2657 printf("%03d: After add to other table + set of strong ref\n", step++);
2658 dump_simple3(idl, myRow, step++);
98a1a320 2659 ovsdb_idl_destroy(idl);
f1ab6e06
RM
2660 printf("%03d: End test\n", step);
2661 return;
2662}
2663
0a8606ee
LR
2664static int
2665test_idl_compound_index_single_column(struct ovsdb_idl *idl,
2666 struct ovsdb_idl_index_cursor *sCursor,
2667 struct ovsdb_idl_index_cursor *iCursor)
2668{
2669 const struct idltest_simple *myRow;
2670 struct ovsdb_idl_txn *txn;
2671 int step = 0;
2672
2673 /* Display records by string index -> sCursor */
2674 ++step;
2675 IDLTEST_SIMPLE_FOR_EACH_BYINDEX (myRow, sCursor) {
2676 printf("%03d: s=%s i=%"PRId64" b=%s r=%f\n", step, myRow->s,
2677 myRow->i, myRow->b?"True":"False", myRow->r);
2678 }
2679 /* Display records by integer index -> iCursor */
2680 ++step;
2681 IDLTEST_SIMPLE_FOR_EACH_BYINDEX (myRow, iCursor) {
2682 printf("%03d: i=%"PRId64" s=%s b=%s r=%f\n", step, myRow->i,
2683 myRow->s, myRow->b?"True":"False", myRow->r);
2684 }
2685 /* Display records by string index -> sCursor with filtering
2686 * where s=\"List001\
2687 */
2688 ++step;
2689 struct idltest_simple *equal;
2690 equal = idltest_simple_index_init_row(idl, &idltest_table_simple);
2691 idltest_simple_index_set_s(equal, "List001");
2692 ovs_assert(strcmp(equal->s, "List001") == 0);
2693 IDLTEST_SIMPLE_FOR_EACH_EQUAL (myRow, sCursor, equal) {
2694 printf("%03d: s=%s i=%"PRId64" b=%s r=%f\n", step, myRow->s,
2695 myRow->i, myRow->b?"True":"False", myRow->r);
2696 }
2697 /* Display records by integer index -> iCursor with filtering where i=5 */
2698 ++step;
2699 idltest_simple_index_set_i(equal, 5);
2700 ovs_assert(equal->i == 5);
2701 IDLTEST_SIMPLE_FOR_EACH_EQUAL (myRow, iCursor, equal) {
2702 printf("%03d: i=%"PRId64" s=%s b=%s r=%f\n", step, myRow->i,
2703 myRow->s, myRow->b?"True":"False", myRow->r);
2704 }
2705 /* Display records by integer index -> iCursor in range i=[3,7] */
2706 ++step;
2707 struct idltest_simple *from, *to;
2708 from = idltest_simple_index_init_row(idl, &idltest_table_simple);
2709 idltest_simple_index_set_i(from, 3);
2710 ovs_assert(from->i == 3);
2711 to = idltest_simple_index_init_row(idl, &idltest_table_simple);
2712 idltest_simple_index_set_i(to, 7);
2713 ovs_assert(to->i == 7);
2714 IDLTEST_SIMPLE_FOR_EACH_RANGE (myRow, iCursor, from, to) {
2715 printf("%03d: i=%"PRId64" s=%s b=%s r=%f\n", step, myRow->i,
2716 myRow->s, myRow->b?"True":"False", myRow->r);
2717 }
2718 /* Delete record i=4 and insert i=54 by integer index -> iCursor */
2719 ++step;
2720 struct idltest_simple *toDelete, *toInsert;
2721 toDelete = idltest_simple_index_init_row(idl, &idltest_table_simple);
2722 idltest_simple_index_set_i(toDelete, 4);
2723 ovs_assert(toDelete->i == 4);
2724 myRow = idltest_simple_index_find(iCursor, toDelete);
2725 ovs_assert(myRow);
2726 ovs_assert(myRow->i == 4);
2727 txn = ovsdb_idl_txn_create(idl);
2728 idltest_simple_delete(myRow);
2729 toInsert = idltest_simple_insert(txn);
2730 idltest_simple_set_i(toInsert, 54);
2731 idltest_simple_set_s(toInsert, "Lista054");
2732 ovsdb_idl_txn_commit_block(txn);
2733 ovsdb_idl_txn_destroy(txn);
2734 idltest_simple_index_set_i(to, 60);
2735 printf("Expected 60, stored %"PRId64"\n", to->i);
2736 ovs_assert(to->i == 60);
2737 IDLTEST_SIMPLE_FOR_EACH_RANGE (myRow, iCursor, from, to) {
2738 printf("%03d: i=%"PRId64" s=%s b=%s r=%f\n", step, myRow->i,
2739 myRow->s, myRow->b?"True":"False", myRow->r);
2740 }
2741
2742 /* Test special-case range, "from" and "to" are both NULL,
2743 * which is interpreted as the range from -infinity to +infinity. */
2744 ++step;
2745 IDLTEST_SIMPLE_FOR_EACH_RANGE (myRow, iCursor, NULL, NULL) {
2746 printf("%03d: i=%"PRId64" s=%s b=%s r=%f\n", step, myRow->i,
2747 myRow->s, myRow->b?"True":"False", myRow->r);
2748 }
2749
2750 /* Free the temporal rows */
2751 idltest_simple_index_destroy_row(from);
2752 idltest_simple_index_destroy_row(to);
2753 idltest_simple_index_destroy_row(equal);
2754 return step;
2755}
2756
2757static int
2758test_idl_compound_index_double_column(struct ovsdb_idl *idl,
2759 struct ovsdb_idl_index_cursor *siCursor,
2760 struct ovsdb_idl_index_cursor *sidCursor,
2761 struct ovsdb_idl_index_cursor *isCursor,
2762 struct ovsdb_idl_index_cursor *idsCursor)
2763{
2764 const struct idltest_simple *myRow;
2765 int step = 0;
2766
2767 /* Display records by string-integer index -> siCursor */
2768 step++;
2769 IDLTEST_SIMPLE_FOR_EACH_BYINDEX (myRow, siCursor) {
2770 printf("%03d: s=%s i=%"PRId64" b=%s r=%f\n", step, myRow->s, myRow->i,
2771 myRow->b?"True":"False", myRow->r);
2772 }
2773 /* Display records by string-integer(down order) index -> sidCursor */
2774 step++;
2775 IDLTEST_SIMPLE_FOR_EACH_BYINDEX (myRow, sidCursor) {
2776 printf("%03d: s=%s i=%"PRId64" b=%s r=%f\n", step, myRow->s, myRow->i,
2777 myRow->b?"True":"False", myRow->r);
2778 }
2779 /* Display records by string-integer index -> siCursor with filtering
2780 * where s="List000" and i=10
2781 */
2782 step++;
2783 struct idltest_simple *equal;
2784 equal = idltest_simple_index_init_row(idl, &idltest_table_simple);
2785 idltest_simple_index_set_s(equal, "List000");
2786 ovs_assert(strcmp(equal->s, "List000") == 0);
2787 idltest_simple_index_set_i(equal, 10);
2788 ovs_assert(equal->i == 10);
2789 IDLTEST_SIMPLE_FOR_EACH_EQUAL (myRow, siCursor, equal) {
2790 printf("%03d: s=%s i=%"PRId64" b=%s r=%f\n", step, myRow->s, myRow->i,
2791 myRow->b?"True":"False", myRow->r);
2792 }
2793 /* Display records by string-integer index -> siCursor in range i=[0,100]
2794 * and s=[\"List002\",\"List003\"]
2795 */
2796 step++;
2797 struct idltest_simple *from, *to;
2798 from = idltest_simple_index_init_row(idl, &idltest_table_simple);
2799 to = idltest_simple_index_init_row(idl, &idltest_table_simple);
2800 idltest_simple_index_set_i(from, 0);
2801 ovs_assert(from->i == 0);
2802 idltest_simple_index_set_s(from, "List001");
2803 ovs_assert(strcmp(from->s, "List001") == 0);
2804 idltest_simple_index_set_i(to, 100);
2805 ovs_assert(to->i == 100);
2806 idltest_simple_index_set_s(to, "List005");
2807 ovs_assert(strcmp(to->s, "List005")==0);
2808 IDLTEST_SIMPLE_FOR_EACH_RANGE (myRow, siCursor, from, to) {
2809 printf("%03d: s=%s i=%"PRId64" b=%s r=%f\n", step, myRow->s, myRow->i,
2810 myRow->b?"True":"False", myRow->r);
2811 }
2812 /* Display records using integer-string index. */
2813 step++;
2814 IDLTEST_SIMPLE_FOR_EACH_BYINDEX (myRow, isCursor) {
2815 printf("%03d: i=%"PRId64" s=%s b=%s r=%f\n", step, myRow->i, myRow->s,
2816 myRow->b?"True":"False", myRow->r);
2817 }
2818 /* Display records using integer(descend)-string index. */
2819 step++;
2820 IDLTEST_SIMPLE_FOR_EACH_BYINDEX (myRow, idsCursor) {
2821 printf("%03d: i=%"PRId64" s=%s b=%s r=%f\n", step, myRow->i, myRow->s,
2822 myRow->b?"True":"False", myRow->r);
2823 }
2824
2825 idltest_simple_index_destroy_row(to);
2826 idltest_simple_index_destroy_row(from);
2827 idltest_simple_index_destroy_row(equal);
2828 return step;
2829}
2830
2831static void
2832do_idl_compound_index(struct ovs_cmdl_context *ctx)
2833{
2834 struct ovsdb_idl *idl;
2835 struct ovsdb_idl_index_cursor sCursor, iCursor, siCursor, sidCursor,
2836 isCursor, idsCursor;
2837 enum TESTS { IDL_COMPOUND_INDEX_WITH_SINGLE_COLUMN,
2838 IDL_COMPOUND_INDEX_WITH_DOUBLE_COLUMN
2839 };
2840 int step = 0;
2841 int i;
2842
2843 idl = ovsdb_idl_create(ctx->argv[1], &idltest_idl_class, false, true);
2844
2845 /* Add tables/columns and initialize index data needed for tests */
2846 ovsdb_idl_add_table(idl, &idltest_table_simple);
2847 ovsdb_idl_add_column(idl, &idltest_simple_col_s);
2848 ovsdb_idl_add_column(idl, &idltest_simple_col_i);
2849 ovsdb_idl_add_column(idl, &idltest_simple_col_r);
2850 ovsdb_idl_add_column(idl, &idltest_simple_col_b);
2851
2852 struct ovsdb_idl_index *index;
2853 index = ovsdb_idl_create_index(idl, &idltest_table_simple, "string");
2854 ovsdb_idl_index_add_column(index, &idltest_simple_col_s, OVSDB_INDEX_ASC,
2855 NULL);
2856
2857 index = ovsdb_idl_create_index(idl, &idltest_table_simple, "integer");
2858 ovsdb_idl_index_add_column(index, &idltest_simple_col_i, OVSDB_INDEX_ASC,
2859 NULL);
2860
2861 index = ovsdb_idl_create_index(idl, &idltest_table_simple,
2862 "string-integer");
2863 ovsdb_idl_index_add_column(index, &idltest_simple_col_s, OVSDB_INDEX_ASC,
2864 NULL);
2865 ovsdb_idl_index_add_column(index, &idltest_simple_col_i, OVSDB_INDEX_ASC,
2866 NULL);
2867
2868 index = ovsdb_idl_create_index(idl, &idltest_table_simple,
2869 "string-integerd");
2870 ovsdb_idl_index_add_column(index, &idltest_simple_col_s, OVSDB_INDEX_ASC,
2871 NULL);
2872 ovsdb_idl_index_add_column(index, &idltest_simple_col_i, OVSDB_INDEX_DESC,
2873 NULL);
2874
2875 index = ovsdb_idl_create_index(idl, &idltest_table_simple,
2876 "integer-string");
2877 ovsdb_idl_index_add_column(index, &idltest_simple_col_i, OVSDB_INDEX_ASC,
2878 NULL);
2879 ovsdb_idl_index_add_column(index, &idltest_simple_col_s, OVSDB_INDEX_ASC,
2880 NULL);
2881
2882 index = ovsdb_idl_create_index(idl, &idltest_table_simple,
2883 "integerd-string");
2884 ovsdb_idl_index_add_column(index, &idltest_simple_col_i, OVSDB_INDEX_DESC,
2885 NULL);
2886 ovsdb_idl_index_add_column(index, &idltest_simple_col_s, OVSDB_INDEX_ASC,
2887 NULL);
2888
2889 /* wait for replica to be updated */
2890 ovsdb_idl_get_initial_snapshot(idl);
2891
2892 /* Initialize cursors to be used by indexes */
2893 ovsdb_idl_initialize_cursor(idl, &idltest_table_simple, "string",
2894 &sCursor);
2895 ovsdb_idl_initialize_cursor(idl, &idltest_table_simple, "integer",
2896 &iCursor);
2897 ovsdb_idl_initialize_cursor(idl, &idltest_table_simple, "string-integer",
2898 &siCursor);
2899 ovsdb_idl_initialize_cursor(idl, &idltest_table_simple, "string-integerd",
2900 &sidCursor);
2901 ovsdb_idl_initialize_cursor(idl, &idltest_table_simple, "integer-string",
2902 &isCursor);
2903 ovsdb_idl_initialize_cursor(idl, &idltest_table_simple, "integerd-string",
2904 &idsCursor);
2905
2906 setvbuf(stdout, NULL, _IONBF, 0);
2907 int test_to_run = -1;
2908 for (i = 2; i < ctx->argc; i++) {
2909 char *arg = ctx->argv[i];
2910
2911 if (strcmp(arg,"idl_compound_index_single_column") == 0) {
2912 test_to_run = IDL_COMPOUND_INDEX_WITH_SINGLE_COLUMN;
2913 } else if (strcmp(arg, "idl_compound_index_double_column") == 0) {
2914 test_to_run = IDL_COMPOUND_INDEX_WITH_DOUBLE_COLUMN;
2915 }
2916
2917 switch (test_to_run) {
2918 case IDL_COMPOUND_INDEX_WITH_SINGLE_COLUMN:
2919 test_idl_compound_index_single_column(idl, &sCursor, &iCursor);
2920 break;
2921 case IDL_COMPOUND_INDEX_WITH_DOUBLE_COLUMN:
2922 test_idl_compound_index_double_column(idl, &siCursor,
2923 &sidCursor, &isCursor, &idsCursor);
2924 break;
2925 default:
2926 printf("%03d: Test %s not implemented.\n", step++, arg);
2927 }
2928 }
2929 ovsdb_idl_destroy(idl);
2930 printf("%03d: done\n", step);
2931}
2932
5f383751 2933static struct ovs_cmdl_command all_commands[] = {
1f4a7252
RM
2934 { "log-io", NULL, 2, INT_MAX, do_log_io, OVS_RO },
2935 { "default-atoms", NULL, 0, 0, do_default_atoms, OVS_RO },
2936 { "default-data", NULL, 0, 0, do_default_data, OVS_RO },
2937 { "diff-data", NULL, 3, INT_MAX, do_diff_data, OVS_RO },
2938 { "parse-atomic-type", NULL, 1, 1, do_parse_atomic_type, OVS_RO },
2939 { "parse-base-type", NULL, 1, 1, do_parse_base_type, OVS_RO },
2940 { "parse-type", NULL, 1, 1, do_parse_type, OVS_RO },
2941 { "parse-atoms", NULL, 2, INT_MAX, do_parse_atoms, OVS_RO },
2942 { "parse-atom-strings", NULL, 2, INT_MAX, do_parse_atom_strings, OVS_RO },
2943 { "parse-data", NULL, 2, INT_MAX, do_parse_data, OVS_RO },
2944 { "parse-data-strings", NULL, 2, INT_MAX, do_parse_data_strings, OVS_RO },
2945 { "sort-atoms", NULL, 2, 2, do_sort_atoms, OVS_RO },
2946 { "parse-column", NULL, 2, 2, do_parse_column, OVS_RO },
2947 { "parse-table", NULL, 2, 3, do_parse_table, OVS_RO },
2948 { "parse-rows", NULL, 2, INT_MAX, do_parse_rows, OVS_RO },
2949 { "compare-rows", NULL, 2, INT_MAX, do_compare_rows, OVS_RO },
2950 { "parse-conditions", NULL, 2, INT_MAX, do_parse_conditions, OVS_RO },
2951 { "evaluate-conditions", NULL, 3, 3, do_evaluate_conditions, OVS_RO },
2952 { "evaluate-conditions-any", NULL, 3, 3, do_evaluate_conditions_any, OVS_RO },
2953 { "compare-conditions", NULL, 2, 2, do_compare_conditions, OVS_RO },
2954 { "parse-mutations", NULL, 2, INT_MAX, do_parse_mutations, OVS_RO },
2955 { "execute-mutations", NULL, 3, 3, do_execute_mutations, OVS_RO },
2956 { "query", NULL, 3, 3, do_query, OVS_RO },
2957 { "query-distinct", NULL, 4, 4, do_query_distinct, OVS_RO },
2958 { "transact", NULL, 1, INT_MAX, do_transact, OVS_RO },
2959 { "parse-schema", NULL, 1, 1, do_parse_schema, OVS_RO },
2960 { "execute", NULL, 2, INT_MAX, do_execute, OVS_RO },
2961 { "execute-readonly", NULL, 2, INT_MAX, do_execute_ro, OVS_RO },
2962 { "trigger", NULL, 2, INT_MAX, do_trigger, OVS_RO },
2963 { "idl", NULL, 1, INT_MAX, do_idl, OVS_RO },
0a8606ee 2964 { "idl-compound-index", NULL, 2, 2, do_idl_compound_index, OVS_RW },
7251075c 2965 { "idl-partial-update-map-column", NULL, 1, INT_MAX,
1f4a7252 2966 do_idl_partial_update_map_column, OVS_RO },
f1ab6e06 2967 { "idl-partial-update-set-column", NULL, 1, INT_MAX,
1f4a7252
RM
2968 do_idl_partial_update_set_column, OVS_RO },
2969 { "help", NULL, 0, INT_MAX, do_help, OVS_RO },
2970 { NULL, NULL, 0, 0, NULL, OVS_RO },
f85f8ebb 2971};
d2586fce 2972
5f383751 2973static struct ovs_cmdl_command *
d2586fce
GS
2974get_all_commands(void)
2975{
2976 return all_commands;
2977}