summaryrefslogtreecommitdiff
path: root/ovsdb/column.c
diff options
context:
space:
mode:
Diffstat (limited to 'ovsdb/column.c')
-rw-r--r--ovsdb/column.c232
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;
+}