From 958ac03a3f785303399316eda76362d26adb09d4 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Mon, 12 Jul 2010 10:05:16 -0700 Subject: [PATCH] ovsdb: New functions ovsdb_atom_default(), ovsdb_datum_default(). Having access to const copies of default atoms and data will allow OVSDB code to avoid memory allocations and reduce copying in upcoming commits. --- lib/ovsdb-data.c | 88 ++++++++++++++++++++++++++++++++++++++++++--- lib/ovsdb-data.h | 2 ++ tests/ovsdb-data.at | 73 +++++++++++++++++++++++++++++++++++++ tests/test-ovsdb.c | 71 ++++++++++++++++++++++++++++++++++++ 4 files changed, 230 insertions(+), 4 deletions(-) diff --git a/lib/ovsdb-data.c b/lib/ovsdb-data.c index d08128f52..9691cf432 100644 --- a/lib/ovsdb-data.c +++ b/lib/ovsdb-data.c @@ -84,6 +84,31 @@ ovsdb_atom_init_default(union ovsdb_atom *atom, enum ovsdb_atomic_type type) } } +/* Returns a read-only atom of the given 'type' that has the default value for + * 'type'. The caller must not modify or free the returned atom. + * + * See ovsdb_atom_init_default() for an explanation of the default value of an + * atom. */ +const union ovsdb_atom * +ovsdb_atom_default(enum ovsdb_atomic_type type) +{ + static union ovsdb_atom default_atoms[OVSDB_N_TYPES]; + static bool inited; + + if (!inited) { + int i; + + for (i = 0; i < OVSDB_N_TYPES; i++) { + if (i != OVSDB_TYPE_VOID) { + ovsdb_atom_init_default(&default_atoms[i], i); + } + } + inited = true; + } + + assert(ovsdb_atomic_type_is_valid(type)); + return &default_atoms[type]; +} /* Returns true if 'atom', which must have the given 'type', has the default * value for that type. @@ -349,8 +374,11 @@ ovsdb_atom_from_json__(union ovsdb_atom *atom, enum ovsdb_atomic_type type, * returns an error and the contents of 'atom' are indeterminate. The caller * is responsible for freeing the error or the atom that is returned. * + * Violations of constraints expressed by 'base' are treated as errors. + * * If 'symtab' is nonnull, then named UUIDs in 'symtab' are accepted. Refer to - * ovsdb/SPECS information about this and other syntactical details. */ + * ovsdb/SPECS for information about this, and for the syntax that this + * function accepts. */ struct ovsdb_error * ovsdb_atom_from_json(union ovsdb_atom *atom, const struct ovsdb_base_type *base, @@ -372,7 +400,10 @@ ovsdb_atom_from_json(union ovsdb_atom *atom, } /* Converts 'atom', of the specified 'type', to JSON format, and returns the - * JSON. The caller is responsible for freeing the returned JSON. */ + * JSON. The caller is responsible for freeing the returned JSON. + * + * Refer to ovsdb/SPECS for the format of the JSON that this function + * produces. */ struct json * ovsdb_atom_to_json(const union ovsdb_atom *atom, enum ovsdb_atomic_type type) { @@ -776,6 +807,39 @@ ovsdb_datum_init_default(struct ovsdb_datum *datum, datum->values = alloc_default_atoms(type->value.type, datum->n); } +/* Returns a read-only datum of the given 'type' that has the default value for + * 'type'. The caller must not modify or free the returned datum. + * + * See ovsdb_datum_init_default() for an explanation of the default value of a + * datum. */ +const struct ovsdb_datum * +ovsdb_datum_default(const struct ovsdb_type *type) +{ + if (type->n_min == 0) { + static const struct ovsdb_datum empty; + return ∅ + } else if (type->n_min == 1) { + static struct ovsdb_datum default_data[OVSDB_N_TYPES][OVSDB_N_TYPES]; + struct ovsdb_datum *d; + int kt = type->key.type; + int vt = type->value.type; + + assert(ovsdb_type_is_valid(type)); + + d = &default_data[kt][vt]; + if (!d->n) { + d->n = 1; + d->keys = (union ovsdb_atom *) ovsdb_atom_default(kt); + if (vt != OVSDB_TYPE_VOID) { + d->values = (union ovsdb_atom *) ovsdb_atom_default(vt); + } + } + return d; + } else { + NOT_REACHED(); + } +} + /* Returns true if 'datum', which must have the given 'type', has the default * value for that type. * @@ -979,6 +1043,16 @@ ovsdb_datum_check_constraints(const struct ovsdb_datum *datum, return NULL; } +/* Parses 'json' as a datum of the type described by 'type'. If successful, + * returns NULL and initializes 'datum' with the parsed datum. On failure, + * returns an error and the contents of 'datum' are indeterminate. The caller + * is responsible for freeing the error or the datum that is returned. + * + * Violations of constraints expressed by 'type' are treated as errors. + * + * If 'symtab' is nonnull, then named UUIDs in 'symtab' are accepted. Refer to + * ovsdb/SPECS for information about this, and for the syntax that this + * function accepts. */ struct ovsdb_error * ovsdb_datum_from_json(struct ovsdb_datum *datum, const struct ovsdb_type *type, @@ -1069,12 +1143,18 @@ ovsdb_datum_from_json(struct ovsdb_datum *datum, } } + +/* Converts 'datum', of the specified 'type', to JSON format, and returns the + * JSON. The caller is responsible for freeing the returned JSON. + * + * 'type' constraints on datum->n are ignored. + * + * Refer to ovsdb/SPECS for the format of the JSON that this function + * produces. */ struct json * ovsdb_datum_to_json(const struct ovsdb_datum *datum, const struct ovsdb_type *type) { - /* These tests somewhat tolerate a 'datum' that does not exactly match - * 'type', in particular a datum with 'n' not in the allowed range. */ if (datum->n == 1 && !ovsdb_type_is_map(type)) { return ovsdb_atom_to_json(&datum->keys[0], type->key.type); } else if (type->value.type == OVSDB_TYPE_VOID) { diff --git a/lib/ovsdb-data.h b/lib/ovsdb-data.h index 29a5b9e0d..4f44fd847 100644 --- a/lib/ovsdb-data.h +++ b/lib/ovsdb-data.h @@ -33,6 +33,7 @@ union ovsdb_atom { }; void ovsdb_atom_init_default(union ovsdb_atom *, enum ovsdb_atomic_type); +const union ovsdb_atom *ovsdb_atom_default(enum ovsdb_atomic_type); bool ovsdb_atom_is_default(const union ovsdb_atom *, enum ovsdb_atomic_type); void ovsdb_atom_clone(union ovsdb_atom *, const union ovsdb_atom *, enum ovsdb_atomic_type); @@ -128,6 +129,7 @@ void ovsdb_datum_init_empty(struct ovsdb_datum *); 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_destroy(struct ovsdb_datum *, const struct ovsdb_type *); diff --git a/tests/ovsdb-data.at b/tests/ovsdb-data.at index af89e7ff4..ac0f0b7be 100644 --- a/tests/ovsdb-data.at +++ b/tests/ovsdb-data.at @@ -1,3 +1,76 @@ +AT_BANNER([OVSDB -- default values]) + +OVSDB_CHECK_POSITIVE([default atoms], + [default-atoms], + [[integer: OK +real: OK +boolean: OK +string: OK +uuid: OK]]) + +OVSDB_CHECK_POSITIVE([default data], + [default-data], + [[key integer, value void, n_min 0: OK +key integer, value integer, n_min 0: OK +key integer, value real, n_min 0: OK +key integer, value boolean, n_min 0: OK +key integer, value string, n_min 0: OK +key integer, value uuid, n_min 0: OK +key real, value void, n_min 0: OK +key real, value integer, n_min 0: OK +key real, value real, n_min 0: OK +key real, value boolean, n_min 0: OK +key real, value string, n_min 0: OK +key real, value uuid, n_min 0: OK +key boolean, value void, n_min 0: OK +key boolean, value integer, n_min 0: OK +key boolean, value real, n_min 0: OK +key boolean, value boolean, n_min 0: OK +key boolean, value string, n_min 0: OK +key boolean, value uuid, n_min 0: OK +key string, value void, n_min 0: OK +key string, value integer, n_min 0: OK +key string, value real, n_min 0: OK +key string, value boolean, n_min 0: OK +key string, value string, n_min 0: OK +key string, value uuid, n_min 0: OK +key uuid, value void, n_min 0: OK +key uuid, value integer, n_min 0: OK +key uuid, value real, n_min 0: OK +key uuid, value boolean, n_min 0: OK +key uuid, value string, n_min 0: OK +key uuid, value uuid, n_min 0: OK +key integer, value void, n_min 1: OK +key integer, value integer, n_min 1: OK +key integer, value real, n_min 1: OK +key integer, value boolean, n_min 1: OK +key integer, value string, n_min 1: OK +key integer, value uuid, n_min 1: OK +key real, value void, n_min 1: OK +key real, value integer, n_min 1: OK +key real, value real, n_min 1: OK +key real, value boolean, n_min 1: OK +key real, value string, n_min 1: OK +key real, value uuid, n_min 1: OK +key boolean, value void, n_min 1: OK +key boolean, value integer, n_min 1: OK +key boolean, value real, n_min 1: OK +key boolean, value boolean, n_min 1: OK +key boolean, value string, n_min 1: OK +key boolean, value uuid, n_min 1: OK +key string, value void, n_min 1: OK +key string, value integer, n_min 1: OK +key string, value real, n_min 1: OK +key string, value boolean, n_min 1: OK +key string, value string, n_min 1: OK +key string, value uuid, n_min 1: OK +key uuid, value void, n_min 1: OK +key uuid, value integer, n_min 1: OK +key uuid, value real, n_min 1: OK +key uuid, value boolean, n_min 1: OK +key uuid, value string, n_min 1: OK +key uuid, value uuid, n_min 1: OK]]) + AT_BANNER([OVSDB -- atoms without constraints]) OVSDB_CHECK_POSITIVE([integer atom from JSON], diff --git a/tests/test-ovsdb.c b/tests/test-ovsdb.c index 2c8470e1a..1c1116e1f 100644 --- a/tests/test-ovsdb.c +++ b/tests/test-ovsdb.c @@ -121,6 +121,10 @@ usage(void) "usage: %s [OPTIONS] COMMAND [ARG...]\n\n" " log-io FILE FLAGS COMMAND...\n" " open FILE with FLAGS, run COMMANDs\n" + " default-atoms\n" + " test ovsdb_atom_default()\n" + " default-data\n" + " test ovsdb_datum_default()\n" " parse-atomic-type TYPE\n" " parse TYPE as OVSDB atomic type, and re-serialize\n" " parse-base-type TYPE\n" @@ -314,6 +318,71 @@ do_log_io(int argc, char *argv[]) ovsdb_log_close(log); } +static void +do_default_atoms(int argc OVS_UNUSED, char *argv[] OVS_UNUSED) +{ + int type; + + for (type = 0; type < OVSDB_N_TYPES; type++) { + union ovsdb_atom atom; + + if (type == OVSDB_TYPE_VOID) { + continue; + } + + printf("%s: ", ovsdb_atomic_type_to_string(type)); + + ovsdb_atom_init_default(&atom, type); + if (!ovsdb_atom_equals(&atom, ovsdb_atom_default(type), type)) { + printf("wrong\n"); + exit(1); + } + ovsdb_atom_destroy(&atom, type); + + printf("OK\n"); + } +} + +static void +do_default_data(int argc OVS_UNUSED, char *argv[] OVS_UNUSED) +{ + unsigned int n_min; + int key, value; + + for (n_min = 0; n_min <= 1; n_min++) { + for (key = 0; key < OVSDB_N_TYPES; key++) { + if (key == OVSDB_TYPE_VOID) { + continue; + } + for (value = 0; value < OVSDB_N_TYPES; value++) { + struct ovsdb_datum datum; + struct ovsdb_type type; + + ovsdb_base_type_init(&type.key, key); + ovsdb_base_type_init(&type.value, value); + type.n_min = n_min; + type.n_max = 1; + assert(ovsdb_type_is_valid(&type)); + + printf("key %s, value %s, n_min %u: ", + ovsdb_atomic_type_to_string(key), + ovsdb_atomic_type_to_string(value), n_min); + + ovsdb_datum_init_default(&datum, &type); + if (!ovsdb_datum_equals(&datum, ovsdb_datum_default(&type), + &type)) { + printf("wrong\n"); + exit(1); + } + ovsdb_datum_destroy(&datum, &type); + ovsdb_type_destroy(&type); + + printf("OK\n"); + } + } + } +} + static void do_parse_atomic_type(int argc OVS_UNUSED, char *argv[]) { @@ -1813,6 +1882,8 @@ do_idl(int argc, char *argv[]) static struct command all_commands[] = { { "log-io", 2, INT_MAX, do_log_io }, + { "default-atoms", 0, 0, do_default_atoms }, + { "default-data", 0, 0, do_default_data }, { "parse-atomic-type", 1, 1, do_parse_atomic_type }, { "parse-base-type", 1, 1, do_parse_base_type }, { "parse-type", 1, 1, do_parse_type }, -- 2.43.0