From a32b4433573ebea26cf3be75446addd029155382 Mon Sep 17 00:00:00 2001 From: Han Zhou Date: Thu, 17 Dec 2015 22:23:22 -0800 Subject: [PATCH] ovsdb: separate json cache for different monitor versions Cached json objects were reused when sending notifications to clients. This created a problem when there were different versions of monitors coexisting. E.g. clients expecting version2 notification would receive messages with method == "update2" but payload in version1 format, which end up failure of processing the updates. This patch fixes the issue by including version in cache node. Signed-off-by: Han Zhou Acked-by: Andy Zhou Signed-off-by: Andy Zhou --- ovsdb/monitor.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/ovsdb/monitor.c b/ovsdb/monitor.c index f08607aa3..0dde54e2a 100644 --- a/ovsdb/monitor.c +++ b/ovsdb/monitor.c @@ -61,6 +61,7 @@ struct ovsdb_monitor { * inclusive. */ struct ovsdb_monitor_json_cache_node { struct hmap_node hmap_node; /* Elements in json cache. */ + enum ovsdb_monitor_version version; uint64_t from_txn; struct json *json; /* Null, or a cloned of json */ }; @@ -134,15 +135,27 @@ static void ovsdb_monitor_changes_destroy( static void ovsdb_monitor_table_track_changes(struct ovsdb_monitor_table *mt, uint64_t unflushed); +static uint32_t +json_cache_hash(enum ovsdb_monitor_version version, uint64_t from_txn) +{ + uint32_t hash; + + hash = hash_uint64(version); + hash = hash_uint64_basis(from_txn, hash); + + return hash; +} + static struct ovsdb_monitor_json_cache_node * ovsdb_monitor_json_cache_search(const struct ovsdb_monitor *dbmon, + enum ovsdb_monitor_version version, uint64_t from_txn) { struct ovsdb_monitor_json_cache_node *node; - uint32_t hash = hash_uint64(from_txn); + uint32_t hash = json_cache_hash(version, from_txn); HMAP_FOR_EACH_WITH_HASH(node, hmap_node, hash, &dbmon->json_cache) { - if (node->from_txn == from_txn) { + if (node->from_txn == from_txn && node->version == version) { return node; } } @@ -152,14 +165,15 @@ ovsdb_monitor_json_cache_search(const struct ovsdb_monitor *dbmon, static void ovsdb_monitor_json_cache_insert(struct ovsdb_monitor *dbmon, + enum ovsdb_monitor_version version, uint64_t from_txn, struct json *json) { struct ovsdb_monitor_json_cache_node *node; - uint32_t hash; + uint32_t hash = json_cache_hash(version, from_txn); node = xmalloc(sizeof *node); - hash = hash_uint64(from_txn); + node->version = version; node->from_txn = from_txn; node->json = json ? json_clone(json) : NULL; @@ -721,7 +735,7 @@ ovsdb_monitor_get_update(struct ovsdb_monitor *dbmon, /* Return a clone of cached json if one exists. Otherwise, * generate a new one and add it to the cache. */ - cache_node = ovsdb_monitor_json_cache_search(dbmon, prev_txn); + cache_node = ovsdb_monitor_json_cache_search(dbmon, version, prev_txn); if (cache_node) { json = cache_node->json ? json_clone(cache_node->json) : NULL; } else { @@ -733,7 +747,7 @@ ovsdb_monitor_get_update(struct ovsdb_monitor *dbmon, json = ovsdb_monitor_compose_update(dbmon, initial, prev_txn, ovsdb_monitor_compose_row_update2); } - ovsdb_monitor_json_cache_insert(dbmon, prev_txn, json); + ovsdb_monitor_json_cache_insert(dbmon, version, prev_txn, json); } /* Maintain transaction id of 'changes'. */ -- 2.20.1