Skip to content

Commit

Permalink
ovsdb-idl: Tolerate initialization races for singleton tables.
Browse files Browse the repository at this point in the history
By verifying that singleton tables (that is, tables that should have exactly
one row) are empty when they emit transactions that insert into them,
ovs-vsctl and similar tools tolerate initialization races, where more than one
client at a time tries to initialize a singleton table.

The upshot is that if you create a database and then run multiple ovs-vsctl
(etc.) commands against it in parallel (without first initializing it
serially), then without this patch sometimes you will sometimes get failures
but this patch avoids them.

Signed-off-by: Ben Pfaff <[email protected]>
Acked-by: Alin Gabriel Serdean <[email protected]>
  • Loading branch information
blp committed Dec 11, 2017
1 parent 7a36082 commit 25540a7
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 6 deletions.
1 change: 1 addition & 0 deletions lib/ovsdb-idl-provider.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ struct ovsdb_idl_column {
struct ovsdb_idl_table_class {
char *name;
bool is_root;
bool is_singleton;
const struct ovsdb_idl_column *columns;
size_t n_columns;
size_t allocation_size;
Expand Down
24 changes: 20 additions & 4 deletions lib/ovsdb-idl.c
Original file line number Diff line number Diff line change
Expand Up @@ -3537,12 +3537,28 @@ ovsdb_idl_txn_commit(struct ovsdb_idl_txn *txn)
}
} else if (row->old_datum != row->new_datum) {
struct json *row_json;
struct json *op;
size_t idx;

op = json_object_create();
json_object_put_string(op, "op", row->old_datum ? "update"
: "insert");
if (!row->old_datum && class->is_singleton) {
/* We're inserting a row into a table that allows only a
* single row. (This is a fairly common OVSDB pattern for
* storing global data.) Verify that the table is empty
* before inserting the row, so that we get a clear
* verification-related failure if there was an insertion
* race with another client. */
struct json *op = json_object_create();
json_array_add(operations, op);
json_object_put_string(op, "op", "wait");
json_object_put_string(op, "table", class->name);
json_object_put(op, "where", json_array_create_empty());
json_object_put(op, "timeout", json_integer_create(0));
json_object_put_string(op, "until", "==");
json_object_put(op, "rows", json_array_create_empty());
}

struct json *op = json_object_create();
json_object_put_string(op, "op",
row->old_datum ? "update" : "insert");
json_object_put_string(op, "table", class->name);
if (row->old_datum) {
json_object_put(op, "where", where_uuid_equals(&row->uuid));
Expand Down
8 changes: 6 additions & 2 deletions ovsdb/ovsdb-idlc.in
Original file line number Diff line number Diff line change
Expand Up @@ -1298,9 +1298,13 @@ void
is_root = "true"
else:
is_root = "false"
print(" {\"%s\", %s," % (tableName, is_root))
if table.max_rows == 1:
is_singleton = "true"
else:
is_singleton = "false"
print(" {\"%s\", %s, %s," % (tableName, is_root, is_singleton))
print(" %s_columns, ARRAY_SIZE(%s_columns)," % (
structName, structName))
structName, structName))
print(" sizeof(struct %s), %s_init__}," % (structName, structName))
print("};")

Expand Down

0 comments on commit 25540a7

Please sign in to comment.