X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=ovsdb%2Fexecution.c;h=1aff0c51eaca917d2c2d8cc86b7c629050bed06e;hb=e0edde6fee279cdbbf3c179f5f50adaf0c7c7f1e;hp=ba8351da757a27127630eb537629642d26102323;hpb=f89d8180056ed6c217f075f0130a26d4b64bc70c;p=sliver-openvswitch.git diff --git a/ovsdb/execution.c b/ovsdb/execution.c index ba8351da7..1aff0c51e 100644 --- a/ovsdb/execution.c +++ b/ovsdb/execution.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2009, 2010 Nicira Networks +/* Copyright (c) 2009, 2010, 2011 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,12 +29,14 @@ #include "ovsdb.h" #include "query.h" #include "row.h" +#include "server.h" #include "table.h" #include "timeval.h" #include "transaction.h" struct ovsdb_execution { struct ovsdb *db; + const struct ovsdb_session *session; struct ovsdb_txn *txn; struct ovsdb_symbol_table *symtab; bool durable; @@ -56,8 +58,8 @@ 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_declare; static ovsdb_operation_executor ovsdb_execute_comment; +static ovsdb_operation_executor ovsdb_execute_assert; static ovsdb_operation_executor * lookup_executor(const char *name) @@ -76,8 +78,8 @@ lookup_executor(const char *name) { "wait", ovsdb_execute_wait }, { "commit", ovsdb_execute_commit }, { "abort", ovsdb_execute_abort }, - { "declare", ovsdb_execute_declare }, { "comment", ovsdb_execute_comment }, + { "assert", ovsdb_execute_assert }, }; size_t i; @@ -92,7 +94,8 @@ lookup_executor(const char *name) } struct json * -ovsdb_execute(struct ovsdb *db, const struct json *params, +ovsdb_execute(struct ovsdb *db, const struct ovsdb_session *session, + const struct json *params, long long int elapsed_msec, long long int *timeout_msec) { struct ovsdb_execution x; @@ -101,16 +104,24 @@ ovsdb_execute(struct ovsdb *db, const struct json *params, size_t n_operations; size_t i; - if (params->type != JSON_ARRAY) { - struct ovsdb_error *error; + 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)) { + 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"); + } - error = ovsdb_syntax_error(params, NULL, "array expected"); results = ovsdb_error_to_json(error); ovsdb_error_destroy(error); return results; } x.db = db; + x.session = session; x.txn = ovsdb_txn_create(db); x.symtab = ovsdb_symbol_table_create(); x.durable = false; @@ -119,9 +130,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; @@ -130,7 +141,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) { @@ -195,9 +206,9 @@ exit: return results; } -struct ovsdb_error * +static 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; @@ -209,9 +220,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"); } @@ -238,13 +249,11 @@ 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, +parse_row(const struct json *json, const struct ovsdb_table *table, + struct ovsdb_symbol_table *symtab, struct ovsdb_row **rowp, struct ovsdb_column_set *columns) { struct ovsdb_error *error; - const struct json *json; struct ovsdb_row *row; *rowp = NULL; @@ -252,9 +261,8 @@ parse_row(struct ovsdb_parser *parser, const char *member, if (!table) { return OVSDB_BUG("null table"); } - json = ovsdb_parser_member(parser, member, OP_OBJECT); if (!json) { - return OVSDB_BUG("null row member"); + return OVSDB_BUG("null row"); } row = ovsdb_row_create(table); @@ -268,43 +276,66 @@ parse_row(struct ovsdb_parser *parser, const char *member, } } -struct ovsdb_error * +static struct ovsdb_error * ovsdb_execute_insert(struct ovsdb_execution *x, struct ovsdb_parser *parser, struct json *result) { struct ovsdb_table *table; struct ovsdb_row *row = NULL; - const struct json *uuid_name; + const struct json *uuid_name, *row_json; 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); + row_json = ovsdb_parser_member(parser, "row", OP_OBJECT); error = ovsdb_parser_get_error(parser); + if (error) { + return error; + } if (uuid_name) { struct ovsdb_symbol *symbol; - symbol = ovsdb_symbol_table_get(x->symtab, json_string(uuid_name)); - if (symbol) { - 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); - ovsdb_symbol_table_put(x->symtab, json_string(uuid_name), - &row_uuid, true); + symbol = ovsdb_symbol_table_insert(x->symtab, json_string(uuid_name)); + if (symbol->created) { + return ovsdb_syntax_error(uuid_name, "duplicate uuid-name", + "This \"uuid-name\" appeared on an " + "earlier \"insert\" operation."); } + row_uuid = symbol->uuid; + symbol->created = true; } else { uuid_generate(&row_uuid); } if (!error) { - error = parse_row(parser, "row", table, x->symtab, &row, NULL); + error = parse_row(row_json, table, x->symtab, &row, NULL); + } + if (!error) { + /* 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; @@ -312,12 +343,11 @@ ovsdb_execute_insert(struct ovsdb_execution *x, struct ovsdb_parser *parser, json_object_put(result, "uuid", ovsdb_datum_to_json(&row->fields[OVSDB_COL_UUID], &ovsdb_type_uuid)); - row = NULL; } return error; } -struct ovsdb_error * +static struct ovsdb_error * ovsdb_execute_select(struct ovsdb_execution *x, struct ovsdb_parser *parser, struct json *result) { @@ -340,10 +370,11 @@ ovsdb_execute_select(struct ovsdb_execution *x, struct ovsdb_parser *parser, &condition); } if (!error) { - error = ovsdb_column_set_from_json(columns_json, table, &columns); + error = ovsdb_column_set_from_json(columns_json, table->schema, + &columns); } if (!error) { - error = ovsdb_column_set_from_json(sort_json, table, &sort); + error = ovsdb_column_set_from_json(sort_json, table->schema, &sort); } if (!error) { struct ovsdb_row_set rows = OVSDB_ROW_SET_INITIALIZER; @@ -384,12 +415,12 @@ update_row_cb(const struct ovsdb_row *row, void *ur_) return true; } -struct ovsdb_error * +static struct ovsdb_error * ovsdb_execute_update(struct ovsdb_execution *x, struct ovsdb_parser *parser, struct json *result) { struct ovsdb_table *table; - const struct json *where; + const struct json *where, *row_json; struct ovsdb_condition condition = OVSDB_CONDITION_INITIALIZER; struct ovsdb_column_set columns = OVSDB_COLUMN_SET_INITIALIZER; struct ovsdb_row *row = NULL; @@ -398,9 +429,10 @@ ovsdb_execute_update(struct ovsdb_execution *x, struct ovsdb_parser *parser, table = parse_table(x, parser, "table"); where = ovsdb_parser_member(parser, "where", OP_ARRAY); + row_json = ovsdb_parser_member(parser, "row", OP_OBJECT); error = ovsdb_parser_get_error(parser); if (!error) { - error = parse_row(parser, "row", table, x->symtab, &row, &columns); + error = parse_row(row_json, table, x->symtab, &row, &columns); } if (!error) { error = ovsdb_condition_from_json(table->schema, where, x->symtab, @@ -426,6 +458,7 @@ struct mutate_row_cbdata { size_t n_matches; struct ovsdb_txn *txn; const struct ovsdb_mutation_set *mutations; + struct ovsdb_error **error; }; static bool @@ -434,13 +467,12 @@ 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; + *mr->error = ovsdb_mutation_set_execute(ovsdb_txn_row_modify(mr->txn, row), + mr->mutations); + return *mr->error == NULL; } -struct ovsdb_error * +static struct ovsdb_error * ovsdb_execute_mutate(struct ovsdb_execution *x, struct ovsdb_parser *parser, struct json *result) { @@ -469,6 +501,7 @@ ovsdb_execute_mutate(struct ovsdb_execution *x, struct ovsdb_parser *parser, mr.n_matches = 0; mr.txn = x->txn; mr.mutations = &mutations; + mr.error = &error; ovsdb_query(table, &condition, mutate_row_cb, &mr); json_object_put(result, "count", json_integer_create(mr.n_matches)); } @@ -497,7 +530,7 @@ delete_row_cb(const struct ovsdb_row *row, void *dr_) return true; } -struct ovsdb_error * +static struct ovsdb_error * ovsdb_execute_delete(struct ovsdb_execution *x, struct ovsdb_parser *parser, struct json *result) { @@ -554,7 +587,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; @@ -580,7 +613,8 @@ ovsdb_execute_wait(struct ovsdb_execution *x, struct ovsdb_parser *parser, &condition); } if (!error) { - error = ovsdb_column_set_from_json(columns_json, table, &columns); + error = ovsdb_column_set_from_json(columns_json, table->schema, + &columns); } if (!error) { if (timeout) { @@ -604,7 +638,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); @@ -666,45 +699,41 @@ ovsdb_execute_wait(struct ovsdb_execution *x, struct ovsdb_parser *parser, } static struct ovsdb_error * -ovsdb_execute_declare(struct ovsdb_execution *x, struct ovsdb_parser *parser, - struct json *result) +ovsdb_execute_comment(struct ovsdb_execution *x, struct ovsdb_parser *parser, + struct json *result OVS_UNUSED) { - const struct json *uuid_name; - struct uuid uuid; + const struct json *comment; - uuid_name = ovsdb_parser_member(parser, "uuid-name", OP_ID); - if (!uuid_name) { + comment = ovsdb_parser_member(parser, "comment", OP_STRING); + if (!comment) { return NULL; } + ovsdb_txn_add_comment(x->txn, json_string(comment)); - if (ovsdb_symbol_table_get(x->symtab, json_string(uuid_name))) { - return ovsdb_syntax_error(uuid_name, "duplicate uuid-name", - "This \"uuid-name\" appeared on an " - "earlier \"declare\" or \"insert\" " - "operation."); - } - - uuid_generate(&uuid); - ovsdb_symbol_table_put(x->symtab, json_string(uuid_name), &uuid, false); - json_object_put(result, "uuid", - json_array_create_2( - json_string_create("uuid"), - json_string_create_nocopy( - xasprintf(UUID_FMT, UUID_ARGS(&uuid))))); return NULL; } static struct ovsdb_error * -ovsdb_execute_comment(struct ovsdb_execution *x, struct ovsdb_parser *parser, - struct json *result UNUSED) +ovsdb_execute_assert(struct ovsdb_execution *x, struct ovsdb_parser *parser, + struct json *result OVS_UNUSED) { - const struct json *comment; + const struct json *lock_name; - comment = ovsdb_parser_member(parser, "comment", OP_STRING); - if (!comment) { + lock_name = ovsdb_parser_member(parser, "lock", OP_ID); + if (!lock_name) { return NULL; } - ovsdb_txn_add_comment(x->txn, json_string(comment)); - return NULL; + if (x->session) { + const struct ovsdb_lock_waiter *waiter; + + waiter = ovsdb_session_get_lock_waiter(x->session, + json_string(lock_name)); + if (waiter && ovsdb_lock_waiter_is_owner(waiter)) { + return NULL; + } + } + + return ovsdb_error("not owner", "Asserted lock %s not held.", + json_string(lock_name)); }