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