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

Reply via email to