]> git.proxmox.com Git - mirror_ovs.git/blame - ovsdb/execution.c
ovsdb: Fix support for systems where libpcre is not installed.
[mirror_ovs.git] / ovsdb / execution.c
CommitLineData
e084f690 1/* Copyright (c) 2009, 2010 Nicira Networks
f85f8ebb
BP
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include <config.h>
17
18#include <assert.h>
19#include <limits.h>
20
21#include "column.h"
22#include "condition.h"
bd06962a 23#include "file.h"
f85f8ebb 24#include "json.h"
e9f8f936 25#include "mutation.h"
f85f8ebb
BP
26#include "ovsdb-data.h"
27#include "ovsdb-error.h"
28#include "ovsdb-parser.h"
29#include "ovsdb.h"
30#include "query.h"
31#include "row.h"
32#include "table.h"
33#include "timeval.h"
34#include "transaction.h"
35
36struct ovsdb_execution {
37 struct ovsdb *db;
38 struct ovsdb_txn *txn;
39 struct ovsdb_symbol_table *symtab;
40 bool durable;
41
42 /* Triggers. */
43 long long int elapsed_msec;
44 long long int timeout_msec;
45};
46
47typedef struct ovsdb_error *ovsdb_operation_executor(struct ovsdb_execution *,
48 struct ovsdb_parser *,
49 struct json *result);
50
f85f8ebb
BP
51static ovsdb_operation_executor ovsdb_execute_insert;
52static ovsdb_operation_executor ovsdb_execute_select;
53static ovsdb_operation_executor ovsdb_execute_update;
e9f8f936 54static ovsdb_operation_executor ovsdb_execute_mutate;
f85f8ebb
BP
55static ovsdb_operation_executor ovsdb_execute_delete;
56static ovsdb_operation_executor ovsdb_execute_wait;
57static ovsdb_operation_executor ovsdb_execute_commit;
58static ovsdb_operation_executor ovsdb_execute_abort;
2d2d6d4a 59static ovsdb_operation_executor ovsdb_execute_declare;
d171b584 60static ovsdb_operation_executor ovsdb_execute_comment;
f85f8ebb
BP
61
62static ovsdb_operation_executor *
63lookup_executor(const char *name)
64{
65 struct ovsdb_operation {
66 const char *name;
67 ovsdb_operation_executor *executor;
68 };
69
70 static const struct ovsdb_operation operations[] = {
71 { "insert", ovsdb_execute_insert },
72 { "select", ovsdb_execute_select },
73 { "update", ovsdb_execute_update },
e9f8f936 74 { "mutate", ovsdb_execute_mutate },
f85f8ebb
BP
75 { "delete", ovsdb_execute_delete },
76 { "wait", ovsdb_execute_wait },
77 { "commit", ovsdb_execute_commit },
78 { "abort", ovsdb_execute_abort },
2d2d6d4a 79 { "declare", ovsdb_execute_declare },
d171b584 80 { "comment", ovsdb_execute_comment },
f85f8ebb
BP
81 };
82
83 size_t i;
84
85 for (i = 0; i < ARRAY_SIZE(operations); i++) {
86 const struct ovsdb_operation *c = &operations[i];
87 if (!strcmp(c->name, name)) {
88 return c->executor;
89 }
90 }
91 return NULL;
92}
93
94struct json *
95ovsdb_execute(struct ovsdb *db, const struct json *params,
96 long long int elapsed_msec, long long int *timeout_msec)
97{
98 struct ovsdb_execution x;
99 struct ovsdb_error *error;
100 struct json *results;
101 size_t n_operations;
102 size_t i;
103
104 if (params->type != JSON_ARRAY) {
105 struct ovsdb_error *error;
106
107 error = ovsdb_syntax_error(params, NULL, "array expected");
108 results = ovsdb_error_to_json(error);
109 ovsdb_error_destroy(error);
110 return results;
111 }
112
113 x.db = db;
114 x.txn = ovsdb_txn_create(db);
115 x.symtab = ovsdb_symbol_table_create();
116 x.durable = false;
117 x.elapsed_msec = elapsed_msec;
118 x.timeout_msec = LLONG_MAX;
119 results = NULL;
120
121 results = json_array_create_empty();
122 n_operations = params->u.array.n;
123 error = NULL;
124 for (i = 0; i < n_operations; i++) {
125 struct json *operation = params->u.array.elems[i];
126 struct ovsdb_error *parse_error;
127 struct ovsdb_parser parser;
128 struct json *result;
129 const struct json *op;
130
131 /* Parse and execute operation. */
132 ovsdb_parser_init(&parser, operation,
133 "ovsdb operation %zu of %zu", i + 1, n_operations);
134 op = ovsdb_parser_member(&parser, "op", OP_ID);
135 result = json_object_create();
136 if (op) {
137 const char *op_name = json_string(op);
138 ovsdb_operation_executor *executor = lookup_executor(op_name);
139 if (executor) {
140 error = executor(&x, &parser, result);
141 } else {
5764c0ed
BP
142 ovsdb_parser_raise_error(&parser, "No operation \"%s\"",
143 op_name);
f85f8ebb
BP
144 }
145 } else {
146 assert(ovsdb_parser_has_error(&parser));
147 }
148
149 /* A parse error overrides any other error.
150 * An error overrides any other result. */
151 parse_error = ovsdb_parser_finish(&parser);
152 if (parse_error) {
153 ovsdb_error_destroy(error);
154 error = parse_error;
155 }
156 if (error) {
157 json_destroy(result);
158 result = ovsdb_error_to_json(error);
159 }
160 if (error && !strcmp(ovsdb_error_get_tag(error), "not supported")
161 && timeout_msec) {
162 ovsdb_txn_abort(x.txn);
163 *timeout_msec = x.timeout_msec;
e084f690
BP
164
165 json_destroy(result);
f85f8ebb 166 json_destroy(results);
e084f690
BP
167 results = NULL;
168 goto exit;
f85f8ebb
BP
169 }
170
171 /* Add result to array. */
172 json_array_add(results, result);
173 if (error) {
174 break;
175 }
176 }
177
178 if (!error) {
bd06962a 179 error = ovsdb_txn_commit(x.txn, x.durable);
f85f8ebb
BP
180 if (error) {
181 json_array_add(results, ovsdb_error_to_json(error));
182 }
183 } else {
184 ovsdb_txn_abort(x.txn);
185 }
186
187 while (json_array(results)->n < n_operations) {
188 json_array_add(results, json_null_create());
189 }
190
e084f690 191exit:
f85f8ebb
BP
192 ovsdb_error_destroy(error);
193 ovsdb_symbol_table_destroy(x.symtab);
194
195 return results;
196}
197
198struct ovsdb_error *
199ovsdb_execute_commit(struct ovsdb_execution *x, struct ovsdb_parser *parser,
200 struct json *result UNUSED)
201{
202 const struct json *durable;
203
204 durable = ovsdb_parser_member(parser, "durable", OP_BOOLEAN);
205 if (durable && json_boolean(durable)) {
206 x->durable = true;
207 }
208 return NULL;
209}
210
211static struct ovsdb_error *
212ovsdb_execute_abort(struct ovsdb_execution *x UNUSED,
213 struct ovsdb_parser *parser UNUSED,
214 struct json *result UNUSED)
215{
216 return ovsdb_error("aborted", "aborted by request");
217}
218
f85f8ebb
BP
219static struct ovsdb_table *
220parse_table(struct ovsdb_execution *x,
221 struct ovsdb_parser *parser, const char *member)
222{
223 struct ovsdb_table *table;
224 const char *table_name;
225 const struct json *json;
226
227 json = ovsdb_parser_member(parser, member, OP_ID);
228 if (!json) {
229 return NULL;
230 }
231 table_name = json_string(json);
232
233 table = shash_find_data(&x->db->tables, table_name);
234 if (!table) {
235 ovsdb_parser_raise_error(parser, "No table named %s.", table_name);
236 }
237 return table;
238}
239
240static WARN_UNUSED_RESULT struct ovsdb_error *
241parse_row(struct ovsdb_parser *parser, const char *member,
242 const struct ovsdb_table *table,
243 const struct ovsdb_symbol_table *symtab,
244 struct ovsdb_row **rowp, struct ovsdb_column_set *columns)
245{
246 struct ovsdb_error *error;
247 const struct json *json;
248 struct ovsdb_row *row;
249
250 *rowp = NULL;
251
252 if (!table) {
253 return OVSDB_BUG("null table");
254 }
255 json = ovsdb_parser_member(parser, member, OP_OBJECT);
256 if (!json) {
257 return OVSDB_BUG("null row member");
258 }
259
260 row = ovsdb_row_create(table);
261 error = ovsdb_row_from_json(row, json, symtab, columns);
262 if (error) {
263 ovsdb_row_destroy(row);
264 return error;
265 } else {
266 *rowp = row;
267 return NULL;
268 }
269}
270
271struct ovsdb_error *
272ovsdb_execute_insert(struct ovsdb_execution *x, struct ovsdb_parser *parser,
273 struct json *result)
274{
275 struct ovsdb_table *table;
276 struct ovsdb_row *row = NULL;
277 const struct json *uuid_name;
278 struct ovsdb_error *error;
6e30ca63 279 struct uuid row_uuid;
f85f8ebb
BP
280
281 table = parse_table(x, parser, "table");
282 uuid_name = ovsdb_parser_member(parser, "uuid-name", OP_ID | OP_OPTIONAL);
283 error = ovsdb_parser_get_error(parser);
6e30ca63 284
6e30ca63 285 if (uuid_name) {
2d2d6d4a
BP
286 struct ovsdb_symbol *symbol;
287
288 symbol = ovsdb_symbol_table_get(x->symtab, json_string(uuid_name));
289 if (symbol) {
290 if (symbol->used) {
291 return ovsdb_syntax_error(uuid_name, "duplicate uuid-name",
292 "This \"uuid-name\" appeared on an "
293 "earlier \"insert\" operation.");
294 }
295 row_uuid = symbol->uuid;
296 symbol->used = true;
297 } else {
298 uuid_generate(&row_uuid);
299 ovsdb_symbol_table_put(x->symtab, json_string(uuid_name),
300 &row_uuid, true);
301 }
302 } else {
303 uuid_generate(&row_uuid);
6e30ca63
BP
304 }
305
f85f8ebb
BP
306 if (!error) {
307 error = parse_row(parser, "row", table, x->symtab, &row, NULL);
308 }
bd76d25d
BP
309 if (!error) {
310 /* Check constraints for columns not included in "row", in case the
311 * default values do not satisfy the constraints. We could check only
312 * the columns that have their default values by supplying an
313 * ovsdb_column_set to parse_row() above, but I suspect that this is
314 * cheaper. */
315 const struct shash_node *node;
316
317 SHASH_FOR_EACH (node, &table->schema->columns) {
318 const struct ovsdb_column *column = node->data;
319 const struct ovsdb_datum *datum = &row->fields[column->index];
320
321 /* If there are 0 keys or pairs, there's nothing to check.
322 * If there is 1, it might be a default value.
323 * If there are more, it can't be a default value, so the value has
324 * already been checked. */
325 if (datum->n == 1) {
326 error = ovsdb_datum_check_constraints(datum, &column->type);
327 if (error) {
328 ovsdb_row_destroy(row);
329 break;
330 }
331 }
332 }
333 }
f85f8ebb 334 if (!error) {
6e30ca63 335 *ovsdb_row_get_uuid_rw(row) = row_uuid;
f85f8ebb
BP
336 ovsdb_txn_row_insert(x->txn, row);
337 json_object_put(result, "uuid",
338 ovsdb_datum_to_json(&row->fields[OVSDB_COL_UUID],
339 &ovsdb_type_uuid));
f85f8ebb
BP
340 }
341 return error;
342}
343
344struct ovsdb_error *
345ovsdb_execute_select(struct ovsdb_execution *x, struct ovsdb_parser *parser,
346 struct json *result)
347{
348 struct ovsdb_table *table;
349 const struct json *where, *columns_json, *sort_json;
350 struct ovsdb_condition condition = OVSDB_CONDITION_INITIALIZER;
351 struct ovsdb_column_set columns = OVSDB_COLUMN_SET_INITIALIZER;
352 struct ovsdb_column_set sort = OVSDB_COLUMN_SET_INITIALIZER;
353 struct ovsdb_error *error;
354
355 table = parse_table(x, parser, "table");
356 where = ovsdb_parser_member(parser, "where", OP_ARRAY);
357 columns_json = ovsdb_parser_member(parser, "columns",
358 OP_ARRAY | OP_OPTIONAL);
359 sort_json = ovsdb_parser_member(parser, "sort", OP_ARRAY | OP_OPTIONAL);
360
361 error = ovsdb_parser_get_error(parser);
362 if (!error) {
363 error = ovsdb_condition_from_json(table->schema, where, x->symtab,
364 &condition);
365 }
366 if (!error) {
367 error = ovsdb_column_set_from_json(columns_json, table, &columns);
368 }
369 if (!error) {
370 error = ovsdb_column_set_from_json(sort_json, table, &sort);
371 }
372 if (!error) {
373 struct ovsdb_row_set rows = OVSDB_ROW_SET_INITIALIZER;
374
375 ovsdb_query_distinct(table, &condition, &columns, &rows);
376 ovsdb_row_set_sort(&rows, &sort);
377 json_object_put(result, "rows",
378 ovsdb_row_set_to_json(&rows, &columns));
379
380 ovsdb_row_set_destroy(&rows);
381 }
382
383 ovsdb_column_set_destroy(&columns);
384 ovsdb_column_set_destroy(&sort);
385 ovsdb_condition_destroy(&condition);
386
387 return error;
388}
389
390struct update_row_cbdata {
391 size_t n_matches;
392 struct ovsdb_txn *txn;
393 const struct ovsdb_row *row;
394 const struct ovsdb_column_set *columns;
395};
396
397static bool
398update_row_cb(const struct ovsdb_row *row, void *ur_)
399{
400 struct update_row_cbdata *ur = ur_;
401
402 ur->n_matches++;
403 if (!ovsdb_row_equal_columns(row, ur->row, ur->columns)) {
404 ovsdb_row_update_columns(ovsdb_txn_row_modify(ur->txn, row),
405 ur->row, ur->columns);
406 }
407
408 return true;
409}
410
411struct ovsdb_error *
412ovsdb_execute_update(struct ovsdb_execution *x, struct ovsdb_parser *parser,
413 struct json *result)
414{
415 struct ovsdb_table *table;
416 const struct json *where;
417 struct ovsdb_condition condition = OVSDB_CONDITION_INITIALIZER;
418 struct ovsdb_column_set columns = OVSDB_COLUMN_SET_INITIALIZER;
419 struct ovsdb_row *row = NULL;
420 struct update_row_cbdata ur;
421 struct ovsdb_error *error;
422
423 table = parse_table(x, parser, "table");
424 where = ovsdb_parser_member(parser, "where", OP_ARRAY);
425 error = ovsdb_parser_get_error(parser);
426 if (!error) {
427 error = parse_row(parser, "row", table, x->symtab, &row, &columns);
428 }
429 if (!error) {
430 error = ovsdb_condition_from_json(table->schema, where, x->symtab,
431 &condition);
432 }
433 if (!error) {
434 ur.n_matches = 0;
435 ur.txn = x->txn;
436 ur.row = row;
437 ur.columns = &columns;
438 ovsdb_query(table, &condition, update_row_cb, &ur);
439 json_object_put(result, "count", json_integer_create(ur.n_matches));
440 }
441
442 ovsdb_row_destroy(row);
443 ovsdb_column_set_destroy(&columns);
444 ovsdb_condition_destroy(&condition);
445
446 return error;
447}
448
e9f8f936
BP
449struct mutate_row_cbdata {
450 size_t n_matches;
451 struct ovsdb_txn *txn;
452 const struct ovsdb_mutation_set *mutations;
453};
454
455static bool
456mutate_row_cb(const struct ovsdb_row *row, void *mr_)
457{
458 struct mutate_row_cbdata *mr = mr_;
459
460 mr->n_matches++;
461 ovsdb_mutation_set_execute(ovsdb_txn_row_modify(mr->txn, row),
462 mr->mutations);
463
464 return true;
465}
466
467struct ovsdb_error *
468ovsdb_execute_mutate(struct ovsdb_execution *x, struct ovsdb_parser *parser,
469 struct json *result)
470{
471 struct ovsdb_table *table;
472 const struct json *where;
473 const struct json *mutations_json;
474 struct ovsdb_condition condition = OVSDB_CONDITION_INITIALIZER;
475 struct ovsdb_mutation_set mutations = OVSDB_MUTATION_SET_INITIALIZER;
476 struct ovsdb_row *row = NULL;
477 struct mutate_row_cbdata mr;
478 struct ovsdb_error *error;
479
480 table = parse_table(x, parser, "table");
481 where = ovsdb_parser_member(parser, "where", OP_ARRAY);
482 mutations_json = ovsdb_parser_member(parser, "mutations", OP_ARRAY);
483 error = ovsdb_parser_get_error(parser);
484 if (!error) {
485 error = ovsdb_mutation_set_from_json(table->schema, mutations_json,
486 x->symtab, &mutations);
487 }
488 if (!error) {
489 error = ovsdb_condition_from_json(table->schema, where, x->symtab,
490 &condition);
491 }
492 if (!error) {
493 mr.n_matches = 0;
494 mr.txn = x->txn;
495 mr.mutations = &mutations;
496 ovsdb_query(table, &condition, mutate_row_cb, &mr);
497 json_object_put(result, "count", json_integer_create(mr.n_matches));
498 }
499
500 ovsdb_row_destroy(row);
501 ovsdb_mutation_set_destroy(&mutations);
502 ovsdb_condition_destroy(&condition);
503
504 return error;
505}
506
f85f8ebb
BP
507struct delete_row_cbdata {
508 size_t n_matches;
509 const struct ovsdb_table *table;
510 struct ovsdb_txn *txn;
511};
512
513static bool
514delete_row_cb(const struct ovsdb_row *row, void *dr_)
515{
516 struct delete_row_cbdata *dr = dr_;
517
518 dr->n_matches++;
519 ovsdb_txn_row_delete(dr->txn, row);
520
521 return true;
522}
523
524struct ovsdb_error *
525ovsdb_execute_delete(struct ovsdb_execution *x, struct ovsdb_parser *parser,
526 struct json *result)
527{
528 struct ovsdb_table *table;
529 const struct json *where;
530 struct ovsdb_condition condition = OVSDB_CONDITION_INITIALIZER;
531 struct ovsdb_error *error;
532
533 where = ovsdb_parser_member(parser, "where", OP_ARRAY);
534 table = parse_table(x, parser, "table");
535 error = ovsdb_parser_get_error(parser);
536 if (!error) {
537 error = ovsdb_condition_from_json(table->schema, where, x->symtab,
538 &condition);
539 }
540 if (!error) {
541 struct delete_row_cbdata dr;
542
543 dr.n_matches = 0;
544 dr.table = table;
545 dr.txn = x->txn;
546 ovsdb_query(table, &condition, delete_row_cb, &dr);
547
548 json_object_put(result, "count", json_integer_create(dr.n_matches));
549 }
550
551 ovsdb_condition_destroy(&condition);
552
553 return error;
554}
555
556struct wait_auxdata {
557 struct ovsdb_row_hash *actual;
558 struct ovsdb_row_hash *expected;
559 bool *equal;
560};
561
562static bool
563ovsdb_execute_wait_query_cb(const struct ovsdb_row *row, void *aux_)
564{
565 struct wait_auxdata *aux = aux_;
566
567 if (ovsdb_row_hash_contains(aux->expected, row)) {
568 ovsdb_row_hash_insert(aux->actual, row);
569 return true;
570 } else {
571 /* The query row isn't in the expected result set, so the actual and
572 * expected results sets definitely differ and we can short-circuit the
573 * rest of the query. */
574 *aux->equal = false;
575 return false;
576 }
577}
578
579static struct ovsdb_error *
580ovsdb_execute_wait(struct ovsdb_execution *x, struct ovsdb_parser *parser,
581 struct json *result UNUSED)
582{
583 struct ovsdb_table *table;
584 const struct json *timeout, *where, *columns_json, *until, *rows;
585 struct ovsdb_condition condition = OVSDB_CONDITION_INITIALIZER;
586 struct ovsdb_column_set columns = OVSDB_COLUMN_SET_INITIALIZER;
587 struct ovsdb_row_hash expected = OVSDB_ROW_HASH_INITIALIZER(expected);
588 struct ovsdb_row_hash actual = OVSDB_ROW_HASH_INITIALIZER(actual);
589 struct ovsdb_error *error;
590 struct wait_auxdata aux;
591 long long int timeout_msec = 0;
592 size_t i;
593
594 timeout = ovsdb_parser_member(parser, "timeout", OP_NUMBER | OP_OPTIONAL);
595 where = ovsdb_parser_member(parser, "where", OP_ARRAY);
596 columns_json = ovsdb_parser_member(parser, "columns",
597 OP_ARRAY | OP_OPTIONAL);
598 until = ovsdb_parser_member(parser, "until", OP_STRING);
599 rows = ovsdb_parser_member(parser, "rows", OP_ARRAY);
600 table = parse_table(x, parser, "table");
601 error = ovsdb_parser_get_error(parser);
602 if (!error) {
603 error = ovsdb_condition_from_json(table->schema, where, x->symtab,
604 &condition);
605 }
606 if (!error) {
607 error = ovsdb_column_set_from_json(columns_json, table, &columns);
608 }
609 if (!error) {
610 if (timeout) {
611 timeout_msec = MIN(LLONG_MAX, json_real(timeout));
612 if (timeout_msec < 0) {
613 error = ovsdb_syntax_error(timeout, NULL,
614 "timeout must be nonnegative");
615 } else if (timeout_msec < x->timeout_msec) {
616 x->timeout_msec = timeout_msec;
617 }
618 } else {
619 timeout_msec = LLONG_MAX;
620 }
621 if (strcmp(json_string(until), "==")
622 && strcmp(json_string(until), "!=")) {
623 error = ovsdb_syntax_error(until, NULL,
624 "\"until\" must be \"==\" or \"!=\"");
625 }
626 }
627 if (!error) {
628 /* Parse "rows" into 'expected'. */
629 ovsdb_row_hash_init(&expected, &columns);
630 for (i = 0; i < rows->u.array.n; i++) {
631 struct ovsdb_error *error;
632 struct ovsdb_row *row;
633
634 row = ovsdb_row_create(table);
635 error = ovsdb_row_from_json(row, rows->u.array.elems[i], x->symtab,
636 NULL);
637 if (error) {
638 break;
639 }
640
641 if (!ovsdb_row_hash_insert(&expected, row)) {
642 /* XXX Perhaps we should abort with an error or log a
643 * warning. */
644 ovsdb_row_destroy(row);
645 }
646 }
647 }
648 if (!error) {
649 /* Execute query. */
650 bool equal = true;
651 ovsdb_row_hash_init(&actual, &columns);
652 aux.actual = &actual;
653 aux.expected = &expected;
654 aux.equal = &equal;
655 ovsdb_query(table, &condition, ovsdb_execute_wait_query_cb, &aux);
656 if (equal) {
657 /* We know that every row in 'actual' is also in 'expected'. We
658 * also know that all of the rows in 'actual' are distinct and that
659 * all of the rows in 'expected' are distinct. Therefore, if
660 * 'actual' and 'expected' have the same number of rows, then they
661 * have the same content. */
662 size_t n_actual = ovsdb_row_hash_count(&actual);
663 size_t n_expected = ovsdb_row_hash_count(&expected);
664 equal = n_actual == n_expected;
665 }
666 if (!strcmp(json_string(until), "==") != equal) {
667 if (timeout && x->elapsed_msec >= timeout_msec) {
668 if (x->elapsed_msec) {
669 error = ovsdb_error("timed out",
670 "\"wait\" timed out after %lld ms",
671 x->elapsed_msec);
672 } else {
673 error = ovsdb_error("timed out", "\"wait\" timed out");
674 }
675 } else {
676 /* ovsdb_execute() will change this, if triggers really are
677 * supported. */
678 error = ovsdb_error("not supported", "triggers not supported");
679 }
680 }
681 }
682
683
684 ovsdb_row_hash_destroy(&expected, true);
685 ovsdb_row_hash_destroy(&actual, false);
686 ovsdb_column_set_destroy(&columns);
687 ovsdb_condition_destroy(&condition);
688
689 return error;
690}
2d2d6d4a
BP
691
692static struct ovsdb_error *
693ovsdb_execute_declare(struct ovsdb_execution *x, struct ovsdb_parser *parser,
694 struct json *result)
695{
696 const struct json *uuid_name;
697 struct uuid uuid;
698
699 uuid_name = ovsdb_parser_member(parser, "uuid-name", OP_ID);
700 if (!uuid_name) {
701 return NULL;
702 }
703
704 if (ovsdb_symbol_table_get(x->symtab, json_string(uuid_name))) {
705 return ovsdb_syntax_error(uuid_name, "duplicate uuid-name",
706 "This \"uuid-name\" appeared on an "
707 "earlier \"declare\" or \"insert\" "
708 "operation.");
709 }
710
711 uuid_generate(&uuid);
712 ovsdb_symbol_table_put(x->symtab, json_string(uuid_name), &uuid, false);
f89d8180
BP
713 json_object_put(result, "uuid",
714 json_array_create_2(
715 json_string_create("uuid"),
716 json_string_create_nocopy(
717 xasprintf(UUID_FMT, UUID_ARGS(&uuid)))));
2d2d6d4a
BP
718 return NULL;
719}
d171b584
BP
720
721static struct ovsdb_error *
722ovsdb_execute_comment(struct ovsdb_execution *x, struct ovsdb_parser *parser,
723 struct json *result UNUSED)
724{
725 const struct json *comment;
726
727 comment = ovsdb_parser_member(parser, "comment", OP_STRING);
728 if (!comment) {
729 return NULL;
730 }
731 ovsdb_txn_add_comment(x->txn, json_string(comment));
732
733 return NULL;
734}