X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=ovsdb%2Fovsdb.c;h=d4a27d40ea3491c87305aa4e1892f29527895951;hb=356180a825c94314f3d1667003e64526d1b69da5;hp=45683766c1c937a4e24dcca013bdd2d61e443e1f;hpb=a0bc29a541fc7dc6e20137d5558e2094d614e6ab;p=openvswitch diff --git a/ovsdb/ovsdb.c b/ovsdb/ovsdb.c index 45683766..d4a27d40 100644 --- a/ovsdb/ovsdb.c +++ b/ovsdb/ovsdb.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2009, 2010 Nicira Networks +/* Copyright (c) 2009, 2010, 2011 Nicira Networks * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,12 +26,14 @@ #include "transaction.h" struct ovsdb_schema * -ovsdb_schema_create(const char *name) +ovsdb_schema_create(const char *name, const char *version, const char *cksum) { struct ovsdb_schema *schema; schema = xzalloc(sizeof *schema); schema->name = xstrdup(name); + schema->version = xstrdup(version); + schema->cksum = xstrdup(cksum); shash_init(&schema->tables); return schema; @@ -43,7 +45,7 @@ ovsdb_schema_clone(const struct ovsdb_schema *old) struct ovsdb_schema *new; struct shash_node *node; - new = ovsdb_schema_create(old->name); + new = ovsdb_schema_create(old->name, old->version, old->cksum); SHASH_FOR_EACH (node, &old->tables) { const struct ovsdb_table_schema *ts = node->data; @@ -52,7 +54,6 @@ ovsdb_schema_clone(const struct ovsdb_schema *old) return new; } - void ovsdb_schema_destroy(struct ovsdb_schema *schema) { @@ -67,6 +68,8 @@ ovsdb_schema_destroy(struct ovsdb_schema *schema) } shash_destroy(&schema->tables); free(schema->name); + free(schema->version); + free(schema->cksum); free(schema); } @@ -116,26 +119,65 @@ ovsdb_schema_check_ref_table(const struct ovsdb_column *column, } } +static bool +is_valid_version(const char *s) +{ + int n = -1; + ignore(sscanf(s, "%*[0-9].%*[0-9].%*[0-9]%n", &n)); + return n != -1 && s[n] == '\0'; +} + +/* Returns the number of tables in 'schema''s root set. */ +static size_t +root_set_size(const struct ovsdb_schema *schema) +{ + struct shash_node *node; + size_t n_root = 0; + + SHASH_FOR_EACH (node, &schema->tables) { + struct ovsdb_table_schema *table = node->data; + + n_root += table->is_root; + } + return n_root; +} + struct ovsdb_error * ovsdb_schema_from_json(struct json *json, struct ovsdb_schema **schemap) { struct ovsdb_schema *schema; - const struct json *name, *tables; + const struct json *name, *tables, *version_json, *cksum; struct ovsdb_error *error; struct shash_node *node; struct ovsdb_parser parser; + const char *version; *schemap = NULL; ovsdb_parser_init(&parser, json, "database schema"); name = ovsdb_parser_member(&parser, "name", OP_ID); + version_json = ovsdb_parser_member(&parser, "version", + OP_STRING | OP_OPTIONAL); + cksum = ovsdb_parser_member(&parser, "cksum", OP_STRING | OP_OPTIONAL); tables = ovsdb_parser_member(&parser, "tables", OP_OBJECT); error = ovsdb_parser_finish(&parser); if (error) { return error; } - schema = ovsdb_schema_create(json_string(name)); + if (version_json) { + version = json_string(version_json); + if (!is_valid_version(version)) { + return ovsdb_syntax_error(json, NULL, "schema version \"%s\" not " + "in format x.y.z", version); + } + } else { + /* Backward compatibility with old databases. */ + version = ""; + } + + schema = ovsdb_schema_create(json_string(name), version, + cksum ? json_string(cksum) : ""); SHASH_FOR_EACH (node, json_object(tables)) { struct ovsdb_table_schema *table; @@ -178,6 +220,18 @@ ovsdb_schema_from_json(struct json *json, struct ovsdb_schema **schemap) } } + /* "isRoot" was not part of the original schema definition. Before it was + * added, there was no support for garbage collection. So, for backward + * compatibility, if the root set is empty then assume that every table is + * in the root set. */ + if (root_set_size(schema) == 0) { + SHASH_FOR_EACH (node, &schema->tables) { + struct ovsdb_table_schema *table = node->data; + + table->is_root = true; + } + } + *schemap = schema; return 0; } @@ -187,21 +241,51 @@ ovsdb_schema_to_json(const struct ovsdb_schema *schema) { struct json *json, *tables; struct shash_node *node; + bool default_is_root; json = json_object_create(); json_object_put_string(json, "name", schema->name); + if (schema->version[0]) { + json_object_put_string(json, "version", schema->version); + } + if (schema->cksum[0]) { + json_object_put_string(json, "cksum", schema->cksum); + } + + /* "isRoot" was not part of the original schema definition. Before it was + * added, there was no support for garbage collection. So, for backward + * compatibility, if every table is in the root set then do not output + * "isRoot" in table schemas. */ + default_is_root = root_set_size(schema) == shash_count(&schema->tables); tables = json_object_create(); SHASH_FOR_EACH (node, &schema->tables) { struct ovsdb_table_schema *table = node->data; json_object_put(tables, table->name, - ovsdb_table_schema_to_json(table)); + ovsdb_table_schema_to_json(table, default_is_root)); } json_object_put(json, "tables", tables); return json; } + +/* Returns true if 'a' and 'b' specify equivalent schemas, false if they + * differ. */ +bool +ovsdb_schema_equal(const struct ovsdb_schema *a, + const struct ovsdb_schema *b) +{ + /* This implementation is simple, stupid, and slow, but I doubt that it + * will ever require much maintenance. */ + struct json *ja = ovsdb_schema_to_json(a); + struct json *jb = ovsdb_schema_to_json(b); + bool equals = json_equal(ja, jb); + json_destroy(ja); + json_destroy(jb); + + return equals; +} static void ovsdb_set_ref_table(const struct shash *tables,