From 2d2d6d4a71776813f8d2fd1af1051f22b836befc Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Mon, 7 Dec 2009 11:47:48 -0800 Subject: [PATCH] ovsdb: Implement new "declare" operation. --- lib/ovsdb-data.c | 28 ++++++++++---------- lib/ovsdb-data.h | 11 +++++--- ovsdb/SPECS | 65 ++++++++++++++++++++++++++++++++++++++++++---- ovsdb/execution.c | 48 ++++++++++++++++++++++++++++++++-- tests/ovsdb-idl.at | 16 ++++++------ tests/test-ovsdb.c | 11 ++++---- 6 files changed, 143 insertions(+), 36 deletions(-) diff --git a/lib/ovsdb-data.c b/lib/ovsdb-data.c index 46298cb47..df445d775 100644 --- a/lib/ovsdb-data.c +++ b/lib/ovsdb-data.c @@ -219,13 +219,13 @@ ovsdb_atom_parse_uuid(struct uuid *uuid, const struct json *json, error1 = unwrap_json(json, "named-uuid", JSON_STRING, &value); if (!error1) { const char *name = json_string(value); - const struct uuid *named_uuid; + const struct ovsdb_symbol *symbol; ovsdb_error_destroy(error0); - named_uuid = ovsdb_symbol_table_get(symtab, name); - if (named_uuid) { - *uuid = *named_uuid; + symbol = ovsdb_symbol_table_get(symtab, name); + if (symbol) { + *uuid = symbol->uuid; return NULL; } else { return ovsdb_syntax_error(json, NULL, @@ -728,7 +728,8 @@ ovsdb_symbol_table_destroy(struct ovsdb_symbol_table *symtab) struct shash_node *node, *next; SHASH_FOR_EACH_SAFE (node, next, &symtab->sh) { - free(node->data); + struct ovsdb_symbol *symbol = node->data; + free(symbol); shash_delete(&symtab->sh, node); } shash_destroy(&symtab->sh); @@ -736,7 +737,7 @@ ovsdb_symbol_table_destroy(struct ovsdb_symbol_table *symtab) } } -const struct uuid * +struct ovsdb_symbol * ovsdb_symbol_table_get(const struct ovsdb_symbol_table *symtab, const char *name) { @@ -745,12 +746,13 @@ ovsdb_symbol_table_get(const struct ovsdb_symbol_table *symtab, void ovsdb_symbol_table_put(struct ovsdb_symbol_table *symtab, const char *name, - const struct uuid *uuid) + const struct uuid *uuid, bool used) { - struct uuid *entry = shash_find_data(&symtab->sh, name); - if (!entry) { - shash_add(&symtab->sh, name, xmemdup(uuid, sizeof *uuid)); - } else { - *entry = *uuid; - } + struct ovsdb_symbol *symbol; + + assert(!ovsdb_symbol_table_get(symtab, name)); + symbol = xmalloc(sizeof *symbol); + symbol->uuid = *uuid; + symbol->used = used; + shash_add(&symtab->sh, name, symbol); } diff --git a/lib/ovsdb-data.h b/lib/ovsdb-data.h index 35c4e3075..b31aa5d49 100644 --- a/lib/ovsdb-data.h +++ b/lib/ovsdb-data.h @@ -118,11 +118,16 @@ ovsdb_datum_conforms_to_type(const struct ovsdb_datum *datum, /* A table mapping from names to data items. Currently the data items are * always UUIDs; perhaps this will be expanded in the future. */ +struct ovsdb_symbol { + struct uuid uuid; /* The UUID that the symbol represents. */ + bool used; /* Already used as row UUID? */ +}; + struct ovsdb_symbol_table *ovsdb_symbol_table_create(void); void ovsdb_symbol_table_destroy(struct ovsdb_symbol_table *); -const struct uuid *ovsdb_symbol_table_get(const struct ovsdb_symbol_table *, - const char *name); +struct ovsdb_symbol *ovsdb_symbol_table_get(const struct ovsdb_symbol_table *, + const char *name); void ovsdb_symbol_table_put(struct ovsdb_symbol_table *, const char *name, - const struct uuid *); + const struct uuid *, bool used); #endif /* ovsdb-data.h */ diff --git a/ovsdb/SPECS b/ovsdb/SPECS index 17b0840ca..93db15d4c 100644 --- a/ovsdb/SPECS +++ b/ovsdb/SPECS @@ -599,7 +599,7 @@ Request object members: "op": "insert" required "table": required "row": required - "uuid-name": optional + "uuid-name": optional Result object members: @@ -611,10 +611,31 @@ Semantics: for all the columns in "table", those columns receive default values. - The new row receives a new, randomly generated UUID, which is - returned as the "uuid" member of the result. If "uuid-name" is - supplied, then the UUID is made available under that name to this - operation and later operations within the same transaction. + If "uuid-name" is not supplied, the new row receives a new, + randomly generated UUID. + + If "uuid-name" is supplied, then it is an error if has + previously appeared as the "uuid-name" in an "insert" operation. + + If "uuid-name" is supplied and its previously appeared as the + "uuid-name" in a "declare" operation, then the new row receives + the UUID associated with that "uuid-name". + + If "uuid-name" is supplied and its has not previously + appeared as the "uuid-name" in a "declare" operation, then the new + row also receives a new, randomly generated UUID. This UUID is + also made available under that name to this operation and later + operations within the same transaction. + + The UUID for the new row is returned as the "uuid" member of the + result. + +Errors: + + "error": "duplicate uuid-name" + + The same "uuid-name" appeared on an earlier "insert" operation + within this transaction. select ...... @@ -797,3 +818,37 @@ Errors: "error": "aborted" This operation always fails with this error. + +declare +....... + +Request object members: + + "op": "declare" required + "uuid-name": required + +Result object members: + + none + +Semantics: + + Predeclares a UUID named that may be referenced in later + operations as ["named-uuid", ] or (at most once) in an + "insert" operation as "uuid-name". + + It is an error if has appeared as the "uuid-name" in a prior + "insert" or "declare" operation within this transaction. + + The generated UUID is returned as the "uuid" member of the result. + +Result object members: + + "uuid": + +Errors: + + "error": "duplicate uuid-name" + + The same "uuid-name" appeared on an earlier "insert" or + "declare" operation within this transaction. diff --git a/ovsdb/execution.c b/ovsdb/execution.c index 0bfe86fb3..932bee238 100644 --- a/ovsdb/execution.c +++ b/ovsdb/execution.c @@ -54,6 +54,7 @@ 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 * lookup_executor(const char *name) @@ -71,6 +72,7 @@ lookup_executor(const char *name) { "wait", ovsdb_execute_wait }, { "commit", ovsdb_execute_commit }, { "abort", ovsdb_execute_abort }, + { "declare", ovsdb_execute_declare }, }; size_t i; @@ -272,9 +274,25 @@ ovsdb_execute_insert(struct ovsdb_execution *x, struct ovsdb_parser *parser, uuid_name = ovsdb_parser_member(parser, "uuid-name", OP_ID | OP_OPTIONAL); error = ovsdb_parser_get_error(parser); - uuid_generate(&row_uuid); if (uuid_name) { - ovsdb_symbol_table_put(x->symtab, json_string(uuid_name), &row_uuid); + 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); + } + } else { + uuid_generate(&row_uuid); } if (!error) { @@ -580,3 +598,29 @@ ovsdb_execute_wait(struct ovsdb_execution *x, struct ovsdb_parser *parser, return error; } + +static struct ovsdb_error * +ovsdb_execute_declare(struct ovsdb_execution *x, struct ovsdb_parser *parser, + struct json *result) +{ + const struct json *uuid_name; + struct uuid uuid; + + uuid_name = ovsdb_parser_member(parser, "uuid-name", OP_ID); + if (!uuid_name) { + return NULL; + } + + 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_string_create_nocopy( + xasprintf(UUID_FMT, UUID_ARGS(&uuid)))); + return NULL; +} diff --git a/tests/ovsdb-idl.at b/tests/ovsdb-idl.at index cf9f1ba37..a1717b8c4 100644 --- a/tests/ovsdb-idl.at +++ b/tests/ovsdb-idl.at @@ -143,18 +143,18 @@ OVSDB_CHECK_IDL([self-linking idl, consistent ops], "table": "link1", "row": {"i": 0, "k": ["named-uuid", "self"]}, "uuid-name": "self"}]' \ - '[{"op": "insert", + '[{"op": "declare", + "uuid-name": "row1"}, + {"op": "declare", + "uuid-name": "row2"}, + {"op": "insert", "table": "link1", - "row": {"i": 1}, + "row": {"i": 1, "k": ["named-uuid", "row2"]}, "uuid-name": "row1"}, {"op": "insert", "table": "link1", "row": {"i": 2, "k": ["named-uuid", "row1"]}, - "uuid-name": "row2"}, - {"op": "update", - "table": "link1", - "where": [["i", "==", 1]], - "row": {"k": ["named-uuid", "row2"]}}]' \ + "uuid-name": "row2"}]' \ '[{"op": "update", "table": "link1", "where": [["i", "==", 1]], @@ -166,7 +166,7 @@ OVSDB_CHECK_IDL([self-linking idl, consistent ops], [[000: empty 001: {"error":null,"result":[{"uuid":["uuid","<0>"]}]} 002: i=0 k=0 ka=[] l2= uuid=<0> -003: {"error":null,"result":[{"uuid":["uuid","<1>"]},{"uuid":["uuid","<2>"]},{"count":1}]} +003: {"error":null,"result":[{"uuid":"<1>"},{"uuid":"<2>"},{"uuid":["uuid","<1>"]},{"uuid":["uuid","<2>"]}]} 004: i=0 k=0 ka=[] l2= uuid=<0> 004: i=1 k=2 ka=[] l2= uuid=<1> 004: i=2 k=1 ka=[] l2= uuid=<2> diff --git a/tests/test-ovsdb.c b/tests/test-ovsdb.c index fb13df9c3..9819d03da 100644 --- a/tests/test-ovsdb.c +++ b/tests/test-ovsdb.c @@ -1346,7 +1346,8 @@ parse_uuids(const struct json *json, struct ovsdb_symbol_table *symtab, if (json->type == JSON_STRING && uuid_from_string(&uuid, json->u.string)) { char *name = xasprintf("#%d#", *n); - ovsdb_symbol_table_put(symtab, name, &uuid); + fprintf(stderr, "%s = "UUID_FMT"\n", name, UUID_ARGS(&uuid)); + ovsdb_symbol_table_put(symtab, name, &uuid, false); free(name); *n += 1; } else if (json->type == JSON_ARRAY) { @@ -1368,12 +1369,12 @@ static void substitute_uuids(struct json *json, const struct ovsdb_symbol_table *symtab) { if (json->type == JSON_STRING) { - const struct uuid *uuid; + const struct ovsdb_symbol *symbol; - uuid = ovsdb_symbol_table_get(symtab, json->u.string); - if (uuid) { + symbol = ovsdb_symbol_table_get(symtab, json->u.string); + if (symbol) { free(json->u.string); - json->u.string = xasprintf(UUID_FMT, UUID_ARGS(uuid)); + json->u.string = xasprintf(UUID_FMT, UUID_ARGS(&symbol->uuid)); } } else if (json->type == JSON_ARRAY) { size_t i; -- 2.43.0