Recent IDL change tracking patches allow quick traversal of changed rows. This patch adds additional support to track changed columns. It allows an IDL client to efficiently check if a specific column of a row was updated by IDL.
Signed-off-by: Shad Ansari <shad.an...@hpe.com> --- lib/ovsdb-idl-provider.h | 4 ++- lib/ovsdb-idl.c | 32 ++++++++++++++++++++++++ lib/ovsdb-idl.h | 2 ++ ovsdb/ovsdb-idlc.in | 15 +++++++++--- tests/ovsdb-idl.at | 11 +++++++++ tests/test-ovsdb.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 122 insertions(+), 5 deletions(-) diff --git a/lib/ovsdb-idl-provider.h b/lib/ovsdb-idl-provider.h index 099535e..190acca 100644 --- a/lib/ovsdb-idl-provider.h +++ b/lib/ovsdb-idl-provider.h @@ -37,8 +37,10 @@ struct ovsdb_idl_row { unsigned long int *written; /* Bitmap of columns from "new" to write. */ struct hmap_node txn_node; /* Node in ovsdb_idl_txn's list. */ + /* Tracking data */ unsigned int change_seqno[OVSDB_IDL_CHANGE_MAX]; - struct ovs_list track_node; + struct ovs_list track_node; /* Rows modified/added/deleted by IDL */ + unsigned long int *updated; /* Bitmap of columns updated by IDL */ }; struct ovsdb_idl_column { diff --git a/lib/ovsdb-idl.c b/lib/ovsdb-idl.c index 8f75bf0..7ab2b19 100644 --- a/lib/ovsdb-idl.c +++ b/lib/ovsdb-idl.c @@ -718,6 +718,29 @@ ovsdb_idl_track_get_next(const struct ovsdb_idl_row *row) return NULL; } +/* Returns true if a tracked 'column' in 'row' was updated by IDL, false + * otherwise. The tracking data is cleared by ovsdb_idl_track_clear() + * + * Function returns false if 'column' is not tracked (see + * ovsdb_idl_track_add_column()). + */ +bool +ovsdb_idl_track_is_updated(const struct ovsdb_idl_row *row, + const struct ovsdb_idl_column *column) +{ + const struct ovsdb_idl_table_class *class; + size_t column_idx; + + class = row->table->class; + column_idx = column - class->columns; + + if (row->updated && bitmap_is_set(row->updated, column_idx)) { + return true; + } else { + return false; + } +} + /* Flushes the tracked rows. Client calls this function after calling * ovsdb_idl_run() and read all tracked rows with the ovsdb_idl_track_get_*() * functions. This is usually done at the end of the client's processing @@ -735,6 +758,10 @@ ovsdb_idl_track_clear(const struct ovsdb_idl *idl) struct ovsdb_idl_row *row, *next; LIST_FOR_EACH_SAFE(row, next, track_node, &table->track_list) { + if (row->updated) { + free(row->updated); + row->updated = NULL; + } list_remove(&row->track_node); list_init(&row->track_node); if (ovsdb_idl_row_is_orphan(row)) { @@ -1075,6 +1102,7 @@ ovsdb_idl_row_update(struct ovsdb_idl_row *row, const struct json *row_json, 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; bool changed = false; @@ -1108,6 +1136,10 @@ ovsdb_idl_row_update(struct ovsdb_idl_row *row, const struct json *row_json, list_push_front(&row->table->track_list, &row->track_node); } + if (!row->updated) { + row->updated = bitmap_allocate(class->n_columns); + } + bitmap_set1(row->updated, column_idx); } } } else { diff --git a/lib/ovsdb-idl.h b/lib/ovsdb-idl.h index 4c66ae0..136c38c 100644 --- a/lib/ovsdb-idl.h +++ b/lib/ovsdb-idl.h @@ -132,6 +132,8 @@ void ovsdb_idl_track_add_all(struct ovsdb_idl *idl); const struct ovsdb_idl_row *ovsdb_idl_track_get_first( const struct ovsdb_idl *, const struct ovsdb_idl_table_class *); const struct ovsdb_idl_row *ovsdb_idl_track_get_next(const struct ovsdb_idl_row *); +bool ovsdb_idl_track_is_updated(const struct ovsdb_idl_row *row, + const struct ovsdb_idl_column *column); void ovsdb_idl_track_clear(const struct ovsdb_idl *); diff --git a/ovsdb/ovsdb-idlc.in b/ovsdb/ovsdb-idlc.in index 282feb2..26b0de4 100755 --- a/ovsdb/ovsdb-idlc.in +++ b/ovsdb/ovsdb-idlc.in @@ -150,7 +150,7 @@ def printCIDLHeader(schemaFile): print "};" # Column indexes. - printEnum(["%s_COL_%s" % (structName.upper(), columnName.upper()) + printEnum("%s_column_id" % structName.lower(), ["%s_COL_%s" % (structName.upper(), columnName.upper()) for columnName in sorted(table.columns)] + ["%s_N_COLUMNS" % structName.upper()]) @@ -189,6 +189,7 @@ const struct %(s)s *%(s)s_track_get_next(const struct %(s)s *); void %(s)s_init(struct %(s)s *); void %(s)s_delete(const struct %(s)s *); struct %(s)s *%(s)s_insert(struct ovsdb_idl_txn *); +bool %(s)s_is_updated(const struct %(s)s *, enum %(s)s_column_id); ''' % {'s': structName, 'S': structName.upper()} for columnName, column in sorted(table.columns.iteritems()): @@ -217,7 +218,7 @@ struct %(s)s *%(s)s_insert(struct ovsdb_idl_txn *); print # Table indexes. - printEnum(["%sTABLE_%s" % (prefix.upper(), tableName.upper()) for tableName in sorted(schema.tables)] + ["%sN_TABLES" % prefix.upper()]) + printEnum("%stable_id" % prefix.lower(), ["%sTABLE_%s" % (prefix.upper(), tableName.upper()) for tableName in sorted(schema.tables)] + ["%sN_TABLES" % prefix.upper()]) print for tableName in schema.tables: print "#define %(p)stable_%(t)s (%(p)stable_classes[%(P)sTABLE_%(T)s])" % { @@ -233,11 +234,11 @@ struct %(s)s *%(s)s_insert(struct ovsdb_idl_txn *); print "\nconst char * %sget_db_version(void);" % prefix print "\n#endif /* %(prefix)sIDL_HEADER */" % {'prefix': prefix.upper()} -def printEnum(members): +def printEnum(type, members): if len(members) == 0: return - print "\nenum {"; + print "\nenum %s {" % type for member in members[:-1]: print " %s," % member print " %s" % members[-1] @@ -522,6 +523,12 @@ struct %(s)s * %(s)s_insert(struct ovsdb_idl_txn *txn) { return %(s)s_cast(ovsdb_idl_txn_insert(txn, &%(p)stable_classes[%(P)sTABLE_%(T)s], NULL)); +} + +bool +%(s)s_is_updated(const struct %(s)s *row, enum %(s)s_column_id column) +{ + return ovsdb_idl_track_is_updated(&row->header_, &%(s)s_columns[column]); }''' % {'s': structName, 'p': prefix, 'P': prefix.upper(), diff --git a/tests/ovsdb-idl.at b/tests/ovsdb-idl.at index abfe005..693d1bb 100644 --- a/tests/ovsdb-idl.at +++ b/tests/ovsdb-idl.at @@ -688,9 +688,11 @@ OVSDB_CHECK_IDL_TRACK([track, simple idl, initially populated], "where": [], "row": {"b": true}}]']], [[000: i=1 r=2 b=true s=mystring u=<0> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<1> <2>] uuid=<3> +000: updated columns: b ba i ia r ra s sa u ua 001: {"error":null,"result":[{"count":2}]} 002: i=0 r=0 b=true s= u=<4> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<5> 002: i=1 r=2 b=true s=mystring u=<0> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<1> <2>] uuid=<3> +002: updated columns: b 003: done ]]) @@ -748,20 +750,29 @@ OVSDB_CHECK_IDL_TRACK([track, simple idl, initially empty, various ops], [[000: empty 001: {"error":null,"result":[{"uuid":["uuid","<0>"]},{"uuid":["uuid","<1>"]}]} 002: i=1 r=2 b=true s=mystring u=<2> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<3> <4>] uuid=<0> +002: updated columns: b ba i ia r ra s sa u ua 003: {"error":null,"result":[{"count":2}]} 004: i=0 r=0 b=true s= u=<5> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> +004: updated columns: b 005: {"error":null,"result":[{"count":2}]} 006: i=0 r=123.5 b=true s= u=<5> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> 006: i=1 r=123.5 b=true s=mystring u=<2> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<3> <4>] uuid=<0> +006: updated columns: r +006: updated columns: r 007: {"error":null,"result":[{"uuid":["uuid","<6>"]}]} 008: i=-1 r=125 b=false s= u=<5> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<6> +008: updated columns: ba i ia r ra 009: {"error":null,"result":[{"count":2}]} 010: i=-1 r=125 b=false s=newstring u=<5> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<6> 010: i=0 r=123.5 b=true s=newstring u=<5> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> +010: updated columns: s +010: updated columns: s 011: {"error":null,"result":[{"count":1}]} 012: ##deleted## uuid=<1> 013: reconnect 014: i=-1 r=125 b=false s=newstring u=<5> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<6> 014: i=1 r=123.5 b=true s=mystring u=<2> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<3> <4>] uuid=<0> +014: updated columns: b ba i ia r ra s sa u ua +014: updated columns: ba i ia r ra s 015: done ]]) diff --git a/tests/test-ovsdb.c b/tests/test-ovsdb.c index 76c9ad9..9630244 100644 --- a/tests/test-ovsdb.c +++ b/tests/test-ovsdb.c @@ -1613,6 +1613,66 @@ compare_link1(const void *a_, const void *b_) } static void +print_idl_row_updated_simple(const struct idltest_simple *s, int step) +{ + size_t i; + bool updated = false; + + for (i = 0; i < IDLTEST_SIMPLE_N_COLUMNS; i++) { + if (idltest_simple_is_updated(s, i)) { + if (!updated) { + printf("%03d: updated columns:", step); + updated = true; + } + printf(" %s", idltest_simple_columns[i].name); + } + } + if (updated) { + printf("\n"); + } +} + +static void +print_idl_row_updated_link1(const struct idltest_link1 *l1, int step) +{ + size_t i; + bool updated = false; + + for (i = 0; i < IDLTEST_LINK1_N_COLUMNS; i++) { + if (idltest_link1_is_updated(l1, i)) { + if (!updated) { + printf("%03d: updated columns:", step); + updated = true; + } + printf(" %s", idltest_link1_columns[i].name); + } + } + if (updated) { + printf("\n"); + } +} + +static void +print_idl_row_updated_link2(const struct idltest_link2 *l2, int step) +{ + size_t i; + bool updated = false; + + for (i = 0; i < IDLTEST_LINK2_N_COLUMNS; i++) { + if (idltest_link2_is_updated(l2, i)) { + if (!updated) { + printf("%03d: updated columns:", step); + updated = true; + } + printf(" %s", idltest_link2_columns[i].name); + } + } + if (updated) { + printf("\n"); + } +} + +static void print_idl_row_simple(const struct idltest_simple *s, int step) { size_t i; @@ -1640,6 +1700,7 @@ print_idl_row_simple(const struct idltest_simple *s, int step) printf("%s"UUID_FMT, i ? " " : "", UUID_ARGS(&s->ua[i])); } printf("] uuid="UUID_FMT"\n", UUID_ARGS(&s->header_.uuid)); + print_idl_row_updated_simple(s, step); } static void @@ -1664,6 +1725,7 @@ print_idl_row_link1(const struct idltest_link1 *l1, int step) printf("%"PRId64, l1->l2->i); } printf(" uuid="UUID_FMT"\n", UUID_ARGS(&l1->header_.uuid)); + print_idl_row_updated_link1(l1, step); } static void @@ -1674,6 +1736,7 @@ print_idl_row_link2(const struct idltest_link2 *l2, int step) printf("%"PRId64, l2->l1->i); } printf(" uuid="UUID_FMT"\n", UUID_ARGS(&l2->header_.uuid)); + print_idl_row_updated_link2(l2, step); } static void -- 1.9.1 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev