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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
Co-Authored-By: Arnoldo Lutz <[email protected]>
Signed-off-by: Sebastian Arguello <[email protected]>
Signed-off-by: Arnoldo Lutz <[email protected]>
Signed-off-by: Randall Esquivel <[email protected]>
---
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
[email protected]
http://openvswitch.org/mailman/listinfo/dev