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