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 <b...@ovn.org> --- lib/ovsdb-idl-provider.h | 1 + lib/ovsdb-idl.c | 24 ++++++++++++++++++++---- ovsdb/ovsdb-idlc.in | 8 ++++++-- 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/lib/ovsdb-idl-provider.h b/lib/ovsdb-idl-provider.h index d15ab1db58a6..b0ebed44f83a 100644 --- a/lib/ovsdb-idl-provider.h +++ b/lib/ovsdb-idl-provider.h @@ -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; diff --git a/lib/ovsdb-idl.c b/lib/ovsdb-idl.c index 12009f568575..e2f9af7f61d4 100644 --- a/lib/ovsdb-idl.c +++ b/lib/ovsdb-idl.c @@ -3538,12 +3538,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)); diff --git a/ovsdb/ovsdb-idlc.in b/ovsdb/ovsdb-idlc.in index c3973e4f5982..d07d527877a6 100755 --- a/ovsdb/ovsdb-idlc.in +++ b/ovsdb/ovsdb-idlc.in @@ -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("};") -- 2.10.2 _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev