Signed-off-by: Andy Zhou <[email protected]>
---
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
[email protected]
http://openvswitch.org/mailman/listinfo/dev