-/* Copyright (c) 2009, 2010 Nicira Networks
+/* Copyright (c) 2009, 2010, 2011, 2012 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include <config.h>
-#include <assert.h>
#include <limits.h>
#include "column.h"
#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;
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 ovsdb_execute_assert;
static ovsdb_operation_executor *
lookup_executor(const char *name)
{ "commit", ovsdb_execute_commit },
{ "abort", ovsdb_execute_abort },
{ "comment", ovsdb_execute_comment },
+ { "assert", ovsdb_execute_assert },
};
size_t i;
}
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;
}
x.db = db;
+ x.session = session;
x.txn = ovsdb_txn_create(db);
x.symtab = ovsdb_symbol_table_create();
x.durable = false;
op_name);
}
} else {
- assert(ovsdb_parser_has_error(&parser));
+ ovs_assert(ovsdb_parser_has_error(&parser));
}
/* A parse error overrides any other error.
return results;
}
-struct ovsdb_error *
+static struct ovsdb_error *
ovsdb_execute_commit(struct ovsdb_execution *x, struct ovsdb_parser *parser,
struct json *result OVS_UNUSED)
{
}
static WARN_UNUSED_RESULT struct ovsdb_error *
-parse_row(struct ovsdb_parser *parser, const char *member,
- const struct ovsdb_table *table,
+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;
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);
}
}
-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_insert(x->symtab, json_string(uuid_name));
- if (symbol->used) {
+ 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->used = true;
+ 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
return error;
}
-struct ovsdb_error *
+static struct ovsdb_error *
ovsdb_execute_select(struct ovsdb_execution *x, struct ovsdb_parser *parser,
struct json *result)
{
&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;
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;
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) {
+ size_t i;
+
+ for (i = 0; i < columns.n_columns; i++) {
+ const struct ovsdb_column *column = columns.columns[i];
+
+ if (!column->mutable) {
+ error = ovsdb_syntax_error(parser->json,
+ "constraint violation",
+ "Cannot update immutable column %s "
+ "in table %s.",
+ column->name, table->schema->name);
+ break;
+ }
+ }
}
if (!error) {
error = ovsdb_condition_from_json(table->schema, where, x->symtab,
size_t n_matches;
struct ovsdb_txn *txn;
const struct ovsdb_mutation_set *mutations;
+ struct ovsdb_error **error;
};
static bool
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)
{
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));
}
return true;
}
-struct ovsdb_error *
+static struct ovsdb_error *
ovsdb_execute_delete(struct ovsdb_execution *x, struct ovsdb_parser *parser,
struct json *result)
{
&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) {
return NULL;
}
+
+static struct ovsdb_error *
+ovsdb_execute_assert(struct ovsdb_execution *x, struct ovsdb_parser *parser,
+ struct json *result OVS_UNUSED)
+{
+ const struct json *lock_name;
+
+ lock_name = ovsdb_parser_member(parser, "lock", OP_ID);
+ if (!lock_name) {
+ 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));
+}