X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=ovsdb%2Fexecution.c;h=7ce9a3f5067245abdd5aa9fb9526da4c1901b494;hb=1089aab7136612acb86cdcd638d7d2261311531a;hp=9edc1a97123d56e14ce4c00515a8c1141c5fec15;hpb=bd06962ad334fa4631b67905fc9f43f96a908915;p=sliver-openvswitch.git diff --git a/ovsdb/execution.c b/ovsdb/execution.c index 9edc1a971..7ce9a3f50 100644 --- a/ovsdb/execution.c +++ b/ovsdb/execution.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2009 Nicira Networks +/* Copyright (c) 2009, 2010 Nicira Networks * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,6 +22,7 @@ #include "condition.h" #include "file.h" #include "json.h" +#include "mutation.h" #include "ovsdb-data.h" #include "ovsdb-error.h" #include "ovsdb-parser.h" @@ -50,10 +51,12 @@ typedef struct ovsdb_error *ovsdb_operation_executor(struct ovsdb_execution *, static ovsdb_operation_executor ovsdb_execute_insert; static ovsdb_operation_executor ovsdb_execute_select; static ovsdb_operation_executor ovsdb_execute_update; +static ovsdb_operation_executor ovsdb_execute_mutate; static ovsdb_operation_executor ovsdb_execute_delete; static ovsdb_operation_executor ovsdb_execute_wait; static ovsdb_operation_executor ovsdb_execute_commit; static ovsdb_operation_executor ovsdb_execute_abort; +static ovsdb_operation_executor ovsdb_execute_comment; static ovsdb_operation_executor * lookup_executor(const char *name) @@ -67,10 +70,12 @@ lookup_executor(const char *name) { "insert", ovsdb_execute_insert }, { "select", ovsdb_execute_select }, { "update", ovsdb_execute_update }, + { "mutate", ovsdb_execute_mutate }, { "delete", ovsdb_execute_delete }, { "wait", ovsdb_execute_wait }, { "commit", ovsdb_execute_commit }, { "abort", ovsdb_execute_abort }, + { "comment", ovsdb_execute_comment }, }; size_t i; @@ -94,10 +99,19 @@ ovsdb_execute(struct ovsdb *db, const struct json *params, size_t n_operations; size_t i; - if (params->type != JSON_ARRAY) { + if (params->type != JSON_ARRAY + || !params->u.array.n + || params->u.array.elems[0]->type != JSON_STRING + || strcmp(params->u.array.elems[0]->u.string, db->schema->name)) { struct ovsdb_error *error; - error = ovsdb_syntax_error(params, NULL, "array expected"); + if (params->type != JSON_ARRAY) { + error = ovsdb_syntax_error(params, NULL, "array expected"); + } else { + error = ovsdb_syntax_error(params, NULL, "database name expected " + "as first parameter"); + } + results = ovsdb_error_to_json(error); ovsdb_error_destroy(error); return results; @@ -112,9 +126,9 @@ ovsdb_execute(struct ovsdb *db, const struct json *params, results = NULL; results = json_array_create_empty(); - n_operations = params->u.array.n; + n_operations = params->u.array.n - 1; error = NULL; - for (i = 0; i < n_operations; i++) { + for (i = 1; i <= n_operations; i++) { struct json *operation = params->u.array.elems[i]; struct ovsdb_error *parse_error; struct ovsdb_parser parser; @@ -123,7 +137,7 @@ ovsdb_execute(struct ovsdb *db, const struct json *params, /* Parse and execute operation. */ ovsdb_parser_init(&parser, operation, - "ovsdb operation %zu of %zu", i + 1, n_operations); + "ovsdb operation %zu of %zu", i, n_operations); op = ovsdb_parser_member(&parser, "op", OP_ID); result = json_object_create(); if (op) { @@ -154,9 +168,11 @@ ovsdb_execute(struct ovsdb *db, const struct json *params, && timeout_msec) { ovsdb_txn_abort(x.txn); *timeout_msec = x.timeout_msec; - ovsdb_error_destroy(error); + + json_destroy(result); json_destroy(results); - return NULL; + results = NULL; + goto exit; } /* Add result to array. */ @@ -179,6 +195,7 @@ ovsdb_execute(struct ovsdb *db, const struct json *params, json_array_add(results, json_null_create()); } +exit: ovsdb_error_destroy(error); ovsdb_symbol_table_destroy(x.symtab); @@ -187,7 +204,7 @@ ovsdb_execute(struct ovsdb *db, const struct json *params, struct ovsdb_error * ovsdb_execute_commit(struct ovsdb_execution *x, struct ovsdb_parser *parser, - struct json *result UNUSED) + struct json *result OVS_UNUSED) { const struct json *durable; @@ -199,9 +216,9 @@ ovsdb_execute_commit(struct ovsdb_execution *x, struct ovsdb_parser *parser, } static struct ovsdb_error * -ovsdb_execute_abort(struct ovsdb_execution *x UNUSED, - struct ovsdb_parser *parser UNUSED, - struct json *result UNUSED) +ovsdb_execute_abort(struct ovsdb_execution *x OVS_UNUSED, + struct ovsdb_parser *parser OVS_UNUSED, + struct json *result OVS_UNUSED) { return ovsdb_error("aborted", "aborted by request"); } @@ -230,7 +247,7 @@ parse_table(struct ovsdb_execution *x, static WARN_UNUSED_RESULT struct ovsdb_error * parse_row(struct ovsdb_parser *parser, const char *member, const struct ovsdb_table *table, - const struct ovsdb_symbol_table *symtab, + struct ovsdb_symbol_table *symtab, struct ovsdb_row **rowp, struct ovsdb_column_set *columns) { struct ovsdb_error *error; @@ -266,24 +283,61 @@ ovsdb_execute_insert(struct ovsdb_execution *x, struct ovsdb_parser *parser, struct ovsdb_row *row = NULL; const struct json *uuid_name; struct ovsdb_error *error; + struct uuid row_uuid; table = parse_table(x, parser, "table"); uuid_name = ovsdb_parser_member(parser, "uuid-name", OP_ID | OP_OPTIONAL); error = ovsdb_parser_get_error(parser); + + if (uuid_name) { + struct ovsdb_symbol *symbol; + + symbol = ovsdb_symbol_table_insert(x->symtab, json_string(uuid_name)); + if (symbol->used) { + return ovsdb_syntax_error(uuid_name, "duplicate uuid-name", + "This \"uuid-name\" appeared on an " + "earlier \"insert\" operation."); + } + row_uuid = symbol->uuid; + symbol->used = true; + } else { + uuid_generate(&row_uuid); + } + if (!error) { error = parse_row(parser, "row", table, x->symtab, &row, NULL); } if (!error) { - uuid_generate(ovsdb_row_get_uuid_rw(row)); - if (uuid_name) { - ovsdb_symbol_table_put(x->symtab, json_string(uuid_name), - ovsdb_row_get_uuid(row)); + /* Check constraints for columns not included in "row", in case the + * default values do not satisfy the constraints. We could check only + * the columns that have their default values by supplying an + * ovsdb_column_set to parse_row() above, but I suspect that this is + * cheaper. */ + const struct shash_node *node; + + SHASH_FOR_EACH (node, &table->schema->columns) { + const struct ovsdb_column *column = node->data; + const struct ovsdb_datum *datum = &row->fields[column->index]; + + /* If there are 0 keys or pairs, there's nothing to check. + * If there is 1, it might be a default value. + * If there are more, it can't be a default value, so the value has + * already been checked. */ + if (datum->n == 1) { + error = ovsdb_datum_check_constraints(datum, &column->type); + if (error) { + ovsdb_row_destroy(row); + break; + } + } } + } + if (!error) { + *ovsdb_row_get_uuid_rw(row) = row_uuid; ovsdb_txn_row_insert(x->txn, row); json_object_put(result, "uuid", ovsdb_datum_to_json(&row->fields[OVSDB_COL_UUID], &ovsdb_type_uuid)); - row = NULL; } return error; } @@ -393,6 +447,64 @@ ovsdb_execute_update(struct ovsdb_execution *x, struct ovsdb_parser *parser, return error; } +struct mutate_row_cbdata { + size_t n_matches; + struct ovsdb_txn *txn; + const struct ovsdb_mutation_set *mutations; +}; + +static bool +mutate_row_cb(const struct ovsdb_row *row, void *mr_) +{ + struct mutate_row_cbdata *mr = mr_; + + mr->n_matches++; + ovsdb_mutation_set_execute(ovsdb_txn_row_modify(mr->txn, row), + mr->mutations); + + return true; +} + +struct ovsdb_error * +ovsdb_execute_mutate(struct ovsdb_execution *x, struct ovsdb_parser *parser, + struct json *result) +{ + struct ovsdb_table *table; + const struct json *where; + const struct json *mutations_json; + struct ovsdb_condition condition = OVSDB_CONDITION_INITIALIZER; + struct ovsdb_mutation_set mutations = OVSDB_MUTATION_SET_INITIALIZER; + struct ovsdb_row *row = NULL; + struct mutate_row_cbdata mr; + struct ovsdb_error *error; + + table = parse_table(x, parser, "table"); + where = ovsdb_parser_member(parser, "where", OP_ARRAY); + mutations_json = ovsdb_parser_member(parser, "mutations", OP_ARRAY); + error = ovsdb_parser_get_error(parser); + if (!error) { + error = ovsdb_mutation_set_from_json(table->schema, mutations_json, + x->symtab, &mutations); + } + if (!error) { + error = ovsdb_condition_from_json(table->schema, where, x->symtab, + &condition); + } + if (!error) { + mr.n_matches = 0; + mr.txn = x->txn; + mr.mutations = &mutations; + ovsdb_query(table, &condition, mutate_row_cb, &mr); + json_object_put(result, "count", json_integer_create(mr.n_matches)); + } + + ovsdb_row_destroy(row); + ovsdb_mutation_set_destroy(&mutations); + ovsdb_condition_destroy(&condition); + + return error; +} + struct delete_row_cbdata { size_t n_matches; const struct ovsdb_table *table; @@ -467,7 +579,7 @@ ovsdb_execute_wait_query_cb(const struct ovsdb_row *row, void *aux_) static struct ovsdb_error * ovsdb_execute_wait(struct ovsdb_execution *x, struct ovsdb_parser *parser, - struct json *result UNUSED) + struct json *result OVS_UNUSED) { struct ovsdb_table *table; const struct json *timeout, *where, *columns_json, *until, *rows; @@ -517,7 +629,6 @@ ovsdb_execute_wait(struct ovsdb_execution *x, struct ovsdb_parser *parser, /* Parse "rows" into 'expected'. */ ovsdb_row_hash_init(&expected, &columns); for (i = 0; i < rows->u.array.n; i++) { - struct ovsdb_error *error; struct ovsdb_row *row; row = ovsdb_row_create(table); @@ -577,3 +688,18 @@ ovsdb_execute_wait(struct ovsdb_execution *x, struct ovsdb_parser *parser, return error; } + +static struct ovsdb_error * +ovsdb_execute_comment(struct ovsdb_execution *x, struct ovsdb_parser *parser, + struct json *result OVS_UNUSED) +{ + const struct json *comment; + + comment = ovsdb_parser_member(parser, "comment", OP_STRING); + if (!comment) { + return NULL; + } + ovsdb_txn_add_comment(x->txn, json_string(comment)); + + return NULL; +}