2
0
mirror of https://github.com/openvswitch/ovs synced 2025-09-04 16:25:17 +00:00

ovsdb-data: Deduplicate string atoms.

ovsdb-server spends a lot of time cloning atoms for various reasons,
e.g. to create a diff of two rows or to clone a row to the transaction.
All atoms, except for strings, contains a simple value that could be
copied in efficient way, but duplicating strings every time has a
significant performance impact.

Introducing a new reference-counted structure 'ovsdb_atom_string'
that allows to not copy strings every time, but just increase a
reference counter.

This change allows to increase transaction throughput in benchmarks
up to 2x for standalone databases and 3x for clustered databases, i.e.
number of transactions that ovsdb-server can handle per second.
It also noticeably reduces memory consumption of ovsdb-server.

Next step will be to consolidate this structure with json strings,
so we will not need to duplicate strings while converting database
objects to json and back.

Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
Acked-by: Dumitru Ceara <dceara@redhat.com>
Acked-by: Mark D. Gray <mark.d.gray@redhat.com>
This commit is contained in:
Ilya Maximets
2021-09-22 09:28:50 +02:00
parent 32b51326ef
commit 429b114c5a
12 changed files with 179 additions and 130 deletions

View File

@@ -247,15 +247,15 @@ record_id_equals(const union ovsdb_atom *name, enum ovsdb_atomic_type type,
const char *record_id) const char *record_id)
{ {
if (type == OVSDB_TYPE_STRING) { if (type == OVSDB_TYPE_STRING) {
if (!strcmp(name->string, record_id)) { if (!strcmp(name->s->string, record_id)) {
return true; return true;
} }
struct uuid uuid; struct uuid uuid;
size_t len = strlen(record_id); size_t len = strlen(record_id);
if (len >= 4 if (len >= 4
&& uuid_from_string(&uuid, name->string) && uuid_from_string(&uuid, name->s->string)
&& !strncmp(name->string, record_id, len)) { && !strncmp(name->s->string, record_id, len)) {
return true; return true;
} }
@@ -318,14 +318,15 @@ get_row_by_id(struct ctl_context *ctx,
if (!id->key) { if (!id->key) {
name = datum->n == 1 ? &datum->keys[0] : NULL; name = datum->n == 1 ? &datum->keys[0] : NULL;
} else { } else {
const union ovsdb_atom key_atom union ovsdb_atom key_atom = {
= { .string = CONST_CAST(char *, id->key) }; .s = ovsdb_atom_string_create(CONST_CAST(char *, id->key)) };
unsigned int i; unsigned int i;
if (ovsdb_datum_find_key(datum, &key_atom, if (ovsdb_datum_find_key(datum, &key_atom,
OVSDB_TYPE_STRING, &i)) { OVSDB_TYPE_STRING, &i)) {
name = &datum->values[i]; name = &datum->values[i];
} }
ovsdb_atom_destroy(&key_atom, OVSDB_TYPE_STRING);
} }
if (!name) { if (!name) {
continue; continue;

View File

@@ -1833,7 +1833,7 @@ server_column_get_string(const struct server_row *row,
{ {
ovs_assert(server_columns[index].type.key.type == OVSDB_TYPE_STRING); ovs_assert(server_columns[index].type.key.type == OVSDB_TYPE_STRING);
const struct ovsdb_datum *d = &row->data[index]; const struct ovsdb_datum *d = &row->data[index];
return d->n == 1 ? d->keys[0].string : default_value; return d->n == 1 ? d->keys[0].s->string : default_value;
} }
static bool static bool

View File

@@ -74,7 +74,7 @@ ovsdb_atom_init_default(union ovsdb_atom *atom, enum ovsdb_atomic_type type)
break; break;
case OVSDB_TYPE_STRING: case OVSDB_TYPE_STRING:
atom->string = xmemdup("", 1); atom->s = ovsdb_atom_string_create_nocopy(xmemdup("", 1));
break; break;
case OVSDB_TYPE_UUID: case OVSDB_TYPE_UUID:
@@ -136,7 +136,7 @@ ovsdb_atom_is_default(const union ovsdb_atom *atom,
return atom->boolean == false; return atom->boolean == false;
case OVSDB_TYPE_STRING: case OVSDB_TYPE_STRING:
return atom->string[0] == '\0'; return atom->s->string[0] == '\0';
case OVSDB_TYPE_UUID: case OVSDB_TYPE_UUID:
return uuid_is_zero(&atom->uuid); return uuid_is_zero(&atom->uuid);
@@ -172,7 +172,8 @@ ovsdb_atom_clone(union ovsdb_atom *new, const union ovsdb_atom *old,
break; break;
case OVSDB_TYPE_STRING: case OVSDB_TYPE_STRING:
new->string = xstrdup(old->string); new->s = old->s;
new->s->n_refs++;
break; break;
case OVSDB_TYPE_UUID: case OVSDB_TYPE_UUID:
@@ -214,7 +215,7 @@ ovsdb_atom_hash(const union ovsdb_atom *atom, enum ovsdb_atomic_type type,
return hash_boolean(atom->boolean, basis); return hash_boolean(atom->boolean, basis);
case OVSDB_TYPE_STRING: case OVSDB_TYPE_STRING:
return hash_string(atom->string, basis); return hash_string(atom->s->string, basis);
case OVSDB_TYPE_UUID: case OVSDB_TYPE_UUID:
return hash_int(uuid_hash(&atom->uuid), basis); return hash_int(uuid_hash(&atom->uuid), basis);
@@ -246,7 +247,7 @@ ovsdb_atom_compare_3way(const union ovsdb_atom *a,
return a->boolean - b->boolean; return a->boolean - b->boolean;
case OVSDB_TYPE_STRING: case OVSDB_TYPE_STRING:
return strcmp(a->string, b->string); return a->s == b->s ? 0 : strcmp(a->s->string, b->s->string);
case OVSDB_TYPE_UUID: case OVSDB_TYPE_UUID:
return uuid_compare_3way(&a->uuid, &b->uuid); return uuid_compare_3way(&a->uuid, &b->uuid);
@@ -404,7 +405,7 @@ ovsdb_atom_from_json__(union ovsdb_atom *atom,
case OVSDB_TYPE_STRING: case OVSDB_TYPE_STRING:
if (json->type == JSON_STRING) { if (json->type == JSON_STRING) {
atom->string = xstrdup(json->string); atom->s = ovsdb_atom_string_create(json->string);
return NULL; return NULL;
} }
break; break;
@@ -473,7 +474,7 @@ ovsdb_atom_to_json(const union ovsdb_atom *atom, enum ovsdb_atomic_type type)
return json_boolean_create(atom->boolean); return json_boolean_create(atom->boolean);
case OVSDB_TYPE_STRING: case OVSDB_TYPE_STRING:
return json_string_create(atom->string); return json_string_create(atom->s->string);
case OVSDB_TYPE_UUID: case OVSDB_TYPE_UUID:
return wrap_json("uuid", json_string_create_nocopy( return wrap_json("uuid", json_string_create_nocopy(
@@ -551,14 +552,18 @@ ovsdb_atom_from_string__(union ovsdb_atom *atom,
if (s_len < 2 || s[s_len - 1] != '"') { if (s_len < 2 || s[s_len - 1] != '"') {
return xasprintf("%s: missing quote at end of " return xasprintf("%s: missing quote at end of "
"quoted string", s); "quoted string", s);
} else if (!json_string_unescape(s + 1, s_len - 2, } else {
&atom->string)) { char *res;
char *error = xasprintf("%s: %s", s, atom->string); if (json_string_unescape(s + 1, s_len - 2, &res)) {
free(atom->string); atom->s = ovsdb_atom_string_create_nocopy(res);
return error; } else {
char *error = xasprintf("%s: %s", s, res);
free(res);
return error;
}
} }
} else { } else {
atom->string = xstrdup(s); atom->s = ovsdb_atom_string_create(s);
} }
break; break;
@@ -721,14 +726,14 @@ ovsdb_atom_to_string(const union ovsdb_atom *atom, enum ovsdb_atomic_type type,
break; break;
case OVSDB_TYPE_STRING: case OVSDB_TYPE_STRING:
if (string_needs_quotes(atom->string)) { if (string_needs_quotes(atom->s->string)) {
struct json json; struct json json;
json.type = JSON_STRING; json.type = JSON_STRING;
json.string = atom->string; json.string = atom->s->string;
json_to_ds(&json, 0, out); json_to_ds(&json, 0, out);
} else { } else {
ds_put_cstr(out, atom->string); ds_put_cstr(out, atom->s->string);
} }
break; break;
@@ -750,7 +755,7 @@ ovsdb_atom_to_bare(const union ovsdb_atom *atom, enum ovsdb_atomic_type type,
struct ds *out) struct ds *out)
{ {
if (type == OVSDB_TYPE_STRING) { if (type == OVSDB_TYPE_STRING) {
ds_put_cstr(out, atom->string); ds_put_cstr(out, atom->s->string);
} else { } else {
ovsdb_atom_to_string(atom, type, out); ovsdb_atom_to_string(atom, type, out);
} }
@@ -877,7 +882,7 @@ ovsdb_atom_check_constraints(const union ovsdb_atom *atom,
return NULL; return NULL;
case OVSDB_TYPE_STRING: case OVSDB_TYPE_STRING:
return check_string_constraints(atom->string, &base->string); return check_string_constraints(atom->s->string, &base->string);
case OVSDB_TYPE_UUID: case OVSDB_TYPE_UUID:
return NULL; return NULL;
@@ -1691,8 +1696,8 @@ ovsdb_datum_from_smap(struct ovsdb_datum *datum, const struct smap *smap)
struct smap_node *node; struct smap_node *node;
size_t i = 0; size_t i = 0;
SMAP_FOR_EACH (node, smap) { SMAP_FOR_EACH (node, smap) {
datum->keys[i].string = xstrdup(node->key); datum->keys[i].s = ovsdb_atom_string_create(node->key);
datum->values[i].string = xstrdup(node->value); datum->values[i].s = ovsdb_atom_string_create(node->value);
i++; i++;
} }
ovs_assert(i == datum->n); ovs_assert(i == datum->n);

View File

@@ -20,6 +20,7 @@
#include "compiler.h" #include "compiler.h"
#include "ovsdb-types.h" #include "ovsdb-types.h"
#include "openvswitch/shash.h" #include "openvswitch/shash.h"
#include "util.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@@ -31,12 +32,33 @@ struct ds;
struct ovsdb_symbol_table; struct ovsdb_symbol_table;
struct smap; struct smap;
struct ovsdb_atom_string {
char *string;
size_t n_refs;
};
static inline struct ovsdb_atom_string *
ovsdb_atom_string_create_nocopy(char *str)
{
struct ovsdb_atom_string *s = xzalloc(sizeof *s);
s->string = str;
s->n_refs = 1;
return s;
}
static inline struct ovsdb_atom_string *
ovsdb_atom_string_create(const char *str)
{
return ovsdb_atom_string_create_nocopy(xstrdup(str));
}
/* One value of an atomic type (given by enum ovs_atomic_type). */ /* One value of an atomic type (given by enum ovs_atomic_type). */
union ovsdb_atom { union ovsdb_atom {
int64_t integer; int64_t integer;
double real; double real;
bool boolean; bool boolean;
char *string; struct ovsdb_atom_string *s;
struct uuid uuid; struct uuid uuid;
}; };
@@ -66,8 +88,9 @@ ovsdb_atom_needs_destruction(enum ovsdb_atomic_type type)
static inline void static inline void
ovsdb_atom_destroy(union ovsdb_atom *atom, enum ovsdb_atomic_type type) ovsdb_atom_destroy(union ovsdb_atom *atom, enum ovsdb_atomic_type type)
{ {
if (type == OVSDB_TYPE_STRING) { if (type == OVSDB_TYPE_STRING && !--atom->s->n_refs) {
free(atom->string); free(atom->s->string);
free(atom->s);
} }
} }

View File

@@ -1951,8 +1951,7 @@ ovsdb_idl_index_destroy_row(const struct ovsdb_idl_row *row_)
BITMAP_FOR_EACH_1 (i, class->n_columns, row->written) { BITMAP_FOR_EACH_1 (i, class->n_columns, row->written) {
c = &class->columns[i]; c = &class->columns[i];
(c->unparse) (row); (c->unparse) (row);
free(row->new_datum[i].values); ovsdb_datum_destroy(&row->new_datum[i], &c->type);
free(row->new_datum[i].keys);
} }
free(row->new_datum); free(row->new_datum);
free(row->written); free(row->written);

View File

@@ -577,20 +577,20 @@ static void
print(" smap_init(&row->%s);" % columnName) print(" smap_init(&row->%s);" % columnName)
print(" for (size_t i = 0; i < datum->n; i++) {") print(" for (size_t i = 0; i < datum->n; i++) {")
print(" smap_add(&row->%s," % columnName) print(" smap_add(&row->%s," % columnName)
print(" datum->keys[i].string,") print(" datum->keys[i].s->string,")
print(" datum->values[i].string);") print(" datum->values[i].s->string);")
print(" }") print(" }")
elif (type.n_min == 1 and type.n_max == 1) or type.is_optional_pointer(): elif (type.n_min == 1 and type.n_max == 1) or type.is_optional_pointer():
print("") print("")
print(" if (datum->n >= 1) {") print(" if (datum->n >= 1) {")
if not type.key.ref_table: if not type.key.ref_table:
print(" %s = datum->keys[0].%s;" % (keyVar, type.key.type.to_string())) print(" %s = datum->keys[0].%s;" % (keyVar, type.key.type.to_rvalue_string()))
else: else:
print(" %s = %s%s_cast(ovsdb_idl_get_row_arc(row_, &%stable_%s, &datum->keys[0].uuid));" % (keyVar, prefix, type.key.ref_table.name.lower(), prefix, type.key.ref_table.name.lower())) print(" %s = %s%s_cast(ovsdb_idl_get_row_arc(row_, &%stable_%s, &datum->keys[0].uuid));" % (keyVar, prefix, type.key.ref_table.name.lower(), prefix, type.key.ref_table.name.lower()))
if valueVar: if valueVar:
if not type.value.ref_table: if not type.value.ref_table:
print(" %s = datum->values[0].%s;" % (valueVar, type.value.type.to_string())) print(" %s = datum->values[0].%s;" % (valueVar, type.value.type.to_rvalue_string()))
else: else:
print(" %s = %s%s_cast(ovsdb_idl_get_row_arc(row_, &%stable_%s, &datum->values[0].uuid));" % (valueVar, prefix, type.value.ref_table.name.lower(), prefix, type.value.ref_table.name.lower())) print(" %s = %s%s_cast(ovsdb_idl_get_row_arc(row_, &%stable_%s, &datum->values[0].uuid));" % (valueVar, prefix, type.value.ref_table.name.lower(), prefix, type.value.ref_table.name.lower()))
print(" } else {") print(" } else {")
@@ -618,7 +618,7 @@ static void
""" % (prefix, type.key.ref_table.name.lower(), prefix, type.key.ref_table.name.lower(), prefix, type.key.ref_table.name.lower())) """ % (prefix, type.key.ref_table.name.lower(), prefix, type.key.ref_table.name.lower(), prefix, type.key.ref_table.name.lower()))
keySrc = "keyRow" keySrc = "keyRow"
else: else:
keySrc = "datum->keys[i].%s" % type.key.type.to_string() keySrc = "datum->keys[i].%s" % type.key.type.to_rvalue_string()
if type.value and type.value.ref_table: if type.value and type.value.ref_table:
print("""\ print("""\
struct %s%s *valueRow = %s%s_cast(ovsdb_idl_get_row_arc(row_, &%stable_%s, &datum->values[i].uuid)); struct %s%s *valueRow = %s%s_cast(ovsdb_idl_get_row_arc(row_, &%stable_%s, &datum->values[i].uuid));
@@ -628,7 +628,7 @@ static void
""" % (prefix, type.value.ref_table.name.lower(), prefix, type.value.ref_table.name.lower(), prefix, type.value.ref_table.name.lower())) """ % (prefix, type.value.ref_table.name.lower(), prefix, type.value.ref_table.name.lower(), prefix, type.value.ref_table.name.lower()))
valueSrc = "valueRow" valueSrc = "valueRow"
elif valueVar: elif valueVar:
valueSrc = "datum->values[i].%s" % type.value.type.to_string() valueSrc = "datum->values[i].%s" % type.value.type.to_rvalue_string()
print(" if (!row->n_%s) {" % (columnName)) print(" if (!row->n_%s) {" % (columnName))
print(" %s = xmalloc(%s * sizeof *%s);" % ( print(" %s = xmalloc(%s * sizeof *%s);" % (
@@ -936,45 +936,45 @@ void
'args': ', '.join(['%(type)s%(name)s' 'args': ', '.join(['%(type)s%(name)s'
% m for m in members])}) % m for m in members])})
if type.n_min == 1 and type.n_max == 1: if type.n_min == 1 and type.n_max == 1:
print(" union ovsdb_atom key;") print(" union ovsdb_atom *key = xmalloc(sizeof *key);")
if type.value: if type.value:
print(" union ovsdb_atom value;") print(" union ovsdb_atom *value = xmalloc(sizeof *value);")
print("") print("")
print(" datum.n = 1;") print(" datum.n = 1;")
print(" datum.keys = &key;") print(" datum.keys = key;")
print(" " + type.key.assign_c_value_casting_away_const("key.%s" % type.key.type.to_string(), keyVar)) print(" " + type.key.copyCValue("key->%s" % type.key.type.to_lvalue_string(), keyVar))
if type.value: if type.value:
print(" datum.values = &value;") print(" datum.values = value;")
print(" "+ type.value.assign_c_value_casting_away_const("value.%s" % type.value.type.to_string(), valueVar)) print(" " + type.value.copyCValue("value->%s" % type.value.type.to_lvalue_string(), valueVar))
else: else:
print(" datum.values = NULL;") print(" datum.values = NULL;")
txn_write_func = "ovsdb_idl_txn_write_clone" txn_write_func = "ovsdb_idl_txn_write"
elif type.is_optional_pointer(): elif type.is_optional_pointer():
print(" union ovsdb_atom key;")
print("") print("")
print(" if (%s) {" % keyVar) print(" if (%s) {" % keyVar)
print(" union ovsdb_atom *key = xmalloc(sizeof *key);")
print(" datum.n = 1;") print(" datum.n = 1;")
print(" datum.keys = &key;") print(" datum.keys = key;")
print(" " + type.key.assign_c_value_casting_away_const("key.%s" % type.key.type.to_string(), keyVar)) print(" " + type.key.copyCValue("key->%s" % type.key.type.to_lvalue_string(), keyVar))
print(" } else {") print(" } else {")
print(" datum.n = 0;") print(" datum.n = 0;")
print(" datum.keys = NULL;") print(" datum.keys = NULL;")
print(" }") print(" }")
print(" datum.values = NULL;") print(" datum.values = NULL;")
txn_write_func = "ovsdb_idl_txn_write_clone" txn_write_func = "ovsdb_idl_txn_write"
elif type.n_max == 1: elif type.n_max == 1:
print(" union ovsdb_atom key;")
print("") print("")
print(" if (%s) {" % nVar) print(" if (%s) {" % nVar)
print(" union ovsdb_atom *key = xmalloc(sizeof *key);")
print(" datum.n = 1;") print(" datum.n = 1;")
print(" datum.keys = &key;") print(" datum.keys = key;")
print(" " + type.key.assign_c_value_casting_away_const("key.%s" % type.key.type.to_string(), "*" + keyVar)) print(" " + type.key.copyCValue("key->%s" % type.key.type.to_lvalue_string(), "*" + keyVar))
print(" } else {") print(" } else {")
print(" datum.n = 0;") print(" datum.n = 0;")
print(" datum.keys = NULL;") print(" datum.keys = NULL;")
print(" }") print(" }")
print(" datum.values = NULL;") print(" datum.values = NULL;")
txn_write_func = "ovsdb_idl_txn_write_clone" txn_write_func = "ovsdb_idl_txn_write"
else: else:
print("") print("")
print(" datum.n = %s;" % nVar) print(" datum.n = %s;" % nVar)
@@ -984,9 +984,9 @@ void
else: else:
print(" datum.values = NULL;") print(" datum.values = NULL;")
print(" for (size_t i = 0; i < %s; i++) {" % nVar) print(" for (size_t i = 0; i < %s; i++) {" % nVar)
print(" " + type.key.copyCValue("datum.keys[i].%s" % type.key.type.to_string(), "%s[i]" % keyVar)) print(" " + type.key.copyCValue("datum.keys[i].%s" % type.key.type.to_lvalue_string(), "%s[i]" % keyVar))
if type.value: if type.value:
print(" " + type.value.copyCValue("datum.values[i].%s" % type.value.type.to_string(), "%s[i]" % valueVar)) print(" " + type.value.copyCValue("datum.values[i].%s" % type.value.type.to_lvalue_string(), "%s[i]" % valueVar))
print(" }") print(" }")
if type.value: if type.value:
valueType = type.value.toAtomicType() valueType = type.value.toAtomicType()
@@ -1022,9 +1022,8 @@ void
''' % {'s': structName, 'c': columnName,'coltype':column.type.key.to_const_c_type(prefix), ''' % {'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(), 'valtype':column.type.value.to_const_c_type(prefix), 'S': structName.upper(),
'C': columnName.upper(), 't': tableName}) 'C': columnName.upper(), 't': tableName})
print(" " + type.key.copyCValue("datum->keys[0].%s" % type.key.type.to_lvalue_string(), "new_key"))
print(" "+ type.key.copyCValue("datum->keys[0].%s" % type.key.type.to_string(), "new_key")) print(" " + type.value.copyCValue("datum->values[0].%s" % type.value.type.to_lvalue_string(), "new_value"))
print(" "+ type.value.copyCValue("datum->values[0].%s" % type.value.type.to_string(), "new_value"))
print(''' print('''
ovsdb_idl_txn_write_partial_map(&row->header_, ovsdb_idl_txn_write_partial_map(&row->header_,
&%(s)s_col_%(c)s, &%(s)s_col_%(c)s,
@@ -1048,8 +1047,7 @@ void
''' % {'s': structName, 'c': columnName,'coltype':column.type.key.to_const_c_type(prefix), ''' % {'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(), 'valtype':column.type.value.to_const_c_type(prefix), 'S': structName.upper(),
'C': columnName.upper(), 't': tableName}) 'C': columnName.upper(), 't': tableName})
print(" " + type.key.copyCValue("datum->keys[0].%s" % type.key.type.to_lvalue_string(), "delete_key"))
print(" "+ type.key.copyCValue("datum->keys[0].%s" % type.key.type.to_string(), "delete_key"))
print(''' print('''
ovsdb_idl_txn_delete_partial_map(&row->header_, ovsdb_idl_txn_delete_partial_map(&row->header_,
&%(s)s_col_%(c)s, &%(s)s_col_%(c)s,
@@ -1075,8 +1073,7 @@ void
datum->values = NULL; datum->values = NULL;
''' % {'s': structName, 'c': columnName, ''' % {'s': structName, 'c': columnName,
'valtype':column.type.key.to_const_c_type(prefix), 't': tableName}) '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"))
print(" "+ type.key.copyCValue("datum->keys[0].%s" % type.key.type.to_string(), "new_value"))
print(''' print('''
ovsdb_idl_txn_write_partial_set(&row->header_, ovsdb_idl_txn_write_partial_set(&row->header_,
&%(s)s_col_%(c)s, &%(s)s_col_%(c)s,
@@ -1100,8 +1097,7 @@ void
''' % {'s': structName, 'c': columnName,'coltype':column.type.key.to_const_c_type(prefix), ''' % {'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(), 'valtype':column.type.key.to_const_c_type(prefix), 'S': structName.upper(),
'C': columnName.upper(), 't': tableName}) 'C': columnName.upper(), 't': tableName})
print(" " + type.key.copyCValue("datum->keys[0].%s" % type.key.type.to_lvalue_string(), "delete_value"))
print(" "+ type.key.copyCValue("datum->keys[0].%s" % type.key.type.to_string(), "delete_value"))
print(''' print('''
ovsdb_idl_txn_delete_partial_set(&row->header_, ovsdb_idl_txn_delete_partial_set(&row->header_,
&%(s)s_col_%(c)s, &%(s)s_col_%(c)s,
@@ -1169,37 +1165,36 @@ void
print(" struct ovsdb_datum datum;") print(" struct ovsdb_datum datum;")
free = [] free = []
if type.n_min == 1 and type.n_max == 1: if type.n_min == 1 and type.n_max == 1:
print(" union ovsdb_atom key;") print(" union ovsdb_atom *key = xmalloc(sizeof *key);")
if type.value: if type.value:
print(" union ovsdb_atom value;") print(" union ovsdb_atom *value = xmalloc(sizeof *value);")
print("") print("")
print(" datum.n = 1;") print(" datum.n = 1;")
print(" datum.keys = &key;") print(" datum.keys = key;")
print(" " + type.key.assign_c_value_casting_away_const("key.%s" % type.key.type.to_string(), keyVar, refTable=False)) print(" " + type.key.copyCValue("key->%s" % type.key.type.to_lvalue_string(), keyVar, refTable=False))
if type.value: if type.value:
print(" datum.values = &value;") print(" " + type.value.copyCValue("value.%s" % type.value.type.to_lvalue_string(), valueVar, refTable=False))
print(" "+ type.value.assign_c_value_casting_away_const("value.%s" % type.value.type.to_string(), valueVar, refTable=False))
else: else:
print(" datum.values = NULL;") print(" datum.values = NULL;")
elif type.is_optional_pointer(): elif type.is_optional_pointer():
print(" union ovsdb_atom key;")
print("") print("")
print(" if (%s) {" % keyVar) print(" if (%s) {" % keyVar)
print(" union ovsdb_atom *key = xmalloc(sizeof *key);")
print(" datum.n = 1;") print(" datum.n = 1;")
print(" datum.keys = &key;") print(" datum.keys = key;")
print(" " + type.key.assign_c_value_casting_away_const("key.%s" % type.key.type.to_string(), keyVar, refTable=False)) print(" " + type.key.copyCValue("key->%s" % type.key.type.to_lvalue_string(), keyVar, refTable=False))
print(" } else {") print(" } else {")
print(" datum.n = 0;") print(" datum.n = 0;")
print(" datum.keys = NULL;") print(" datum.keys = NULL;")
print(" }") print(" }")
print(" datum.values = NULL;") print(" datum.values = NULL;")
elif type.n_max == 1: elif type.n_max == 1:
print(" union ovsdb_atom key;")
print("") print("")
print(" if (%s) {" % nVar) print(" if (%s) {" % nVar)
print(" union ovsdb_atom *key = xmalloc(sizeof *key);")
print(" datum.n = 1;") print(" datum.n = 1;")
print(" datum.keys = &key;") print(" datum.keys = key;")
print(" " + type.key.assign_c_value_casting_away_const("key.%s" % type.key.type.to_string(), "*" + keyVar, refTable=False)) print(" " + type.key.copyCValue("key->%s" % type.key.type.to_lvalue_string(), "*" + keyVar, refTable=False))
print(" } else {") print(" } else {")
print(" datum.n = 0;") print(" datum.n = 0;")
print(" datum.keys = NULL;") print(" datum.keys = NULL;")
@@ -1208,16 +1203,14 @@ void
else: else:
print(" datum.n = %s;" % nVar) print(" datum.n = %s;" % nVar)
print(" datum.keys = %s ? xmalloc(%s * sizeof *datum.keys) : NULL;" % (nVar, nVar)) print(" datum.keys = %s ? xmalloc(%s * sizeof *datum.keys) : NULL;" % (nVar, nVar))
free += ['datum.keys']
if type.value: if type.value:
print(" datum.values = xmalloc(%s * sizeof *datum.values);" % nVar) print(" datum.values = xmalloc(%s * sizeof *datum.values);" % nVar)
free += ['datum.values']
else: else:
print(" datum.values = NULL;") print(" datum.values = NULL;")
print(" for (size_t i = 0; i < %s; i++) {" % nVar) print(" for (size_t i = 0; i < %s; i++) {" % nVar)
print(" " + type.key.assign_c_value_casting_away_const("datum.keys[i].%s" % type.key.type.to_string(), "%s[i]" % keyVar, refTable=False)) print(" " + type.key.copyCValue("datum.keys[i].%s" % type.key.type.to_lvalue_string(), "%s[i]" % keyVar, refTable=False))
if type.value: if type.value:
print(" " + type.value.assign_c_value_casting_away_const("datum.values[i].%s" % type.value.type.to_string(), "%s[i]" % valueVar, refTable=False)) print(" " + type.value.copyCValue("datum.values[i].%s" % type.value.type.to_lvalue_string(), "%s[i]" % valueVar, refTable=False))
print(" }") print(" }")
if type.value: if type.value:
valueType = type.value.toAtomicType() valueType = type.value.toAtomicType()
@@ -1237,8 +1230,8 @@ void
's': structName, 's': structName,
'S': structName.upper(), 'S': structName.upper(),
'c': columnName}) 'c': columnName})
for var in free: print(" ovsdb_datum_destroy(&datum, &%(s)s_col_%(c)s.type);" \
print(" free(%s);" % var) % {'s': structName, 'c': columnName})
print("}") print("}")
# Index table related functions # Index table related functions
@@ -1335,8 +1328,8 @@ struct %(s)s *
i = 0; i = 0;
SMAP_FOR_EACH (node, %(c)s) { SMAP_FOR_EACH (node, %(c)s) {
datum->keys[i].string = node->key; datum->keys[i].s = ovsdb_atom_string_create(node->key);
datum->values[i].string = node->value; datum->values[i].s = ovsdb_atom_string_create(node->value);
i++; i++;
} }
ovsdb_datum_sort_unique(datum, OVSDB_TYPE_STRING, OVSDB_TYPE_STRING); ovsdb_datum_sort_unique(datum, OVSDB_TYPE_STRING, OVSDB_TYPE_STRING);
@@ -1385,10 +1378,10 @@ struct %(s)s *
print() print()
print(" datum.n = 1;") print(" datum.n = 1;")
print(" datum.keys = key;") print(" datum.keys = key;")
print(" " + type.key.assign_c_value_casting_away_const("key->%s" % type.key.type.to_string(), keyVar)) print(" " + type.key.copyCValue("key->%s" % type.key.type.to_lvalue_string(), keyVar))
if type.value: if type.value:
print(" datum.values = value;") print(" datum.values = value;")
print(" "+ type.value.assign_c_value_casting_away_const("value->%s" % type.value.type.to_string(), valueVar)) print(" " + type.value.copyCValue("value->%s" % type.value.type.to_lvalue_string(), valueVar))
else: else:
print(" datum.values = NULL;") print(" datum.values = NULL;")
txn_write_func = "ovsdb_idl_index_write" txn_write_func = "ovsdb_idl_index_write"
@@ -1399,7 +1392,7 @@ struct %(s)s *
print(" key = xmalloc(sizeof (union ovsdb_atom));") print(" key = xmalloc(sizeof (union ovsdb_atom));")
print(" datum.n = 1;") print(" datum.n = 1;")
print(" datum.keys = key;") print(" datum.keys = key;")
print(" " + type.key.assign_c_value_casting_away_const("key->%s" % type.key.type.to_string(), keyVar)) print(" " + type.key.copyCValue("key->%s" % type.key.type.to_lvalue_string(), keyVar))
print(" } else {") print(" } else {")
print(" datum.n = 0;") print(" datum.n = 0;")
print(" datum.keys = NULL;") print(" datum.keys = NULL;")
@@ -1413,7 +1406,7 @@ struct %(s)s *
print(" key = xmalloc(sizeof(union ovsdb_atom));") print(" key = xmalloc(sizeof(union ovsdb_atom));")
print(" datum.n = 1;") print(" datum.n = 1;")
print(" datum.keys = key;") print(" datum.keys = key;")
print(" " + type.key.assign_c_value_casting_away_const("key->%s" % type.key.type.to_string(), "*" + keyVar)) print(" " + type.key.copyCValue("key->%s" % type.key.type.to_lvalue_string(), "*" + keyVar))
print(" } else {") print(" } else {")
print(" datum.n = 0;") print(" datum.n = 0;")
print(" datum.keys = NULL;") print(" datum.keys = NULL;")
@@ -1430,9 +1423,9 @@ struct %(s)s *
else: else:
print(" datum.values = NULL;") print(" datum.values = NULL;")
print(" for (i = 0; i < %s; i++) {" % nVar) print(" for (i = 0; i < %s; i++) {" % nVar)
print(" " + type.key.copyCValue("datum.keys[i].%s" % type.key.type.to_string(), "%s[i]" % keyVar)) print(" " + type.key.copyCValue("datum.keys[i].%s" % type.key.type.to_lvalue_string(), "%s[i]" % keyVar))
if type.value: if type.value:
print(" " + type.value.copyCValue("datum.values[i].%s" % type.value.type.to_string(), "%s[i]" % valueVar)) print(" " + type.value.copyCValue("datum.values[i].%s" % type.value.type.to_lvalue_string(), "%s[i]" % valueVar))
print(" }") print(" }")
if type.value: if type.value:
valueType = type.value.toAtomicType() valueType = type.value.toAtomicType()

View File

@@ -904,8 +904,8 @@ query_db_string(const struct shash *all_dbs, const char *name,
datum = &row->fields[column->index]; datum = &row->fields[column->index];
for (i = 0; i < datum->n; i++) { for (i = 0; i < datum->n; i++) {
if (datum->keys[i].string[0]) { if (datum->keys[i].s->string[0]) {
return datum->keys[i].string; return datum->keys[i].s->string;
} }
} }
} }
@@ -1018,7 +1018,7 @@ query_db_remotes(const char *name, const struct shash *all_dbs,
datum = &row->fields[column->index]; datum = &row->fields[column->index];
for (i = 0; i < datum->n; i++) { for (i = 0; i < datum->n; i++) {
add_remote(remotes, datum->keys[i].string); add_remote(remotes, datum->keys[i].s->string);
} }
} }
} else if (column->type.key.type == OVSDB_TYPE_UUID } else if (column->type.key.type == OVSDB_TYPE_UUID

View File

@@ -111,13 +111,13 @@ ovsdb_util_read_map_string_column(const struct ovsdb_row *row,
for (i = 0; i < datum->n; i++) { for (i = 0; i < datum->n; i++) {
atom_key = &datum->keys[i]; atom_key = &datum->keys[i];
if (!strcmp(atom_key->string, key)) { if (!strcmp(atom_key->s->string, key)) {
atom_value = &datum->values[i]; atom_value = &datum->values[i];
break; break;
} }
} }
return atom_value ? atom_value->string : NULL; return atom_value ? atom_value->s->string : NULL;
} }
/* Read string-uuid key-values from a map. Returns the row associated with /* Read string-uuid key-values from a map. Returns the row associated with
@@ -143,7 +143,7 @@ ovsdb_util_read_map_string_uuid_column(const struct ovsdb_row *row,
const struct ovsdb_datum *datum = &row->fields[column->index]; const struct ovsdb_datum *datum = &row->fields[column->index];
for (size_t i = 0; i < datum->n; i++) { for (size_t i = 0; i < datum->n; i++) {
union ovsdb_atom *atom_key = &datum->keys[i]; union ovsdb_atom *atom_key = &datum->keys[i];
if (!strcmp(atom_key->string, key)) { if (!strcmp(atom_key->s->string, key)) {
const union ovsdb_atom *atom_value = &datum->values[i]; const union ovsdb_atom *atom_value = &datum->values[i];
return ovsdb_table_get_row(ref_table, &atom_value->uuid); return ovsdb_table_get_row(ref_table, &atom_value->uuid);
} }
@@ -181,7 +181,7 @@ ovsdb_util_read_string_column(const struct ovsdb_row *row,
const union ovsdb_atom *atom; const union ovsdb_atom *atom;
atom = ovsdb_util_read_column(row, column_name, OVSDB_TYPE_STRING); atom = ovsdb_util_read_column(row, column_name, OVSDB_TYPE_STRING);
*stringp = atom ? atom->string : NULL; *stringp = atom ? atom->s->string : NULL;
return atom != NULL; return atom != NULL;
} }
@@ -269,8 +269,10 @@ ovsdb_util_write_string_column(struct ovsdb_row *row, const char *column_name,
const char *string) const char *string)
{ {
if (string) { if (string) {
const union ovsdb_atom atom = { .string = CONST_CAST(char *, string) }; union ovsdb_atom atom = {
.s = ovsdb_atom_string_create(CONST_CAST(char *, string)) };
ovsdb_util_write_singleton(row, column_name, &atom, OVSDB_TYPE_STRING); ovsdb_util_write_singleton(row, column_name, &atom, OVSDB_TYPE_STRING);
ovsdb_atom_destroy(&atom, OVSDB_TYPE_STRING);
} else { } else {
ovsdb_util_clear_column(row, column_name); ovsdb_util_clear_column(row, column_name);
} }
@@ -305,8 +307,8 @@ ovsdb_util_write_string_string_column(struct ovsdb_row *row,
datum->values = xmalloc(n * sizeof *datum->values); datum->values = xmalloc(n * sizeof *datum->values);
for (i = 0; i < n; ++i) { for (i = 0; i < n; ++i) {
datum->keys[i].string = keys[i]; datum->keys[i].s = ovsdb_atom_string_create_nocopy(keys[i]);
datum->values[i].string = values[i]; datum->values[i].s = ovsdb_atom_string_create_nocopy(values[i]);
} }
/* Sort and check constraints. */ /* Sort and check constraints. */

View File

@@ -53,8 +53,8 @@ ovsdb_find_row_by_string_key(const struct ovsdb_table *table,
HMAP_FOR_EACH (row, hmap_node, &table->rows) { HMAP_FOR_EACH (row, hmap_node, &table->rows) {
const struct ovsdb_datum *datum = &row->fields[column->index]; const struct ovsdb_datum *datum = &row->fields[column->index];
for (size_t i = 0; i < datum->n; i++) { for (size_t i = 0; i < datum->n; i++) {
if (datum->keys[i].string[0] && if (datum->keys[i].s->string[0] &&
!strcmp(key, datum->keys[i].string)) { !strcmp(key, datum->keys[i].s->string)) {
return row; return row;
} }
} }
@@ -113,7 +113,7 @@ ovsdb_rbac_authorized(const struct ovsdb_row *perms,
} }
for (i = 0; i < datum->n; i++) { for (i = 0; i < datum->n; i++) {
const char *name = datum->keys[i].string; const char *name = datum->keys[i].s->string;
const char *value = NULL; const char *value = NULL;
bool is_map; bool is_map;
@@ -271,7 +271,7 @@ rbac_column_modification_permitted(const struct ovsdb_column *column,
size_t i; size_t i;
for (i = 0; i < modifiable->n; i++) { for (i = 0; i < modifiable->n; i++) {
char *name = modifiable->keys[i].string; char *name = modifiable->keys[i].s->string;
if (!strcmp(name, column->name)) { if (!strcmp(name, column->name)) {
return true; return true;

View File

@@ -204,7 +204,7 @@ class Atom(object):
else: else:
return '.boolean = false' return '.boolean = false'
elif self.type == ovs.db.types.StringType: elif self.type == ovs.db.types.StringType:
return '.string = "%s"' % escapeCString(self.value) return '.s = %s' % escapeCString(self.value)
elif self.type == ovs.db.types.UuidType: elif self.type == ovs.db.types.UuidType:
return '.uuid = %s' % ovs.ovsuuid.to_c_assignment(self.value) return '.uuid = %s' % ovs.ovsuuid.to_c_assignment(self.value)
@@ -563,16 +563,41 @@ class Datum(object):
if n == 0: if n == 0:
return ["static struct ovsdb_datum %s = { .n = 0 };"] return ["static struct ovsdb_datum %s = { .n = 0 };"]
s = ["static union ovsdb_atom %s_keys[%d] = {" % (name, n)] s = []
for key in sorted(self.values): if self.type.key.type == ovs.db.types.StringType:
s += [" { %s }," % key.cInitAtom(key)] s += ["static struct ovsdb_atom_string %s_key_strings[%d] = {"
s += ["};"] % (name, n)]
for key in sorted(self.values):
s += [' { .string = "%s", .n_refs = 2 },'
% escapeCString(key.value)]
s += ["};"]
s += ["static union ovsdb_atom %s_keys[%d] = {" % (name, n)]
for i in range(n):
s += [" { .s = &%s_key_strings[%d] }," % (name, i)]
s += ["};"]
else:
s = ["static union ovsdb_atom %s_keys[%d] = {" % (name, n)]
for key in sorted(self.values):
s += [" { %s }," % key.cInitAtom(key)]
s += ["};"]
if self.type.value: if self.type.value:
s = ["static union ovsdb_atom %s_values[%d] = {" % (name, n)] if self.type.value.type == ovs.db.types.StringType:
for k, v in sorted(self.values.items()): s += ["static struct ovsdb_atom_string %s_val_strings[%d] = {"
s += [" { %s }," % v.cInitAtom(v)] % (name, n)]
s += ["};"] for k, v in sorted(self.values):
s += [' { .string = "%s", .n_refs = 2 },'
% escapeCString(v.value)]
s += ["};"]
s += ["static union ovsdb_atom %s_values[%d] = {" % (name, n)]
for i in range(n):
s += [" { .s = &%s_val_strings[%d] }," % (name, i)]
s += ["};"]
else:
s = ["static union ovsdb_atom %s_values[%d] = {" % (name, n)]
for k, v in sorted(self.values.items()):
s += [" { %s }," % v.cInitAtom(v)]
s += ["};"]
s += ["static struct ovsdb_datum %s = {" % name] s += ["static struct ovsdb_datum %s = {" % name]
s += [" .n = %d," % n] s += [" .n = %d," % n]

View File

@@ -48,6 +48,16 @@ class AtomicType(object):
def to_string(self): def to_string(self):
return self.name return self.name
def to_rvalue_string(self):
if self == StringType:
return 's->' + self.name
return self.name
def to_lvalue_string(self):
if self == StringType:
return 's'
return self.name
def to_json(self): def to_json(self):
return self.name return self.name
@@ -373,18 +383,7 @@ class BaseType(object):
return "%(dst)s = *%(src)s;" % args return "%(dst)s = *%(src)s;" % args
return ("%(dst)s = %(src)s->header_.uuid;") % args return ("%(dst)s = %(src)s->header_.uuid;") % args
elif self.type == StringType: elif self.type == StringType:
return "%(dst)s = xstrdup(%(src)s);" % args return "%(dst)s = ovsdb_atom_string_create(%(src)s);" % args
else:
return "%(dst)s = %(src)s;" % args
def assign_c_value_casting_away_const(self, dst, src, refTable=True):
args = {'dst': dst, 'src': src}
if self.ref_table_name:
if not refTable:
return "%(dst)s = *%(src)s;" % args
return ("%(dst)s = %(src)s->header_.uuid;") % args
elif self.type == StringType:
return "%(dst)s = CONST_CAST(char *, %(src)s);" % args
else: else:
return "%(dst)s = %(src)s;" % args return "%(dst)s = %(src)s;" % args

View File

@@ -2744,13 +2744,15 @@ print_idl_row_simple2(const struct idltest_simple2 *s, int step)
printf("%03d: name=%s smap=[", printf("%03d: name=%s smap=[",
step, s->name); step, s->name);
for (i = 0; i < smap->n; i++) { for (i = 0; i < smap->n; i++) {
printf("[%s : %s]%s", smap->keys[i].string, smap->values[i].string, printf("[%s : %s]%s",
i < smap->n-1? ",": ""); smap->keys[i].s->string, smap->values[i].s->string,
i < smap->n - 1 ? "," : "");
} }
printf("] imap=["); printf("] imap=[");
for (i = 0; i < imap->n; i++) { for (i = 0; i < imap->n; i++) {
printf("[%"PRId64" : %s]%s", imap->keys[i].integer, imap->values[i].string, printf("[%"PRId64" : %s]%s",
i < imap->n-1? ",":""); imap->keys[i].integer, imap->values[i].s->string,
i < imap->n - 1 ? "," : "");
} }
printf("]\n"); printf("]\n");
} }
@@ -2819,8 +2821,8 @@ do_idl_partial_update_map_column(struct ovs_cmdl_context *ctx)
myTxn = ovsdb_idl_txn_create(idl); myTxn = ovsdb_idl_txn_create(idl);
smap = idltest_simple2_get_smap(myRow, OVSDB_TYPE_STRING, smap = idltest_simple2_get_smap(myRow, OVSDB_TYPE_STRING,
OVSDB_TYPE_STRING); OVSDB_TYPE_STRING);
strcpy(key_to_delete, smap->keys[0].string); ovs_strlcpy(key_to_delete, smap->keys[0].s->string, sizeof key_to_delete);
idltest_simple2_update_smap_delkey(myRow, smap->keys[0].string); idltest_simple2_update_smap_delkey(myRow, smap->keys[0].s->string);
ovsdb_idl_txn_commit_block(myTxn); ovsdb_idl_txn_commit_block(myTxn);
ovsdb_idl_txn_destroy(myTxn); ovsdb_idl_txn_destroy(myTxn);
ovsdb_idl_get_initial_snapshot(idl); ovsdb_idl_get_initial_snapshot(idl);