diff options
Diffstat (limited to 'ovsdb/column.c')
-rw-r--r-- | ovsdb/column.c | 232 |
1 files changed, 232 insertions, 0 deletions
diff --git a/ovsdb/column.c b/ovsdb/column.c new file mode 100644 index 000000000..1e8a2d09d --- /dev/null +++ b/ovsdb/column.c @@ -0,0 +1,232 @@ +/* Copyright (c) 2009 Nicira Networks + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <config.h> + +#include "ovsdb/column.h" + +#include <stdlib.h> + +#include "column.h" +#include "json.h" +#include "ovsdb-error.h" +#include "ovsdb-parser.h" +#include "table.h" +#include "util.h" + +struct ovsdb_column * +ovsdb_column_create(const char *name, const char *comment, + bool mutable, bool persistent, + const struct ovsdb_type *type) +{ + struct ovsdb_column *ts; + + ts = xzalloc(sizeof *ts); + ts->name = xstrdup(name); + ts->comment = comment ? xstrdup(comment) : NULL; + ts->mutable = mutable; + ts->persistent = persistent; + ts->type = *type; + + return ts; +} + +void +ovsdb_column_destroy(struct ovsdb_column *column) +{ + free(column->name); + free(column->comment); + free(column); +} + +struct ovsdb_error * +ovsdb_column_from_json(const struct json *json, const char *name, + struct ovsdb_column **columnp) +{ + const struct json *comment, *mutable, *ephemeral, *type_json; + struct ovsdb_error *error; + struct ovsdb_type type; + struct ovsdb_parser parser; + bool persistent; + + *columnp = NULL; + + ovsdb_parser_init(&parser, json, "schema for column %s", name); + comment = ovsdb_parser_member(&parser, "comment", OP_STRING | OP_OPTIONAL); + mutable = ovsdb_parser_member(&parser, "mutable", + OP_TRUE | OP_FALSE | OP_OPTIONAL); + ephemeral = ovsdb_parser_member(&parser, "ephemeral", + OP_TRUE | OP_FALSE | OP_OPTIONAL); + type_json = ovsdb_parser_member(&parser, "type", OP_STRING | OP_OBJECT); + error = ovsdb_parser_finish(&parser); + if (error) { + return error; + } + + error = ovsdb_type_from_json(&type, type_json); + if (error) { + return error; + } + + persistent = ephemeral ? !json_boolean(ephemeral) : true; + *columnp = ovsdb_column_create(name, + comment ? json_string(comment) : NULL, + mutable ? json_boolean(mutable) : true, + persistent, &type); + return NULL; +} + +struct json * +ovsdb_column_to_json(const struct ovsdb_column *column) +{ + struct json *json = json_object_create(); + if (column->comment) { + json_object_put_string(json, "comment", column->comment); + } + if (!column->mutable) { + json_object_put(json, "mutable", json_boolean_create(false)); + } + if (!column->persistent) { + json_object_put(json, "ephemeral", json_boolean_create(true)); + } + json_object_put(json, "type", ovsdb_type_to_json(&column->type)); + return json; +} + +void +ovsdb_column_set_init(struct ovsdb_column_set *set) +{ + set->columns = NULL; + set->n_columns = set->allocated_columns = 0; +} + +void +ovsdb_column_set_destroy(struct ovsdb_column_set *set) +{ + free(set->columns); +} + +void +ovsdb_column_set_clone(struct ovsdb_column_set *new, + const struct ovsdb_column_set *old) +{ + new->columns = xmemdup(old->columns, + old->n_columns * sizeof *old->columns); + new->n_columns = new->allocated_columns = old->n_columns; +} + +struct ovsdb_error * +ovsdb_column_set_from_json(const struct json *json, + const struct ovsdb_table *table, + struct ovsdb_column_set *set) +{ + ovsdb_column_set_init(set); + if (!json) { + struct shash_node *node; + + SHASH_FOR_EACH (node, &table->schema->columns) { + const struct ovsdb_column *column = node->data; + ovsdb_column_set_add(set, column); + } + + return NULL; + } else { + size_t i; + + if (json->type != JSON_ARRAY) { + goto error; + } + + /* XXX this is O(n**2) */ + for (i = 0; i < json->u.array.n; i++) { + struct ovsdb_column *column; + + if (json->u.array.elems[i]->type != JSON_STRING) { + goto error; + } + + column = shash_find_data(&table->schema->columns, + json->u.array.elems[i]->u.string); + if (ovsdb_column_set_contains(set, column->index)) { + goto error; + } + ovsdb_column_set_add(set, column); + } + + return NULL; + } + +error: + ovsdb_column_set_destroy(set); + return ovsdb_syntax_error(json, NULL, + "array of distinct column names expected"); +} + +void +ovsdb_column_set_add(struct ovsdb_column_set *set, + const struct ovsdb_column *column) +{ + if (set->n_columns >= set->allocated_columns) { + set->columns = x2nrealloc(set->columns, &set->allocated_columns, + sizeof *set->columns); + } + set->columns[set->n_columns++] = column; +} + +void +ovsdb_column_set_add_all(struct ovsdb_column_set *set, + const struct ovsdb_table *table) +{ + struct shash_node *node; + + SHASH_FOR_EACH (node, &table->schema->columns) { + const struct ovsdb_column *column = node->data; + ovsdb_column_set_add(set, column); + } +} + +bool +ovsdb_column_set_contains(const struct ovsdb_column_set *set, + unsigned int column_index) +{ + size_t i; + + for (i = 0; i < set->n_columns; i++) { + if (set->columns[i]->index == column_index) { + return true; + } + } + return false; +} + +/* This comparison is sensitive to ordering of columns within a set, but that's + * good: the only existing caller wants to make sure that hash values are + * comparable, which is only true if column ordering is the same. */ +bool +ovsdb_column_set_equals(const struct ovsdb_column_set *a, + const struct ovsdb_column_set *b) +{ + size_t i; + + if (a->n_columns != b->n_columns) { + return false; + } + for (i = 0; i < a->n_columns; i++) { + if (a->columns[i] != b->columns[i]) { + return false; + } + } + return true; +} |