2
0
mirror of https://github.com/openvswitch/ovs synced 2025-09-02 15:25:22 +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)
{
if (type == OVSDB_TYPE_STRING) {
if (!strcmp(name->string, record_id)) {
if (!strcmp(name->s->string, record_id)) {
return true;
}
struct uuid uuid;
size_t len = strlen(record_id);
if (len >= 4
&& uuid_from_string(&uuid, name->string)
&& !strncmp(name->string, record_id, len)) {
&& uuid_from_string(&uuid, name->s->string)
&& !strncmp(name->s->string, record_id, len)) {
return true;
}
@@ -318,14 +318,15 @@ get_row_by_id(struct ctl_context *ctx,
if (!id->key) {
name = datum->n == 1 ? &datum->keys[0] : NULL;
} else {
const union ovsdb_atom key_atom
= { .string = CONST_CAST(char *, id->key) };
union ovsdb_atom key_atom = {
.s = ovsdb_atom_string_create(CONST_CAST(char *, id->key)) };
unsigned int i;
if (ovsdb_datum_find_key(datum, &key_atom,
OVSDB_TYPE_STRING, &i)) {
name = &datum->values[i];
}
ovsdb_atom_destroy(&key_atom, OVSDB_TYPE_STRING);
}
if (!name) {
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);
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

View File

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

View File

@@ -20,6 +20,7 @@
#include "compiler.h"
#include "ovsdb-types.h"
#include "openvswitch/shash.h"
#include "util.h"
#ifdef __cplusplus
extern "C" {
@@ -31,12 +32,33 @@ struct ds;
struct ovsdb_symbol_table;
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). */
union ovsdb_atom {
int64_t integer;
double real;
bool boolean;
char *string;
struct ovsdb_atom_string *s;
struct uuid uuid;
};
@@ -66,8 +88,9 @@ ovsdb_atom_needs_destruction(enum ovsdb_atomic_type type)
static inline void
ovsdb_atom_destroy(union ovsdb_atom *atom, enum ovsdb_atomic_type type)
{
if (type == OVSDB_TYPE_STRING) {
free(atom->string);
if (type == OVSDB_TYPE_STRING && !--atom->s->n_refs) {
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) {
c = &class->columns[i];
(c->unparse) (row);
free(row->new_datum[i].values);
free(row->new_datum[i].keys);
ovsdb_datum_destroy(&row->new_datum[i], &c->type);
}
free(row->new_datum);
free(row->written);

View File

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

View File

@@ -111,13 +111,13 @@ ovsdb_util_read_map_string_column(const struct ovsdb_row *row,
for (i = 0; i < datum->n; i++) {
atom_key = &datum->keys[i];
if (!strcmp(atom_key->string, key)) {
if (!strcmp(atom_key->s->string, key)) {
atom_value = &datum->values[i];
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
@@ -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];
for (size_t i = 0; i < datum->n; 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];
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;
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;
}
@@ -269,8 +269,10 @@ ovsdb_util_write_string_column(struct ovsdb_row *row, const char *column_name,
const char *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_atom_destroy(&atom, OVSDB_TYPE_STRING);
} else {
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);
for (i = 0; i < n; ++i) {
datum->keys[i].string = keys[i];
datum->values[i].string = values[i];
datum->keys[i].s = ovsdb_atom_string_create_nocopy(keys[i]);
datum->values[i].s = ovsdb_atom_string_create_nocopy(values[i]);
}
/* 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) {
const struct ovsdb_datum *datum = &row->fields[column->index];
for (size_t i = 0; i < datum->n; i++) {
if (datum->keys[i].string[0] &&
!strcmp(key, datum->keys[i].string)) {
if (datum->keys[i].s->string[0] &&
!strcmp(key, datum->keys[i].s->string)) {
return row;
}
}
@@ -113,7 +113,7 @@ ovsdb_rbac_authorized(const struct ovsdb_row *perms,
}
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;
bool is_map;
@@ -271,7 +271,7 @@ rbac_column_modification_permitted(const struct ovsdb_column *column,
size_t 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)) {
return true;

View File

@@ -204,7 +204,7 @@ class Atom(object):
else:
return '.boolean = false'
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:
return '.uuid = %s' % ovs.ovsuuid.to_c_assignment(self.value)
@@ -563,12 +563,37 @@ class Datum(object):
if n == 0:
return ["static struct ovsdb_datum %s = { .n = 0 };"]
s = []
if self.type.key.type == ovs.db.types.StringType:
s += ["static struct ovsdb_atom_string %s_key_strings[%d] = {"
% (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.type == ovs.db.types.StringType:
s += ["static struct ovsdb_atom_string %s_val_strings[%d] = {"
% (name, n)]
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)]

View File

@@ -48,6 +48,16 @@ class AtomicType(object):
def to_string(self):
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):
return self.name
@@ -373,18 +383,7 @@ class BaseType(object):
return "%(dst)s = *%(src)s;" % args
return ("%(dst)s = %(src)s->header_.uuid;") % args
elif self.type == StringType:
return "%(dst)s = xstrdup(%(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
return "%(dst)s = ovsdb_atom_string_create(%(src)s);" % args
else:
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=[",
step, s->name);
for (i = 0; i < smap->n; i++) {
printf("[%s : %s]%s", smap->keys[i].string, smap->values[i].string,
i < smap->n-1? ",": "");
printf("[%s : %s]%s",
smap->keys[i].s->string, smap->values[i].s->string,
i < smap->n - 1 ? "," : "");
}
printf("] imap=[");
for (i = 0; i < imap->n; i++) {
printf("[%"PRId64" : %s]%s", imap->keys[i].integer, imap->values[i].string,
i < imap->n-1? ",":"");
printf("[%"PRId64" : %s]%s",
imap->keys[i].integer, imap->values[i].s->string,
i < imap->n - 1 ? "," : "");
}
printf("]\n");
}
@@ -2819,8 +2821,8 @@ do_idl_partial_update_map_column(struct ovs_cmdl_context *ctx)
myTxn = ovsdb_idl_txn_create(idl);
smap = idltest_simple2_get_smap(myRow, OVSDB_TYPE_STRING,
OVSDB_TYPE_STRING);
strcpy(key_to_delete, smap->keys[0].string);
idltest_simple2_update_smap_delkey(myRow, 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].s->string);
ovsdb_idl_txn_commit_block(myTxn);
ovsdb_idl_txn_destroy(myTxn);
ovsdb_idl_get_initial_snapshot(idl);