Global replace of Nicira Networks.
[sliver-openvswitch.git] / ovsdb / execution.c
index e2f10cb..1aff0c5 100644 (file)
@@ -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.
 #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;
@@ -57,6 +59,7 @@ 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 ovsdb_execute_assert;
 
 static ovsdb_operation_executor *
 lookup_executor(const char *name)
@@ -76,6 +79,7 @@ lookup_executor(const char *name)
         { "commit", ovsdb_execute_commit },
         { "abort", ovsdb_execute_abort },
         { "comment", ovsdb_execute_comment },
+        { "assert", ovsdb_execute_assert },
     };
 
     size_t i;
@@ -90,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;
@@ -116,6 +121,7 @@ ovsdb_execute(struct ovsdb *db, const struct json *params,
     }
 
     x.db = db;
+    x.session = session;
     x.txn = ovsdb_txn_create(db);
     x.symtab = ovsdb_symbol_table_create();
     x.durable = false;
@@ -200,7 +206,7 @@ exit:
     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)
 {
@@ -243,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,
+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;
@@ -257,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);
@@ -273,38 +276,41 @@ 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_insert(x->symtab, json_string(uuid_name));
-        if (symbol->used) {
-            ovsdb_error_destroy(error);
+        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
@@ -341,7 +347,7 @@ ovsdb_execute_insert(struct ovsdb_execution *x, struct ovsdb_parser *parser,
     return error;
 }
 
-struct ovsdb_error *
+static struct ovsdb_error *
 ovsdb_execute_select(struct ovsdb_execution *x, struct ovsdb_parser *parser,
                      struct json *result)
 {
@@ -364,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;
@@ -408,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;
@@ -422,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,
@@ -450,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
@@ -458,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)
 {
@@ -493,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));
     }
@@ -521,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)
 {
@@ -604,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) {
@@ -702,3 +712,28 @@ ovsdb_execute_comment(struct ovsdb_execution *x, struct ovsdb_parser *parser,
 
     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));
+}