]> git.proxmox.com Git - mirror_ovs.git/blobdiff - ovsdb/row.c
monitor: Fix crash when monitor condition adds new columns.
[mirror_ovs.git] / ovsdb / row.c
index d088ff98a1c6a7e957c7549fbed30dc3cf31448d..755ab91a8c1cb9675737dc778079f4be9af56ef2 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009, 2010 Nicira Networks
+/* Copyright (c) 2009, 2010, 2011, 2012 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 
 #include "row.h"
 
-#include <assert.h>
 #include <stddef.h>
 
-#include "json.h"
+#include "openvswitch/dynamic-string.h"
+#include "openvswitch/json.h"
 #include "ovsdb-error.h"
-#include "shash.h"
+#include "openvswitch/shash.h"
 #include "sort.h"
 #include "table.h"
+#include "util.h"
 
 static struct ovsdb_row *
 allocate_row(const struct ovsdb_table *table)
 {
     size_t n_fields = shash_count(&table->schema->columns);
+    size_t n_indexes = table->schema->n_indexes;
     size_t row_size = (offsetof(struct ovsdb_row, fields)
-                       + sizeof(struct ovsdb_datum) * n_fields);
+                       + sizeof(struct ovsdb_datum) * n_fields
+                       + sizeof(struct hmap_node) * n_indexes);
     struct ovsdb_row *row = xmalloc(row_size);
-    row->table = (struct ovsdb_table *) table;
+    row->table = CONST_CAST(struct ovsdb_table *, table);
     row->txn_row = NULL;
+    ovs_list_init(&row->src_refs);
+    ovs_list_init(&row->dst_refs);
     row->n_refs = 0;
     return row;
 }
 
+/* Creates and returns a new row suitable for insertion into 'table'.  Does not
+ * actually insert the row into 'table' (use ovsdb_txn_row_insert()).  The
+ * caller must assign a UUID to the row. */
 struct ovsdb_row *
 ovsdb_row_create(const struct ovsdb_table *table)
 {
@@ -77,8 +85,21 @@ ovsdb_row_destroy(struct ovsdb_row *row)
 {
     if (row) {
         const struct ovsdb_table *table = row->table;
+        struct ovsdb_weak_ref *weak, *next;
         const struct shash_node *node;
 
+        LIST_FOR_EACH_SAFE (weak, next, dst_node, &row->dst_refs) {
+            ovs_list_remove(&weak->src_node);
+            ovs_list_remove(&weak->dst_node);
+            free(weak);
+        }
+
+        LIST_FOR_EACH_SAFE (weak, next, src_node, &row->src_refs) {
+            ovs_list_remove(&weak->src_node);
+            ovs_list_remove(&weak->dst_node);
+            free(weak);
+        }
+
         SHASH_FOR_EACH (node, &table->schema->columns) {
             const struct ovsdb_column *column = node->data;
             ovsdb_datum_destroy(&row->fields[column->index], &column->type);
@@ -158,6 +179,23 @@ ovsdb_row_update_columns(struct ovsdb_row *dst,
     }
 }
 
+/* Appends the string form of the value in 'row' of each of the columns in
+ * 'columns' to 'out', e.g. "1, \"xyz\", and [1, 2, 3]". */
+void
+ovsdb_row_columns_to_string(const struct ovsdb_row *row,
+                            const struct ovsdb_column_set *columns,
+                            struct ds *out)
+{
+    size_t i;
+
+    for (i = 0; i < columns->n_columns; i++) {
+        const struct ovsdb_column *column = columns->columns[i];
+
+        ds_put_cstr(out, english_list_delimiter(i, columns->n_columns));
+        ovsdb_datum_to_string(&row->fields[column->index], &column->type, out);
+    }
+}
+
 struct ovsdb_error *
 ovsdb_row_from_json(struct ovsdb_row *row, const struct json *json,
                     struct ovsdb_symbol_table *symtab,
@@ -307,13 +345,11 @@ ovsdb_row_hash_init(struct ovsdb_row_hash *rh,
 void
 ovsdb_row_hash_destroy(struct ovsdb_row_hash *rh, bool destroy_rows)
 {
-    struct ovsdb_row_hash_node *node, *next;
+    struct ovsdb_row_hash_node *node;
 
-    HMAP_FOR_EACH_SAFE (node, next, struct ovsdb_row_hash_node, hmap_node,
-                        &rh->rows) {
-        hmap_remove(&rh->rows, &node->hmap_node);
+    HMAP_FOR_EACH_POP (node, hmap_node, &rh->rows) {
         if (destroy_rows) {
-            ovsdb_row_destroy((struct ovsdb_row *) node->row);
+            ovsdb_row_destroy(CONST_CAST(struct ovsdb_row *, node->row));
         }
         free(node);
     }
@@ -342,8 +378,8 @@ ovsdb_row_hash_contains_all(const struct ovsdb_row_hash *a,
 {
     struct ovsdb_row_hash_node *node;
 
-    assert(ovsdb_column_set_equals(&a->columns, &b->columns));
-    HMAP_FOR_EACH (node, struct ovsdb_row_hash_node, hmap_node, &b->rows) {
+    ovs_assert(ovsdb_column_set_equals(&a->columns, &b->columns));
+    HMAP_FOR_EACH (node, hmap_node, &b->rows) {
         if (!ovsdb_row_hash_contains__(a, node->row, node->hmap_node.hash)) {
             return false;
         }
@@ -363,8 +399,7 @@ ovsdb_row_hash_contains__(const struct ovsdb_row_hash *rh,
                           const struct ovsdb_row *row, size_t hash)
 {
     struct ovsdb_row_hash_node *node;
-    HMAP_FOR_EACH_WITH_HASH (node, struct ovsdb_row_hash_node, hmap_node,
-                             hash, &rh->rows) {
+    HMAP_FOR_EACH_WITH_HASH (node, hmap_node, hash, &rh->rows) {
         if (ovsdb_row_equal_columns(row, node->row, &rh->columns)) {
             return true;
         }