Skip to content

Commit 276a3fe

Browse files
committed
ovsdb: transaction: Fix logging order of duplicate index rows.
The message about conflicting rows is trying to order the two rows in a consistent manner, so the log messages do not change in tests. But it fails to do so, because the order of columns in the column set depends on the order of columns inside the hash map, which depends on the hash function and the internal implementation details of the hash map. This results in random test failures, when two rows end up in the opposite order. Uncovered while testing a different hash map implementation, but the failure is technically possible even without any changes in the code, e.g., by running on a different CPU architecture or with different compiler flags. Fix that by introducing a new function that constructs the column set with columns in a predictable order and without UUID columns that have random values in most cases and so not actually comparable. Fixes: 6910a6e ("ovsdb: Implement table uniqueness constraints ("indexes").") Reported-by: Rosemarie O'Riorden <[email protected]> Acked-by: Eelco Chaudron [email protected] Acked-by: Dumitru Ceara <[email protected]> Signed-off-by: Ilya Maximets <[email protected]>
1 parent 2c6b5bb commit 276a3fe

File tree

3 files changed

+22
-1
lines changed

3 files changed

+22
-1
lines changed

ovsdb/column.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,25 @@ ovsdb_column_set_add_all(struct ovsdb_column_set *set,
254254
}
255255
}
256256

257+
void
258+
ovsdb_column_set_add_all_comparable(struct ovsdb_column_set *set,
259+
const struct ovsdb_table *table)
260+
{
261+
const struct shash_node **nodes = shash_sort(&table->schema->columns);
262+
size_t i, n = shash_count(&table->schema->columns);
263+
264+
for (i = 0; i < n; i++) {
265+
const struct ovsdb_column *column = nodes[i]->data;
266+
267+
/* UUIDs would cause a random order if used for comparison. */
268+
if (column->type.key.type != OVSDB_TYPE_UUID
269+
&& column->type.value.type != OVSDB_TYPE_UUID) {
270+
ovsdb_column_set_add(set, column);
271+
}
272+
}
273+
free(nodes);
274+
}
275+
257276
bool
258277
ovsdb_column_set_contains(const struct ovsdb_column_set *set,
259278
unsigned int column_index)

ovsdb/column.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ void ovsdb_column_set_add(struct ovsdb_column_set *,
7979
const struct ovsdb_column *);
8080
void ovsdb_column_set_add_all(struct ovsdb_column_set *,
8181
const struct ovsdb_table *);
82+
void ovsdb_column_set_add_all_comparable(struct ovsdb_column_set *,
83+
const struct ovsdb_table *);
8284
bool ovsdb_column_set_contains(const struct ovsdb_column_set *,
8385
unsigned int column_index);
8486
bool ovsdb_column_set_equals(const struct ovsdb_column_set *,

ovsdb/transaction.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -950,7 +950,7 @@ duplicate_index_row(const struct ovsdb_column_set *index,
950950
/* Put 'a' and 'b' in a predictable order to make error messages
951951
* reproducible for testing. */
952952
ovsdb_column_set_init(&all_columns);
953-
ovsdb_column_set_add_all(&all_columns, a->table);
953+
ovsdb_column_set_add_all_comparable(&all_columns, a->table);
954954
if (ovsdb_row_compare_columns_3way(a, b, &all_columns) < 0) {
955955
const struct ovsdb_row *tmp = a;
956956
a = b;

0 commit comments

Comments
 (0)