Compatible schemas can be joined together by merging their tables and columns. Schemas are compatible if they don't contain tables or columns that are conflict in types.
Signed-off-by: Andy Zhou <az...@nicira.com> --- ovsdb/column.c | 16 +++++++++++++- ovsdb/column.h | 4 +++- ovsdb/ovsdb.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++- ovsdb/ovsdb.h | 6 +++++- ovsdb/table.c | 39 +++++++++++++++++++++++++++++++++ ovsdb/table.h | 3 +++ 6 files changed, 132 insertions(+), 4 deletions(-) diff --git a/ovsdb/column.c b/ovsdb/column.c index 26b7a0b..007ff9b 100644 --- a/ovsdb/column.c +++ b/ovsdb/column.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2009, 2010, 2011 Nicira, Inc. +/* Copyright (c) 2009, 2010, 2011, 2015 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -53,6 +53,20 @@ ovsdb_column_clone(const struct ovsdb_column *old) &old->type); } +bool +ovsdb_column_equal(const struct ovsdb_column *a, + const struct ovsdb_column *b) +{ + struct json *ja = ovsdb_column_to_json(a); + struct json *jb = ovsdb_column_to_json(b); + bool equals = json_equal(ja, jb); + + json_destroy(ja); + json_destroy(jb); + + return equals; +} + void ovsdb_column_destroy(struct ovsdb_column *column) { diff --git a/ovsdb/column.h b/ovsdb/column.h index f75a107..a5f67b9 100644 --- a/ovsdb/column.h +++ b/ovsdb/column.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2009, 2010, 2011 Nicira, Inc. +/* Copyright (c) 2009, 2010, 2011, 2015 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -48,6 +48,8 @@ struct ovsdb_column *ovsdb_column_create( const char *name, bool mutable, bool persistent, const struct ovsdb_type *); struct ovsdb_column *ovsdb_column_clone(const struct ovsdb_column *); +bool ovsdb_column_equal(const struct ovsdb_column *, + const struct ovsdb_column *); void ovsdb_column_destroy(struct ovsdb_column *); struct ovsdb_error *ovsdb_column_from_json(const struct json *, diff --git a/ovsdb/ovsdb.c b/ovsdb/ovsdb.c index 56d2333..4a2353f 100644 --- a/ovsdb/ovsdb.c +++ b/ovsdb/ovsdb.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2009, 2010, 2011, 2012, 2013 Nicira, Inc. +/* Copyright (c) 2009, 2010, 2011, 2012, 2013, 2015 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -74,6 +74,35 @@ ovsdb_schema_destroy(struct ovsdb_schema *schema) free(schema); } +/* Join two schemas into a single schema, by adding missing tables from 'src' + * to 'dst'. In case 'src' and 'dst' both has the same table, the joined 'dst' table + * will contain the columns from both 'src' and 'dst' tables. */ +static struct ovsdb_error * +ovsdb_schema_join(struct ovsdb_schema *dst, const struct ovsdb_schema *src) +{ + struct shash_node *snode; + + SHASH_FOR_EACH (snode, &src->tables) { + const struct ovsdb_table_schema *sts = snode->data; + struct shash_node *dnode; + + dnode = shash_find(&dst->tables, sts->name); + if (dnode) { + struct ovsdb_table_schema *dts = dnode->data; + struct ovsdb_error *err; + + err = ovsdb_table_schema_join(dts, sts); + if (err) { + return err; + } + } else { + shash_add(&dst->tables, sts->name, ovsdb_table_schema_clone(sts)); + } + } + + return NULL; +} + struct ovsdb_error * ovsdb_schema_from_file(const char *file_name, struct ovsdb_schema **schemap) { @@ -429,3 +458,40 @@ ovsdb_remove_replica(struct ovsdb *db OVS_UNUSED, struct ovsdb_replica *r) list_remove(&r->node); (r->class->destroy)(r); } + +/* Join each schema within 'schemas' into a single joined schema. + * 'schemas' passed in should have at least one schema. + * + * On success, this function returns NULL, 'schemap' points to the newly created + * joined schema. The caller is responsible for reclaiming memory via + * ovsdb_schema_destroy(). + * + * On error, an ovsdb_error will be allocated describing the error, the caller + * is only needs to dispose memory of the error. */ +struct ovsdb_error * +ovsdb_schemas_join(const struct shash *schemas, struct ovsdb_schema **schemap) +{ + struct shash_node *first_node = shash_first(schemas), *node; + struct ovsdb_schema *schema; + + ovs_assert(first_node); + schema = ovsdb_schema_clone(first_node->data); + + SHASH_FOR_EACH (node, schemas) { + struct ovsdb_error *error; + + if (node == first_node) { + continue; + } + + error = ovsdb_schema_join(schema, node->data); + if (error) { + ovsdb_schema_destroy(schema); + *schemap = NULL; + return error; + } + } + + *schemap = schema; + return NULL; +} diff --git a/ovsdb/ovsdb.h b/ovsdb/ovsdb.h index 04586e7..4faad20 100644 --- a/ovsdb/ovsdb.h +++ b/ovsdb/ovsdb.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2009, 2010, 2011, 2012, 2013 Nicira, Inc. +/* Copyright (c) 2009, 2010, 2011, 2012, 2013, 2015 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -52,6 +52,10 @@ struct json *ovsdb_schema_to_json(const struct ovsdb_schema *); bool ovsdb_schema_equal(const struct ovsdb_schema *, const struct ovsdb_schema *); + +struct ovsdb_error *ovsdb_schemas_join(const struct shash *schemas, + struct ovsdb_schema **) + OVS_WARN_UNUSED_RESULT; /* Database. */ struct ovsdb { diff --git a/ovsdb/table.c b/ovsdb/table.c index e7545ad..ec43d98 100644 --- a/ovsdb/table.c +++ b/ovsdb/table.c @@ -102,6 +102,45 @@ ovsdb_table_schema_clone(const struct ovsdb_table_schema *old) return new; } +struct ovsdb_error * +ovsdb_table_schema_join(struct ovsdb_table_schema *dst, + const struct ovsdb_table_schema *src) +{ + struct shash_node *node; + +#undef CHECK_TABLE_FIELD +#define CHECK_TABLE_FIELD(dst, src, field) \ + if (dst->field != src->field) { \ + return ovsdb_error("schema join error", \ + "attribute %s of table %s match failed", \ + #field, dst->name); \ + } + + CHECK_TABLE_FIELD(dst, src, mutable); + CHECK_TABLE_FIELD(dst, src, is_root); + CHECK_TABLE_FIELD(dst, src, max_rows); + +#undef CHECK_TABLE_FIELD + + SHASH_FOR_EACH (node, &src->columns) { + struct ovsdb_column *scol = node->data; + const struct ovsdb_column *dcol; + + dcol = ovsdb_table_schema_get_column(dst, scol->name); + if (dcol) { + if (!ovsdb_column_equal(dcol, scol)) { + return ovsdb_error("schema join error", + "column %s of table %s match failed", + dcol->name, dst->name); + } + } else { + add_column(dst, ovsdb_column_clone(scol)); + } + } + + return NULL; +} + void ovsdb_table_schema_destroy(struct ovsdb_table_schema *ts) { diff --git a/ovsdb/table.h b/ovsdb/table.h index 68a59ad..8572ee4 100644 --- a/ovsdb/table.h +++ b/ovsdb/table.h @@ -39,6 +39,9 @@ struct ovsdb_table_schema *ovsdb_table_schema_create( const char *name, bool mutable, unsigned int max_rows, bool is_root); struct ovsdb_table_schema *ovsdb_table_schema_clone( const struct ovsdb_table_schema *); +struct ovsdb_error *ovsdb_table_schema_join(struct ovsdb_table_schema *, + const struct ovsdb_table_schema *) + OVS_WARN_UNUSED_RESULT; void ovsdb_table_schema_destroy(struct ovsdb_table_schema *); struct ovsdb_error *ovsdb_table_schema_from_json(const struct json *, -- 1.9.1 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev