return next_real_row(table, hmap_next(&table->rows, &row->hmap_node));
}
+
+/* Reads and returns the value of 'column' within 'row'. If an ongoing
+ * transaction has changed 'column''s value, the modified value is returned.
+ *
+ * The caller must not modify or free the returned value.
+ *
+ * Various kinds of changes can invalidate the returned value: writing to the
+ * same 'column' in 'row' (e.g. with ovsdb_idl_txn_write()), deleting 'row'
+ * (e.g. with ovsdb_idl_txn_delete()), or completing an ongoing transaction
+ * (e.g. with ovsdb_idl_txn_commit() or ovsdb_idl_txn_abort()). If the
+ * returned value is needed for a long time, it is best to make a copy of it
+ * with ovsdb_datum_clone(). */
+const struct ovsdb_datum *
+ovsdb_idl_read(const struct ovsdb_idl_row *row,
+ const struct ovsdb_idl_column *column)
+{
+ const struct ovsdb_idl_table_class *class = row->table->class;
+ size_t column_idx = column - class->columns;
+
+ assert(row->new != NULL);
+ assert(column_idx < class->n_columns);
+
+ if (row->written && bitmap_is_set(row->written, column_idx)) {
+ return &row->new[column_idx];
+ } else if (row->old) {
+ return &row->old[column_idx];
+ } else {
+ return ovsdb_datum_default(&column->type);
+ }
+}
+
+/* Same as ovsdb_idl_read(), except that it also asserts that 'column' has key
+ * type 'key_type' and value type 'value_type'. (Scalar and set types will
+ * have a value type of OVSDB_TYPE_VOID.)
+ *
+ * This is useful in code that "knows" that a particular column has a given
+ * type, so that it will abort if someone changes the column's type without
+ * updating the code that uses it. */
+const struct ovsdb_datum *
+ovsdb_idl_get(const struct ovsdb_idl_row *row,
+ const struct ovsdb_idl_column *column,
+ enum ovsdb_atomic_type key_type OVS_UNUSED,
+ enum ovsdb_atomic_type value_type OVS_UNUSED)
+{
+ assert(column->type.key.type == key_type);
+ assert(column->type.value.type == value_type);
+
+ return ovsdb_idl_read(row, column);
+}
\f
/* Transactions. */
hmap_remove(&txn->idl->outstanding_txns, &txn->hmap_node);
}
-void
-ovsdb_idl_txn_read(const struct ovsdb_idl_row *row,
- const struct ovsdb_idl_column *column,
- struct ovsdb_datum *datum)
-{
- const struct ovsdb_idl_table_class *class = row->table->class;
- size_t column_idx = column - class->columns;
-
- assert(row->new != NULL);
- if (row->written && bitmap_is_set(row->written, column_idx)) {
- ovsdb_datum_clone(datum, &row->new[column_idx], &column->type);
- } else if (row->old) {
- ovsdb_datum_clone(datum, &row->old[column_idx], &column->type);
- } else {
- ovsdb_datum_init_default(datum, &column->type);
- }
-}
-
void
ovsdb_idl_txn_write(const struct ovsdb_idl_row *row_,
const struct ovsdb_idl_column *column,
const struct ovsdb_idl_row *row;
unsigned int best_score = 0;
- /* It might make sense to relax this assertion. */
- assert(id->name_column->type.key.type == OVSDB_TYPE_STRING);
-
referrer = NULL;
for (row = ovsdb_idl_first_row(ctx->idl, id->table);
row != NULL && best_score != UINT_MAX;
row = ovsdb_idl_next_row(row))
{
- struct ovsdb_datum name;
+ const struct ovsdb_datum *name;
- ovsdb_idl_txn_read(row, id->name_column, &name);
- if (name.n == 1) {
+ name = ovsdb_idl_get(row, id->name_column,
+ OVSDB_TYPE_STRING, OVSDB_TYPE_VOID);
+ if (name->n == 1) {
unsigned int score;
score = (partial_match_ok
- ? score_partial_match(name.keys[0].string, record_id)
- : !strcmp(name.keys[0].string, record_id));
+ ? score_partial_match(name->keys[0].string, record_id)
+ : !strcmp(name->keys[0].string, record_id));
if (score > best_score) {
referrer = row;
best_score = score;
referrer = NULL;
}
}
- ovsdb_datum_destroy(&name, &id->name_column->type);
}
if (best_score && !referrer) {
vsctl_fatal("multiple rows in %s match \"%s\"",
final = NULL;
if (id->uuid_column) {
- struct ovsdb_datum uuid;
-
- assert(id->uuid_column->type.key.type == OVSDB_TYPE_UUID);
- assert(id->uuid_column->type.value.type == OVSDB_TYPE_VOID);
+ const struct ovsdb_datum *uuid;
- ovsdb_idl_txn_read(referrer, id->uuid_column, &uuid);
- if (uuid.n == 1) {
+ uuid = ovsdb_idl_get(referrer, id->uuid_column,
+ OVSDB_TYPE_UUID, OVSDB_TYPE_VOID);
+ if (uuid->n == 1) {
final = ovsdb_idl_get_row_for_uuid(ctx->idl, table->class,
- &uuid.keys[0].uuid);
+ &uuid->keys[0].uuid);
}
- ovsdb_datum_destroy(&uuid, &id->uuid_column->type);
} else {
final = referrer;
}
row = must_get_row(ctx, table, record_id);
for (i = 3; i < ctx->argc; i++) {
const struct ovsdb_idl_column *column;
- struct ovsdb_datum datum;
+ const struct ovsdb_datum *datum;
char *key_string;
/* Special case for obtaining the UUID of a row. We can't just do this
&column, &key_string,
NULL, NULL, 0, NULL));
- ovsdb_idl_txn_read(row, column, &datum);
+ datum = ovsdb_idl_read(row, column);
if (key_string) {
union ovsdb_atom key;
unsigned int idx;
&column->type.key,
key_string, ctx->symtab));
- idx = ovsdb_datum_find_key(&datum, &key,
+ idx = ovsdb_datum_find_key(datum, &key,
column->type.key.type);
if (idx == UINT_MAX) {
if (!if_exists) {
column->name);
}
} else {
- ovsdb_atom_to_string(&datum.values[idx],
+ ovsdb_atom_to_string(&datum->values[idx],
column->type.value.type, out);
}
ovsdb_atom_destroy(&key, column->type.key.type);
} else {
- ovsdb_datum_to_string(&datum, &column->type, out);
+ ovsdb_datum_to_string(datum, &column->type, out);
}
ds_put_char(out, '\n');
- ovsdb_datum_destroy(&datum, &column->type);
free(key_string);
}
UUID_ARGS(&row->uuid));
for (i = 0; i < table->class->n_columns; i++) {
const struct ovsdb_idl_column *column = &table->class->columns[i];
- struct ovsdb_datum datum;
+ const struct ovsdb_datum *datum;
- ovsdb_idl_txn_read(row, column, &datum);
+ datum = ovsdb_idl_read(row, column);
ds_put_format(out, "%-20s: ", column->name);
- ovsdb_datum_to_string(&datum, &column->type, out);
+ ovsdb_datum_to_string(datum, &column->type, out);
ds_put_char(out, '\n');
-
- ovsdb_datum_destroy(&datum, &column->type);
}
}
if (key_string) {
union ovsdb_atom key, value;
- struct ovsdb_datum old, new;
+ struct ovsdb_datum datum;
if (column->type.value.type == OVSDB_TYPE_VOID) {
vsctl_fatal("cannot specify key to set for non-map column %s",
die_if_error(ovsdb_atom_from_string(&value, &column->type.value,
value_string, symtab));
- ovsdb_datum_init_empty(&new);
- ovsdb_datum_add_unsafe(&new, &key, &value, &column->type);
+ ovsdb_datum_init_empty(&datum);
+ ovsdb_datum_add_unsafe(&datum, &key, &value, &column->type);
ovsdb_atom_destroy(&key, column->type.key.type);
ovsdb_atom_destroy(&value, column->type.value.type);
- ovsdb_idl_txn_read(row, column, &old);
- ovsdb_datum_union(&old, &new, &column->type, true);
- ovsdb_idl_txn_write(row, column, &old);
-
- ovsdb_datum_destroy(&new, &column->type);
+ ovsdb_datum_union(&datum, ovsdb_idl_read(row, column),
+ &column->type, false);
+ ovsdb_idl_txn_write(row, column, &datum);
} else {
struct ovsdb_datum datum;
die_if_error(get_column(table, column_name, &column));
type = &column->type;
- ovsdb_idl_txn_read(row, column, &old);
+ ovsdb_datum_clone(&old, ovsdb_idl_read(row, column), &column->type);
for (i = 4; i < ctx->argc; i++) {
struct ovsdb_type add_type;
struct ovsdb_datum add;
die_if_error(get_column(table, column_name, &column));
type = &column->type;
- ovsdb_idl_txn_read(row, column, &old);
+ ovsdb_datum_clone(&old, ovsdb_idl_read(row, column), &column->type);
for (i = 4; i < ctx->argc; i++) {
struct ovsdb_type rm_type;
struct ovsdb_datum rm;
};
const struct ovsdb_idl_column *column;
+ const struct ovsdb_datum *have_datum;
char *key_string, *value_string;
- struct ovsdb_datum have_datum;
const char *operator;
unsigned int idx;
char *error;
vsctl_fatal("%s: missing value", arg);
}
- ovsdb_idl_txn_read(row, column, &have_datum);
+ have_datum = ovsdb_idl_read(row, column);
if (key_string) {
union ovsdb_atom want_key, want_value;
die_if_error(ovsdb_atom_from_string(&want_value, &column->type.value,
value_string, symtab));
- idx = ovsdb_datum_find_key(&have_datum,
+ idx = ovsdb_datum_find_key(have_datum,
&want_key, column->type.key.type);
if (idx != UINT_MAX) {
- cmp = ovsdb_atom_compare_3way(&have_datum.values[idx],
+ cmp = ovsdb_atom_compare_3way(&have_datum->values[idx],
&want_value,
column->type.value.type);
}
die_if_error(ovsdb_datum_from_string(&want_datum, &column->type,
value_string, symtab));
idx = 0;
- cmp = ovsdb_datum_compare_3way(&have_datum, &want_datum,
+ cmp = ovsdb_datum_compare_3way(have_datum, &want_datum,
&column->type);
ovsdb_datum_destroy(&want_datum, &column->type);
}
- ovsdb_datum_destroy(&have_datum, &column->type);
free(key_string);
free(value_string);