Hi Ben, I finally got some time to catch up with this. Thanks for the suggestions, I agree with all of them. I integrated them with the rest of the code and all everything worked well.
Should I send an updated patch set with that includes your suggestions? Also, I noticed that you closed the pull request, but this haven't been merged yet. Do I need to create a new one? Regards, Sebastian -----Original Message----- From: Ben Pfaff [mailto:b...@ovn.org] Sent: Tuesday, May 17, 2016 4:52 PM To: Arguello, Sebastian <sebastian.argue...@hpe.com> Cc: dev@openvswitch.org Subject: Re: [ovs-dev] Subject: [PATCH v3 1/3] ovsdb-idl: Add support for on-demand columns On Thu, Apr 28, 2016 at 04:18:25PM +0000, Arguello, Sebastian wrote: > The IDL only supports reading from columns that are being monitored. > In the case where the column represent a frequently changing entity > (e.g. counter), and the reads are relatively infrequent (e.g. CLI > client), there is a significant overhead in replication. > > This patch introduces a new column mode called OVSDB_IDL_ON_DEMAND. > An on-demand column will have its default value if it has never been updated. > This can happen if: 1) the user has not called explicitly a fetch > operation over it or 2) the server reply with the actual value has not > been received/processed (i.e. ovsdb_idl_run() has not been called). > The on-demand columns will keep the last value received from the OVSDB server. > > The on-demand columns are not updated by the IDL automatically, they > are updated when the IDL user asks it by the calling one of the new > fetching functions that were added to the IDL. When this happens, the > IDL sends a select operation to request the data from the server. > After calling ovsdb_idl_run(), the IDL updates the replica with the > information received from the server. > > With this new column mode, the state of the replica could diverge from > the state of the database, as some of the columns could be outdated. > The process using the IDL is responsible for requesting the information > before using it. > > The main user visible changes in this patch are: > - There is a new function that adds on-demand columns: > ovsdb_idl_add_on_demand_column() > - Functions for fetching a cells (columns for specific rows), > columns, and table were added: ovsdb_idl_fetch_row(), > ovsdb_idl_fetch_column(), and ovsdb_idl_fetch_table() > - Functions for verifying if the fetch requests of on-demand columns > were processed were added: ovsdb_idl_is_row_fetch_pending(), > ovsdb_idl_is_column_fetch_pending(), ovsdb_idl_is_table_fetch_pending() > - When an on-demand column is updated, the IDL seqno is changed as > well > > Note that the Python IDL already has a feature similar to this called > Read-only columns. > > Signed-off-by: Sebastian Arguello <sebastian.argue...@hpe.com> Thanks. I have some suggestions for this patch. I'm appending my suggestions as an incremental diff, followed by a full revised patch. Here's a description of what I changed. There are two members in different structs with different meanings but the same name. I renamed one of them to 'n_fetch_reqs' since it's clearer and makes it easier to search for uses of each member by name. The values weren't used for the shash member of struct ovsdb_idl_table, 'outstanding_col_fetch_reqs', only the names, so I changed it to an sset. Nothing was actually comparing the JSON ids of the fetch requests against the replies, only the hash values of the ids. I added comparisons of the ids. Fixed some apparent memory leaks. Simplified ovsdb_idl_resend_on_demand_requests(). Minor style changes and comment improvements. diff --git a/lib/ovsdb-idl-provider.h b/lib/ovsdb-idl-provider.h index 866fd4c..2e29489 100644 --- a/lib/ovsdb-idl-provider.h +++ b/lib/ovsdb-idl-provider.h @@ -22,6 +22,7 @@ #include "ovsdb-idl.h" #include "ovsdb-types.h" #include "shash.h" +#include "sset.h" #include "uuid.h" struct ovsdb_idl_row { @@ -29,7 +30,7 @@ struct ovsdb_idl_row { struct uuid uuid; /* Row "_uuid" field. */ struct ovs_list src_arcs; /* Forward arcs (ovsdb_idl_arc.src_node). */ struct ovs_list dst_arcs; /* Backward arcs (ovsdb_idl_arc.dst_node). */ - struct ovsdb_idl_table *table; /* Containing table. */ + struct ovsdb_idl_table *table; /* Containing table. */ struct ovsdb_datum *old; /* Committed data (null if orphaned). */ /* Transactional data. */ @@ -43,8 +44,7 @@ struct ovsdb_idl_row { struct ovs_list track_node; /* Rows modified/added/deleted by IDL */ unsigned long int *updated; /* Bitmap of columns updated by IDL */ - size_t outstanding_fetch_reqs; /* Number of on-demand columns in this - * row with on-going fetch operations */ + size_t n_fetch_reqs; /* Number of columns with fetches pending. */ }; @@ -77,11 +77,7 @@ struct ovsdb_idl_table { struct ovs_list track_list; /* Tracked rows (ovsdb_idl_row.track_node). */ bool has_pending_fetch; /* Indicates if the table has a pending fetch * operation */ - struct shash outstanding_col_fetch_reqs; /* Contains the name of the - * columns with on-demand - * fetch request pending. It - * does not store any data, - * just keys */ + struct sset outstanding_col_fetch_reqs; /* Columns with pending + fetches. */ size_t n_on_demand_columns; /* Number of columns in the table configured * in OVSDB_IDL_ON_DEMAND mode. */ }; diff --git a/lib/ovsdb-idl.c b/lib/ovsdb-idl.c index f7b72c9..59bb883 100644 --- a/lib/ovsdb-idl.c +++ b/lib/ovsdb-idl.c @@ -88,6 +88,7 @@ enum ovsdb_idl_state { /* Keeps the information of on-demand columns fetch requests. */ struct ovsdb_idl_fetch_node { struct hmap_node hmap_node; /* To store this structure in hmaps. */ + struct json *id; /* ID for matching the reply. */ struct ovsdb_idl_table *table; /* Pointer to the requested table. */ struct ovsdb_idl_column const **columns; /* Contains requested columns. */ @@ -216,8 +217,10 @@ static void ovsdb_idl_parse_lock_reply(struct ovsdb_idl *, static void ovsdb_idl_parse_lock_notify(struct ovsdb_idl *, const struct json *params, bool new_has_lock); +static struct ovsdb_idl_fetch_node *ovsdb_idl_find_fetch_node( + struct ovsdb_idl *, const struct json *id); static void ovsdb_idl_parse_fetch_reply(struct ovsdb_idl *, - struct hmap_node *, + struct ovsdb_idl_fetch_node *, const struct json *); static struct ovsdb_error *ovsdb_idl_parse_fetch_reply__(struct ovsdb_idl *, struct ovsdb_idl_fetch_node *, struct json_array *); @@ -284,7 +287,7 @@ ovsdb_idl_create(const char *remote, const struct ovsdb_idl_class *class, } hmap_init(&table->rows); ovs_list_init(&table->track_list); - shash_init(&table->outstanding_col_fetch_reqs); + sset_init(&table->outstanding_col_fetch_reqs); table->n_on_demand_columns = 0; table->change_seqno[OVSDB_IDL_CHANGE_INSERT] = table->change_seqno[OVSDB_IDL_CHANGE_MODIFY] @@ -329,7 +332,7 @@ ovsdb_idl_destroy(struct ovsdb_idl *idl) struct ovsdb_idl_table *table = &idl->tables[i]; shash_destroy(&table->columns); hmap_destroy(&table->rows); - shash_destroy(&table->outstanding_col_fetch_reqs); + sset_destroy(&table->outstanding_col_fetch_reqs); free(table->modes); } shash_destroy(&idl->table_by_name); @@ -339,7 +342,17 @@ ovsdb_idl_destroy(struct ovsdb_idl *idl) json_destroy(idl->lock_request_id); json_destroy(idl->schema); hmap_destroy(&idl->outstanding_txns); + + struct ovsdb_idl_fetch_node *fetch, *next; + HMAP_FOR_EACH_SAFE (fetch, next, hmap_node, + &idl->outstanding_fetch_reqs) { + hmap_remove(&idl->outstanding_fetch_reqs, &fetch->hmap_node); + json_destroy(fetch->id); + free(fetch->columns); + free(fetch); + } hmap_destroy(&idl->outstanding_fetch_reqs); + free(idl); } } @@ -392,8 +405,8 @@ ovsdb_idl_clear(struct ovsdb_idl *idl) void ovsdb_idl_run(struct ovsdb_idl *idl) { + struct ovsdb_idl_fetch_node *fetch_node; int i; - struct hmap_node *hmap_node; ovs_assert(!idl->txn); jsonrpc_session_run(idl->session); @@ -436,11 +449,9 @@ ovsdb_idl_run(struct ovsdb_idl *idl) } else if (msg->type == JSONRPC_REPLY && msg->result->type == JSON_ARRAY && msg->result->u.array.n == 1 - && (hmap_node = - hmap_first_with_hash(&idl->outstanding_fetch_reqs, - json_hash(msg->id, 0))) != NULL) { + && (fetch_node = ovsdb_idl_find_fetch_node(idl, + msg->id))) { /* On-demand fetch reply received. */ - ovsdb_idl_parse_fetch_reply(idl, hmap_node, + ovsdb_idl_parse_fetch_reply(idl, fetch_node, msg->result->u.array.elems[0]); } else if (msg->type == JSONRPC_REPLY && idl->request_id @@ -689,8 +700,8 @@ add_ref_table(struct ovsdb_idl *idl, const struct ovsdb_base_type *base) } /* - * Turns on OVSDB_IDL_MANUAL_FETCH for 'column' in 'idl'. Columns in this mode - * are not synchronized automatically. + * Turns on OVSDB_IDL_ON_DEMAND for 'column' in 'idl'. Columns in this + mode are + * not synchronized automatically. * * In order to get its value from the database, it is necessary to explicity * ask them from the server by calling one of this functions: @@ -1272,6 +1283,21 @@ ovsdb_idl_parse_update__(struct ovsdb_idl *idl, return NULL; } +/* Searches the set of on-demand fetch requests in 'idl' for one with +an ID + * matching 'id', and returns it if successful, otherwise NULL. */ +static struct ovsdb_idl_fetch_node * ovsdb_idl_find_fetch_node(struct +ovsdb_idl *idl, const struct json *id) { + struct ovsdb_idl_fetch_node *node; + HMAP_FOR_EACH_WITH_HASH (node, hmap_node, json_hash(id, 0), + &idl->outstanding_fetch_reqs) { + if (json_equal(node->id, id)) { + return node; + } + } + return NULL; +} + /* Processes the on-demand fetch reply 'msg' and updates 'idl'. * * 'pending_node' is the node inside the outstanding_fetch_reqs that contains @@ -1281,17 +1307,12 @@ ovsdb_idl_parse_update__(struct ovsdb_idl *idl, */ static void ovsdb_idl_parse_fetch_reply(struct ovsdb_idl *idl, - struct hmap_node *pending_node, + struct ovsdb_idl_fetch_node *fetch_node, const struct json *msg) { struct ovsdb_error *error = NULL; - struct ovsdb_idl_fetch_node *fetch_node; struct json *rows; - /* Retrive the fetch node from the pending fetch hmap */ - fetch_node = CONTAINER_OF(pending_node, struct ovsdb_idl_fetch_node, - hmap_node); - if (msg->type != JSON_OBJECT) { error = ovsdb_syntax_error(msg, NULL, "Result is not an object"); } else { @@ -1306,12 +1327,10 @@ ovsdb_idl_parse_fetch_reply(struct ovsdb_idl *idl, } } - hmap_remove(&idl->outstanding_fetch_reqs, pending_node); - if (fetch_node->columns) { - free(fetch_node->columns); - } - - free(pending_node); + hmap_remove(&idl->outstanding_fetch_reqs, &fetch_node->hmap_node); + json_destroy(fetch_node->id); + free(fetch_node->columns); + free(fetch_node); if (error) { if (!VLOG_DROP_WARN(&syntax_rl)) { @@ -1416,13 +1435,13 @@ ovsdb_idl_parse_fetch_reply__(struct ovsdb_idl *idl, break; case OVSDB_IDL_COLUMN_FETCH: if (column) { - shash_find_and_delete(&table->outstanding_col_fetch_reqs, - column->name); + sset_find_and_delete(&table->outstanding_col_fetch_reqs, + column->name); } break; case OVSDB_IDL_ROW_FETCH: if (row) { - row->outstanding_fetch_reqs--; + row->n_fetch_reqs--; } break; default: @@ -1819,7 +1838,7 @@ ovsdb_idl_row_create__(const struct ovsdb_idl_table_class *class) ovs_list_init(&row->dst_arcs); hmap_node_nullify(&row->txn_node); ovs_list_init(&row->track_node); - row->outstanding_fetch_reqs = 0; + row->n_fetch_reqs = 0; return row; } @@ -2118,7 +2137,7 @@ ovsdb_idl_get(const struct ovsdb_idl_row *row, bool ovsdb_idl_is_row_fetch_pending(const struct ovsdb_idl_row *row) { - return row->outstanding_fetch_reqs > 0; + return row->n_fetch_reqs > 0; } /* Return true if 'column' has a pending fetch operation @@ -2139,8 +2158,7 @@ ovsdb_idl_is_column_fetch_pending(struct ovsdb_idl * idl, shash_node = shash_find(&idl->table_by_name, tc->name); table = shash_node->data; - return shash_find(&table->outstanding_col_fetch_reqs, - column->name) != NULL; + return sset_contains(&table->outstanding_col_fetch_reqs, + column->name); } /* Return true if 'table' has a pending fetch operation. @@ -2181,8 +2199,8 @@ ovsdb_idl_clear_on_demand_pending_flags(struct ovsdb_idl *idl) break; case OVSDB_IDL_COLUMN_FETCH: for (int i = 0; i < fetch_node->n_columns; ++i) { - shash_find_and_delete(&table->outstanding_col_fetch_reqs, - fetch_node->columns[i]->name); + sset_find_and_delete(&table->outstanding_col_fetch_reqs, + fetch_node->columns[i]->name); } break; case OVSDB_IDL_ROW_FETCH: @@ -2192,7 +2210,7 @@ ovsdb_idl_clear_on_demand_pending_flags(struct ovsdb_idl *idl) /* It could be possible that the row is no longer part of the * replica */ if (row) { - row->outstanding_fetch_reqs--; + row->n_fetch_reqs--; } break; default: @@ -2210,30 +2228,23 @@ ovsdb_idl_clear_on_demand_pending_flags(struct ovsdb_idl *idl) static void ovsdb_idl_resend_on_demand_requests(struct ovsdb_idl *idl) { - struct ovsdb_idl_fetch_node **pending_requests; - struct ovsdb_idl_fetch_node *fetch_node; - int requests = idl->outstanding_fetch_reqs.n; - int i = 0; - - pending_requests = - xmalloc(sizeof (struct ovsdb_idl_fetch_node *) * requests); - HMAP_FOR_EACH(fetch_node, hmap_node, &idl->outstanding_fetch_reqs) { - pending_requests[i++] = fetch_node; - } - - hmap_clear(&idl->outstanding_fetch_reqs); + struct hmap old_reqs = HMAP_INITIALIZER(&old_reqs); + hmap_swap(&idl->outstanding_fetch_reqs, &old_reqs); - for (i = 0; i < requests; ++i) { - ovsdb_idl_send_on_demand_request(idl, pending_requests[i]); + struct ovsdb_idl_fetch_node *fetch, *next; + HMAP_FOR_EACH_SAFE (fetch, next, hmap_node, &idl->outstanding_fetch_reqs) { + hmap_remove(&idl->outstanding_fetch_reqs, &fetch->hmap_node); + ovsdb_idl_send_on_demand_request(idl, fetch); } - - free(pending_requests); + hmap_destroy(&old_reqs); } /* Sends an on-demand request using the information from 'fetch_node'. * * Depending on the fetch request, this function marks as pending the * corresponding element (row, column, or table) in 'idl'. + * + * Takes ownership of 'fetch_node'. */ static void ovsdb_idl_send_on_demand_request(struct ovsdb_idl *idl, @@ -2244,7 +2255,6 @@ ovsdb_idl_send_on_demand_request(struct ovsdb_idl *idl, struct json *request; struct json *op; struct json *columns; - struct json *fetch_id; int status; table = fetch_node->table; @@ -2272,18 +2282,20 @@ ovsdb_idl_send_on_demand_request(struct ovsdb_idl *idl, status = jsonrpc_session_send(idl->session, jsonrpc_create_request("transact", request, - &fetch_id)); + + &fetch_node->id)); if (status) { VLOG_WARN_RL(&syntax_rl, "Error while sending on-demand fetch request (%s)", ovs_strerror(status)); - json_destroy(fetch_id); + json_destroy(fetch_node->id); + free(fetch_node->columns); + free(fetch_node); return; } hmap_insert(&idl->outstanding_fetch_reqs, &fetch_node->hmap_node, - json_hash(fetch_id, 0)); + json_hash(fetch_node->id, 0)); /* Mark the corresponding level of the request as pending. */ switch (fetch_node->fetch_type) { @@ -2292,22 +2304,20 @@ ovsdb_idl_send_on_demand_request(struct ovsdb_idl *idl, break; case OVSDB_IDL_COLUMN_FETCH: for (int i = 0; i < fetch_node->n_columns; ++i) { - shash_add(&table->outstanding_col_fetch_reqs, - fetch_node->columns[i]->name, NULL); + sset_add(&table->outstanding_col_fetch_reqs, + fetch_node->columns[i]->name); } break; case OVSDB_IDL_ROW_FETCH: row = CONST_CAST(struct ovsdb_idl_row *, ovsdb_idl_get_row_for_uuid(idl, table->class, &fetch_node->row_uuid)); - row->outstanding_fetch_reqs++; + row->n_fetch_reqs++; break; default: OVS_NOT_REACHED(); break; } - - json_destroy(fetch_id); } /* This function fetches the value of 'column' for the especified 'row'. --8<--------------------------cut here-------------------------->8-- From: Sebastian Arguello <sebastian.argue...@hpe.com> Date: Mon, 29 Feb 2016 07:43:10 -0800 Subject: [PATCH] ovsdb-idl: Add on-demand columns tests Add tests for the OVSDB IDL on-demand column mode. This commit includes three tests to verify the correct functionality of the on-demand fetching at row, column, and table level. Co-Authored-By: Randall Esquivel <randall.esqui...@hpe.com> Co-Authored-By: Arnoldo Lutz <arnoldo.lutz.guev...@hpe.com> Signed-off-by: Sebastian Arguello <sebastian.argue...@hpe.com> Signed-off-by: Arnoldo Lutz <arnoldo.lutz.guev...@hpe.com> Signed-off-by: Randall Esquivel <randall.esqui...@hpe.com> --- tests/ovsdb-idl.at | 165 ++++++++++++++++++++++++++++++++++++ tests/test-ovsdb.c | 243 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 408 insertions(+) diff --git a/tests/ovsdb-idl.at b/tests/ovsdb-idl.at index 33d508c..efd8217 100644 --- a/tests/ovsdb-idl.at +++ b/tests/ovsdb-idl.at @@ -800,3 +800,168 @@ OVSDB_CHECK_IDL_TRACK([track, simple idl, initially empty, various ops], 014: updated columns: ba i ia r ra s 015: done ]]) + +m4_define([OVSDB_CHECK_IDL_ON_DEMAND_FETCH_COL_ROW_C], + [AT_SETUP([$1 - C]) + AT_KEYWORDS([ovsdb idl on-demand fetch positive $5]) + AT_CHECK([ovsdb-tool create db $abs_srcdir/idltest.ovsschema], + [0], [stdout], [ignore]) + AT_CHECK([ovsdb-server '-vPATTERN:console:ovsdb-server|%c|%m' --detach --no-chdir --pidfile="`pwd`"/pid --remote=punix:socket --unixctl="`pwd`"/unixctl db], [0], [ignore], [ignore]) + m4_if([$2], [], [], + [AT_CHECK([ovsdb-client transact unix:socket $2], [0], [ignore], [ignore], [kill `cat pid`])]) + AT_CHECK([test-ovsdb '-vPATTERN:console:test-ovsdb|%c|%m' -vjsonrpc -t10 -c idl-fetch-column-row unix:socket $2], + [0], [stdout], [ignore], [kill `cat pid`]) + AT_CHECK([sort stdout | ${PERL} $srcdir/uuidfilt.pl]m4_if([$6],,, [[| $6]]), + [0], [$3], [], [kill `cat pid`]) + OVSDB_SERVER_SHUTDOWN + AT_CLEANUP]) + +m4_define([OVSDB_CHECK_IDL_ON_DEMAND_FETCH_COL_ROW], + [OVSDB_CHECK_IDL_ON_DEMAND_FETCH_COL_ROW_C($@)]) + +OVSDB_CHECK_IDL_ON_DEMAND_FETCH_COL_ROW([on-demand-fetch-col-row, +simple idl, initially populated], + [['["idltest", + {"op": "insert", + "table": "simple", + "row": {"i": 1, + "r": 2.0, + "b": true, + "s": "name", + "u": ["uuid", "84f5c8f5-ac76-4dbc-a24f-8860eb407fc1"], + "ia": ["set", [1, 2, 3]], + "ra": ["set", [-0.5]], + "ba": ["set", [true]], + "sa": ["set", ["abc", "def"]], + "ua": ["set", [["uuid", "69443985-7806-45e2-b35f-574a04e720f9"], + ["uuid", "aad11ef0-816a-4b01-93e6-03b8b4256b98"]]]}}, + {"op": "insert", + "table": "simple", + "row": {"i": 1, + "r": 2.0, + "b": true, + "s": "name", + "u": ["uuid", "84f5c8f5-ac76-4dbc-a24f-8860eb407fc1"], + "ia": ["set", [1, 2, 3]], + "ra": ["set", [-0.5]], + "ba": ["set", [true]], + "sa": ["set", ["abc", "def"]], + "ua": ["set", [["uuid", "69443985-7806-45e2-b35f-574a04e720f9"], + ["uuid", +"aad11ef0-816a-4b01-93e6-03b8b4256b98"]]]}} + ]']], + [[000: Initial. On-demand columns: [s ia ua] +000: i=1 r=2 b=true s= u=<0> ia=[] ra=[-0.5] ba=[true] sa=[abc def] +ua=[] uuid=<1> +001: i=1 r=2 b=true s= u=<0> ia=[] ra=[-0.5] ba=[true] sa=[abc def] +ua=[] uuid=<2> +002: After changes with fetch for ua column in only one row +002: i=1 r=2 b=true s= u=<0> ia=[] ra=[-0.5] ba=[true] sa=[abc def] +ua=[<3> <4>] uuid=<1> +003: i=1 r=2 b=true s= u=<0> ia=[] ra=[-0.5] ba=[true] sa=[abc def] +ua=[] uuid=<2> +]]) + +m4_define([OVSDB_CHECK_IDL_ON_DEMAND_FETCH_COLUMN_C], + [AT_SETUP([$1 - C]) + AT_KEYWORDS([ovsdb idl on-demand fetch positive $5]) + AT_CHECK([ovsdb-tool create db $abs_srcdir/idltest.ovsschema], + [0], [stdout], [ignore]) + AT_CHECK([ovsdb-server '-vPATTERN:console:ovsdb-server|%c|%m' --detach --no-chdir --pidfile="`pwd`"/pid --remote=punix:socket --unixctl="`pwd`"/unixctl db], [0], [ignore], [ignore]) + m4_if([$2], [], [], + [AT_CHECK([ovsdb-client transact unix:socket $2], [0], [ignore], [ignore], [kill `cat pid`])]) + AT_CHECK([test-ovsdb '-vPATTERN:console:test-ovsdb|%c|%m' -vjsonrpc -t10 -c idl-fetch-column unix:socket $2], + [0], [stdout], [ignore], [kill `cat pid`]) + AT_CHECK([sort stdout | ${PERL} $srcdir/uuidfilt.pl]m4_if([$6],,, [[| $6]]), + [0], [$3], [], [kill `cat pid`]) + OVSDB_SERVER_SHUTDOWN + AT_CLEANUP]) + +m4_define([OVSDB_CHECK_IDL_ON_DEMAND_FETCH_COLUMN], + [OVSDB_CHECK_IDL_ON_DEMAND_FETCH_COLUMN_C($@)]) + +OVSDB_CHECK_IDL_ON_DEMAND_FETCH_COLUMN([on-demand-fetch-column, simple +idl, initially populated], + [['["idltest", + {"op": "insert", + "table": "simple", + "row": {"i": 1, + "r": 2.0, + "b": true, + "s": "name", + "u": ["uuid", "84f5c8f5-ac76-4dbc-a24f-8860eb407fc1"], + "ia": ["set", [1, 2, 3]], + "ra": ["set", [-0.5]], + "ba": ["set", [true]], + "sa": ["set", ["abc", "def"]], + "ua": ["set", [["uuid", "69443985-7806-45e2-b35f-574a04e720f9"], + ["uuid", "aad11ef0-816a-4b01-93e6-03b8b4256b98"]]]}}, + {"op": "insert", + "table": "simple", + "row": {"i": 1, + "r": 2.0, + "b": true, + "s": "name", + "u": ["uuid", "84f5c8f5-ac76-4dbc-a24f-8860eb407fc1"], + "ia": ["set", [1, 2, 3]], + "ra": ["set", [-0.5]], + "ba": ["set", [true]], + "sa": ["set", ["abc", "def"]], + "ua": ["set", [["uuid", "69443985-7806-45e2-b35f-574a04e720f9"], + ["uuid", +"aad11ef0-816a-4b01-93e6-03b8b4256b98"]]]}} + ]']], + [[000: Initial. On-demand columns: [s ia ua] +000: i=1 r=2 b=true s= u=<0> ia=[] ra=[-0.5] ba=[true] sa=[abc def] +ua=[] uuid=<1> +001: i=1 r=2 b=true s= u=<0> ia=[] ra=[-0.5] ba=[true] sa=[abc def] +ua=[] uuid=<2> +002: After fetch for entire s column +002: i=1 r=2 b=true s=name u=<0> ia=[] ra=[-0.5] ba=[true] sa=[abc def] +ua=[] uuid=<1> +003: i=1 r=2 b=true s=name u=<0> ia=[] ra=[-0.5] ba=[true] sa=[abc def] +ua=[] uuid=<2> +]]) + +m4_define([OVSDB_CHECK_IDL_ON_DEMAND_FETCH_TABLE_C], + [AT_SETUP([$1 - C]) + AT_KEYWORDS([ovsdb idl on-demand fetch positive $5]) + AT_CHECK([ovsdb-tool create db $abs_srcdir/idltest.ovsschema], + [0], [stdout], [ignore]) + AT_CHECK([ovsdb-server '-vPATTERN:console:ovsdb-server|%c|%m' --detach --no-chdir --pidfile="`pwd`"/pid --remote=punix:socket --unixctl="`pwd`"/unixctl db], [0], [ignore], [ignore]) + m4_if([$2], [], [], + [AT_CHECK([ovsdb-client transact unix:socket $2], [0], [ignore], [ignore], [kill `cat pid`])]) + AT_CHECK([test-ovsdb '-vPATTERN:console:test-ovsdb|%c|%m' -vjsonrpc -t10 -c idl-fetch-table unix:socket $2], + [0], [stdout], [ignore], [kill `cat pid`]) + AT_CHECK([sort stdout | ${PERL} $srcdir/uuidfilt.pl]m4_if([$6],,, [[| $6]]), + [0], [$3], [], [kill `cat pid`]) + OVSDB_SERVER_SHUTDOWN + AT_CLEANUP]) + +m4_define([OVSDB_CHECK_IDL_ON_DEMAND_FETCH_TABLE], + [OVSDB_CHECK_IDL_ON_DEMAND_FETCH_TABLE_C($@)]) + +OVSDB_CHECK_IDL_ON_DEMAND_FETCH_TABLE([on-demand-fetch-table, simple +idl, initially populated], + [['["idltest", + {"op": "insert", + "table": "simple", + "row": {"i": 1, + "r": 2.0, + "b": true, + "s": "name", + "u": ["uuid", "84f5c8f5-ac76-4dbc-a24f-8860eb407fc1"], + "ia": ["set", [1, 2, 3]], + "ra": ["set", [-0.5]], + "ba": ["set", [true]], + "sa": ["set", ["abc", "def"]], + "ua": ["set", [["uuid", "69443985-7806-45e2-b35f-574a04e720f9"], + ["uuid", "aad11ef0-816a-4b01-93e6-03b8b4256b98"]]]}}, + {"op": "insert", + "table": "simple", + "row": {"i": 1, + "r": 2.0, + "b": true, + "s": "name", + "u": ["uuid", "84f5c8f5-ac76-4dbc-a24f-8860eb407fc1"], + "ia": ["set", [1, 2, 3]], + "ra": ["set", [-0.5]], + "ba": ["set", [true]], + "sa": ["set", ["abc", "def"]], + "ua": ["set", [["uuid", "69443985-7806-45e2-b35f-574a04e720f9"], + ["uuid", +"aad11ef0-816a-4b01-93e6-03b8b4256b98"]]]}} + ]']], + [[000: Initial. On-demand columns: [s ia ua] +000: i=1 r=2 b=true s= u=<0> ia=[] ra=[-0.5] ba=[true] sa=[abc def] +ua=[] uuid=<1> +001: i=1 r=2 b=true s= u=<0> ia=[] ra=[-0.5] ba=[true] sa=[abc def] +ua=[] uuid=<2> +002: After complete table fetch +002: i=1 r=2 b=true s=name u=<0> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc +def] ua=[<3> <4>] uuid=<1> +003: i=1 r=2 b=true s=name u=<0> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc +def] ua=[<3> <4>] uuid=<2> +]]) diff --git a/tests/test-ovsdb.c b/tests/test-ovsdb.c index dbb6897..1633c0d 100644 --- a/tests/test-ovsdb.c +++ b/tests/test-ovsdb.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2015 Nicira, Inc. + * Copyright (C) 2016 Hewlett Packard Enterprise Development LP * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -198,6 +199,11 @@ usage(void) " connect to SERVER and dump the contents of the database\n" " as seen initially by the IDL implementation and after\n" " executing each TRANSACTION. (Each TRANSACTION must modify\n" + " the database or this command will hang.)\n" + " idl-fetch SERVER [TRANSACTION...]\n" + " connect to SERVER and dump the contents of the database\n" + " as seen initially by the IDL implementation and after\n" + " executing each TRANSACTION. (Each TRANSACTION must modify\n" " the database or this command will hang.)\n", program_name, program_name); vlog_usage(); @@ -2179,6 +2185,240 @@ do_idl(struct ovs_cmdl_context *ctx) printf("%03d: done\n", step); } +static void +do_fetch_column_row(struct ovs_cmdl_context *ctx) { + struct jsonrpc *rpc; + struct ovsdb_idl *idl; + unsigned int seqno = 0; + int step = 0; + int error; + const struct idltest_simple *s; + + idltest_init(); + + idl = ovsdb_idl_create(ctx->argv[1], &idltest_idl_class, true, true); + if (ctx->argc > 2) { + struct stream *stream; + + error = stream_open_block(jsonrpc_stream_open(ctx->argv[1], &stream, + DSCP_DEFAULT), &stream); + if (error) { + ovs_fatal(error, "failed to connect to \"%s\"", ctx->argv[1]); + } + rpc = jsonrpc_open(stream); + } else { + rpc = NULL; + } + + ovsdb_idl_add_table(idl, &idltest_table_simple); + ovsdb_idl_add_column(idl, &idltest_simple_col_b); + ovsdb_idl_add_column(idl, &idltest_simple_col_ba); + ovsdb_idl_add_column(idl, &idltest_simple_col_i); + ovsdb_idl_add_on_demand_column(idl, &idltest_table_simple, + &idltest_simple_col_ia); + ovsdb_idl_add_column(idl, &idltest_simple_col_r); + ovsdb_idl_add_column(idl, &idltest_simple_col_ra); + ovsdb_idl_add_column(idl, &idltest_simple_col_sa); + ovsdb_idl_add_column(idl, &idltest_simple_col_u); + ovsdb_idl_add_on_demand_column(idl, &idltest_table_simple, + &idltest_simple_col_s); + ovsdb_idl_add_on_demand_column(idl, &idltest_table_simple, + &idltest_simple_col_ua); + + ovsdb_idl_get_initial_snapshot(idl); + ovsdb_idl_run(idl); + + /* Wait for update. */ + for (;;) { + ovsdb_idl_run(idl); + if (ovsdb_idl_get_seqno(idl) != seqno) { + break; + } + jsonrpc_run(rpc); + + ovsdb_idl_wait(idl); + jsonrpc_wait(rpc); + poll_block(); + } + + /* Print initial simple data without fetching column. */ + printf("%03d: Initial. On-demand columns: [s ia ua]\n", step); + s = idltest_simple_first(idl); + IDLTEST_SIMPLE_FOR_EACH(s, idl) { + print_idl_row_simple(s, step++); + } + + /* get ondemand column of second row */ + printf("%03d: After changes with fetch for ua column in only one row\n", + step); + s = idltest_simple_first(idl); + idltest_simple_fetch_ua(idl, s); + do { + ovsdb_idl_run(idl); + } while (idltest_simple_is_row_fetch_pending(s)); + IDLTEST_SIMPLE_FOR_EACH(s, idl) { + print_idl_row_simple(s, step++); + } + + ovsdb_idl_destroy(idl); +} + +static void +do_fetch_column(struct ovs_cmdl_context *ctx) { + struct jsonrpc *rpc; + struct ovsdb_idl *idl; + unsigned int seqno = 0; + int step = 0; + int error; + const struct idltest_simple *s; + + idltest_init(); + + idl = ovsdb_idl_create(ctx->argv[1], &idltest_idl_class, true, true); + if (ctx->argc > 2) { + struct stream *stream; + + error = stream_open_block(jsonrpc_stream_open(ctx->argv[1], &stream, + DSCP_DEFAULT), &stream); + if (error) { + ovs_fatal(error, "failed to connect to \"%s\"", ctx->argv[1]); + } + rpc = jsonrpc_open(stream); + } else { + rpc = NULL; + } + + ovsdb_idl_add_table(idl, &idltest_table_simple); + ovsdb_idl_add_column(idl, &idltest_simple_col_b); + ovsdb_idl_add_column(idl, &idltest_simple_col_ba); + ovsdb_idl_add_column(idl, &idltest_simple_col_i); + ovsdb_idl_add_on_demand_column(idl, &idltest_table_simple, + &idltest_simple_col_ia); + ovsdb_idl_add_column(idl, &idltest_simple_col_r); + ovsdb_idl_add_column(idl, &idltest_simple_col_ra); + ovsdb_idl_add_column(idl, &idltest_simple_col_sa); + ovsdb_idl_add_column(idl, &idltest_simple_col_u); + ovsdb_idl_add_on_demand_column(idl, &idltest_table_simple, + &idltest_simple_col_s); + ovsdb_idl_add_on_demand_column(idl, &idltest_table_simple, + &idltest_simple_col_ua); + + ovsdb_idl_get_initial_snapshot(idl); + ovsdb_idl_run(idl); + + /* Wait for update. */ + for (;;) { + ovsdb_idl_run(idl); + if (ovsdb_idl_get_seqno(idl) != seqno) { + break; + } + jsonrpc_run(rpc); + + ovsdb_idl_wait(idl); + jsonrpc_wait(rpc); + poll_block(); + } + + /* Print initial simple data without fetching column. */ + printf("%03d: Initial. On-demand columns: [s ia ua]\n", step); + s = idltest_simple_first(idl); + IDLTEST_SIMPLE_FOR_EACH(s, idl) { + print_idl_row_simple(s, step++); + } + + /* Print simple data after fetching s column */ + printf("%03d: After fetch for entire s column\n", step); + s = idltest_simple_first(idl); + idltest_simple_fetch_col_s(idl); + do { + ovsdb_idl_run(idl); + } while (idltest_simple_is_s_fetch_pending(idl)); + IDLTEST_SIMPLE_FOR_EACH(s, idl) { + print_idl_row_simple(s, step++); + } + + ovsdb_idl_destroy(idl); +} + +static void +do_fetch_table(struct ovs_cmdl_context *ctx) { + struct jsonrpc *rpc; + struct ovsdb_idl *idl; + unsigned int seqno = 0; + int step = 0; + int error; + const struct idltest_simple *s; + + idltest_init(); + + idl = ovsdb_idl_create(ctx->argv[1], &idltest_idl_class, true, true); + if (ctx->argc > 2) { + struct stream *stream; + + error = stream_open_block(jsonrpc_stream_open(ctx->argv[1], &stream, + DSCP_DEFAULT), &stream); + if (error) { + ovs_fatal(error, "failed to connect to \"%s\"", ctx->argv[1]); + } + rpc = jsonrpc_open(stream); + } else { + rpc = NULL; + } + + ovsdb_idl_add_table(idl, &idltest_table_simple); + ovsdb_idl_add_column(idl, &idltest_simple_col_b); + ovsdb_idl_add_column(idl, &idltest_simple_col_ba); + ovsdb_idl_add_column(idl, &idltest_simple_col_i); + ovsdb_idl_add_on_demand_column(idl, &idltest_table_simple, + &idltest_simple_col_ia); + ovsdb_idl_add_column(idl, &idltest_simple_col_r); + ovsdb_idl_add_column(idl, &idltest_simple_col_ra); + ovsdb_idl_add_column(idl, &idltest_simple_col_sa); + ovsdb_idl_add_column(idl, &idltest_simple_col_u); + ovsdb_idl_add_on_demand_column(idl, &idltest_table_simple, + &idltest_simple_col_s); + ovsdb_idl_add_on_demand_column(idl, &idltest_table_simple, + &idltest_simple_col_ua); + + ovsdb_idl_get_initial_snapshot(idl); + ovsdb_idl_run(idl); + + /* Wait for update. */ + for (;;) { + ovsdb_idl_run(idl); + if (ovsdb_idl_get_seqno(idl) != seqno) { + break; + } + jsonrpc_run(rpc); + + ovsdb_idl_wait(idl); + jsonrpc_wait(rpc); + poll_block(); + } + + /* Print initial simple data without fetching column. */ + printf("%03d: Initial. On-demand columns: [s ia ua]\n", step); + s = idltest_simple_first(idl); + IDLTEST_SIMPLE_FOR_EACH(s, idl) { + print_idl_row_simple(s, step++); + } + + /* fetch complete table */ + printf("%03d: After complete table fetch\n", step); + idltest_simple_fetch_table(idl); + do { + ovsdb_idl_run(idl); + } while (idltest_simple_is_table_fetch_pending(idl)); + IDLTEST_SIMPLE_FOR_EACH(s, idl) { + print_idl_row_simple(s, step++); + } + + ovsdb_idl_destroy(idl); +} + static struct ovs_cmdl_command all_commands[] = { { "log-io", NULL, 2, INT_MAX, do_log_io }, { "default-atoms", NULL, 0, 0, do_default_atoms }, @@ -2207,6 +2447,9 @@ static struct ovs_cmdl_command all_commands[] = { { "execute", NULL, 2, INT_MAX, do_execute }, { "trigger", NULL, 2, INT_MAX, do_trigger }, { "idl", NULL, 1, INT_MAX, do_idl }, + { "idl-fetch-column-row", NULL, 1, INT_MAX, do_fetch_column_row }, + { "idl-fetch-column", NULL, 1, INT_MAX, do_fetch_column }, + { "idl-fetch-table", NULL, 1, INT_MAX, do_fetch_table }, { "help", NULL, 0, INT_MAX, do_help }, { NULL, NULL, 0, 0, NULL }, }; -- 2.1.3 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev