ovsdb-idl: Fix iteration over rows in IDL tables.
authorBen Pfaff <blp@nicira.com>
Wed, 3 Mar 2010 17:59:47 +0000 (09:59 -0800)
committerBen Pfaff <blp@nicira.com>
Wed, 3 Mar 2010 17:59:47 +0000 (09:59 -0800)
The IDL was returning rows that had existed in the database and were
deleted by the current transaction (that is, row->old && !row->new).
This commit fixes the problem.

The condition used by next_real_row() was just blatantly wrong and
illogical.  The correct condition is row->new != NULL.  The old condition
only got one case wrong (the one mentioned above), even though it didn't
make much sense.

This fixes an ovs-vsctl call that assert-failed in a "set" command that
iterated through a table from which a previous ovs-vsctl command (in the
same invocation) had deleted a row.

lib/ovsdb-idl.c

index 4826d62ed489c2cb89417366abd911c1bfb7843a..cc9deac91e56baf82b83115933369b15efe4c374 100644 (file)
@@ -545,6 +545,26 @@ static bool
 ovsdb_idl_row_is_orphan(const struct ovsdb_idl_row *row)
 {
     return !row->old;
+/* Returns true if 'row' is conceptually part of the database as modified by
+ * the current transaction (if any), false otherwise.
+ *
+ * This function will return true if 'row' is not an orphan (see the comment on
+ * ovsdb_idl_row_is_orphan()) and:
+ *
+ *   - 'row' exists in the database and has not been deleted within the
+ *     current transaction (if any).
+ *
+ *   - 'row' was inserted within the current transaction and has not been
+ *     deleted.  (In the latter case you should not have passed 'row' in at
+ *     all, because ovsdb_idl_txn_delete() freed it.)
+ *
+ * This function will return false if 'row' is an orphan or if 'row' was
+ * deleted within the current transaction.
+ */
+static bool
+ovsdb_idl_row_exists(const struct ovsdb_idl_row *row)
+{
+    return row->new != NULL;
 }
 
 static void
@@ -810,7 +830,7 @@ next_real_row(struct ovsdb_idl_table *table, struct hmap_node *node)
         struct ovsdb_idl_row *row;
 
         row = CONTAINER_OF(node, struct ovsdb_idl_row, hmap_node);
-        if (row->new || !ovsdb_idl_row_is_orphan(row)) {
+        if (ovsdb_idl_row_exists(row)) {
             return row;
         }
     }