X-Git-Url: http://git.cascardo.eti.br/?a=blobdiff_plain;f=ovsdb%2Fmonitor.c;h=6b0d13d676785c4810b39bd9f59034e58d60f034;hb=HEAD;hp=f08607aa3322c62a3bcba62b26b0a62c7bd4acb0;hpb=52553aeaa95ab46a1c120a8628621d8ed390a91f;p=cascardo%2Fovs.git diff --git a/ovsdb/monitor.c b/ovsdb/monitor.c index f08607aa3..6b0d13d67 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; @@ -710,40 +724,40 @@ ovsdb_monitor_compose_update(struct ovsdb_monitor *dbmon, * going to be used as part of an "update" notification. */ struct json * ovsdb_monitor_get_update(struct ovsdb_monitor *dbmon, - bool initial, uint64_t *unflushed, + bool initial, uint64_t *unflushed_, enum ovsdb_monitor_version version) { struct ovsdb_monitor_json_cache_node *cache_node; struct shash_node *node; struct json *json; - uint64_t prev_txn = *unflushed; - uint64_t next_txn = dbmon->n_transactions + 1; + const uint64_t unflushed = *unflushed_; + const uint64_t next_unflushed = dbmon->n_transactions + 1; /* 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, unflushed); if (cache_node) { json = cache_node->json ? json_clone(cache_node->json) : NULL; } else { if (version == OVSDB_MONITOR_V1) { - json = ovsdb_monitor_compose_update(dbmon, initial, prev_txn, + json = ovsdb_monitor_compose_update(dbmon, initial, unflushed, ovsdb_monitor_compose_row_update); } else { ovs_assert(version == OVSDB_MONITOR_V2); - json = ovsdb_monitor_compose_update(dbmon, initial, prev_txn, + json = ovsdb_monitor_compose_update(dbmon, initial, unflushed, ovsdb_monitor_compose_row_update2); } - ovsdb_monitor_json_cache_insert(dbmon, prev_txn, json); + ovsdb_monitor_json_cache_insert(dbmon, version, unflushed, json); } /* Maintain transaction id of 'changes'. */ SHASH_FOR_EACH (node, &dbmon->tables) { struct ovsdb_monitor_table *mt = node->data; - ovsdb_monitor_table_untrack_changes(mt, prev_txn); - ovsdb_monitor_table_track_changes(mt, next_txn); + ovsdb_monitor_table_untrack_changes(mt, unflushed); + ovsdb_monitor_table_track_changes(mt, next_unflushed); } - *unflushed = next_txn; + *unflushed_ = next_unflushed; return json; } @@ -945,7 +959,8 @@ ovsdb_monitor_get_initial(const struct ovsdb_monitor *dbmon) void ovsdb_monitor_remove_jsonrpc_monitor(struct ovsdb_monitor *dbmon, - struct ovsdb_jsonrpc_monitor *jsonrpc_monitor) + struct ovsdb_jsonrpc_monitor *jsonrpc_monitor, + uint64_t unflushed) { struct jsonrpc_monitor_node *jm; @@ -957,6 +972,12 @@ ovsdb_monitor_remove_jsonrpc_monitor(struct ovsdb_monitor *dbmon, /* Find and remove the jsonrpc monitor from the list. */ LIST_FOR_EACH(jm, node, &dbmon->jsonrpc_monitors) { if (jm->jsonrpc_monitor == jsonrpc_monitor) { + /* Release the tracked changes. */ + struct shash_node *node; + SHASH_FOR_EACH (node, &dbmon->tables) { + struct ovsdb_monitor_table *mt = node->data; + ovsdb_monitor_table_untrack_changes(mt, unflushed); + } list_remove(&jm->node); free(jm); @@ -1107,11 +1128,24 @@ ovsdb_monitor_commit(struct ovsdb_replica *replica, struct ovsdb_monitor_aux aux; ovsdb_monitor_init_aux(&aux, m); + /* Update ovsdb_monitor's transaction number for + * each transaction, before calling ovsdb_monitor_change_cb(). */ + m->n_transactions++; ovsdb_txn_for_each_change(txn, ovsdb_monitor_change_cb, &aux); - if (aux.efficacy == OVSDB_CHANGES_REQUIRE_EXTERNAL_UPDATE) { + switch(aux.efficacy) { + case OVSDB_CHANGES_NO_EFFECT: + /* The transaction is ignored by the monitor. + * Roll back the 'n_transactions' as if the transaction + * has never happened. */ + m->n_transactions--; + break; + case OVSDB_CHANGES_REQUIRE_INTERNAL_UPDATE: + /* Nothing. */ + break; + case OVSDB_CHANGES_REQUIRE_EXTERNAL_UPDATE: ovsdb_monitor_json_cache_flush(m); - m->n_transactions++; + break; } return NULL; @@ -1131,6 +1165,14 @@ ovsdb_monitor_destroy_callback(struct ovsdb_replica *replica) } } +/* Add some memory usage statics for monitors into 'usage', for use with + * memory_report(). */ +void +ovsdb_monitor_get_memory_usage(struct simap *usage) +{ + simap_put(usage, "monitors", hmap_count(&ovsdb_monitors)); +} + static const struct ovsdb_replica_class ovsdb_jsonrpc_replica_class = { ovsdb_monitor_commit, ovsdb_monitor_destroy_callback,