X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=lib%2Fovsdb-data.c;h=ee98c80d3e6f3926e7a8c3b032fc8cb334d3b4df;hb=69123704450703f7ebea4af9e3b9635399fc21f2;hp=76d046f17a38440e5fc25d91e7e780189cc8832a;hpb=0d0f05b909b6428d44eb147bd4edd73782d2a137;p=openvswitch diff --git a/lib/ovsdb-data.c b/lib/ovsdb-data.c index 76d046f1..ee98c80d 100644 --- a/lib/ovsdb-data.c +++ b/lib/ovsdb-data.c @@ -229,14 +229,9 @@ parse_json_pair(const struct json *json, return NULL; } -static struct ovsdb_error * -ovsdb_atom_parse_uuid(struct uuid *uuid, const struct json *json, - const struct ovsdb_symbol_table *symtab) - WARN_UNUSED_RESULT; - -static struct ovsdb_error * +static struct ovsdb_error * WARN_UNUSED_RESULT ovsdb_atom_parse_uuid(struct uuid *uuid, const struct json *json, - const struct ovsdb_symbol_table *symtab) + struct ovsdb_symbol_table *symtab) { struct ovsdb_error *error0; const struct json *value; @@ -254,18 +249,10 @@ ovsdb_atom_parse_uuid(struct uuid *uuid, const struct json *json, error1 = unwrap_json(json, "named-uuid", JSON_STRING, &value); if (!error1) { const char *name = json_string(value); - const struct ovsdb_symbol *symbol; ovsdb_error_destroy(error0); - - symbol = ovsdb_symbol_table_get(symtab, name); - if (symbol) { - *uuid = symbol->uuid; - return NULL; - } else { - return ovsdb_syntax_error(json, NULL, - "unknown named-uuid \"%s\"", name); - } + *uuid = ovsdb_symbol_table_insert(symtab, name)->uuid; + return NULL; } ovsdb_error_destroy(error1); } @@ -276,7 +263,7 @@ ovsdb_atom_parse_uuid(struct uuid *uuid, const struct json *json, static struct ovsdb_error * WARN_UNUSED_RESULT ovsdb_atom_from_json__(union ovsdb_atom *atom, enum ovsdb_atomic_type type, const struct json *json, - const struct ovsdb_symbol_table *symtab) + struct ovsdb_symbol_table *symtab) { switch (type) { case OVSDB_TYPE_VOID: @@ -332,7 +319,7 @@ struct ovsdb_error * ovsdb_atom_from_json(union ovsdb_atom *atom, const struct ovsdb_base_type *base, const struct json *json, - const struct ovsdb_symbol_table *symtab) + struct ovsdb_symbol_table *symtab) { struct ovsdb_error *error; @@ -379,7 +366,7 @@ ovsdb_atom_to_json(const union ovsdb_atom *atom, enum ovsdb_atomic_type type) static char * ovsdb_atom_from_string__(union ovsdb_atom *atom, enum ovsdb_atomic_type type, - const char *s) + const char *s, struct ovsdb_symbol_table *symtab) { switch (type) { case OVSDB_TYPE_VOID: @@ -440,7 +427,9 @@ ovsdb_atom_from_string__(union ovsdb_atom *atom, enum ovsdb_atomic_type type, break; case OVSDB_TYPE_UUID: - if (!uuid_from_string(&atom->uuid, s)) { + if (*s == '@') { + atom->uuid = ovsdb_symbol_table_insert(symtab, s)->uuid; + } else if (!uuid_from_string(&atom->uuid, s)) { return xasprintf("\"%s\" is not a valid UUID", s); } break; @@ -467,19 +456,24 @@ ovsdb_atom_from_string__(union ovsdb_atom *atom, enum ovsdb_atomic_type type, * - OVSDB_TYPE_STRING: A JSON string if it begins with a quote, otherwise * an arbitrary string. * - * - OVSDB_TYPE_UUID: A UUID in RFC 4122 format. + * - OVSDB_TYPE_UUID: A UUID in RFC 4122 format. If 'symtab' is nonnull, + * then an identifier beginning with '@' is also acceptable. If the + * named identifier is already in 'symtab', then the associated UUID is + * used; otherwise, a new, random UUID is used and added to the symbol + * table. * * Returns a null pointer if successful, otherwise an error message describing * the problem. The caller is responsible for freeing the error. */ char * ovsdb_atom_from_string(union ovsdb_atom *atom, - const struct ovsdb_base_type *base, const char *s) + const struct ovsdb_base_type *base, const char *s, + struct ovsdb_symbol_table *symtab) { struct ovsdb_error *error; char *msg; - msg = ovsdb_atom_from_string__(atom, base->type, s); + msg = ovsdb_atom_from_string__(atom, base->type, s, symtab); if (msg) { return msg; } @@ -590,30 +584,6 @@ check_string_constraints(const char *s, "length %u", s, n_chars, c->maxLen); } -#if HAVE_PCRE - if (c->re) { - int retval; - - retval = pcre_exec(c->re, NULL, s, strlen(s), 0, - PCRE_ANCHORED | PCRE_NO_UTF8_CHECK, NULL, 0); - if (retval == PCRE_ERROR_NOMATCH) { - if (c->reComment) { - return ovsdb_error("constraint violation", - "\"%s\" is not a %s", s, c->reComment); - } else { - return ovsdb_error("constraint violation", - "\"%s\" does not match regular expression " - "/%s/", s, c->reMatch); - } - } else if (retval < 0) { - /* PCRE doesn't have a function to translate an error code to a - * description. Bizarre. See pcreapi(3) for error details. */ - return ovsdb_error("internal error", "PCRE returned error %d", - retval); - } - } -#endif /* HAVE_PCRE */ - return NULL; } @@ -627,6 +597,25 @@ struct ovsdb_error * ovsdb_atom_check_constraints(const union ovsdb_atom *atom, const struct ovsdb_base_type *base) { + if (base->enum_ + && ovsdb_datum_find_key(base->enum_, atom, base->type) == UINT_MAX) { + struct ovsdb_error *error; + struct ds actual = DS_EMPTY_INITIALIZER; + struct ds valid = DS_EMPTY_INITIALIZER; + + ovsdb_atom_to_string(atom, base->type, &actual); + ovsdb_datum_to_string(base->enum_, + ovsdb_base_type_get_enum_type(base->type), + &valid); + error = ovsdb_error("constraint violation", + "%s is not one of the allowed values (%s)", + ds_cstr(&actual), ds_cstr(&valid)); + ds_destroy(&actual); + ds_destroy(&valid); + + return error; + } + switch (base->type) { case OVSDB_TYPE_VOID: NOT_REACHED(); @@ -814,7 +803,7 @@ ovsdb_datum_swap(struct ovsdb_datum *a, struct ovsdb_datum *b) } struct ovsdb_datum_sort_cbdata { - const struct ovsdb_type *type; + enum ovsdb_atomic_type key_type; struct ovsdb_datum *datum; }; @@ -825,7 +814,7 @@ ovsdb_datum_sort_compare_cb(size_t a, size_t b, void *cbdata_) return ovsdb_atom_compare_3way(&cbdata->datum->keys[a], &cbdata->datum->keys[b], - cbdata->type->key.type); + cbdata->key_type); } static void @@ -834,13 +823,13 @@ ovsdb_datum_sort_swap_cb(size_t a, size_t b, void *cbdata_) struct ovsdb_datum_sort_cbdata *cbdata = cbdata_; ovsdb_atom_swap(&cbdata->datum->keys[a], &cbdata->datum->keys[b]); - if (cbdata->type->value.type != OVSDB_TYPE_VOID) { + if (cbdata->datum->values) { ovsdb_atom_swap(&cbdata->datum->values[a], &cbdata->datum->values[b]); } } struct ovsdb_error * -ovsdb_datum_sort(struct ovsdb_datum *datum, const struct ovsdb_type *type) +ovsdb_datum_sort(struct ovsdb_datum *datum, enum ovsdb_atomic_type key_type) { if (datum->n < 2) { return NULL; @@ -848,15 +837,15 @@ ovsdb_datum_sort(struct ovsdb_datum *datum, const struct ovsdb_type *type) struct ovsdb_datum_sort_cbdata cbdata; size_t i; - cbdata.type = type; + cbdata.key_type = key_type; cbdata.datum = datum; sort(datum->n, ovsdb_datum_sort_compare_cb, ovsdb_datum_sort_swap_cb, &cbdata); for (i = 0; i < datum->n - 1; i++) { if (ovsdb_atom_equals(&datum->keys[i], &datum->keys[i + 1], - type->key.type)) { - if (ovsdb_type_is_map(type)) { + key_type)) { + if (datum->values) { return ovsdb_error(NULL, "map contains duplicate key"); } else { return ovsdb_error(NULL, "set contains duplicate"); @@ -868,6 +857,16 @@ ovsdb_datum_sort(struct ovsdb_datum *datum, const struct ovsdb_type *type) } } +void +ovsdb_datum_sort_assert(struct ovsdb_datum *datum, + enum ovsdb_atomic_type key_type) +{ + struct ovsdb_error *error = ovsdb_datum_sort(datum, key_type); + if (error) { + NOT_REACHED(); + } +} + /* Checks that each of the atoms in 'datum' conforms to the constraints * specified by its 'type'. Returns an error if a constraint is violated, * otherwise a null pointer. @@ -906,30 +905,21 @@ struct ovsdb_error * ovsdb_datum_from_json(struct ovsdb_datum *datum, const struct ovsdb_type *type, const struct json *json, - const struct ovsdb_symbol_table *symtab) + struct ovsdb_symbol_table *symtab) { struct ovsdb_error *error; - if (ovsdb_type_is_scalar(type)) { - datum->n = 1; - datum->keys = xmalloc(sizeof *datum->keys); - datum->values = NULL; - - error = ovsdb_atom_from_json(&datum->keys[0], &type->key, - json, symtab); - if (error) { - free(datum->keys); - } - return error; - } else { + if (ovsdb_type_is_map(type) + || (json->type == JSON_ARRAY + && json->u.array.n > 0 + && json->u.array.elems[0]->type == JSON_STRING + && !strcmp(json->u.array.elems[0]->u.string, "set"))) { bool is_map = ovsdb_type_is_map(type); const char *class = is_map ? "map" : "set"; const struct json *inner; unsigned int i; size_t n; - assert(is_map || ovsdb_type_is_set(type)); - error = unwrap_json(json, class, JSON_ARRAY, &inner); if (error) { return error; @@ -977,7 +967,7 @@ ovsdb_datum_from_json(struct ovsdb_datum *datum, datum->n++; } - error = ovsdb_datum_sort(datum, type); + error = ovsdb_datum_sort(datum, type->key.type); if (error) { goto error; } @@ -987,6 +977,17 @@ ovsdb_datum_from_json(struct ovsdb_datum *datum, error: ovsdb_datum_destroy(datum, type); return error; + } else { + datum->n = 1; + datum->keys = xmalloc(sizeof *datum->keys); + datum->values = NULL; + + error = ovsdb_atom_from_json(&datum->keys[0], &type->key, + json, symtab); + if (error) { + free(datum->keys); + } + return error; } } @@ -996,7 +997,7 @@ ovsdb_datum_to_json(const struct ovsdb_datum *datum, { /* 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_scalar(type)) { + 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) { struct json **elems; @@ -1034,13 +1035,13 @@ skip_spaces(const char *p) static char * parse_atom_token(const char **s, const struct ovsdb_base_type *base, - union ovsdb_atom *atom) + union ovsdb_atom *atom, struct ovsdb_symbol_table *symtab) { char *token, *error; error = ovsdb_token_parse(s, &token); if (!error) { - error = ovsdb_atom_from_string(atom, base, token); + error = ovsdb_atom_from_string(atom, base, token, symtab); free(token); } return error; @@ -1048,18 +1049,19 @@ parse_atom_token(const char **s, const struct ovsdb_base_type *base, static char * parse_key_value(const char **s, const struct ovsdb_type *type, - union ovsdb_atom *key, union ovsdb_atom *value) + union ovsdb_atom *key, union ovsdb_atom *value, + struct ovsdb_symbol_table *symtab) { const char *start = *s; char *error; - error = parse_atom_token(s, &type->key, key); + error = parse_atom_token(s, &type->key, key, symtab); if (!error && type->value.type != OVSDB_TYPE_VOID) { *s = skip_spaces(*s); if (**s == '=') { (*s)++; *s = skip_spaces(*s); - error = parse_atom_token(s, &type->value, value); + error = parse_atom_token(s, &type->value, value, symtab); } else { error = xasprintf("%s: syntax error at \"%c\" expecting \"=\"", start, **s); @@ -1086,10 +1088,14 @@ free_key_value(const struct ovsdb_type *type, * or, for a map, '='-delimited pairs of atoms. Each atom must in a format * acceptable to ovsdb_atom_from_string(). Optionally, a set may be enclosed * in "[]" or a map in "{}"; for an empty set or map these punctuators are - * required. */ + * required. + * + * Optionally, a symbol table may be supplied as 'symtab'. It is passed to + * ovsdb_atom_to_string(). */ char * ovsdb_datum_from_string(struct ovsdb_datum *datum, - const struct ovsdb_type *type, const char *s) + const struct ovsdb_type *type, const char *s, + struct ovsdb_symbol_table *symtab) { bool is_map = ovsdb_type_is_map(type); struct ovsdb_error *dberror; @@ -1124,7 +1130,7 @@ ovsdb_datum_from_string(struct ovsdb_datum *datum, } /* Add to datum. */ - error = parse_key_value(&p, type, &key, &value); + error = parse_key_value(&p, type, &key, &value, symtab); if (error) { goto error; } @@ -1163,7 +1169,7 @@ ovsdb_datum_from_string(struct ovsdb_datum *datum, goto error; } - dberror = ovsdb_datum_sort(datum, type); + dberror = ovsdb_datum_sort(datum, type->key.type); if (dberror) { ovsdb_error_destroy(dberror); if (ovsdb_type_is_map(type)) { @@ -1459,7 +1465,7 @@ ovsdb_datum_union(struct ovsdb_datum *a, const struct ovsdb_datum *b, if (n != a->n) { struct ovsdb_error *error; a->n = n; - error = ovsdb_datum_sort(a, type); + error = ovsdb_datum_sort(a, type->key.type); assert(!error); } } @@ -1487,8 +1493,7 @@ ovsdb_datum_subtract(struct ovsdb_datum *a, const struct ovsdb_type *a_type, } } if (changed) { - struct ovsdb_error *error = ovsdb_datum_sort(a, a_type); - assert(!error); + ovsdb_datum_sort_assert(a, a_type->key.type); } } @@ -1527,7 +1532,7 @@ ovsdb_symbol_table_get(const struct ovsdb_symbol_table *symtab, return shash_find_data(&symtab->sh, name); } -void +struct ovsdb_symbol * ovsdb_symbol_table_put(struct ovsdb_symbol_table *symtab, const char *name, const struct uuid *uuid, bool used) { @@ -1538,6 +1543,38 @@ ovsdb_symbol_table_put(struct ovsdb_symbol_table *symtab, const char *name, symbol->uuid = *uuid; symbol->used = used; shash_add(&symtab->sh, name, symbol); + return symbol; +} + +struct ovsdb_symbol * +ovsdb_symbol_table_insert(struct ovsdb_symbol_table *symtab, + const char *name) +{ + struct ovsdb_symbol *symbol; + + symbol = ovsdb_symbol_table_get(symtab, name); + if (!symbol) { + struct uuid uuid; + + uuid_generate(&uuid); + symbol = ovsdb_symbol_table_put(symtab, name, &uuid, false); + } + return symbol; +} + +const char * +ovsdb_symbol_table_find_unused(const struct ovsdb_symbol_table *symtab) +{ + struct shash_node *node; + + SHASH_FOR_EACH (node, &symtab->sh) { + struct ovsdb_symbol *symbol = node->data; + if (!symbol->used) { + return node->name; + } + } + + return NULL; } /* Extracts a token from the beginning of 's' and returns a pointer just after