From patchwork Thu Dec 10 09:38:58 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Ansari, Shad" X-Patchwork-Id: 555092 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from archives.nicira.com (li376-54.members.linode.com [96.126.127.54]) by ozlabs.org (Postfix) with ESMTP id 8A1F514029E for ; Thu, 10 Dec 2015 20:40:38 +1100 (AEDT) Received: from archives.nicira.com (localhost [127.0.0.1]) by archives.nicira.com (Postfix) with ESMTP id 49F4F10173; Thu, 10 Dec 2015 01:40:37 -0800 (PST) X-Original-To: dev@openvswitch.org Delivered-To: dev@openvswitch.org Received: from mx3v3.cudamail.com (mx3.cudamail.com [64.34.241.5]) by archives.nicira.com (Postfix) with ESMTPS id 9441A10863 for ; Thu, 10 Dec 2015 01:40:35 -0800 (PST) Received: from bar4.cudamail.com (localhost [127.0.0.1]) by mx3v3.cudamail.com (Postfix) with ESMTPS id 7C26C1615EB for ; Thu, 10 Dec 2015 02:40:32 -0700 (MST) X-ASG-Debug-ID: 1449740431-03dc21603ee81ea0001-byXFYA Received: from mx3-pf3.cudamail.com ([192.168.14.3]) by bar4.cudamail.com with ESMTP id AdBuDq3rYyyseIF4 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Thu, 10 Dec 2015 02:40:31 -0700 (MST) X-Barracuda-Envelope-From: shad.ansari@hpe.com X-Barracuda-RBL-Trusted-Forwarder: 192.168.14.3 Received: from unknown (HELO g4t3425.houston.hp.com) (15.201.208.53) by mx3-pf3.cudamail.com with ESMTPS (DHE-RSA-AES256-SHA encrypted); 10 Dec 2015 09:50:32 -0000 Received-SPF: none (mx3-pf3.cudamail.com: domain at hpe.com does not designate permitted sender hosts) X-Barracuda-Apparent-Source-IP: 15.201.208.53 X-Barracuda-RBL-IP: 15.201.208.53 Received: from G4W6310.americas.hpqcorp.net (g4w6310.houston.hp.com [16.210.26.217]) (using TLSv1 with cipher AES128-SHA (128/128 bits)) (No client certificate requested) by g4t3425.houston.hp.com (Postfix) with ESMTPS id BE64B58 for ; Thu, 10 Dec 2015 09:40:20 +0000 (UTC) Received: from G9W3611.americas.hpqcorp.net (16.216.186.46) by G4W6310.americas.hpqcorp.net (16.210.26.217) with Microsoft SMTP Server (TLS) id 14.3.169.1; Thu, 10 Dec 2015 09:38:58 +0000 Received: from G9W0717.americas.hpqcorp.net ([169.254.4.14]) by G9W3611.americas.hpqcorp.net ([16.216.186.46]) with mapi id 14.03.0169.001; Thu, 10 Dec 2015 09:38:58 +0000 X-CudaMail-Envelope-Sender: shad.ansari@hpe.com From: "Ansari, Shad" To: "dev@openvswitch.org" X-CudaMail-MID: CM-V3-1209002951 X-CudaMail-DTE: 121015 X-CudaMail-Originating-IP: 15.201.208.53 Thread-Topic: [PATCH] ovsdb-idl: Add support for column tracking in IDL X-ASG-Orig-Subj: [##CM-V3-1209002951##][PATCH] ovsdb-idl: Add support for column tracking in IDL Thread-Index: AdEzLlFhJjthg4fTRhy2A0D9iInchg== Date: Thu, 10 Dec 2015 09:38:58 +0000 Message-ID: <8CA204A851B7B14E86E75054661E41750F9DD702@G9W0717.americas.hpqcorp.net> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-originating-ip: [16.210.48.21] MIME-Version: 1.0 X-GBUdb-Analysis: 0, 15.201.208.53, Ugly c=0 p=0 Source New X-MessageSniffer-Rules: 0-0-0-22448-c X-Barracuda-Connect: UNKNOWN[192.168.14.3] X-Barracuda-Start-Time: 1449740431 X-Barracuda-Encrypted: DHE-RSA-AES256-SHA X-Barracuda-URL: https://web.cudamail.com:443/cgi-mod/mark.cgi X-Virus-Scanned: by bsmtpd at cudamail.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.60 X-Barracuda-Spam-Status: No, SCORE=0.60 using per-user scores of TAG_LEVEL=3.5 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=4.0 tests=BSF_RULE7568M, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.25133 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.50 BSF_RULE7568M Custom Rule 7568M 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS Subject: [ovs-dev] [PATCH] ovsdb-idl: Add support for column tracking in IDL X-BeenThere: dev@openvswitch.org X-Mailman-Version: 2.1.16 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@openvswitch.org Sender: "dev" 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 --- 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