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