1 /* Copyright (c) 2009, 2010 Nicira Networks
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
7 * http://www.apache.org/licenses/LICENSE-2.0
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
24 #include "ovsdb-error.h"
29 static struct ovsdb_row *
30 allocate_row(const struct ovsdb_table *table)
32 size_t n_fields = shash_count(&table->schema->columns);
33 size_t row_size = (offsetof(struct ovsdb_row, fields)
34 + sizeof(struct ovsdb_datum) * n_fields);
35 struct ovsdb_row *row = xmalloc(row_size);
36 row->table = (struct ovsdb_table *) table;
43 ovsdb_row_create(const struct ovsdb_table *table)
45 struct shash_node *node;
46 struct ovsdb_row *row;
48 row = allocate_row(table);
49 SHASH_FOR_EACH (node, &table->schema->columns) {
50 const struct ovsdb_column *column = node->data;
51 ovsdb_datum_init_default(&row->fields[column->index], &column->type);
57 ovsdb_row_clone(const struct ovsdb_row *old)
59 const struct ovsdb_table *table = old->table;
60 const struct shash_node *node;
61 struct ovsdb_row *new;
63 new = allocate_row(table);
64 SHASH_FOR_EACH (node, &table->schema->columns) {
65 const struct ovsdb_column *column = node->data;
66 ovsdb_datum_clone(&new->fields[column->index],
67 &old->fields[column->index],
73 /* The caller is responsible for ensuring that 'row' has been removed from its
74 * table and that it is not participating in a transaction. */
76 ovsdb_row_destroy(struct ovsdb_row *row)
79 const struct ovsdb_table *table = row->table;
80 const struct shash_node *node;
82 SHASH_FOR_EACH (node, &table->schema->columns) {
83 const struct ovsdb_column *column = node->data;
84 ovsdb_datum_destroy(&row->fields[column->index], &column->type);
91 ovsdb_row_hash_columns(const struct ovsdb_row *row,
92 const struct ovsdb_column_set *columns,
97 for (i = 0; i < columns->n_columns; i++) {
98 const struct ovsdb_column *column = columns->columns[i];
99 basis = ovsdb_datum_hash(&row->fields[column->index], &column->type,
107 ovsdb_row_compare_columns_3way(const struct ovsdb_row *a,
108 const struct ovsdb_row *b,
109 const struct ovsdb_column_set *columns)
113 for (i = 0; i < columns->n_columns; i++) {
114 const struct ovsdb_column *column = columns->columns[i];
115 int cmp = ovsdb_datum_compare_3way(&a->fields[column->index],
116 &b->fields[column->index],
127 ovsdb_row_equal_columns(const struct ovsdb_row *a,
128 const struct ovsdb_row *b,
129 const struct ovsdb_column_set *columns)
133 for (i = 0; i < columns->n_columns; i++) {
134 const struct ovsdb_column *column = columns->columns[i];
135 if (!ovsdb_datum_equals(&a->fields[column->index],
136 &b->fields[column->index],
146 ovsdb_row_update_columns(struct ovsdb_row *dst,
147 const struct ovsdb_row *src,
148 const struct ovsdb_column_set *columns)
152 for (i = 0; i < columns->n_columns; i++) {
153 const struct ovsdb_column *column = columns->columns[i];
154 ovsdb_datum_destroy(&dst->fields[column->index], &column->type);
155 ovsdb_datum_clone(&dst->fields[column->index],
156 &src->fields[column->index],
162 ovsdb_row_from_json(struct ovsdb_row *row, const struct json *json,
163 struct ovsdb_symbol_table *symtab,
164 struct ovsdb_column_set *included)
166 struct ovsdb_table_schema *schema = row->table->schema;
167 struct ovsdb_error *error;
168 struct shash_node *node;
170 if (json->type != JSON_OBJECT) {
171 return ovsdb_syntax_error(json, NULL, "row must be JSON object");
174 SHASH_FOR_EACH (node, json_object(json)) {
175 const char *column_name = node->name;
176 const struct ovsdb_column *column;
177 struct ovsdb_datum datum;
179 column = ovsdb_table_schema_get_column(schema, column_name);
181 return ovsdb_syntax_error(json, "unknown column",
182 "No column %s in table %s.",
183 column_name, schema->name);
186 error = ovsdb_datum_from_json(&datum, &column->type, node->data,
191 ovsdb_datum_swap(&row->fields[column->index], &datum);
192 ovsdb_datum_destroy(&datum, &column->type);
194 ovsdb_column_set_add(included, column);
202 put_json_column(struct json *object, const struct ovsdb_row *row,
203 const struct ovsdb_column *column)
205 json_object_put(object, column->name,
206 ovsdb_datum_to_json(&row->fields[column->index],
211 ovsdb_row_to_json(const struct ovsdb_row *row,
212 const struct ovsdb_column_set *columns)
217 json = json_object_create();
218 for (i = 0; i < columns->n_columns; i++) {
219 put_json_column(json, row, columns->columns[i]);
225 ovsdb_row_set_init(struct ovsdb_row_set *set)
228 set->n_rows = set->allocated_rows = 0;
232 ovsdb_row_set_destroy(struct ovsdb_row_set *set)
238 ovsdb_row_set_add_row(struct ovsdb_row_set *set, const struct ovsdb_row *row)
240 if (set->n_rows >= set->allocated_rows) {
241 set->rows = x2nrealloc(set->rows, &set->allocated_rows,
244 set->rows[set->n_rows++] = row;
248 ovsdb_row_set_to_json(const struct ovsdb_row_set *rows,
249 const struct ovsdb_column_set *columns)
251 struct json **json_rows;
254 json_rows = xmalloc(rows->n_rows * sizeof *json_rows);
255 for (i = 0; i < rows->n_rows; i++) {
256 json_rows[i] = ovsdb_row_to_json(rows->rows[i], columns);
258 return json_array_create(json_rows, rows->n_rows);
261 struct ovsdb_row_set_sort_cbdata {
262 struct ovsdb_row_set *set;
263 const struct ovsdb_column_set *columns;
267 ovsdb_row_set_sort_compare_cb(size_t a, size_t b, void *cbdata_)
269 struct ovsdb_row_set_sort_cbdata *cbdata = cbdata_;
270 return ovsdb_row_compare_columns_3way(cbdata->set->rows[a],
271 cbdata->set->rows[b],
276 ovsdb_row_set_sort_swap_cb(size_t a, size_t b, void *cbdata_)
278 struct ovsdb_row_set_sort_cbdata *cbdata = cbdata_;
279 const struct ovsdb_row *tmp = cbdata->set->rows[a];
280 cbdata->set->rows[a] = cbdata->set->rows[b];
281 cbdata->set->rows[b] = tmp;
285 ovsdb_row_set_sort(struct ovsdb_row_set *set,
286 const struct ovsdb_column_set *columns)
288 if (columns && columns->n_columns && set->n_rows > 1) {
289 struct ovsdb_row_set_sort_cbdata cbdata;
291 cbdata.columns = columns;
293 ovsdb_row_set_sort_compare_cb,
294 ovsdb_row_set_sort_swap_cb,
300 ovsdb_row_hash_init(struct ovsdb_row_hash *rh,
301 const struct ovsdb_column_set *columns)
303 hmap_init(&rh->rows);
304 ovsdb_column_set_clone(&rh->columns, columns);
308 ovsdb_row_hash_destroy(struct ovsdb_row_hash *rh, bool destroy_rows)
310 struct ovsdb_row_hash_node *node, *next;
312 HMAP_FOR_EACH_SAFE (node, next, struct ovsdb_row_hash_node, hmap_node,
314 hmap_remove(&rh->rows, &node->hmap_node);
316 ovsdb_row_destroy((struct ovsdb_row *) node->row);
320 hmap_destroy(&rh->rows);
321 ovsdb_column_set_destroy(&rh->columns);
325 ovsdb_row_hash_count(const struct ovsdb_row_hash *rh)
327 return hmap_count(&rh->rows);
331 ovsdb_row_hash_contains(const struct ovsdb_row_hash *rh,
332 const struct ovsdb_row *row)
334 size_t hash = ovsdb_row_hash_columns(row, &rh->columns, 0);
335 return ovsdb_row_hash_contains__(rh, row, hash);
338 /* Returns true if every row in 'b' has an equal row in 'a'. */
340 ovsdb_row_hash_contains_all(const struct ovsdb_row_hash *a,
341 const struct ovsdb_row_hash *b)
343 struct ovsdb_row_hash_node *node;
345 assert(ovsdb_column_set_equals(&a->columns, &b->columns));
346 HMAP_FOR_EACH (node, struct ovsdb_row_hash_node, hmap_node, &b->rows) {
347 if (!ovsdb_row_hash_contains__(a, node->row, node->hmap_node.hash)) {
355 ovsdb_row_hash_insert(struct ovsdb_row_hash *rh, const struct ovsdb_row *row)
357 size_t hash = ovsdb_row_hash_columns(row, &rh->columns, 0);
358 return ovsdb_row_hash_insert__(rh, row, hash);
362 ovsdb_row_hash_contains__(const struct ovsdb_row_hash *rh,
363 const struct ovsdb_row *row, size_t hash)
365 struct ovsdb_row_hash_node *node;
366 HMAP_FOR_EACH_WITH_HASH (node, struct ovsdb_row_hash_node, hmap_node,
368 if (ovsdb_row_equal_columns(row, node->row, &rh->columns)) {
376 ovsdb_row_hash_insert__(struct ovsdb_row_hash *rh, const struct ovsdb_row *row,
379 if (!ovsdb_row_hash_contains__(rh, row, hash)) {
380 struct ovsdb_row_hash_node *node = xmalloc(sizeof *node);
382 hmap_insert(&rh->rows, &node->hmap_node, hash);