diff --git a/lib/db-ctl-base.c b/lib/db-ctl-base.c index 707456158..bc85e9921 100644 --- a/lib/db-ctl-base.c +++ b/lib/db-ctl-base.c @@ -1503,7 +1503,7 @@ cmd_add(struct ctl_context *ctx) } type = &column->type; - ovsdb_datum_clone(&old, ovsdb_idl_read(row, column), &column->type); + ovsdb_datum_clone(&old, ovsdb_idl_read(row, column)); for (i = 4; i < ctx->argc; i++) { struct ovsdb_type add_type; struct ovsdb_datum add; @@ -1588,7 +1588,7 @@ cmd_remove(struct ctl_context *ctx) } type = &column->type; - ovsdb_datum_clone(&old, ovsdb_idl_read(row, column), &column->type); + ovsdb_datum_clone(&old, ovsdb_idl_read(row, column)); for (i = 4; i < ctx->argc; i++) { struct ovsdb_type rm_type; struct ovsdb_datum rm; diff --git a/lib/ovsdb-data.c b/lib/ovsdb-data.c index 61ad7679a..183e75258 100644 --- a/lib/ovsdb-data.c +++ b/lib/ovsdb-data.c @@ -896,6 +896,7 @@ ovsdb_datum_init_empty(struct ovsdb_datum *datum) datum->n = 0; datum->keys = NULL; datum->values = NULL; + datum->refcnt = NULL; } /* Initializes 'datum' as a datum that has the default value for 'type'. @@ -917,6 +918,7 @@ ovsdb_datum_init_default(struct ovsdb_datum *datum, datum->n = type->n_min; datum->keys = alloc_default_atoms(type->key.type, datum->n); datum->values = alloc_default_atoms(type->value.type, datum->n); + datum->refcnt = NULL; } /* Returns a read-only datum of the given 'type' that has the default value for @@ -928,10 +930,12 @@ const struct ovsdb_datum * ovsdb_datum_default(const struct ovsdb_type *type) { if (type->n_min == 0) { - static const struct ovsdb_datum empty; + static unsigned int refcnt = 1; + static const struct ovsdb_datum empty = { .refcnt = &refcnt }; return ∅ } else if (type->n_min == 1) { static struct ovsdb_datum default_data[OVSDB_N_TYPES][OVSDB_N_TYPES]; + static unsigned int refcnt[OVSDB_N_TYPES][OVSDB_N_TYPES]; struct ovsdb_datum *d; int kt = type->key.type; int vt = type->value.type; @@ -946,6 +950,8 @@ ovsdb_datum_default(const struct ovsdb_type *type) d->values = CONST_CAST(union ovsdb_atom *, ovsdb_atom_default(vt)); } + d->refcnt = &refcnt[kt][vt]; + *d->refcnt = 1; } return d; } else { @@ -999,18 +1005,23 @@ clone_atoms(const union ovsdb_atom *old, enum ovsdb_atomic_type type, size_t n) } } -/* Initializes 'new' as a copy of 'old', with the given 'type'. +/* Initializes 'new' as a shallow copy of 'old_'. * * The caller must eventually arrange for 'new' to be destroyed (with - * ovsdb_datum_destroy()). */ + * ovsdb_datum_destroy()). The caller must call ovsdb_datum_unshare() + * before attempting direct modifications of the 'new' or 'old_', i.e. + * modifications outside of the ovsdb_datum_* API. */ void -ovsdb_datum_clone(struct ovsdb_datum *new, const struct ovsdb_datum *old, - const struct ovsdb_type *type) +ovsdb_datum_clone(struct ovsdb_datum *new, const struct ovsdb_datum *old_) { - unsigned int n = old->n; - new->n = n; - new->keys = clone_atoms(old->keys, type->key.type, n); - new->values = clone_atoms(old->values, type->value.type, n); + struct ovsdb_datum *old = CONST_CAST(struct ovsdb_datum *, old_); + + if (!old->refcnt) { + old->refcnt = xmalloc(sizeof *old->refcnt); + *old->refcnt = 1; + } + memcpy(new, old, sizeof *new); + (*new->refcnt)++; } static void @@ -1037,8 +1048,25 @@ free_data(enum ovsdb_atomic_type type, void ovsdb_datum_destroy(struct ovsdb_datum *datum, const struct ovsdb_type *type) { - free_data(type->key.type, datum->keys, datum->n); - free_data(type->value.type, datum->values, datum->n); + if (!datum->refcnt || !--(*datum->refcnt)) { + free_data(type->key.type, datum->keys, datum->n); + free_data(type->value.type, datum->values, datum->n); + free(datum->refcnt); + } +} + +/* This function should be called before attempting direct modifications + * of the 'datum', i.e. modifications outside of the ovsdb_datum_* API. */ +void +ovsdb_datum_unshare(struct ovsdb_datum *datum, const struct ovsdb_type *type) +{ + if (!datum->refcnt || *datum->refcnt == 1) { + return; + } + datum->keys = clone_atoms(datum->keys, type->key.type, datum->n); + datum->values = clone_atoms(datum->values, type->value.type, datum->n); + (*datum->refcnt)--; + datum->refcnt = NULL; } /* Swaps the contents of 'a' and 'b', which need not have the same type. */ @@ -1107,7 +1135,7 @@ ovsdb_datum_sort__(struct ovsdb_datum *datum, enum ovsdb_atomic_type key_type, * caller must free the returned error when it is no longer needed. On error, * 'datum' is sorted but not unique. */ struct ovsdb_error * -ovsdb_datum_sort(struct ovsdb_datum *datum, enum ovsdb_atomic_type key_type) +ovsdb_datum_sort(struct ovsdb_datum *datum, const struct ovsdb_type *type) { size_t i; @@ -1115,11 +1143,13 @@ ovsdb_datum_sort(struct ovsdb_datum *datum, enum ovsdb_atomic_type key_type) return NULL; } - ovsdb_datum_sort__(datum, key_type, OVSDB_TYPE_VOID); + ovsdb_datum_unshare(datum, type); + + ovsdb_datum_sort__(datum, type->key.type, OVSDB_TYPE_VOID); for (i = 0; i < datum->n - 1; i++) { if (ovsdb_atom_equals(&datum->keys[i], &datum->keys[i + 1], - key_type)) { + type->key.type)) { if (datum->values) { return ovsdb_error(NULL, "map contains duplicate key"); } else { @@ -1135,9 +1165,9 @@ ovsdb_datum_sort(struct ovsdb_datum *datum, enum ovsdb_atomic_type key_type) * this function assert-fails if it actually does. */ void ovsdb_datum_sort_assert(struct ovsdb_datum *datum, - enum ovsdb_atomic_type key_type) + const struct ovsdb_type *type) { - struct ovsdb_error *error = ovsdb_datum_sort(datum, key_type); + struct ovsdb_error *error = ovsdb_datum_sort(datum, type); if (error) { OVS_NOT_REACHED(); } @@ -1150,8 +1180,7 @@ ovsdb_datum_sort_assert(struct ovsdb_datum *datum, * Returns the number of keys (or pairs) that were dropped. */ size_t ovsdb_datum_sort_unique(struct ovsdb_datum *datum, - enum ovsdb_atomic_type key_type, - enum ovsdb_atomic_type value_type) + const struct ovsdb_type *type) { size_t src, dst; @@ -1159,20 +1188,21 @@ ovsdb_datum_sort_unique(struct ovsdb_datum *datum, return 0; } - ovsdb_datum_sort__(datum, key_type, value_type); + ovsdb_datum_unshare(datum, type); + ovsdb_datum_sort__(datum, type->key.type, type->value.type); dst = 1; for (src = 1; src < datum->n; src++) { if (ovsdb_atom_equals(&datum->keys[src], &datum->keys[dst - 1], - key_type)) { - ovsdb_atom_destroy(&datum->keys[src], key_type); - if (value_type != OVSDB_TYPE_VOID) { - ovsdb_atom_destroy(&datum->values[src], value_type); + type->key.type)) { + ovsdb_atom_destroy(&datum->keys[src], type->key.type); + if (type->value.type != OVSDB_TYPE_VOID) { + ovsdb_atom_destroy(&datum->values[src], type->value.type); } } else { if (src != dst) { datum->keys[dst] = datum->keys[src]; - if (value_type != OVSDB_TYPE_VOID) { + if (type->value.type != OVSDB_TYPE_VOID) { datum->values[dst] = datum->values[src]; } } @@ -1258,6 +1288,7 @@ ovsdb_datum_from_json__(struct ovsdb_datum *datum, datum->n = 0; datum->keys = xmalloc(n * sizeof *datum->keys); datum->values = is_map ? xmalloc(n * sizeof *datum->values) : NULL; + datum->refcnt = NULL; for (i = 0; i < n; i++) { const struct json *element = inner->array.elems[i]; const struct json *key = NULL; @@ -1298,6 +1329,7 @@ ovsdb_datum_from_json__(struct ovsdb_datum *datum, datum->n = 1; datum->keys = xmalloc(sizeof *datum->keys); datum->values = NULL; + datum->refcnt = NULL; error = ovsdb_atom_from_json(&datum->keys[0], &type->key, json, symtab); @@ -1331,7 +1363,7 @@ ovsdb_datum_from_json(struct ovsdb_datum *datum, return error; } - error = ovsdb_datum_sort(datum, type->key.type); + error = ovsdb_datum_sort(datum, type); if (error) { ovsdb_datum_destroy(datum, type); } @@ -1609,7 +1641,7 @@ ovsdb_datum_from_string(struct ovsdb_datum *datum, goto error; } - dberror = ovsdb_datum_sort(datum, type->key.type); + dberror = ovsdb_datum_sort(datum, type); if (dberror) { ovsdb_error_destroy(dberror); if (ovsdb_type_is_map(type)) { @@ -1687,6 +1719,7 @@ ovsdb_datum_from_smap(struct ovsdb_datum *datum, const struct smap *smap) datum->n = smap_count(smap); datum->keys = xmalloc(datum->n * sizeof *datum->keys); datum->values = xmalloc(datum->n * sizeof *datum->values); + datum->refcnt = NULL; struct smap_node *node; size_t i = 0; @@ -1697,7 +1730,11 @@ ovsdb_datum_from_smap(struct ovsdb_datum *datum, const struct smap *smap) } ovs_assert(i == datum->n); - ovsdb_datum_sort_unique(datum, OVSDB_TYPE_STRING, OVSDB_TYPE_STRING); + struct ovsdb_type type = { + OVSDB_BASE_STRING_INIT, OVSDB_BASE_STRING_INIT, + 0, UINT_MAX + }; + ovsdb_datum_sort_unique(datum, &type); } struct ovsdb_error * OVS_WARN_UNUSED_RESULT @@ -1774,6 +1811,10 @@ ovsdb_datum_compare_3way(const struct ovsdb_datum *a, return a->n < b->n ? -1 : 1; } + if (a->refcnt && a->refcnt == b->refcnt) { + return 0; + } + cmp = atom_arrays_compare_3way(a->keys, b->keys, type->key.type, a->n); if (cmp) { return cmp; @@ -1893,6 +1934,8 @@ static void ovsdb_datum_reallocate(struct ovsdb_datum *a, const struct ovsdb_type *type, unsigned int capacity) { + ovsdb_datum_unshare(a, type); + a->keys = xrealloc(a->keys, capacity * sizeof *a->keys); if (type->value.type != OVSDB_TYPE_VOID) { a->values = xrealloc(a->values, capacity * sizeof *a->values); @@ -1909,6 +1952,8 @@ void ovsdb_datum_remove_unsafe(struct ovsdb_datum *datum, size_t idx, const struct ovsdb_type *type) { + ovsdb_datum_unshare(datum, type); + ovsdb_atom_destroy(&datum->keys[idx], type->key.type); datum->keys[idx] = datum->keys[datum->n - 1]; if (type->value.type != OVSDB_TYPE_VOID) { @@ -1940,6 +1985,9 @@ ovsdb_datum_add_unsafe(struct ovsdb_datum *datum, const union ovsdb_atom *range_end_atom) { size_t idx = datum->n; + + ovsdb_datum_unshare(datum, type); + datum->n += range_end_atom ? (range_end_atom->integer - key->integer + 1) : 1; datum->keys = xrealloc(datum->keys, datum->n * sizeof *datum->keys); @@ -1984,6 +2032,8 @@ ovsdb_datum_push_unsafe(struct ovsdb_datum *dst, return; } + ovsdb_datum_unshare(dst, type); + memcpy(&dst->keys[dst->n], &src->keys[start_idx], n * sizeof src->keys[0]); if (type->value.type != OVSDB_TYPE_VOID) { memcpy(&dst->values[dst->n], &src->values[start_idx], @@ -1999,6 +2049,7 @@ ovsdb_datum_union(struct ovsdb_datum *a, const struct ovsdb_datum *b, struct ovsdb_datum result; unsigned int copied, pos; + ovsdb_datum_unshare(a, type); ovsdb_datum_init_empty(&result); copied = 0; @@ -2050,6 +2101,8 @@ ovsdb_datum_subtract(struct ovsdb_datum *a, const struct ovsdb_type *a_type, ovs_assert(a_type->value.type == b_type->value.type || b_type->value.type == OVSDB_TYPE_VOID); + ovsdb_datum_unshare(a, a_type); + idx = xmalloc(b->n * sizeof *idx); n_idx = 0; for (size_t bi = 0; bi < b->n; bi++) { @@ -2168,8 +2221,8 @@ ovsdb_datum_added_removed(struct ovsdb_datum *added, ovsdb_datum_init_empty(added); ovsdb_datum_init_empty(removed); if (!ovsdb_type_is_composite(type)) { - ovsdb_datum_clone(removed, old, type); - ovsdb_datum_clone(added, new, type); + ovsdb_datum_clone(removed, old); + ovsdb_datum_clone(added, new); return; } @@ -2228,7 +2281,7 @@ ovsdb_datum_diff(struct ovsdb_datum *diff, ovsdb_datum_init_empty(diff); if (!ovsdb_type_is_composite(type)) { - ovsdb_datum_clone(diff, new, type); + ovsdb_datum_clone(diff, new); return; } @@ -2283,10 +2336,12 @@ ovsdb_datum_apply_diff_in_place(struct ovsdb_datum *a, if (!ovsdb_type_is_composite(type)) { ovsdb_datum_destroy(a, type); - ovsdb_datum_clone(a, diff, type); + ovsdb_datum_clone(a, diff); return NULL; } + ovsdb_datum_unshare(a, type); + operation = xmalloc(diff->n * sizeof *operation); idx = xmalloc(diff->n * sizeof *idx); new_size = a->n; diff --git a/lib/ovsdb-data.h b/lib/ovsdb-data.h index ba5d179a6..dcb620513 100644 --- a/lib/ovsdb-data.h +++ b/lib/ovsdb-data.h @@ -146,6 +146,8 @@ struct ovsdb_datum { unsigned int n; /* Number of 'keys' and 'values'. */ union ovsdb_atom *keys; /* Each of the ovsdb_type's 'key_type'. */ union ovsdb_atom *values; /* Each of the ovsdb_type's 'value_type'. */ + unsigned int *refcnt; /* Number of copies with the same + * 'keys' and 'values'. */ }; #define OVSDB_DATUM_INITIALIZER { 0, NULL, NULL } @@ -155,22 +157,21 @@ void ovsdb_datum_init_default(struct ovsdb_datum *, const struct ovsdb_type *); bool ovsdb_datum_is_default(const struct ovsdb_datum *, const struct ovsdb_type *); const struct ovsdb_datum *ovsdb_datum_default(const struct ovsdb_type *); -void ovsdb_datum_clone(struct ovsdb_datum *, const struct ovsdb_datum *, - const struct ovsdb_type *); +void ovsdb_datum_clone(struct ovsdb_datum *, const struct ovsdb_datum *); void ovsdb_datum_destroy(struct ovsdb_datum *, const struct ovsdb_type *); +void ovsdb_datum_unshare(struct ovsdb_datum *, const struct ovsdb_type *); void ovsdb_datum_swap(struct ovsdb_datum *, struct ovsdb_datum *); /* Checking and maintaining invariants. */ struct ovsdb_error *ovsdb_datum_sort(struct ovsdb_datum *, - enum ovsdb_atomic_type key_type) + const struct ovsdb_type *type) OVS_WARN_UNUSED_RESULT; void ovsdb_datum_sort_assert(struct ovsdb_datum *, - enum ovsdb_atomic_type key_type); + const struct ovsdb_type *type); size_t ovsdb_datum_sort_unique(struct ovsdb_datum *, - enum ovsdb_atomic_type key_type, - enum ovsdb_atomic_type value_type); + const struct ovsdb_type *type); struct ovsdb_error *ovsdb_datum_check_constraints( const struct ovsdb_datum *, const struct ovsdb_type *) diff --git a/lib/ovsdb-idl.c b/lib/ovsdb-idl.c index 3b8741408..51dae1d02 100644 --- a/lib/ovsdb-idl.c +++ b/lib/ovsdb-idl.c @@ -1088,7 +1088,7 @@ ovsdb_idl_condition_add_clause__(struct ovsdb_idl_condition *condition, struct ovsdb_idl_clause *clause = xmalloc(sizeof *clause); clause->function = src->function; clause->column = src->column; - ovsdb_datum_clone(&clause->arg, &src->arg, &src->column->type); + ovsdb_datum_clone(&clause->arg, &src->arg); hmap_insert(&condition->clauses, &clause->hmap_node, hash); } @@ -1128,12 +1128,14 @@ ovsdb_idl_condition_add_clause(struct ovsdb_idl_condition *condition, struct ovsdb_idl_clause clause = { .function = function, .column = column, - .arg = *arg, }; + ovsdb_datum_clone(&clause.arg, arg); + uint32_t hash = ovsdb_idl_clause_hash(&clause); if (!ovsdb_idl_condition_find_clause(condition, &clause, hash)) { ovsdb_idl_condition_add_clause__(condition, &clause, hash); } + ovsdb_datum_destroy(&clause.arg, &column->type); } } @@ -3611,7 +3613,7 @@ ovsdb_idl_txn_write__(const struct ovsdb_idl_row *row_, if (owns_datum) { row->new_datum[column_idx] = *datum; } else { - ovsdb_datum_clone(&row->new_datum[column_idx], datum, &column->type); + ovsdb_datum_clone(&row->new_datum[column_idx], datum); } (column->unparse)(row); (column->parse)(row, &row->new_datum[column_idx]); @@ -3650,8 +3652,7 @@ ovsdb_idl_txn_write(const struct ovsdb_idl_row *row, const struct ovsdb_idl_column *column, struct ovsdb_datum *datum) { - ovsdb_datum_sort_unique(datum, - column->type.key.type, column->type.value.type); + ovsdb_datum_sort_unique(datum, &column->type); ovsdb_idl_txn_write__(row, column, datum, true); } diff --git a/lib/ovsdb-types.c b/lib/ovsdb-types.c index 24ccdd1cc..61efe59cf 100644 --- a/lib/ovsdb-types.c +++ b/lib/ovsdb-types.c @@ -189,8 +189,7 @@ ovsdb_base_type_clone(struct ovsdb_base_type *dst, if (src->enum_) { dst->enum_ = xmalloc(sizeof *dst->enum_); - ovsdb_datum_clone(dst->enum_, src->enum_, - ovsdb_base_type_get_enum_type(dst->type)); + ovsdb_datum_clone(dst->enum_, src->enum_); } switch (dst->type) { diff --git a/ovsdb/condition.c b/ovsdb/condition.c index 9aa3788db..d0016fa7f 100644 --- a/ovsdb/condition.c +++ b/ovsdb/condition.c @@ -376,9 +376,7 @@ ovsdb_clause_clone(struct ovsdb_clause *new, struct ovsdb_clause *old) { new->function = old->function; new->column = old->column; - ovsdb_datum_clone(&new->arg, - &old->arg, - &old->column->type); + ovsdb_datum_clone(&new->arg, &old->arg); } bool diff --git a/ovsdb/monitor.c b/ovsdb/monitor.c index 952fa902e..191befcae 100644 --- a/ovsdb/monitor.c +++ b/ovsdb/monitor.c @@ -334,9 +334,8 @@ clone_monitor_row_data(const struct ovsdb_monitor_table *mt, const struct ovsdb_column *c = mt->columns[i].column; const struct ovsdb_datum *src = &row->fields[c->index]; struct ovsdb_datum *dst = &data[i]; - const struct ovsdb_type *type = &c->type; - ovsdb_datum_clone(dst, src, type); + ovsdb_datum_clone(dst, src); } return data; } @@ -359,7 +358,7 @@ update_monitor_row_data(const struct ovsdb_monitor_table *mt, if (!ovsdb_datum_equals(src, dst, type)) { ovsdb_datum_destroy(dst, type); - ovsdb_datum_clone(dst, src, type); + ovsdb_datum_clone(dst, src); } } } diff --git a/ovsdb/mutation.c b/ovsdb/mutation.c index 03d1c3499..cbc71bc49 100644 --- a/ovsdb/mutation.c +++ b/ovsdb/mutation.c @@ -287,6 +287,8 @@ mutate_scalar(const struct ovsdb_type *dst_type, struct ovsdb_datum *dst, struct ovsdb_error *error; unsigned int i; + ovsdb_datum_unshare(dst, dst_type); + if (base->type == OVSDB_TYPE_INTEGER) { int64_t y = arg->integer; for (i = 0; i < dst->n; i++) { @@ -322,7 +324,7 @@ mutate_scalar(const struct ovsdb_type *dst_type, struct ovsdb_datum *dst, } } - error = ovsdb_datum_sort(dst, dst_type->key.type); + error = ovsdb_datum_sort(dst, dst_type); if (error) { ovsdb_error_destroy(error); return ovsdb_error("constraint violation", diff --git a/ovsdb/ovsdb-idlc.in b/ovsdb/ovsdb-idlc.in index 13c535939..5a97a8ea3 100755 --- a/ovsdb/ovsdb-idlc.in +++ b/ovsdb/ovsdb-idlc.in @@ -951,7 +951,10 @@ void 'c': columnName, 'args': ', '.join(['%(type)s%(name)s' % m for m in members])}) + print() + print(" datum.refcnt = NULL;") if type.n_min == 1 and type.n_max == 1: + print() print(" union ovsdb_atom *key = xmalloc(sizeof *key);") if type.value: print(" union ovsdb_atom *value = xmalloc(sizeof *value);") @@ -1004,10 +1007,6 @@ void if type.value: print(" " + type.value.copyCValue("datum.values[i].%s" % type.value.type.to_lvalue_string(), "%s[i]" % valueVar)) print(" }") - if type.value: - valueType = type.value.toAtomicType() - else: - valueType = "OVSDB_TYPE_VOID" txn_write_func = "ovsdb_idl_txn_write" print(" %(f)s(&row->header_, &%(s)s_col_%(c)s, &datum);" \ % {'f': txn_write_func, @@ -1035,6 +1034,7 @@ void datum->n = 1; datum->keys = xmalloc(datum->n * sizeof *datum->keys); datum->values = xmalloc(datum->n * sizeof *datum->values); + datum->refcnt = NULL; ''' % {'s': structName, 'c': columnName,'coltype':column.type.key.to_const_c_type(prefix), 'valtype':column.type.value.to_const_c_type(prefix), 'S': structName.upper(), 'C': columnName.upper(), 't': tableName}) @@ -1060,6 +1060,7 @@ void datum->n = 1; datum->keys = xmalloc(datum->n * sizeof *datum->keys); datum->values = NULL; + datum->refcnt = NULL; ''' % {'s': structName, 'c': columnName,'coltype':column.type.key.to_const_c_type(prefix), 'valtype':column.type.value.to_const_c_type(prefix), 'S': structName.upper(), 'C': columnName.upper(), 't': tableName}) @@ -1087,6 +1088,7 @@ void datum->n = 1; datum->keys = xmalloc(datum->n * sizeof *datum->values); datum->values = NULL; + datum->refcnt = NULL; ''' % {'s': structName, 'c': columnName, 'valtype':column.type.key.to_const_c_type(prefix), 't': tableName}) print(" " + type.key.copyCValue("datum->keys[0].%s" % type.key.type.to_lvalue_string(), "new_value")) @@ -1110,6 +1112,7 @@ void datum->n = 1; datum->keys = xmalloc(datum->n * sizeof *datum->values); datum->values = NULL; + datum->refcnt = NULL; ''' % {'s': structName, 'c': columnName,'coltype':column.type.key.to_const_c_type(prefix), 'valtype':column.type.key.to_const_c_type(prefix), 'S': structName.upper(), 'C': columnName.upper(), 't': tableName}) @@ -1179,8 +1182,11 @@ void 'args': ', '.join(['%(type)s%(name)s' % m for m in members])}) print("{") print(" struct ovsdb_datum datum;") + print("") + print(" datum.refcnt = NULL;") free = [] if type.n_min == 1 and type.n_max == 1: + print() print(" union ovsdb_atom *key = xmalloc(sizeof *key);") if type.value: print(" union ovsdb_atom *value = xmalloc(sizeof *value);") @@ -1228,12 +1234,8 @@ void if type.value: print(" " + type.value.copyCValue("datum.values[i].%s" % type.value.type.to_lvalue_string(), "%s[i]" % valueVar, refTable=False)) print(" }") - if type.value: - valueType = type.value.toAtomicType() - else: - valueType = "OVSDB_TYPE_VOID" - print(" ovsdb_datum_sort_unique(&datum, %s, %s);" % ( - type.key.toAtomicType(), valueType)) + print(" ovsdb_datum_sort_unique(&datum, &%(s)s_col_%(c)s.type);" \ + % {'s': structName, 'c': columnName}) print(""" ovsdb_idl_condition_add_clause(cond, function, @@ -1341,6 +1343,7 @@ struct %(s)s * datum->n = smap_count(%(c)s); datum->keys = xmalloc(datum->n * sizeof *datum->keys); datum->values = xmalloc(datum->n * sizeof *datum->values); + datum->refcnt = NULL; i = 0; SMAP_FOR_EACH (node, %(c)s) { @@ -1348,7 +1351,7 @@ struct %(s)s * datum->values[i].s = ovsdb_atom_string_create(node->value); i++; } - ovsdb_datum_sort_unique(datum, OVSDB_TYPE_STRING, OVSDB_TYPE_STRING); + ovsdb_datum_sort_unique(datum, &%(s)s_col_%(c)s.type); } else { ovsdb_datum_init_empty(datum); } @@ -1387,6 +1390,8 @@ struct %(s)s * 'args': ', '.join(['%(type)s%(name)s' % m for m in members])}) print("{") print(" struct ovsdb_datum datum;") + print() + print(" datum.refcnt = NULL;") if type.n_min == 1 and type.n_max == 1: print(" union ovsdb_atom *key = xmalloc(sizeof(union ovsdb_atom));") if type.value: @@ -1443,12 +1448,8 @@ struct %(s)s * if type.value: print(" " + type.value.copyCValue("datum.values[i].%s" % type.value.type.to_lvalue_string(), "%s[i]" % valueVar)) print(" }") - if type.value: - valueType = type.value.toAtomicType() - else: - valueType = "OVSDB_TYPE_VOID" - print(" ovsdb_datum_sort_unique(&datum, %s, %s);" % ( - type.key.toAtomicType(), valueType)) + print(" ovsdb_datum_sort_unique(&datum, &%(s)s_col_%(c)s.type);" + % {'s': structName, 'c': columnName}) txn_write_func = "ovsdb_idl_index_write" print(" %(f)s(CONST_CAST(struct ovsdb_idl_row *, &row->header_), &%(s)s_columns[ %(S)s_COL_%(C)s ], &datum, &%(p)stable_classes[%(P)sTABLE_%(T)s]);" \ % {'f': txn_write_func, diff --git a/ovsdb/ovsdb-util.c b/ovsdb/ovsdb-util.c index 6d7be066b..303191dc8 100644 --- a/ovsdb/ovsdb-util.c +++ b/ovsdb/ovsdb-util.c @@ -221,6 +221,8 @@ ovsdb_util_write_singleton(struct ovsdb_row *row, const char *column_name, return; } + ovsdb_datum_unshare(datum, &column->type); + if (datum->n == 1) { if (ovsdb_atom_equals(&datum->keys[0], atom, type)) { return; @@ -231,6 +233,7 @@ ovsdb_util_write_singleton(struct ovsdb_row *row, const char *column_name, datum->n = 1; datum->keys = xmalloc(sizeof *datum->keys); datum->values = NULL; + datum->refcnt = NULL; } ovsdb_atom_clone(&datum->keys[0], atom, type); } @@ -305,6 +308,7 @@ ovsdb_util_write_string_string_column(struct ovsdb_row *row, datum->n = n; datum->keys = xmalloc(n * sizeof *datum->keys); datum->values = xmalloc(n * sizeof *datum->values); + datum->refcnt = NULL; for (i = 0; i < n; ++i) { datum->keys[i].s = ovsdb_atom_string_create_nocopy(keys[i]); @@ -312,5 +316,5 @@ ovsdb_util_write_string_string_column(struct ovsdb_row *row, } /* Sort and check constraints. */ - ovsdb_datum_sort_assert(datum, column->type.key.type); + ovsdb_datum_sort_assert(datum, &column->type); } diff --git a/ovsdb/row.c b/ovsdb/row.c index f93fe2306..fd50c7e7b 100644 --- a/ovsdb/row.c +++ b/ovsdb/row.c @@ -143,8 +143,7 @@ ovsdb_row_clone(const struct ovsdb_row *old) SHASH_FOR_EACH (node, &table->schema->columns) { const struct ovsdb_column *column = node->data; ovsdb_datum_clone(&new->fields[column->index], - &old->fields[column->index], - &column->type); + &old->fields[column->index]); } struct ovsdb_weak_ref *weak, *clone; @@ -257,8 +256,7 @@ ovsdb_row_update_columns(struct ovsdb_row *dst, } else { ovsdb_datum_destroy(&dst->fields[column->index], &column->type); ovsdb_datum_clone(&dst->fields[column->index], - &src->fields[column->index], - &column->type); + &src->fields[column->index]); } } return NULL; diff --git a/ovsdb/transaction.c b/ovsdb/transaction.c index ab7bb0eb1..6864fe099 100644 --- a/ovsdb/transaction.c +++ b/ovsdb/transaction.c @@ -693,8 +693,7 @@ assess_weak_refs(struct ovsdb_txn *txn, struct ovsdb_txn_row *txn_row) ovs_list_init(&weak->src_node); } } - ovsdb_datum_sort_unique(&deleted_refs, column->type.key.type, - column->type.value.type); + ovsdb_datum_sort_unique(&deleted_refs, &column->type); /* Removing elements that references deleted rows. */ ovsdb_datum_subtract(datum, &column->type, @@ -708,7 +707,7 @@ assess_weak_refs(struct ovsdb_txn *txn, struct ovsdb_txn_row *txn_row) datum, &column->type); } else { ovsdb_datum_init_empty(&removed); - ovsdb_datum_clone(&added, datum, &column->type); + ovsdb_datum_clone(&added, datum); } /* Checking added data and creating new references. */ @@ -732,8 +731,7 @@ assess_weak_refs(struct ovsdb_txn *txn, struct ovsdb_txn_row *txn_row) } if (deleted_refs.n) { /* Removing all the references that doesn't point to valid rows. */ - ovsdb_datum_sort_unique(&deleted_refs, column->type.key.type, - column->type.value.type); + ovsdb_datum_sort_unique(&deleted_refs, &column->type); ovsdb_datum_subtract(datum, &column->type, &deleted_refs, &column->type); ovsdb_datum_destroy(&deleted_refs, &column->type); diff --git a/tests/test-ovsdb.c b/tests/test-ovsdb.c index 0fef1f978..343833151 100644 --- a/tests/test-ovsdb.c +++ b/tests/test-ovsdb.c @@ -1679,6 +1679,7 @@ do_transact_set_integer(struct ovsdb_row *row, const char *column_name, column = ovsdb_table_schema_get_column(do_transact_table->schema, column_name); + ovsdb_datum_unshare(&row->fields[column->index], &column->type); row->fields[column->index].keys[0].integer = integer; } }