Signed-off-by: Andy Zhou <az...@nicira.com> --- ovsdb/ovsdb-monitor.c | 124 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 85 insertions(+), 39 deletions(-)
diff --git a/ovsdb/ovsdb-monitor.c b/ovsdb/ovsdb-monitor.c index a1efa66..3259f3c 100644 --- a/ovsdb/ovsdb-monitor.c +++ b/ovsdb/ovsdb-monitor.c @@ -87,6 +87,7 @@ struct ovsdb_monitor_changes { struct hmap rows; int n_refs; uint64_t transaction; + struct ovs_list node; /* Element in ovsdb_monitor_tables' changes list */ }; /* A particular table being monitored. */ @@ -101,18 +102,21 @@ struct ovsdb_monitor_table { struct ovsdb_monitor_column *columns; size_t n_columns; - /* Contains 'struct ovsdb_monitor_row's for rows that have been - * updated but not yet flushed to the jsonrpc connection. */ - struct ovsdb_monitor_changes *changes; + /* Contains unsorted list of 'ovsdb_monitor_changes'. Each 'changes' + * tracks updates of rows starting from a different + * 'unflushed_transaction'. */ + struct ovs_list changes_list; }; static void ovsdb_monitor_destroy(struct ovsdb_monitor *dbmon); static void ovsdb_monitor_table_add_changes(struct ovsdb_monitor_table *mt, uint64_t next_txn); +static struct ovsdb_monitor_changes *ovsdb_monitor_table_find_changes( + struct ovsdb_monitor_table *mt, uint64_t unflushed); static void ovsdb_monitor_changes_destroy_rows( struct ovsdb_monitor_changes *changes); static void ovsdb_monitor_table_track_changes(struct ovsdb_monitor_table *mt, - uint64_t transaction); + uint64_t unflushed); static int compare_ovsdb_monitor_column(const void *a_, const void *b_) @@ -133,13 +137,13 @@ ovsdb_monitor_cast(struct ovsdb_replica *replica) /* Finds and returns the ovsdb_monitor_row in 'mt->changes->rows' for the * given 'uuid', or NULL if there is no such row. */ static struct ovsdb_monitor_row * -ovsdb_monitor_row_find(const struct ovsdb_monitor_table *mt, - const struct uuid *uuid) +ovsdb_monitor_changes_row_find(const struct ovsdb_monitor_changes *changes, + const struct uuid *uuid) { struct ovsdb_monitor_row *row; HMAP_FOR_EACH_WITH_HASH (row, hmap_node, uuid_hash(uuid), - &mt->changes->rows) { + &changes->rows) { if (uuid_equals(uuid, &row->uuid)) { return row; } @@ -258,8 +262,8 @@ ovsdb_monitor_add_table(struct ovsdb_monitor *m, mt = xzalloc(sizeof *mt); mt->table = table; - mt->changes = NULL; shash_add(&m->tables, table->schema->name, mt); + list_init(&mt->changes_list); } void @@ -323,9 +327,25 @@ ovsdb_monitor_table_add_changes(struct ovsdb_monitor_table *mt, changes->mt = mt; changes->n_refs = 1; hmap_init(&changes->rows); - mt->changes = changes; + list_push_back(&mt->changes_list, &changes->node); }; + +static struct ovsdb_monitor_changes * +ovsdb_monitor_table_find_changes(struct ovsdb_monitor_table *mt, + uint64_t transaction) +{ + struct ovsdb_monitor_changes *changes; + + LIST_FOR_EACH(changes, node, &mt->changes_list) { + if (changes->transaction == transaction) { + return changes; + } + } + + return NULL; +} + /* Stop currently tracking changes to table 'mt' since 'transaction'. * * Return 'true' if the 'transaction' is being tracked. 'false' otherwise. */ @@ -335,14 +355,14 @@ ovsdb_monitor_table_untrack_changes(struct ovsdb_monitor_table *mt, { struct ovsdb_monitor_changes *changes; - changes = mt->changes; + changes = ovsdb_monitor_table_find_changes(mt, transaction); if (changes) { ovs_assert(changes->transaction == transaction); if (--changes->n_refs == 0) { ovsdb_monitor_changes_destroy_rows(changes); + list_remove(&changes->node); free(changes); - mt->changes = NULL; } } } @@ -355,7 +375,7 @@ ovsdb_monitor_table_track_changes(struct ovsdb_monitor_table *mt, { struct ovsdb_monitor_changes *changes; - changes = mt->changes; + changes = ovsdb_monitor_table_find_changes(mt, transaction); if (changes) { ovs_assert(false); } else { @@ -474,6 +494,9 @@ ovsdb_monitor_compose_update(const struct ovsdb_monitor *dbmon, unsigned long int *changed; struct json *json; size_t max_columns; + uint64_t from_txn; + + from_txn = initial ? 0 : *unflushed; *unflushed = dbmon->n_transactions + 1; @@ -489,13 +512,15 @@ ovsdb_monitor_compose_update(const struct ovsdb_monitor *dbmon, SHASH_FOR_EACH (node, &dbmon->tables) { struct ovsdb_monitor_table *mt = node->data; struct ovsdb_monitor_row *row, *next; + struct ovsdb_monitor_changes *changes; struct json *table_json = NULL; - if (!mt->changes) { + changes = ovsdb_monitor_table_find_changes(mt, from_txn); + if (!changes) { continue; } - HMAP_FOR_EACH_SAFE (row, next, hmap_node, &mt->changes->rows) { + HMAP_FOR_EACH_SAFE (row, next, hmap_node, &changes->rows) { struct json *row_json; row_json = ovsdb_monitor_compose_row_update( @@ -519,7 +544,7 @@ ovsdb_monitor_compose_update(const struct ovsdb_monitor *dbmon, json_object_put(table_json, uuid, row_json); } - hmap_remove(&mt->changes->rows, &row->hmap_node); + hmap_remove(&changes->rows, &row->hmap_node); ovsdb_monitor_row_destroy(mt, row); } } @@ -560,33 +585,19 @@ ovsdb_monitor_init_aux(struct ovsdb_monitor_aux *aux, aux->mt = NULL; } -static bool -ovsdb_monitor_change_cb(const struct ovsdb_row *old, - const struct ovsdb_row *new, - const unsigned long int *changed OVS_UNUSED, - void *aux_) +static void +ovsdb_monitor_changes_update(const struct ovsdb_row *old, + const struct ovsdb_row *new, + const struct ovsdb_monitor_table *mt, + struct ovsdb_monitor_changes *changes) { - struct ovsdb_monitor_aux *aux = aux_; - const struct ovsdb_monitor *m = aux->monitor; - struct ovsdb_table *table = new ? new->table : old->table; const struct uuid *uuid = ovsdb_row_get_uuid(new ? new : old); struct ovsdb_monitor_row *change; - struct ovsdb_monitor_table *mt; - if (!aux->mt || table != aux->mt->table) { - aux->mt = shash_find_data(&m->tables, table->schema->name); - if (!aux->mt) { - /* We don't care about rows in this table at all. Tell the caller - * to skip it. */ - return false; - } - } - mt = aux->mt; - - change = ovsdb_monitor_row_find(mt, uuid); + change = ovsdb_monitor_changes_row_find(changes, uuid); if (!change) { change = xmalloc(sizeof *change); - hmap_insert(&mt->changes->rows, &change->hmap_node, uuid_hash(uuid)); + hmap_insert(&changes->rows, &change->hmap_node, uuid_hash(uuid)); change->uuid = *uuid; change->old = clone_monitor_row_data(mt, old); change->new = clone_monitor_row_data(mt, new); @@ -599,11 +610,38 @@ ovsdb_monitor_change_cb(const struct ovsdb_row *old, if (!change->old) { /* This row was added then deleted. Forget about it. */ - hmap_remove(&mt->changes->rows, &change->hmap_node); + hmap_remove(&changes->rows, &change->hmap_node); free(change); } } } +} + +static bool +ovsdb_monitor_change_cb(const struct ovsdb_row *old, + const struct ovsdb_row *new, + const unsigned long int *changed OVS_UNUSED, + void *aux_) +{ + struct ovsdb_monitor_aux *aux = aux_; + const struct ovsdb_monitor *m = aux->monitor; + struct ovsdb_table *table = new ? new->table : old->table; + struct ovsdb_monitor_table *mt; + struct ovsdb_monitor_changes *changes; + + if (!aux->mt || table != aux->mt->table) { + aux->mt = shash_find_data(&m->tables, table->schema->name); + if (!aux->mt) { + /* We don't care about rows in this table at all. Tell the caller + * to skip it. */ + return false; + } + } + mt = aux->mt; + + LIST_FOR_EACH(changes, node, &mt->changes_list) { + ovsdb_monitor_changes_update(old, new, mt, changes); + } return true; } @@ -620,7 +658,7 @@ ovsdb_monitor_get_initial(const struct ovsdb_monitor *dbmon) if (mt->select & OJMS_INITIAL) { struct ovsdb_row *row; - if (!mt->changes) { + if (list_is_empty(&mt->changes_list)) { ovsdb_monitor_table_add_changes(mt, 0); } @@ -658,6 +696,8 @@ ovsdb_monitor_remove_jsonrpc_monitor(struct ovsdb_monitor *dbmon, ovs_assert(true); } +/* Stop tracking changes since 'last_txn', and, start to + * track changes starting from the 'next_txn'. */ void ovsdb_monitor_renew_tracking_changes(struct ovsdb_monitor *dbmon, uint64_t prev_txn, uint64_t next_txn) @@ -681,8 +721,14 @@ ovsdb_monitor_destroy(struct ovsdb_monitor *dbmon) SHASH_FOR_EACH (node, &dbmon->tables) { struct ovsdb_monitor_table *mt = node->data; + struct ovsdb_monitor_changes *changes, *next; + + LIST_FOR_EACH_SAFE (changes, next, node, &mt->changes_list) { + list_remove(&changes->node); + ovsdb_monitor_changes_destroy_rows(changes); + free(changes); + } - ovsdb_monitor_changes_destroy_rows(mt->changes); free(mt->columns); free(mt); } -- 1.9.1 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev