From a13e21b713f5b4bbf363a35d72e47620c1bd3ef0 Mon Sep 17 00:00:00 2001 From: Ilya Maximets Date: Tue, 17 Dec 2024 23:53:43 +0100 Subject: [PATCH] json: Use JSON maps instead of string hashes for objects. Use of shash requires copying of the keys every time a new JSON object is constructed. We're spending a lot of CPU and memory resources on copying column names into objects for every database row, we copy all the sets between database datum and JSON objects, and we copy all the keys in maps. Let's use jsmap instead of an shash as a base data structure for JSON objects. That will allow sharing keys between the ovsdb_datum and JSON objects using reference counting, because keys will be now JSON structures (JSON_STRING) instead of plain byte arrays. This commit, however, is only a ground work replacing the base data structure and updating all the users. No functional changes are done here. If anything, it can make performance a little worse until the optimizations are done in the next commits. Signed-off-by: Ilya Maximets --- include/openvswitch/json.h | 8 ++- lib/json.c | 130 +++++++++++++++++-------------------- lib/jsonrpc.c | 21 +++--- lib/ovsdb-cs.c | 87 +++++++++++++------------ lib/ovsdb-cs.h | 2 +- lib/ovsdb-idl.c | 51 ++++++++------- lib/ovsdb-parser.c | 19 +++--- lib/smap.c | 8 +-- ovsdb/file.c | 34 +++++----- ovsdb/jsonrpc-server.c | 27 ++++---- ovsdb/ovsdb-client.c | 67 ++++++++++--------- ovsdb/ovsdb-server.c | 53 +++++++-------- ovsdb/ovsdb-tool.c | 61 +++++++++-------- ovsdb/ovsdb.c | 23 ++++--- ovsdb/raft-private.c | 13 ++-- ovsdb/raft.c | 6 +- ovsdb/relay.c | 13 +--- ovsdb/replication.c | 22 ++++--- ovsdb/row.c | 11 ++-- ovsdb/table.c | 21 +++--- ovsdb/table.h | 5 +- tests/test-json.c | 13 ++-- tests/test-ovsdb.c | 13 ++-- 23 files changed, 358 insertions(+), 350 deletions(-) diff --git a/include/openvswitch/json.h b/include/openvswitch/json.h index fbdb3523362..5f9b833d65d 100644 --- a/include/openvswitch/json.h +++ b/include/openvswitch/json.h @@ -31,7 +31,6 @@ */ #include -#include "openvswitch/shash.h" #include "openvswitch/util.h" #ifdef __cplusplus @@ -40,6 +39,7 @@ extern "C" { struct ds; struct uuid; +struct jsmap; /* Type of a JSON value. */ enum json_type { @@ -88,7 +88,7 @@ struct json { enum json_storage_type storage_type; size_t count; union { - struct shash *object; /* Contains "struct json *"s. */ + struct jsmap *object; /* Contains "struct json *"s. */ union { struct json *elements[JSON_ARRAY_INLINE_LEN]; struct json_array array; @@ -129,12 +129,14 @@ void json_object_put_string(struct json *, void json_object_put_format(struct json *, const char *name, const char *format, ...) OVS_PRINTF_FORMAT(3, 4); +struct json *json_object_find(const struct json *json, const char *); +struct json *json_object_find_and_delete(struct json *json, const char *); const char *json_string(const struct json *); const char *json_serialized_object(const struct json *); size_t json_array_size(const struct json *); const struct json *json_array_at(const struct json *, size_t index); -struct shash *json_object(const struct json *); +struct jsmap *json_object(const struct json *); bool json_boolean(const struct json *); double json_real(const struct json *); int64_t json_integer(const struct json *); diff --git a/lib/json.c b/lib/json.c index bbf3055cb37..76cdc7b4d35 100644 --- a/lib/json.c +++ b/lib/json.c @@ -25,10 +25,10 @@ #include #include "cooperative-multitasking.h" -#include "openvswitch/dynamic-string.h" #include "hash.h" #include "json.h" -#include "openvswitch/shash.h" +#include "openvswitch/dynamic-string.h" +#include "openvswitch/jsmap.h" #include "unicode.h" #include "util.h" #include "uuid.h" @@ -390,7 +390,7 @@ json_object_create(void) { struct json *json = json_create(JSON_OBJECT); json->object = xmalloc(sizeof *json->object); - shash_init(json->object); + jsmap_init(json->object); return json; } @@ -413,13 +413,21 @@ json_real_create(double real) void json_object_put(struct json *json, const char *name, struct json *value) { - json_destroy(shash_replace(json->object, name, value)); + struct json *key = json_string_create(name); + + jsmap_replace(json->object, key, value, false); + json_destroy(key); + json_destroy(value); } void json_object_put_nocopy(struct json *json, char *name, struct json *value) { - json_destroy(shash_replace_nocopy(json->object, name, value)); + struct json *key = json_string_create_nocopy(name); + + jsmap_replace(json->object, key, value, false); + json_destroy(key); + json_destroy(value); } void @@ -439,6 +447,26 @@ json_object_put_format(struct json *json, va_end(args); } +struct json * +json_object_find(const struct json *json, const char *name) +{ + struct json *key = json_string_create(name); + struct jsmap_node *node = jsmap_get_node(json->object, key); + + json_destroy(key); + return node ? node->value : NULL; +} + +struct json * +json_object_find_and_delete(struct json *json, const char *name) +{ + struct json *key = json_string_create(name); + struct json *value = jsmap_find_and_delete(json->object, key); + + json_destroy(key); + return value; +} + const char * json_string(const struct json *json) { @@ -483,11 +511,11 @@ json_array_at(const struct json *json, size_t index) return json->elements[index]; } -struct shash * +struct jsmap * json_object(const struct json *json) { ovs_assert(json->type == JSON_OBJECT); - return CONST_CAST(struct shash *, json->object); + return CONST_CAST(struct jsmap *, json->object); } bool @@ -511,7 +539,7 @@ json_integer(const struct json *json) return json->integer; } -static void json_destroy_object(struct shash *object, bool yield); +static void json_destroy_object(struct jsmap *object, bool yield); static void json_destroy_array(struct json *json, bool yield); /* Frees 'json' and everything it points to, recursively. */ @@ -551,25 +579,12 @@ json_destroy__(struct json *json, bool yield) } static void -json_destroy_object(struct shash *object, bool yield) +json_destroy_object(struct jsmap *object, bool yield) { - struct shash_node *node; - if (yield) { cooperative_multitasking_yield(); } - - SHASH_FOR_EACH_SAFE (node, object) { - struct json *value = node->data; - - if (yield) { - json_destroy_with_yield(value); - } else { - json_destroy(value); - } - shash_delete(object, node); - } - shash_destroy(object); + jsmap_destroy(object, yield); free(object); } @@ -595,7 +610,7 @@ json_destroy_array(struct json *json, bool yield) } } -static struct json *json_deep_clone_object(const struct shash *object); +static struct json *json_deep_clone_object(const struct jsmap *object); static struct json *json_deep_clone_array(const struct json *); /* Returns a deep copy of 'json'. */ @@ -639,16 +654,11 @@ json_nullable_clone(const struct json *json) } static struct json * -json_deep_clone_object(const struct shash *object) +json_deep_clone_object(const struct jsmap *object) { - struct shash_node *node; - struct json *json; + struct json *json = json_object_create(); - json = json_object_create(); - SHASH_FOR_EACH (node, object) { - struct json *value = node->data; - json_object_put(json, node->name, json_deep_clone(value)); - } + jsmap_clone(json->object, object, true); return json; } @@ -683,17 +693,18 @@ json_deep_clone_array(const struct json *json) } static size_t -json_hash_object(const struct shash *object, size_t basis) +json_hash_object(const struct jsmap *object, size_t basis) { - const struct shash_node **nodes; + const struct jsmap_node **nodes; size_t n, i; - nodes = shash_sort(object); - n = shash_count(object); + nodes = jsmap_sort(object); + n = jsmap_count(object); for (i = 0; i < n; i++) { - const struct shash_node *node = nodes[i]; - basis = hash_string(node->name, basis); - basis = json_hash(node->data, basis); + const struct jsmap_node *node = nodes[i]; + + basis = json_hash(node->key, basis); + basis = json_hash(node->value, basis); } free(nodes); return basis; @@ -744,25 +755,6 @@ json_hash(const struct json *json, size_t basis) } } -static bool -json_equal_object(const struct shash *a, const struct shash *b) -{ - struct shash_node *a_node; - - if (shash_count(a) != shash_count(b)) { - return false; - } - - SHASH_FOR_EACH (a_node, a) { - struct shash_node *b_node = shash_find(b, a_node->name); - if (!b_node || !json_equal(a_node->data, b_node->data)) { - return false; - } - } - - return true; -} - static bool json_equal_array(const struct json *a, const struct json *b) { @@ -794,7 +786,7 @@ json_equal(const struct json *a, const struct json *b) switch (a->type) { case JSON_OBJECT: - return json_equal_object(a->object, b->object); + return jsmap_equal(a->object, b->object); case JSON_ARRAY: return json_equal_array(a, b); @@ -1718,7 +1710,7 @@ struct json_serializer { }; static void json_serialize(const struct json *, struct json_serializer *); -static void json_serialize_object(const struct shash *object, +static void json_serialize_object(const struct jsmap *object, struct json_serializer *); static void json_serialize_array(const struct json *, struct json_serializer *); @@ -1818,7 +1810,7 @@ indent_line(struct json_serializer *s) } static void -json_serialize_object_member(size_t i, const struct shash_node *node, +json_serialize_object_member(size_t i, const struct jsmap_node *node, struct json_serializer *s) { struct ds *ds = s->ds; @@ -1828,16 +1820,16 @@ json_serialize_object_member(size_t i, const struct shash_node *node, indent_line(s); } - json_serialize_string(node->name, ds); + json_serialize(node->key, s); ds_put_char(ds, ':'); if (s->flags & JSSF_PRETTY) { ds_put_char(ds, ' '); } - json_serialize(node->data, s); + json_serialize(node->value, s); } static void -json_serialize_object(const struct shash *object, struct json_serializer *s) +json_serialize_object(const struct jsmap *object, struct json_serializer *s) { struct ds *ds = s->ds; @@ -1851,21 +1843,21 @@ json_serialize_object(const struct shash *object, struct json_serializer *s) } if (s->flags & JSSF_SORT) { - const struct shash_node **nodes; + const struct jsmap_node **nodes; size_t n, i; - nodes = shash_sort(object); - n = shash_count(object); + nodes = jsmap_sort(object); + n = jsmap_count(object); for (i = 0; i < n; i++) { json_serialize_object_member(i, nodes[i], s); } free(nodes); } else { - struct shash_node *node; + struct jsmap_node *node; size_t i; i = 0; - SHASH_FOR_EACH (node, object) { + JSMAP_FOR_EACH (node, object) { json_serialize_object_member(i++, node, s); } } diff --git a/lib/jsonrpc.c b/lib/jsonrpc.c index d5fa7b45b13..fe275add669 100644 --- a/lib/jsonrpc.c +++ b/lib/jsonrpc.c @@ -23,6 +23,7 @@ #include "byteq.h" #include "openvswitch/dynamic-string.h" #include "fatal-signal.h" +#include "openvswitch/jsmap.h" #include "openvswitch/json.h" #include "openvswitch/list.h" #include "openvswitch/ofpbuf.h" @@ -713,16 +714,14 @@ jsonrpc_msg_from_json(struct json *json, struct jsonrpc_msg **msgp) { struct json *method = NULL; struct jsonrpc_msg *msg = NULL; - struct shash *object; char *error; if (json->type != JSON_OBJECT) { error = xstrdup("message is not a JSON object"); goto exit; } - object = json_object(json); - method = shash_find_and_delete(object, "method"); + method = json_object_find_and_delete(json, "method"); if (method && method->type != JSON_STRING) { error = xstrdup("method is not a JSON string"); goto exit; @@ -730,17 +729,21 @@ jsonrpc_msg_from_json(struct json *json, struct jsonrpc_msg **msgp) msg = xzalloc(sizeof *msg); msg->method = method ? xstrdup(json_string(method)) : NULL; - msg->params = null_from_json_null(shash_find_and_delete(object, "params")); - msg->result = null_from_json_null(shash_find_and_delete(object, "result")); - msg->error = null_from_json_null(shash_find_and_delete(object, "error")); - msg->id = null_from_json_null(shash_find_and_delete(object, "id")); + msg->params = null_from_json_null( + json_object_find_and_delete(json, "params")); + msg->result = null_from_json_null( + json_object_find_and_delete(json, "result")); + msg->error = null_from_json_null( + json_object_find_and_delete(json, "error")); + msg->id = null_from_json_null( + json_object_find_and_delete(json, "id")); msg->type = (msg->result ? JSONRPC_REPLY : msg->error ? JSONRPC_ERROR : msg->id ? JSONRPC_REQUEST : JSONRPC_NOTIFY); - if (!shash_is_empty(object)) { + if (!jsmap_is_empty(json_object(json))) { error = xasprintf("message has unexpected member \"%s\"", - shash_first(object)->name); + json_string(jsmap_first(json_object(json))->key)); goto exit; } error = jsonrpc_msg_is_valid(msg); diff --git a/lib/ovsdb-cs.c b/lib/ovsdb-cs.c index facad3793b8..57a06fa686c 100644 --- a/lib/ovsdb-cs.c +++ b/lib/ovsdb-cs.c @@ -24,6 +24,7 @@ #include "jsonrpc.h" #include "openvswitch/dynamic-string.h" #include "openvswitch/hmap.h" +#include "openvswitch/jsmap.h" #include "openvswitch/json.h" #include "openvswitch/poll-loop.h" #include "openvswitch/shash.h" @@ -1370,7 +1371,7 @@ ovsdb_cs_db_parse_lock_reply(struct ovsdb_cs_db *db, if (result->type == JSON_OBJECT) { const struct json *locked; - locked = shash_find_data(json_object(result), "locked"); + locked = json_object_find(result, "locked"); got_lock = locked && locked->type == JSON_TRUE; } else { got_lock = false; @@ -1516,8 +1517,8 @@ ovsdb_cs_send_monitor_request(struct ovsdb_cs *cs, struct ovsdb_cs_db *db, struct ovsdb_cs_db_table *table; HMAP_FOR_EACH (table, hmap_node, &db->tables) { if (table->ack_cond) { - struct json *mr = shash_find_data(json_object(mrs), - table->name); + struct json *mr = json_object_find(mrs, table->name); + if (!mr) { mr = json_array_create_empty(); json_object_put(mrs, table->name, mr); @@ -1782,15 +1783,14 @@ ovsdb_cs_insert_server_row(struct ovsdb_cs *cs, const struct uuid *uuid) static void ovsdb_cs_update_server_row(struct server_row *row, - const struct shash *update, bool xor) + const struct json *update, bool xor) { for (size_t i = 0; i < N_SERVER_COLUMNS; i++) { const struct server_column *column = &server_columns[i]; - struct shash_node *node = shash_find(update, column->name); - if (!node) { + const struct json *json = json_object_find(update, column->name); + if (!json) { continue; } - const struct json *json = node->data; struct ovsdb_datum *old = &row->data[i]; struct ovsdb_datum new; @@ -2115,7 +2115,7 @@ ovsdb_cs_parse_schema(const struct json *schema_json) struct ovsdb_parser parser; const struct json *tables_json; struct ovsdb_error *error; - struct shash_node *node; + struct jsmap_node *node; struct shash *schema; ovsdb_parser_init(&parser, schema_json, "database schema"); @@ -2128,9 +2128,9 @@ ovsdb_cs_parse_schema(const struct json *schema_json) schema = xmalloc(sizeof *schema); shash_init(schema); - SHASH_FOR_EACH (node, json_object(tables_json)) { - const char *table_name = node->name; - const struct json *json = node->data; + JSMAP_FOR_EACH (node, json_object(tables_json)) { + const char *table_name = json_string(node->key); + const struct json *json = node->value; const struct json *columns_json; ovsdb_parser_init(&parser, json, "table schema for table %s", @@ -2146,9 +2146,9 @@ ovsdb_cs_parse_schema(const struct json *schema_json) struct sset *columns = xmalloc(sizeof *columns); sset_init(columns); - struct shash_node *node2; - SHASH_FOR_EACH (node2, json_object(columns_json)) { - const char *column_name = node2->name; + struct jsmap_node *node2; + JSMAP_FOR_EACH (node2, json_object(columns_json)) { + const char *column_name = json_string(node2->key); sset_add(columns, column_name); } shash_add(schema, table_name, columns); @@ -2181,8 +2181,8 @@ ovsdb_cs_parse_row_update1(const struct json *in, { const struct json *old_json, *new_json; - old_json = shash_find_data(json_object(in), "old"); - new_json = shash_find_data(json_object(in), "new"); + old_json = json_object_find(in, "old"); + new_json = json_object_find(in, "new"); if (old_json && old_json->type != JSON_OBJECT) { return ovsdb_syntax_error(old_json, NULL, "\"old\" is not object"); @@ -2190,7 +2190,7 @@ ovsdb_cs_parse_row_update1(const struct json *in, return ovsdb_syntax_error(new_json, NULL, "\"new\" is not object"); } else if ((old_json != NULL) + (new_json != NULL) - != shash_count(json_object(in))) { + != jsmap_count(json_object(in))) { return ovsdb_syntax_error(in, NULL, " contains " "unexpected member"); @@ -2202,13 +2202,13 @@ ovsdb_cs_parse_row_update1(const struct json *in, if (!new_json) { out->type = OVSDB_CS_ROW_DELETE; - out->columns = json_object(old_json); + out->columns = old_json; } else if (!old_json) { out->type = OVSDB_CS_ROW_INSERT; - out->columns = json_object(new_json); + out->columns = new_json; } else { out->type = OVSDB_CS_ROW_UPDATE; - out->columns = json_object(new_json); + out->columns = new_json; } return NULL; } @@ -2217,20 +2217,22 @@ static struct ovsdb_error * OVS_WARN_UNUSED_RESULT ovsdb_cs_parse_row_update2(const struct json *in, struct ovsdb_cs_row_update *out) { - const struct shash *object = json_object(in); - if (shash_count(object) != 1) { + const struct jsmap *object = json_object(in); + if (jsmap_count(object) != 1) { return ovsdb_syntax_error( in, NULL, " has %"PRIuSIZE" members " - "instead of expected 1", shash_count(object)); + "instead of expected 1", jsmap_count(object)); } - struct shash_node *node = shash_first(object); - const struct json *columns = node->data; - if (!strcmp(node->name, "insert") || !strcmp(node->name, "initial")) { + struct jsmap_node *node = jsmap_first(object); + const struct json *columns = node->value; + const char *op = json_string(node->key); + + if (!strcmp(op, "insert") || !strcmp(op, "initial")) { out->type = OVSDB_CS_ROW_INSERT; - } else if (!strcmp(node->name, "modify")) { + } else if (!strcmp(op, "modify")) { out->type = OVSDB_CS_ROW_XOR; - } else if (!strcmp(node->name, "delete")) { + } else if (!strcmp(op, "delete")) { out->type = OVSDB_CS_ROW_DELETE; if (columns->type != JSON_NULL) { return ovsdb_syntax_error( @@ -2241,16 +2243,16 @@ ovsdb_cs_parse_row_update2(const struct json *in, } else { return ovsdb_syntax_error(in, NULL, " has unknown member \"%s\"", - node->name); + op); } if (columns->type != JSON_OBJECT) { return ovsdb_syntax_error( in, NULL, " \"%s\" operation has unexpected value", - node->name); + op); } - out->columns = json_object(columns); + out->columns = columns; return NULL; } @@ -2286,13 +2288,14 @@ ovsdb_cs_parse_table_update(const char *table_name, in, NULL, " for table \"%s\" is not an object", suffix, table_name); } - struct shash *in_rows = json_object(in); + struct jsmap *in_rows = json_object(in); - out->row_updates = xmalloc(shash_count(in_rows) * sizeof *out->row_updates); + out->row_updates = xmalloc( + jsmap_count(in_rows) * sizeof *out->row_updates); - const struct shash_node *node; - SHASH_FOR_EACH (node, in_rows) { - const char *row_uuid_string = node->name; + const struct jsmap_node *node; + JSMAP_FOR_EACH (node, in_rows) { + const char *row_uuid_string = json_string(node->key); struct uuid row_uuid; if (!uuid_from_string(&row_uuid, row_uuid_string)) { return ovsdb_syntax_error( @@ -2302,7 +2305,7 @@ ovsdb_cs_parse_table_update(const char *table_name, suffix, table_name, row_uuid_string); } - const struct json *in_ru = node->data; + const struct json *in_ru = node->value; struct ovsdb_cs_row_update *out_ru = &out->row_updates[out->n++]; *out_ru = (struct ovsdb_cs_row_update) { .row_uuid = row_uuid }; @@ -2338,12 +2341,12 @@ ovsdb_cs_parse_db_update(const struct json *in, int version, } struct ovsdb_cs_db_update *out = xzalloc(sizeof *out); - out->table_updates = xmalloc(shash_count(json_object(in)) + out->table_updates = xmalloc(jsmap_count(json_object(in)) * sizeof *out->table_updates); - const struct shash_node *node; - SHASH_FOR_EACH (node, json_object(in)) { - const char *table_name = node->name; - const struct json *in_tu = node->data; + const struct jsmap_node *node; + JSMAP_FOR_EACH (node, json_object(in)) { + const char *table_name = json_string(node->key); + const struct json *in_tu = node->value; struct ovsdb_cs_table_update *out_tu = &out->table_updates[out->n++]; *out_tu = (struct ovsdb_cs_table_update) { .table_name = table_name }; diff --git a/lib/ovsdb-cs.h b/lib/ovsdb-cs.h index bcc3dcd7167..ba25d39e830 100644 --- a/lib/ovsdb-cs.h +++ b/lib/ovsdb-cs.h @@ -181,7 +181,7 @@ enum ovsdb_cs_row_update_type { struct ovsdb_cs_row_update { struct uuid row_uuid; /* Row's _uuid. */ enum ovsdb_cs_row_update_type type; /* Type of change. */ - const struct shash *columns; /* Map from column name to json data. */ + const struct json *columns; /* Map (object) from column name to data. */ }; /* Partially parsed or . */ diff --git a/lib/ovsdb-idl.c b/lib/ovsdb-idl.c index 7c4ad2581c2..2007b8444c0 100644 --- a/lib/ovsdb-idl.c +++ b/lib/ovsdb-idl.c @@ -39,6 +39,7 @@ #include "ovsdb-parser.h" #include "ovsdb-server-idl.h" #include "ovsdb-session.h" +#include "openvswitch/jsmap.h" #include "openvswitch/poll-loop.h" #include "openvswitch/shash.h" #include "skiplist.h" @@ -145,10 +146,10 @@ static void ovsdb_idl_clear(struct ovsdb_idl *); static enum update_result ovsdb_idl_process_update( struct ovsdb_idl_table *, const struct ovsdb_cs_row_update *); static void ovsdb_idl_insert_row(struct ovsdb_idl_row *, - const struct shash *values); + const struct json *values); static void ovsdb_idl_delete_row(struct ovsdb_idl_row *); static bool ovsdb_idl_modify_row(struct ovsdb_idl_row *, - const struct shash *values, bool xor); + const struct json *values, bool xor); static void ovsdb_idl_parse_update(struct ovsdb_idl *, const struct ovsdb_cs_update_event *); static void ovsdb_idl_reparse_deleted(struct ovsdb_idl *); @@ -1699,16 +1700,16 @@ add_tracked_change_for_references(struct ovsdb_idl_row *row) * Caller needs to provide either valid 'row_json' or 'diff', but not * both. */ static bool -ovsdb_idl_row_change(struct ovsdb_idl_row *row, const struct shash *values, +ovsdb_idl_row_change(struct ovsdb_idl_row *row, const struct json *values, bool xor, enum ovsdb_idl_change change) { struct ovsdb_idl_table *table = row->table; const struct ovsdb_idl_table_class *class = table->class_; - struct shash_node *node; + struct jsmap_node *node; bool changed = false; - SHASH_FOR_EACH (node, values) { - const char *column_name = node->name; + JSMAP_FOR_EACH (node, json_object(values)) { + const char *column_name = json_string(node->key); const struct ovsdb_idl_column *column; struct ovsdb_error *error; unsigned int column_idx; @@ -1729,7 +1730,7 @@ ovsdb_idl_row_change(struct ovsdb_idl_row *row, const struct shash *values, struct ovsdb_datum diff; error = ovsdb_transient_datum_from_json(&diff, &column->type, - node->data); + node->value); if (!error) { error = ovsdb_datum_apply_diff_in_place(old, &diff, &column->type); @@ -1739,7 +1740,7 @@ ovsdb_idl_row_change(struct ovsdb_idl_row *row, const struct shash *values, } else { struct ovsdb_datum datum; - error = ovsdb_datum_from_json(&datum, &column->type, node->data, + error = ovsdb_datum_from_json(&datum, &column->type, node->value, NULL); if (!error) { if (!ovsdb_datum_equals(old, &datum, &column->type)) { @@ -2412,7 +2413,7 @@ ovsdb_idl_row_destroy_postprocess(struct ovsdb_idl *idl) } static void -ovsdb_idl_insert_row(struct ovsdb_idl_row *row, const struct shash *data) +ovsdb_idl_insert_row(struct ovsdb_idl_row *row, const struct json *data) { const struct ovsdb_idl_table_class *class = row->table->class_; size_t i, datum_size; @@ -2448,7 +2449,7 @@ ovsdb_idl_delete_row(struct ovsdb_idl_row *row) /* Returns true if a column with mode OVSDB_IDL_MODE_RW changed, false * otherwise. */ static bool -ovsdb_idl_modify_row(struct ovsdb_idl_row *row, const struct shash *values, +ovsdb_idl_modify_row(struct ovsdb_idl_row *row, const struct json *values, bool xor) { ovsdb_idl_remove_from_indexes(row); @@ -2890,10 +2891,10 @@ substitute_uuids(struct json *json, const struct ovsdb_idl_txn *txn) CONST_CAST(struct json *, json_array_at(json, i)), txn)); } } else if (json->type == JSON_OBJECT) { - struct shash_node *node; + struct jsmap_node *node; - SHASH_FOR_EACH (node, json_object(json)) { - node->data = substitute_uuids(node->data, txn); + JSMAP_FOR_EACH (node, json_object(json)) { + node->value = substitute_uuids(node->value, txn); } } return json; @@ -3359,7 +3360,7 @@ ovsdb_idl_txn_commit(struct ovsdb_idl_txn *txn) } } - if (!row->old_datum || !shash_is_empty(json_object(row_json))) { + if (!row->old_datum || !jsmap_is_empty(json_object(row_json))) { json_array_add(operations, op); } else { json_destroy(op); @@ -3910,7 +3911,7 @@ ovsdb_idl_txn_process_inc_reply(struct ovsdb_idl_txn *txn, const struct json *results) { const struct json *count, *rows, *row, *column; - struct shash *mutate, *select; + const struct json *mutate, *select; if (txn->inc_index + 2 > json_array_size(results)) { VLOG_WARN_RL(&syntax_rl, "reply does not contain enough operations " @@ -3921,8 +3922,8 @@ ovsdb_idl_txn_process_inc_reply(struct ovsdb_idl_txn *txn, /* We know that this is a JSON object because the loop in * ovsdb_idl_txn_process_reply() checked. */ - mutate = json_object(json_array_at(results, txn->inc_index)); - count = shash_find_data(mutate, "count"); + mutate = json_array_at(results, txn->inc_index); + count = json_object_find(mutate, "count"); if (!check_json_type(count, JSON_INTEGER, "\"mutate\" reply \"count\"")) { return false; } @@ -3933,8 +3934,8 @@ ovsdb_idl_txn_process_inc_reply(struct ovsdb_idl_txn *txn, return false; } - select = json_object(json_array_at(results, txn->inc_index + 1)); - rows = shash_find_data(select, "rows"); + select = json_array_at(results, txn->inc_index + 1); + rows = json_object_find(select, "rows"); if (!check_json_type(rows, JSON_ARRAY, "\"select\" reply \"rows\"")) { return false; } @@ -3948,7 +3949,7 @@ ovsdb_idl_txn_process_inc_reply(struct ovsdb_idl_txn *txn, if (!check_json_type(row, JSON_OBJECT, "\"select\" reply row")) { return false; } - column = shash_find_data(json_object(row), txn->inc_column); + column = json_object_find(row, txn->inc_column); if (!check_json_type(column, JSON_INTEGER, "\"select\" reply inc column")) { return false; @@ -3963,9 +3964,9 @@ ovsdb_idl_txn_process_insert_reply(struct ovsdb_idl_txn_insert *insert, { static const struct ovsdb_base_type uuid_type = OVSDB_BASE_UUID_INIT; struct ovsdb_error *error; + const struct json *reply; struct json *json_uuid; union ovsdb_atom uuid; - struct shash *reply; if (insert->op_index >= json_array_size(results)) { VLOG_WARN_RL(&syntax_rl, "reply does not contain enough operations " @@ -3976,8 +3977,8 @@ ovsdb_idl_txn_process_insert_reply(struct ovsdb_idl_txn_insert *insert, /* We know that this is a JSON object because the loop in * ovsdb_idl_txn_process_reply() checked. */ - reply = json_object(json_array_at(results, insert->op_index)); - json_uuid = shash_find_data(reply, "uuid"); + reply = json_array_at(results, insert->op_index); + json_uuid = json_object_find(reply, "uuid"); if (!check_json_type(json_uuid, JSON_ARRAY, "\"insert\" reply \"uuid\"")) { return false; } @@ -4038,9 +4039,9 @@ ovsdb_idl_txn_process_reply(struct ovsdb_idl *idl, * operation failed, so make sure that we know about it. */ soft_errors++; } else if (op->type == JSON_OBJECT) { - struct json *error; + const struct json *error; - error = shash_find_data(json_object(op), "error"); + error = json_object_find(op, "error"); if (error) { if (error->type == JSON_STRING) { const char *error_string = json_string(error); diff --git a/lib/ovsdb-parser.c b/lib/ovsdb-parser.c index 07a6707811b..ac800b22b85 100644 --- a/lib/ovsdb-parser.c +++ b/lib/ovsdb-parser.c @@ -20,6 +20,7 @@ #include #include +#include "openvswitch/jsmap.h" #include "ovsdb-error.h" void @@ -71,7 +72,7 @@ ovsdb_parser_member(struct ovsdb_parser *parser, const char *name, return NULL; } - value = shash_find_data(json_object(parser->json), name); + value = json_object_find(parser->json, name); if (!value) { if (!(types & OP_OPTIONAL)) { ovsdb_parser_raise_error(parser, @@ -151,26 +152,28 @@ struct ovsdb_error * ovsdb_parser_finish(struct ovsdb_parser *parser) { if (!parser->error) { - const struct shash *object = json_object(parser->json); + const struct jsmap *object = json_object(parser->json); size_t n_unused; - n_unused = shash_count(object) - sset_count(&parser->used); + n_unused = jsmap_count(object) - sset_count(&parser->used); if (n_unused) { - struct shash_node *node; + struct jsmap_node *node; - SHASH_FOR_EACH (node, object) { - if (!sset_contains(&parser->used, node->name)) { + JSMAP_FOR_EACH (node, object) { + const char *name = json_string(node->key); + + if (!sset_contains(&parser->used, name)) { if (n_unused > 1) { ovsdb_parser_raise_error( parser, "Member '%s' and %"PRIuSIZE" other member%s " "are present but not allowed here.", - node->name, n_unused - 1, n_unused > 2 ? "s" : ""); + name, n_unused - 1, n_unused > 2 ? "s" : ""); } else { ovsdb_parser_raise_error( parser, "Member '%s' is present but not allowed here.", - node->name); + name); } break; } diff --git a/lib/smap.c b/lib/smap.c index 122adca2717..393f8701156 100644 --- a/lib/smap.c +++ b/lib/smap.c @@ -18,6 +18,7 @@ #include #include "hash.h" +#include "openvswitch/jsmap.h" #include "openvswitch/json.h" #include "packets.h" #include "util.h" @@ -354,11 +355,10 @@ smap_sort(const struct smap *smap) void smap_from_json(struct smap *smap, const struct json *json) { - const struct shash_node *node; + const struct jsmap_node *node; - SHASH_FOR_EACH (node, json_object(json)) { - const struct json *value = node->data; - smap_add(smap, node->name, json_string(value)); + JSMAP_FOR_EACH (node, json_object(json)) { + smap_add(smap, json_string(node->key), json_string(node->value)); } } diff --git a/ovsdb/file.c b/ovsdb/file.c index 66ef87a1f16..b0096fe2143 100644 --- a/ovsdb/file.c +++ b/ovsdb/file.c @@ -25,6 +25,7 @@ #include "column.h" #include "cooperative-multitasking.h" #include "log.h" +#include "openvswitch/jsmap.h" #include "openvswitch/json.h" #include "lockfile.h" #include "ovsdb.h" @@ -87,14 +88,14 @@ ovsdb_file_update_row_from_json(struct ovsdb_row *row, struct ovsdb_row *diff, { struct ovsdb_table_schema *schema = row->table->schema; struct ovsdb_error *error; - struct shash_node *node; + struct jsmap_node *node; if (json->type != JSON_OBJECT) { return ovsdb_syntax_error(json, NULL, "row must be JSON object"); } - SHASH_FOR_EACH (node, json_object(json)) { - const char *column_name = node->name; + JSMAP_FOR_EACH (node, json_object(json)) { + const char *column_name = json_string(node->key); const struct ovsdb_column *column; struct ovsdb_datum datum; @@ -111,10 +112,10 @@ ovsdb_file_update_row_from_json(struct ovsdb_row *row, struct ovsdb_row *diff, if (row_contains_diff) { /* Diff may violate the type size rules. */ error = ovsdb_transient_datum_from_json(&datum, &column->type, - node->data); + node->value); } else { error = ovsdb_datum_from_json(&datum, &column->type, - node->data, NULL); + node->value, NULL); } if (error) { return error; @@ -145,7 +146,8 @@ ovsdb_file_update_row_from_json(struct ovsdb_row *row, struct ovsdb_row *diff, static struct ovsdb_error * ovsdb_file_txn_row_from_json(struct ovsdb_txn *txn, struct ovsdb_table *table, bool converting, bool row_contains_diff, - const struct uuid *row_uuid, struct json *json) + const struct uuid *row_uuid, + const struct json *json) { const struct ovsdb_row *row = ovsdb_table_get_row(table, row_uuid); if (json->type == JSON_NULL) { @@ -185,17 +187,17 @@ ovsdb_file_txn_table_from_json(struct ovsdb_txn *txn, struct ovsdb_table *table, bool converting, bool row_contains_diff, - struct json *json) + const struct json *json) { - struct shash_node *node; + struct jsmap_node *node; if (json->type != JSON_OBJECT) { return ovsdb_syntax_error(json, NULL, "object expected"); } - SHASH_FOR_EACH (node, json->object) { - const char *uuid_string = node->name; - struct json *txn_row_json = node->data; + JSMAP_FOR_EACH (node, json_object(json)) { + const char *uuid_string = json_string(node->key); + const struct json *txn_row_json = node->value; struct ovsdb_error *error; struct uuid row_uuid; @@ -226,7 +228,7 @@ ovsdb_file_txn_from_json(struct ovsdb *db, const struct json *json, bool converting, struct ovsdb_txn **txnp) { struct ovsdb_error *error; - struct shash_node *node; + struct jsmap_node *node; struct ovsdb_txn *txn; *txnp = NULL; @@ -235,7 +237,7 @@ ovsdb_file_txn_from_json(struct ovsdb *db, const struct json *json, return ovsdb_syntax_error(json, NULL, "object expected"); } - struct json *is_diff = shash_find_data(json->object, "_is_diff"); + const struct json *is_diff = json_object_find(json, "_is_diff"); bool row_contains_diff = false; if (is_diff && is_diff->type == JSON_TRUE) { @@ -243,9 +245,9 @@ ovsdb_file_txn_from_json(struct ovsdb *db, const struct json *json, } txn = ovsdb_txn_create(db); - SHASH_FOR_EACH (node, json->object) { - const char *table_name = node->name; - struct json *node_json = node->data; + JSMAP_FOR_EACH (node, json_object(json)) { + const char *table_name = json_string(node->key); + const struct json *node_json = node->value; struct ovsdb_table *table; table = shash_find_data(&db->tables, table_name); diff --git a/ovsdb/jsonrpc-server.c b/ovsdb/jsonrpc-server.c index a47c2c76cea..f2d878baa2d 100644 --- a/ovsdb/jsonrpc-server.c +++ b/ovsdb/jsonrpc-server.c @@ -30,6 +30,7 @@ #include "ovsdb-parser.h" #include "ovsdb.h" #include "condition.h" +#include "openvswitch/jsmap.h" #include "openvswitch/poll-loop.h" #include "reconnect.h" #include "row.h" @@ -1501,7 +1502,7 @@ ovsdb_jsonrpc_monitor_create(struct ovsdb_jsonrpc_session *s, struct ovsdb *db, struct ovsdb_jsonrpc_monitor *m = NULL; struct ovsdb_monitor *dbmon = NULL; struct ovsdb_error *error = NULL; - struct shash_node *node; + struct jsmap_node *node; struct json *json; if ((version == OVSDB_MONITOR_V2 && json_array_size(params) != 3) || @@ -1533,22 +1534,23 @@ ovsdb_jsonrpc_monitor_create(struct ovsdb_jsonrpc_session *s, struct ovsdb *db, hmap_insert(&s->monitors, &m->node, json_hash(monitor_id, 0)); m->monitor_id = json_clone(monitor_id); - SHASH_FOR_EACH (node, json_object(monitor_requests)) { + JSMAP_FOR_EACH (node, json_object(monitor_requests)) { const struct ovsdb_table *table; const struct json *mr_value; size_t i, n; - table = ovsdb_get_table(m->db, node->name); + table = ovsdb_get_table(m->db, json_string(node->key)); if (!table) { error = ovsdb_syntax_error(NULL, NULL, - "no table named %s", node->name); + "no table named %s", + json_string(node->key)); goto error; } ovsdb_monitor_add_table(m->dbmon, table); /* Parse columns. */ - mr_value = node->data; + mr_value = node->value; if (mr_value->type == JSON_ARRAY) { n = json_array_size(mr_value); for (i = 0; i < n; i++) { @@ -1672,7 +1674,7 @@ ovsdb_jsonrpc_monitor_cond_change(struct ovsdb_jsonrpc_session *s, const struct json *monitor_cond_change_reqs; struct ovsdb_jsonrpc_monitor *m; struct ovsdb_error *error; - struct shash_node *node; + struct jsmap_node *node; if (json_array_size(params) != 3) { error = ovsdb_syntax_error(params, NULL, "invalid parameters"); @@ -1702,25 +1704,26 @@ ovsdb_jsonrpc_monitor_cond_change(struct ovsdb_jsonrpc_session *s, goto error; } - SHASH_FOR_EACH (node, json_object(monitor_cond_change_reqs)) { + JSMAP_FOR_EACH (node, json_object(monitor_cond_change_reqs)) { + const char *table_name = json_string(node->key); const struct ovsdb_table *table; const struct json *mr_value; size_t i, n; - table = ovsdb_get_table(m->db, node->name); + table = ovsdb_get_table(m->db, table_name); if (!table) { error = ovsdb_syntax_error(NULL, NULL, - "no table named %s", node->name); + "no table named %s", table_name); goto error; } if (!ovsdb_monitor_table_exists(m->dbmon, table)) { error = ovsdb_syntax_error(NULL, NULL, "no table named %s in monitor session", - node->name); + table_name); goto error; } - mr_value = node->data; + mr_value = node->value; if (mr_value->type == JSON_ARRAY) { n = json_array_size(mr_value); for (i = 0; i < n; i++) { @@ -1734,7 +1737,7 @@ ovsdb_jsonrpc_monitor_cond_change(struct ovsdb_jsonrpc_session *s, error = ovsdb_syntax_error( NULL, NULL, "table %s no monitor-cond-change JSON array", - node->name); + table_name); goto error; } } diff --git a/ovsdb/ovsdb-client.c b/ovsdb/ovsdb-client.c index 1639c426af0..d50bfd88cdc 100644 --- a/ovsdb/ovsdb-client.c +++ b/ovsdb/ovsdb-client.c @@ -34,6 +34,7 @@ #include "openvswitch/dynamic-string.h" #include "fatal-signal.h" #include "file.h" +#include "openvswitch/jsmap.h" #include "openvswitch/json.h" #include "jsonrpc.h" #include "lib/table.h" @@ -606,14 +607,14 @@ fetch_dbs(struct jsonrpc *rpc, struct svec *dbs) static const char * parse_string_column(const struct json *row, const char *column_name) { - const struct json *column = shash_find_data(json_object(row), column_name); + const struct json *column = json_object_find(row, column_name); return column && column->type == JSON_STRING ? json_string(column) : ""; } static int parse_boolean_column(const struct json *row, const char *column_name) { - const struct json *column = shash_find_data(json_object(row), column_name); + const struct json *column = json_object_find(row, column_name); return (!column ? -1 : column->type == JSON_TRUE ? true : column->type == JSON_FALSE ? false @@ -623,7 +624,7 @@ parse_boolean_column(const struct json *row, const char *column_name) static struct uuid parse_uuid_column(const struct json *row, const char *column_name) { - const struct json *column = shash_find_data(json_object(row), column_name); + const struct json *column = json_object_find(row, column_name); if (!column) { return UUID_ZERO; } @@ -672,7 +673,7 @@ parse_database_info_reply(const struct jsonrpc_msg *reply, const char *server, } const struct json *op_result = json_array_at(result, 0); - const struct json *rows = shash_find_data(json_object(op_result), "rows"); + const struct json *rows = json_object_find(op_result, "rows"); if (!rows || rows->type != JSON_ARRAY) { VLOG_WARN("%s: missing \"rows\" member in _Server reply for %s", server, database); @@ -927,7 +928,7 @@ do_query(struct jsonrpc *rpc OVS_UNUSED, const char *database OVS_UNUSED, && json_array_size(result) == abort_idx + 1 && json_array_at(result, abort_idx)->type == JSON_OBJECT) { const struct json *op_result = json_array_at(result, abort_idx); - struct json *error = shash_find_data(json_object(op_result), "error"); + struct json *error = json_object_find(op_result, "error"); if (error && error->type == JSON_STRING && !strcmp(json_string(error), "aborted")) { @@ -965,7 +966,7 @@ monitor_print_row(const struct json *row, const char *type, const char *uuid, table_add_cell(t)->text = xstrdup(type); for (i = 0; i < columns->n_columns; i++) { const struct ovsdb_column *column = columns->columns[i]; - struct json *value = shash_find_data(json_object(row), column->name); + struct json *value = json_object_find(row, column->name); struct cell *cell = table_add_cell(t); if (value) { cell->json = json_clone(value); @@ -981,7 +982,7 @@ monitor_print_table(struct json *table_update, { const struct ovsdb_table_schema *table = mt->table; const struct ovsdb_column_set *columns = &mt->columns; - struct shash_node *node; + struct jsmap_node *node; struct table t; size_t i; @@ -999,24 +1000,25 @@ monitor_print_table(struct json *table_update, for (i = 0; i < columns->n_columns; i++) { table_add_column(&t, "%s", columns->columns[i]->name); } - SHASH_FOR_EACH (node, json_object(table_update)) { - struct json *row_update = node->data; + JSMAP_FOR_EACH (node, json_object(table_update)) { + const char *name = json_string(node->key); + struct json *row_update = node->value; struct json *old, *new; if (row_update->type != JSON_OBJECT) { ovs_error(0, " is not object"); continue; } - old = shash_find_data(json_object(row_update), "old"); - new = shash_find_data(json_object(row_update), "new"); + old = json_object_find(row_update, "old"); + new = json_object_find(row_update, "new"); if (initial) { - monitor_print_row(new, "initial", node->name, columns, &t); + monitor_print_row(new, "initial", name, columns, &t); } else if (!old) { - monitor_print_row(new, "insert", node->name, columns, &t); + monitor_print_row(new, "insert", name, columns, &t); } else if (!new) { - monitor_print_row(old, "delete", node->name, columns, &t); + monitor_print_row(old, "delete", name, columns, &t); } else { - monitor_print_row(old, "old", node->name, columns, &t); + monitor_print_row(old, "old", name, columns, &t); monitor_print_row(new, "new", "", columns, &t); } } @@ -1038,8 +1040,8 @@ monitor_print(const struct json *table_updates, for (i = 0; i < n_mts; i++) { const struct monitored_table *mt = &mts[i]; - struct json *table_update = shash_find_data(json_object(table_updates), - mt->table->name); + struct json *table_update = json_object_find(table_updates, + mt->table->name); if (table_update) { monitor_print_table(table_update, mt, n_mts > 1 ? xstrdup(mt->table->name) : NULL, @@ -1076,7 +1078,7 @@ monitor2_print_table(const struct json *table_update2, { const struct ovsdb_table_schema *table = mt->table; const struct ovsdb_column_set *columns = &mt->columns; - struct shash_node *node; + struct jsmap_node *node; struct table t; if (table_update2->type != JSON_OBJECT) { @@ -1093,8 +1095,8 @@ monitor2_print_table(const struct json *table_update2, for (size_t i = 0; i < columns->n_columns; i++) { table_add_column(&t, "%s", columns->columns[i]->name); } - SHASH_FOR_EACH (node, json_object(table_update2)) { - struct json *row_update2 = node->data; + JSMAP_FOR_EACH (node, json_object(table_update2)) { + struct json *row_update2 = node->value; const char *operation; struct json *row; const char *ops[] = {"delete", "initial", "modify", "insert"}; @@ -1107,10 +1109,11 @@ monitor2_print_table(const struct json *table_update2, /* row_update2 contains one of objects indexed by ops[] */ for (int i = 0; i < ARRAY_SIZE(ops); i++) { operation = ops[i]; - row = shash_find_data(json_object(row_update2), operation); + row = json_object_find(row_update2, operation); if (row) { - monitor2_print_row(row, operation, node->name, columns, &t); + monitor2_print_row(row, operation, json_string(node->key), + columns, &t); break; } } @@ -1132,9 +1135,8 @@ monitor2_print(const struct json *table_updates2, for (i = 0; i < n_mts; i++) { const struct monitored_table *mt = &mts[i]; - struct json *table_update = shash_find_data( - json_object(table_updates2), - mt->table->name); + struct json *table_update = json_object_find(table_updates2, + mt->table->name); if (table_update) { monitor2_print_table(table_update, mt, n_mts > 1 ? xstrdup(mt->table->name) : NULL); @@ -1790,17 +1792,15 @@ dump_table(const char *table_name, const struct shash *cols, data = xmalloc(n * sizeof *data); for (y = 0; y < n; y++) { const struct json *elem = json_array_at(rows, y); - struct shash *row; if (elem->type != JSON_OBJECT) { ovs_fatal(0, "row %"PRIuSIZE" in table %s response is not a JSON object: " "%s", y, table_name, json_to_string(elem, 0)); } - row = json_object(elem); data[y] = xmalloc(n_columns * sizeof **data); for (x = 0; x < n_columns; x++) { - const struct json *json = shash_find_data(row, columns[x]->name); + const struct json *json = json_object_find(elem, columns[x]->name); if (!json) { ovs_fatal(0, "row %"PRIuSIZE" in table %s response lacks %s column", y, table_name, columns[x]->name); @@ -1926,7 +1926,7 @@ do_dump(struct jsonrpc *rpc, const char *database, struct json *rows; if (op_result->type != JSON_OBJECT - || !(rows = shash_find_data(json_object(op_result), "rows")) + || !(rows = json_object_find(op_result, "rows")) || rows->type != JSON_ARRAY) { ovs_fatal(0, "%s table reply is not an object with a \"rows\" " "member array: %s", @@ -2045,7 +2045,7 @@ do_backup(struct jsonrpc *rpc, const char *database, struct json *rows; if (op_result->type != JSON_OBJECT - || !(rows = shash_find_data(json_object(op_result), "rows")) + || !(rows = json_object_find(op_result, "rows")) || rows->type != JSON_ARRAY) { ovs_fatal(0, "%s table reply is not an object with a \"rows\" " "member array: %s", @@ -2065,8 +2065,8 @@ do_backup(struct jsonrpc *rpc, const char *database, table_name, json_to_string(row, 0)); } - struct json *uuid_json = shash_find_and_delete(json_object(row), - "_uuid"); + struct json *uuid_json = json_object_find_and_delete( + CONST_CAST(struct json *, row), "_uuid"); if (!uuid_json) { ovs_fatal(0, "%s table reply row lacks _uuid member: %s", table_name, json_to_string(row, 0)); @@ -2103,8 +2103,7 @@ check_transaction_reply(struct jsonrpc_msg *reply) if (json->type != JSON_OBJECT) { ovs_fatal(0, "result array element is not object"); } - struct shash *object = json_object(json); - if (shash_find(object, "error")) { + if (json_object_find(json, "error")) { ovs_fatal(0, "server returned error reply: %s", json_to_string(json, JSSF_SORT)); } diff --git a/ovsdb/ovsdb-server.c b/ovsdb/ovsdb-server.c index 8d9249aad58..1f9f99a16fe 100644 --- a/ovsdb/ovsdb-server.c +++ b/ovsdb/ovsdb-server.c @@ -32,6 +32,7 @@ #include "fatal-signal.h" #include "file.h" #include "hash.h" +#include "openvswitch/jsmap.h" #include "openvswitch/json.h" #include "jsonrpc.h" #include "jsonrpc-server.h" @@ -2966,8 +2967,8 @@ static bool remotes_from_json(struct shash *remotes, const struct json *json) { struct ovsdb_jsonrpc_options *options; - const struct shash_node *node; - const struct shash *object; + const struct jsmap_node *node; + const struct json *json_opt; free_remotes(remotes); @@ -2980,17 +2981,16 @@ remotes_from_json(struct shash *remotes, const struct json *json) return false; } - object = json_object(json); - SHASH_FOR_EACH (node, object) { - options = ovsdb_jsonrpc_default_options(node->name); - shash_add(remotes, node->name, options); + JSMAP_FOR_EACH (node, json_object(json)) { + options = ovsdb_jsonrpc_default_options(json_string(node->key)); + shash_add(remotes, json_string(node->key), options); - json = node->data; - if (json->type == JSON_OBJECT) { - ovsdb_jsonrpc_options_update_from_json(options, node->data, false); - } else if (json->type != JSON_NULL) { + json_opt = node->value; + if (json_opt->type == JSON_OBJECT) { + ovsdb_jsonrpc_options_update_from_json(options, json_opt, false); + } else if (json_opt->type != JSON_NULL) { VLOG_WARN("%s: JSON-RPC options are not a JSON object or null", - node->name); + json_string(node->key)); free_remotes(remotes); return false; } @@ -3060,16 +3060,16 @@ db_config_from_json(const char *name, const struct json *json) } source = ovsdb_parser_member(&parser, "source", type); - if (source && shash_count(json_object(source)) != 1) { + if (source && jsmap_count(json_object(source)) != 1) { ovsdb_parser_raise_error(&parser, "'source' should be an object with exactly one element"); } else if (source) { - const struct shash_node *node = shash_first(json_object(source)); + const struct jsmap_node *node = jsmap_first(json_object(source)); const struct json *options; ovs_assert(node); - conf->source = xstrdup(node->name); - options = node->data; + conf->source = xstrdup(json_string(node->key)); + options = node->value; conf->options = get_jsonrpc_options(conf->source, conf->model); @@ -3100,8 +3100,7 @@ db_config_from_json(const char *name, const struct json *json) static bool databases_from_json(struct shash *db_conf, const struct json *json) { - const struct shash_node *node; - const struct shash *object; + const struct jsmap_node *node; free_database_configs(db_conf); @@ -3113,12 +3112,12 @@ databases_from_json(struct shash *db_conf, const struct json *json) VLOG_WARN("config: 'databases' is not a JSON object or null"); } - object = json_object(json); - SHASH_FOR_EACH (node, object) { - struct db_config *conf = db_config_from_json(node->name, node->data); + JSMAP_FOR_EACH (node, json_object(json)) { + const char *db_name = json_string(node->key); + struct db_config *conf = db_config_from_json(db_name, node->value); if (conf) { - shash_add(db_conf, node->name, conf); + shash_add(db_conf, db_name, conf); } else { free_database_configs(db_conf); return false; @@ -3154,14 +3153,12 @@ load_config(FILE *config_file, struct shash *remotes, return false; } - if (!remotes_from_json(remotes, - shash_find_data(json_object(json), "remotes"))) { + if (!remotes_from_json(remotes, json_object_find(json, "remotes"))) { VLOG_WARN("config: failed to parse 'remotes'"); json_destroy(json); return false; } - if (!databases_from_json(db_conf, shash_find_data(json_object(json), - "databases"))) { + if (!databases_from_json(db_conf, json_object_find(json, "databases"))) { VLOG_WARN("config: failed to parse 'databases'"); free_remotes(remotes); json_destroy(json); @@ -3169,15 +3166,15 @@ load_config(FILE *config_file, struct shash *remotes, } struct json *string; - string = shash_find_data(json_object(json), "sync_from"); + string = json_object_find(json, "sync_from"); free(*sync_from); *sync_from = string ? xstrdup(json_string(string)) : NULL; - string = shash_find_data(json_object(json), "sync_exclude"); + string = json_object_find(json, "sync_exclude"); free(*sync_exclude); *sync_exclude = string ? xstrdup(json_string(string)) : NULL; - struct json *boolean = shash_find_data(json_object(json), "is_backup"); + struct json *boolean = json_object_find(json, "is_backup"); *is_backup = boolean ? json_boolean(boolean) : false; json_destroy(json); diff --git a/ovsdb/ovsdb-tool.c b/ovsdb/ovsdb-tool.c index 368e7a5276e..009a1e85c12 100644 --- a/ovsdb/ovsdb-tool.c +++ b/ovsdb/ovsdb-tool.c @@ -33,6 +33,7 @@ #include "lockfile.h" #include "log.h" #include "openvswitch/hmap.h" +#include "openvswitch/jsmap.h" #include "openvswitch/json.h" #include "ovsdb.h" #include "ovsdb-data.h" @@ -663,21 +664,21 @@ do_transact(struct ovs_cmdl_context *ctx) } static void -print_db_changes(struct shash *tables, struct smap *names, +print_db_changes(const struct json *tables, struct smap *names, const struct ovsdb_schema *schema) { - struct json *is_diff = shash_find_data(tables, "_is_diff"); + const struct json *is_diff = json_object_find(tables, "_is_diff"); bool diff = (is_diff && is_diff->type == JSON_TRUE); - struct shash_node *n1; + struct jsmap_node *n1; int i = 0; - SHASH_FOR_EACH (n1, tables) { - const char *table = n1->name; + JSMAP_FOR_EACH (n1, json_object(tables)) { + const char *table = json_string(n1->key); struct ovsdb_table_schema *table_schema; - struct json *rows = n1->data; - struct shash_node *n2; + const struct json *rows = n1->value; + struct jsmap_node *n2; - if (n1->name[0] == '_' || rows->type != JSON_OBJECT) { + if (table[0] == '_' || rows->type != JSON_OBJECT) { continue; } @@ -686,17 +687,17 @@ print_db_changes(struct shash *tables, struct smap *names, } table_schema = schema ? shash_find_data(&schema->tables, table) : NULL; - SHASH_FOR_EACH (n2, json_object(rows)) { - const char *row_uuid = n2->name; - struct json *columns = n2->data; - struct shash_node *n3; + JSMAP_FOR_EACH (n2, json_object(rows)) { + const char *row_uuid = json_string(n2->key); + const struct json *columns = n2->value; + struct jsmap_node *n3; const char *old_name = smap_get(names, row_uuid); char *new_name = NULL; if (columns->type == JSON_OBJECT) { struct json *new_name_json; - new_name_json = shash_find_data(json_object(columns), "name"); + new_name_json = json_object_find(columns, "name"); if (new_name_json) { new_name = json_to_string(new_name_json, JSSF_SORT); } @@ -717,10 +718,10 @@ print_db_changes(struct shash *tables, struct smap *names, if (columns->type == JSON_OBJECT) { if (show_log_verbosity > 1) { - SHASH_FOR_EACH (n3, json_object(columns)) { - const char *column = n3->name; + JSMAP_FOR_EACH (n3, json_object(columns)) { + const char *column = json_string(n3->key); const struct ovsdb_column *column_schema; - struct json *value = n3->data; + const struct json *value = n3->value; char *value_string = NULL; column_schema = @@ -781,7 +782,7 @@ print_change_record(const struct json *json, const struct ovsdb_schema *schema, struct json *date, *comment; - date = shash_find_data(json_object(json), "_date"); + date = json_object_find(json, "_date"); if (date && date->type == JSON_INTEGER) { long long int t = json_integer(date); char *s; @@ -796,13 +797,13 @@ print_change_record(const struct json *json, const struct ovsdb_schema *schema, free(s); } - comment = shash_find_data(json_object(json), "_comment"); + comment = json_object_find(json, "_comment"); if (comment && comment->type == JSON_STRING) { printf(" \"%s\"", json_string(comment)); } if (show_log_verbosity > 0) { - print_db_changes(json_object(json), names, schema); + print_db_changes(json, names, schema); } } @@ -845,17 +846,17 @@ print_servers(const char *name, const struct json *servers) printf(" %s: ", name); - const struct shash_node **nodes = shash_sort(json_object(servers)); - size_t n = shash_count(json_object(servers)); + const struct jsmap_node **nodes = jsmap_sort(json_object(servers)); + size_t n = jsmap_count(json_object(servers)); for (size_t i = 0; i < n; i++) { if (i > 0) { printf(", "); } - const struct shash_node *node = nodes[i]; - printf("%.4s(", node->name); + const struct jsmap_node *node = nodes[i]; + printf("%.4s(", json_string(node->key)); - const struct json *address = node->data; + const struct json *address = node->value; char *s = json_to_string(address, JSSF_SORT); fputs(s, stdout); free(s); @@ -1566,13 +1567,12 @@ do_check_cluster(struct ovs_cmdl_context *ctx) */ for (struct server *s = c.servers; s < &c.servers[c.n_servers]; s++) { - struct shash *servers_obj = json_object(s->snap->servers); char *server_id = xasprintf(SID_FMT, SID_ARGS(&s->header.sid)); bool found = false; - const struct shash_node *node; + const struct jsmap_node *node; - SHASH_FOR_EACH (node, servers_obj) { - if (!strncmp(server_id, node->name, SID_LEN)) { + JSMAP_FOR_EACH (node, json_object(s->snap->servers)) { + if (!strncmp(server_id, json_string(node->key), SID_LEN)) { found = true; } } @@ -1583,9 +1583,8 @@ do_check_cluster(struct ovs_cmdl_context *ctx) if (e->servers == NULL) { continue; } - struct shash *log_servers_obj = json_object(e->servers); - SHASH_FOR_EACH (node, log_servers_obj) { - if (!strncmp(server_id, node->name, SID_LEN)) { + JSMAP_FOR_EACH (node, json_object(e->servers)) { + if (!strncmp(server_id, json_string(node->key), SID_LEN)) { found = true; } } diff --git a/ovsdb/ovsdb.c b/ovsdb/ovsdb.c index 298616a64d0..dd8722a4493 100644 --- a/ovsdb/ovsdb.c +++ b/ovsdb/ovsdb.c @@ -24,6 +24,7 @@ #include "column.h" #include "file.h" #include "monitor.h" +#include "openvswitch/jsmap.h" #include "openvswitch/json.h" #include "openvswitch/poll-loop.h" #include "ovs-thread.h" @@ -231,8 +232,9 @@ ovsdb_schema_from_json(const struct json *json, struct ovsdb_schema **schemap) { struct ovsdb_schema *schema; const struct json *name, *tables, *version_json, *cksum; + struct shash_node *schema_node; struct ovsdb_error *error; - struct shash_node *node; + struct jsmap_node *node; struct ovsdb_parser parser; const char *version; @@ -262,17 +264,18 @@ ovsdb_schema_from_json(const struct json *json, struct ovsdb_schema **schemap) schema = ovsdb_schema_create(json_string(name), version, cksum ? json_string(cksum) : ""); - SHASH_FOR_EACH (node, json_object(tables)) { + JSMAP_FOR_EACH (node, json_object(tables)) { + const char *table_name = json_string(node->key); struct ovsdb_table_schema *table; - if (node->name[0] == '_') { + if (table_name[0] == '_') { error = ovsdb_syntax_error(json, NULL, "names beginning with " "\"_\" are reserved"); - } else if (!ovsdb_parser_is_id(node->name)) { + } else if (!ovsdb_parser_is_id(table_name)) { error = ovsdb_syntax_error(json, NULL, "name must be a valid id"); } else { - error = ovsdb_table_schema_from_json(node->data, node->name, - &table); + error = ovsdb_table_schema_from_json(node->value, + table_name, &table); } if (error) { ovsdb_schema_destroy(schema); @@ -287,8 +290,8 @@ ovsdb_schema_from_json(const struct json *json, struct ovsdb_schema **schemap) * compatibility, if the root set is empty then assume that every table is * in the root set. */ if (root_set_size(schema) == 0) { - SHASH_FOR_EACH (node, &schema->tables) { - struct ovsdb_table_schema *table = node->data; + SHASH_FOR_EACH (schema_node, &schema->tables) { + struct ovsdb_table_schema *table = schema_node->data; table->is_root = true; } @@ -299,8 +302,8 @@ ovsdb_schema_from_json(const struct json *json, struct ovsdb_schema **schemap) * Also force certain columns to be persistent, as explained in * ovsdb_schema_check_ref_table(). This requires 'is_root' to be known, so * this must follow the loop updating 'is_root' above. */ - SHASH_FOR_EACH (node, &schema->tables) { - struct ovsdb_table_schema *table = node->data; + SHASH_FOR_EACH (schema_node, &schema->tables) { + struct ovsdb_table_schema *table = schema_node->data; struct shash_node *node2; SHASH_FOR_EACH (node2, &table->columns) { diff --git a/ovsdb/raft-private.c b/ovsdb/raft-private.c index c880e32acd0..8147afd2ce3 100644 --- a/ovsdb/raft-private.c +++ b/ovsdb/raft-private.c @@ -19,6 +19,7 @@ #include "raft-private.h" #include "coverage.h" +#include "openvswitch/jsmap.h" #include "openvswitch/dynamic-string.h" #include "ovsdb-error.h" #include "ovsdb-parser.h" @@ -210,21 +211,21 @@ raft_servers_from_json__(const struct json *json, struct hmap *servers) { if (!json || json->type != JSON_OBJECT) { return ovsdb_syntax_error(json, NULL, "servers must be JSON object"); - } else if (shash_is_empty(json_object(json))) { + } else if (jsmap_is_empty(json_object(json))) { return ovsdb_syntax_error(json, NULL, "must have at least one server"); } /* Parse new servers. */ - struct shash_node *node; - SHASH_FOR_EACH (node, json_object(json)) { + struct jsmap_node *node; + JSMAP_FOR_EACH (node, json_object(json)) { /* Parse server UUID. */ struct uuid sid; - if (!uuid_from_string(&sid, node->name)) { + if (!uuid_from_string(&sid, json_string(node->key))) { return ovsdb_syntax_error(json, NULL, "%s is not a UUID", - node->name); + json_string(node->key)); } - const struct json *address = node->data; + const struct json *address = node->value; struct ovsdb_error *error = raft_address_validate_json(address); if (error) { return error; diff --git a/ovsdb/raft.c b/ovsdb/raft.c index 9c3c351b5be..a9e72502fff 100644 --- a/ovsdb/raft.c +++ b/ovsdb/raft.c @@ -519,9 +519,9 @@ raft_create_cluster(const char *file_name, const char *name, }, }; raft_entry_set_parsed_data(&h.snap, data); - shash_add_nocopy(json_object(h.snap.servers), - xasprintf(UUID_FMT, UUID_ARGS(&h.sid)), - json_string_create(local_address)); + json_object_put_nocopy(h.snap.servers, + xasprintf(UUID_FMT, UUID_ARGS(&h.sid)), + json_string_create(local_address)); error = ovsdb_log_write_and_free(log, raft_header_to_json(&h)); raft_header_uninit(&h); if (error) { diff --git a/ovsdb/relay.c b/ovsdb/relay.c index 71a5b8e1cec..53412bf5cba 100644 --- a/ovsdb/relay.c +++ b/ovsdb/relay.c @@ -198,15 +198,9 @@ ovsdb_relay_process_row_update(struct ovsdb_table *table, const struct ovsdb_cs_row_update *ru, struct ovsdb_txn *txn) { + const struct json *json_row = ru->columns; const struct uuid *uuid = &ru->row_uuid; - struct ovsdb_error * error = NULL; - - /* XXX: ovsdb-cs module returns shash which was previously part of a json - * structure and we need json row format in order to use ovsdb_row* - * functions. Creating a json object out of shash. */ - struct json *json_row = json_object_create(); - struct shash *obj = json_row->object; - json_row->object = CONST_CAST(struct shash *, ru->columns); + struct ovsdb_error *error = NULL; switch (ru->type) { case OVSDB_CS_ROW_DELETE: @@ -229,9 +223,6 @@ ovsdb_relay_process_row_update(struct ovsdb_table *table, OVS_NOT_REACHED(); } - json_row->object = obj; - json_destroy(json_row); - return error; } diff --git a/ovsdb/replication.c b/ovsdb/replication.c index bb21ff7d398..745f1f85b80 100644 --- a/ovsdb/replication.c +++ b/ovsdb/replication.c @@ -22,6 +22,7 @@ #include "jsonrpc.h" #include "openvswitch/dynamic-string.h" #include "openvswitch/hmap.h" +#include "openvswitch/jsmap.h" #include "openvswitch/json.h" #include "openvswitch/vlog.h" #include "ovsdb-error.h" @@ -602,11 +603,12 @@ process_notification(const struct json *table_updates, struct ovsdb *db) txn = ovsdb_txn_create(db); /* Process each table update. */ - struct shash_node *node; - SHASH_FOR_EACH (node, json_object(table_updates)) { - struct json *table_update = node->data; + struct jsmap_node *node; + JSMAP_FOR_EACH (node, json_object(table_updates)) { + struct json *table_update = node->value; if (table_update) { - error = process_table_update(table_update, node->name, db, txn); + error = process_table_update(table_update, + json_string(node->key), db, txn); if (error) { break; } @@ -639,9 +641,9 @@ process_table_update(const struct json *table_update, const char *table_name, " for table is not object"); } - struct shash_node *node; - SHASH_FOR_EACH (node, json_object(table_update)) { - struct json *row_update = node->data; + struct jsmap_node *node; + JSMAP_FOR_EACH (node, json_object(table_update)) { + struct json *row_update = node->value; struct json *old, *new; if (row_update->type != JSON_OBJECT) { @@ -650,13 +652,13 @@ process_table_update(const struct json *table_update, const char *table_name, } struct uuid uuid; - if (!uuid_from_string(&uuid, node->name)) { + if (!uuid_from_string(&uuid, json_string(node->key))) { return ovsdb_syntax_error(table_update, "bad row UUID", " names must be UUIDs"); } - old = shash_find_data(json_object(row_update), "old"); - new = shash_find_data(json_object(row_update), "new"); + old = json_object_find(row_update, "old"); + new = json_object_find(row_update, "new"); struct ovsdb_error *error; error = (!new ? ovsdb_table_execute_delete(txn, &uuid, table) diff --git a/ovsdb/row.c b/ovsdb/row.c index 6b52509a91c..f8af7307766 100644 --- a/ovsdb/row.c +++ b/ovsdb/row.c @@ -20,6 +20,7 @@ #include #include "openvswitch/dynamic-string.h" +#include "openvswitch/jsmap.h" #include "openvswitch/json.h" #include "openvswitch/shash.h" #include "ovsdb-error.h" @@ -306,7 +307,7 @@ ovsdb_row_from_json(struct ovsdb_row *row, const struct json *json, { struct ovsdb_table_schema *schema = row->table->schema; struct ovsdb_error *error; - struct shash_node *node; + struct jsmap_node *node; ovs_assert(!is_diff || !symtab); @@ -314,8 +315,8 @@ ovsdb_row_from_json(struct ovsdb_row *row, const struct json *json, return ovsdb_syntax_error(json, NULL, "row must be JSON object"); } - SHASH_FOR_EACH (node, json_object(json)) { - const char *column_name = node->name; + JSMAP_FOR_EACH (node, json_object(json)) { + const char *column_name = json_string(node->key); const struct ovsdb_column *column; struct ovsdb_datum datum; @@ -328,9 +329,9 @@ ovsdb_row_from_json(struct ovsdb_row *row, const struct json *json, if (is_diff) { error = ovsdb_transient_datum_from_json(&datum, &column->type, - node->data); + node->value); } else { - error = ovsdb_datum_from_json(&datum, &column->type, node->data, + error = ovsdb_datum_from_json(&datum, &column->type, node->value, symtab); } if (error) { diff --git a/ovsdb/table.c b/ovsdb/table.c index 589ee5e8c32..b22e69da3db 100644 --- a/ovsdb/table.c +++ b/ovsdb/table.c @@ -19,6 +19,7 @@ #include +#include "openvswitch/jsmap.h" #include "openvswitch/json.h" #include "column.h" #include "ovsdb-error.h" @@ -128,7 +129,7 @@ ovsdb_table_schema_from_json(const struct json *json, const char *name, { struct ovsdb_table_schema *ts; const struct json *columns, *mutable, *max_rows, *is_root, *indexes; - struct shash_node *node; + struct jsmap_node *node; struct ovsdb_parser parser; struct ovsdb_error *error; long long int n_max_rows; @@ -158,7 +159,7 @@ ovsdb_table_schema_from_json(const struct json *json, const char *name, n_max_rows = UINT_MAX; } - if (shash_is_empty(json_object(columns))) { + if (jsmap_is_empty(json_object(columns))) { return ovsdb_syntax_error(json, NULL, "table must have at least one column"); } @@ -167,16 +168,17 @@ ovsdb_table_schema_from_json(const struct json *json, const char *name, mutable ? json_boolean(mutable) : true, MIN(n_max_rows, UINT_MAX), is_root ? json_boolean(is_root) : false); - SHASH_FOR_EACH (node, json_object(columns)) { + JSMAP_FOR_EACH (node, json_object(columns)) { + const char *column_name = json_string(node->key); struct ovsdb_column *column; - if (node->name[0] == '_') { + if (column_name[0] == '_') { error = ovsdb_syntax_error(json, NULL, "names beginning with " "\"_\" are reserved"); - } else if (!ovsdb_parser_is_id(node->name)) { + } else if (!ovsdb_parser_is_id(column_name)) { error = ovsdb_syntax_error(json, NULL, "name must be a valid id"); } else { - error = ovsdb_column_from_json(node->data, node->name, &column); + error = ovsdb_column_from_json(node->value, column_name, &column); } if (error) { goto error; @@ -356,7 +358,8 @@ ovsdb_table_get_row(const struct ovsdb_table *table, const struct uuid *uuid) struct ovsdb_error * ovsdb_table_execute_insert(struct ovsdb_txn *txn, const struct uuid *row_uuid, - struct ovsdb_table *table, struct json *json_row) + struct ovsdb_table *table, + const struct json *json_row) { const struct ovsdb_row *old_row = ovsdb_table_get_row(table, row_uuid); if (old_row) { @@ -398,8 +401,8 @@ ovsdb_table_execute_delete(struct ovsdb_txn *txn, const struct uuid *row_uuid, struct ovsdb_error * ovsdb_table_execute_update(struct ovsdb_txn *txn, const struct uuid *row_uuid, - struct ovsdb_table *table, struct json *json_row, - bool xor) + struct ovsdb_table *table, + const struct json *json_row, bool xor) { const struct ovsdb_row *row = ovsdb_table_get_row(table, row_uuid); if (!row) { diff --git a/ovsdb/table.h b/ovsdb/table.h index 614c4ed826a..4cb9900882f 100644 --- a/ovsdb/table.h +++ b/ovsdb/table.h @@ -79,13 +79,14 @@ const struct ovsdb_row *ovsdb_table_get_row(const struct ovsdb_table *, struct ovsdb_error *ovsdb_table_execute_insert(struct ovsdb_txn *txn, const struct uuid *row_uuid, struct ovsdb_table *table, - struct json *new); + const struct json *new); struct ovsdb_error *ovsdb_table_execute_delete(struct ovsdb_txn *txn, const struct uuid *row_uuid, struct ovsdb_table *table); struct ovsdb_error *ovsdb_table_execute_update(struct ovsdb_txn *txn, const struct uuid *row_uuid, struct ovsdb_table *table, - struct json *new, bool xor); + const struct json *new, + bool xor); #endif /* ovsdb/table.h */ diff --git a/tests/test-json.c b/tests/test-json.c index f5b0ad3713a..c5cab4afd59 100644 --- a/tests/test-json.c +++ b/tests/test-json.c @@ -16,6 +16,7 @@ #include #undef NDEBUG +#include "openvswitch/jsmap.h" #include "openvswitch/json.h" #include #include @@ -38,10 +39,10 @@ static void test_json_equal(const struct json *a, const struct json *b, bool allow_the_same); static void -test_json_equal_object(const struct shash *a, const struct shash *b, +test_json_equal_object(const struct jsmap *a, const struct jsmap *b, bool allow_the_same) { - struct shash_node *a_node; + struct jsmap_node *a_node; ovs_assert(allow_the_same || a != b); @@ -49,13 +50,13 @@ test_json_equal_object(const struct shash *a, const struct shash *b, return; } - ovs_assert(shash_count(a) == shash_count(b)); + ovs_assert(jsmap_count(a) == jsmap_count(b)); - SHASH_FOR_EACH (a_node, a) { - struct shash_node *b_node = shash_find(b, a_node->name); + JSMAP_FOR_EACH (a_node, a) { + struct jsmap_node *b_node = jsmap_get_node(b, a_node->key); ovs_assert(b_node); - test_json_equal(a_node->data, b_node->data, allow_the_same); + test_json_equal(a_node->value, b_node->value, allow_the_same); } } diff --git a/tests/test-ovsdb.c b/tests/test-ovsdb.c index 5b41526937b..0d48eb9ec24 100644 --- a/tests/test-ovsdb.c +++ b/tests/test-ovsdb.c @@ -26,6 +26,7 @@ #include "byte-order.h" #include "command-line.h" #include "openvswitch/dynamic-string.h" +#include "openvswitch/jsmap.h" #include "openvswitch/json.h" #include "jsonrpc.h" #include "ovsdb-data.h" @@ -2397,10 +2398,10 @@ parse_uuids(const struct json *json, struct ovsdb_symbol_table *symtab, parse_uuids(json_array_at(json, i), symtab, n); } } else if (json->type == JSON_OBJECT) { - const struct shash_node *node; + const struct jsmap_node *node; - SHASH_FOR_EACH (node, json_object(json)) { - parse_uuids(node->data, symtab, n); + JSMAP_FOR_EACH (node, json_object(json)) { + parse_uuids(node->value, symtab, n); } } } @@ -2427,10 +2428,10 @@ substitute_uuids(struct json *json, const struct ovsdb_symbol_table *symtab) symtab); } } else if (json->type == JSON_OBJECT) { - const struct shash_node *node; + const struct jsmap_node *node; - SHASH_FOR_EACH (node, json_object(json)) { - substitute_uuids(node->data, symtab); + JSMAP_FOR_EACH (node, json_object(json)) { + substitute_uuids(node->value, symtab); } } }