[ovs-dev] [PATCH monitor_cond V2 04/12] ovsdb-client: support monitor-cond

Andy Zhou azhou at ovn.org
Fri Jan 22 01:32:19 UTC 2016


On Sat, Jan 16, 2016 at 12:16 AM, Liran Schour <lirans at il.ibm.com> wrote:

> Add monitor_cond method to ovsdb-client. Add unit tests.
> See ovsdb-client(1) man page for details.
>
> Signed-off-by: Liran Schour <lirans at il.ibm.com>
> ---
>  NEWS                    |   3 +-
>  ovsdb/ovsdb-client.1.in |  37 +++++-----
>  ovsdb/ovsdb-client.c    |  74 ++++++++++++++------
>  tests/ovsdb-monitor.at  | 178
> ++++++++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 252 insertions(+), 40 deletions(-)
>
> diff --git a/NEWS b/NEWS
> index 4433329..21a6f63 100644
> --- a/NEWS
> +++ b/NEWS
> @@ -1,7 +1,8 @@
>  Post-v2.5.0
>  ---------------------
>     - ovsdb-server:
> -     * New "monitor2" and "update2" extensions to RFC 7047.
> +     * New "monitor_cond" "monitor_cond_chane" and "update2" extensions to
>

s/monitor_cond_chane/monitor_cond_update/

+     RFC 7047.
>     - OpenFlow:
>       * OpenFlow 1.1+ OFPT_QUEUE_GET_CONFIG_REQUEST now supports OFPP_ANY.
>
> diff --git a/ovsdb/ovsdb-client.1.in b/ovsdb/ovsdb-client.1.in
> index 5d99f59..1d58db8 100644
> --- a/ovsdb/ovsdb-client.1.in
> +++ b/ovsdb/ovsdb-client.1.in
> @@ -33,10 +33,8 @@ ovsdb\-client \- command-line interface to
> \fBovsdb-server\fR(1)
>  .br
>  \fBovsdb\-client \fR[\fIoptions\fR] \fBmonitor\fI \fR[\fIserver\fR]
> \fR[\fIdatabase\fR] \fBALL\fR
>  .br
> -\fBovsdb\-client \fR[\fIoptions\fR] \fBmonitor2\fI \fR[\fIserver\fR]
> \fR[\fIdatabase\fR] \fItable\fR
> -[\fIcolumn\fR[\fB,\fIcolumn\fR]...]...
> -.br
> -\fBovsdb\-client \fR[\fIoptions\fR] \fBmonitor2\fI \fR[\fIserver\fR]
> \fR[\fIdatabase\fR] \fBALL\fR
> +\fBovsdb\-client \fR[\fIoptions\fR] \fBmonitor-cond\fI \fR[\fIserver\fR]
> \fR[\fIdatabase\fR] \fItable\fR
> +\fIconditions [\fIcolumn\fR[\fB,\fIcolumn\fR]...]...
>  .br
>  \fBovsdb\-client help\fR
>  .IP "Output formatting options:"
> @@ -113,12 +111,12 @@ specified, only that table is retrieved.  If at
> least one \fIcolumn\fR
>  is specified, only those columns are retrieved.
>  .
>  .IP "\fBmonitor\fI \fR[\fIserver\fR] \fR[\fIdatabase\fR] \fItable\fR
> [\fIcolumn\fR[\fB,\fIcolumn\fR]...]..."
> -.IQ "\fBmonitor2\fI \fR[\fIserver\fR] \fR[\fIdatabase\fR] \fItable\fR
> [\fIcolumn\fR[\fB,\fIcolumn\fR]...]..."
> -Connects to \fIserver\fR and monitors the contents of \fItable\fR in
> -\fIdatabase\fR.  By default, the initial contents of \fItable\fR are
> -printed, followed by each change as it occurs.  If at least one
> -\fIcolumn\fR is specified, only those columns are monitored.  The
> -following \fIcolumn\fR names have special meanings:
> +.IQ "\fBmonitor-cond\fI \fR[\fIserver\fR] \fR[\fIdatabase\fR] \fItable\fR
> \fIconditions\fR [\fIcolumn\fR[\fB,\fIcolumn\fR]...]..."
>

Would it be more consistent to have ovsdb-client monitor-cond [server]
[database] conditions table [column[....   This should
also make sharing command line parsing between monitor and monitor-cond
less cumbersome.

+Connects to \fIserver\fR and monitors the contents of rows that match
> conditions in
> +\fItable\fR in \fIdatabase\fR. By default, the initial contents of
> \fItable\fR are
> +printed, followed by each change as it occurs.  If conditions is missing
> or emtpy,
> +all rows will be monitored. If at least one \fIcolumn\fR is specified,
> only those
> +columns are monitored.  The following \fIcolumn\fR names have special
> meanings:
>  .RS
>  .IP "\fB!initial\fR"
>  Do not print the initial contents of the specified columns.
> @@ -136,16 +134,18 @@ each group.  Whether multiple groups or only a
> single group is
>  specified, any given column may only be mentioned once on the command
>  line.
>  .IP
> -If \fB\-\-detach\fR is used with \fBmonitor\fR or \fBmointor2\fR, then
> +\fBconditions\fR is a JSON array of <condition> as defined in RFC 7047 5.1
> +with the following change: A condition can be either a 3-element JSON
> array
> +as deescribed in the RFC or a boolean value..
> +.IP
> +If \fB\-\-detach\fR is used with \fBmonitor\fR or \fBmointor-cond\fR, then
>  \fBovsdb\-client\fR detaches after it has successfully received and
>  printed the initial contents of \fItable\fR.
>  .IP
>  The \fBmonitor\fR command uses RFC 7047 "monitor" method to open a monitor
> -session with the server. The \fBmonitor2\fR command uses RFC 7047
> -extension "monitor2" method. See \fBovsdb\-server\fR(1) for details.
> -.
> +session with the server. The \fBmonitor-cond\fR command uses RFC 7047
> +extension "monitor_cond" method. See \fBovsdb\-server\fR(1) for details.
>  .IP "\fBmonitor\fI \fR[\fIserver\fR] \fR[\fIdatabase\fR] \fBALL\fR"
> -.IQ "\fBmonitor2\fI \fR[\fIserver\fR] \fR[\fIdatabase\fR] \fBALL\fR"
>  Connects to \fIserver\fR and monitors the contents of all tables in
>  \fIdatabase\fR.  Prints initial values and all kinds of changes to all
>  columns in the database.  The \fB\-\-detach\fR option causes
> @@ -153,8 +153,7 @@ columns in the database.  The \fB\-\-detach\fR option
> causes
>  prints the initial database contents.
>  .IP
>  The \fBmonitor\fR command uses RFC 7047 "monitor" method to open a monitor
> -session with the server. The \fBmonitor2\fR command uses RFC 7047
> -extension "monitor2" method. See \fBovsdb\-server\fR(1) for details.
> +session with the server.
>  .
>  .SH OPTIONS
>  .SS "Output Formatting Options"
> @@ -165,13 +164,13 @@ The following options controlling output formatting:
>  .so lib/table.man
>  .
>  .IP "\fB\-\-timestamp\fR"
> -For the \fBmonitor\fR and \fBmonitor2\fR commands, add a timestamp to each
> +For the \fBmonitor\fR and \fBmonitor-cond\fR commands, add a timestamp to
> each
>  table update.  Most output formats add the timestamp on a line of its own
>  just above the table.  The JSON output format puts the timestamp in a
>  member of the top-level JSON object named \fBtime\fR.
>  .
>  .SS "Daemon Options"
> -The daemon options apply only to the \fBmonitor\fR and \fBmonitor2\fR
> commands.
> +The daemon options apply only to the \fBmonitor\fR and \fBmonitor-cond\fR
> commands.
>  With any other command, they have no effect.
>  .ds DD
>  .so lib/daemon.man
> diff --git a/ovsdb/ovsdb-client.c b/ovsdb/ovsdb-client.c
> index 06155ec..e48677e 100644
> --- a/ovsdb/ovsdb-client.c
> +++ b/ovsdb/ovsdb-client.c
> @@ -38,6 +38,7 @@
>  #include "ovsdb.h"
>  #include "ovsdb-data.h"
>  #include "ovsdb-error.h"
> +#include "condition.h"
>  #include "poll-loop.h"
>  #include "sort.h"
>  #include "svec.h"
> @@ -261,7 +262,10 @@ usage(void)
>             "    in DATBASE on SERVER.\n"
>             "\n  monitor2 [SERVER] [DATABASE] ALL\n"
>             "    same usage as monitor, but uses \"monitor2\" method over"
> -           "    the wire."
> +           "    the wire.\n"
> +           "\n  monitor-cond [SERVER] [DATABASE] TABLE CONDITION
> [COLUMN,..]\n"
> +           "    conditionally monitor contents of COLUMNS in TABLE in\n"
> +           "    DATABASE on SERVER.\n"
>             "\n  dump [SERVER] [DATABASE]\n"
>             "    dump contents of DATABASE on SERVER to stdout\n"
>             "\nThe default SERVER is unix:%s/db.sock.\n"
> @@ -734,14 +738,13 @@ add_column(const char *server, const struct
> ovsdb_column *column,
>  static struct json *
>  parse_monitor_columns(char *arg, const char *server, const char *database,
>                        const struct ovsdb_table_schema *table,
> -                      struct ovsdb_column_set *columns)
> +                      struct ovsdb_column_set *columns, struct json *mr)
>  {
>      bool initial, insert, delete, modify;
> -    struct json *mr, *columns_json;
> +    struct json *columns_json;
>      char *save_ptr = NULL;
>      char *token;
>
> -    mr = json_object_create();
>      columns_json = json_array_create_empty();
>      json_object_put(mr, "columns", columns_json);
>
> @@ -841,12 +844,15 @@ static void
>  add_monitored_table(int argc, char *argv[],
>                      const char *server, const char *database,
>                      struct ovsdb_table_schema *table,
> +                    const bool conditional,
>                      struct json *monitor_requests,
>                      struct monitored_table **mts,
>                      size_t *n_mts, size_t *allocated_mts)
>
See comments above, It may be nicer to just pass in the 'mr' pointer, after
poping the conditions
from argc/argv.

>  {
> -    struct json *monitor_request_array;
> +    struct json *monitor_request_array, *condition;
>      struct monitored_table *mt;
> +    struct json *mr = json_object_create();;
> +    char *columns = NULL;
>
>      if (*n_mts >= *allocated_mts) {
>          *mts = x2nrealloc(*mts, allocated_mts, sizeof **mts);
> @@ -856,23 +862,38 @@ add_monitored_table(int argc, char *argv[],
>      ovsdb_column_set_init(&mt->columns);
>
>      monitor_request_array = json_array_create_empty();
> -    if (argc > 1) {
> -        int i;
>
> -        for (i = 1; i < argc; i++) {
> -            json_array_add(
> -                monitor_request_array,
> -                parse_monitor_columns(argv[i], server, database, table,
> -                                      &mt->columns));
> +    if (!conditional) {
> +        if (argc > 1) {
> +            columns = argv[1];
>          }
>      } else {
> +        struct ovsdb_condition cnd;
> +
> +        condition = parse_json(argv[1]);
> +        check_ovsdb_error(ovsdb_condition_from_json(table, condition,
> +                                                    NULL, &cnd));
> +        ovsdb_condition_destroy(&cnd);
> +
> +        json_object_put(mr, "where", condition);
> +
> +        if(argc > 2) {
> +            columns = argv[2];
> +        }
> +    }
> +
> +    if (columns) {
> +        json_array_add(monitor_request_array,
> +                       parse_monitor_columns(columns, server, database,
> table,
> +                                             &mt->columns, mr));
> +    } else {
>          /* Allocate a writable empty string since parse_monitor_columns()
>           * is going to strtok() it and that's risky with literal "". */
>          char empty[] = "";
>          json_array_add(
>              monitor_request_array,
>              parse_monitor_columns(empty, server, database,
> -                                  table, &mt->columns));
> +                                  table, &mt->columns, mr));
>      }
>
>      json_object_put(monitor_requests, table->name, monitor_request_array);
> @@ -893,7 +914,7 @@ destroy_monitored_table(struct monitored_table *mts,
> size_t n)
>
>  static void
>  do_monitor__(struct jsonrpc *rpc, const char *database,
> -             enum ovsdb_monitor_version version,
> +             enum ovsdb_monitor_version version, const bool conditional,
>
Do we need both version and conditional ?

>               int argc, char *argv[])
>  {
>      const char *server = jsonrpc_get_name(rpc);
> @@ -945,7 +966,7 @@ do_monitor__(struct jsonrpc *rpc, const char *database,
>                        server, database, table_name);
>          }
>
> -        add_monitored_table(argc, argv, server, database, table,
> +        add_monitored_table(argc, argv, server, database, table,
> conditional,
>                              monitor_requests, &mts, &n_mts,
> &allocated_mts);
>      } else {
>          size_t n = shash_count(&schema->tables);
> @@ -956,7 +977,7 @@ do_monitor__(struct jsonrpc *rpc, const char *database,
>              struct ovsdb_table_schema *table = nodes[i]->data;
>
>              add_monitored_table(argc, argv, server, database, table,
> -                                monitor_requests,
> +                                conditional, monitor_requests,
>                                  &mts, &n_mts, &allocated_mts);
>          }
>          free(nodes);
> @@ -964,8 +985,13 @@ do_monitor__(struct jsonrpc *rpc, const char
> *database,
>
>      monitor = json_array_create_3(json_string_create(database),
>                                    json_null_create(), monitor_requests);
> -    const char *method = version == OVSDB_MONITOR_V2 ? "monitor2"
> -                                                     : "monitor";
> +    const char *method;
> +    if (!conditional) {
> +        method = version == OVSDB_MONITOR_V2 ? "monitor2"
> +                                             : "monitor";
> +    } else {
> +        method = "monitor_cond";
> +    }
>
>      request = jsonrpc_create_request(method, monitor, NULL);
>      request_id = json_clone(request->id);
> @@ -1048,14 +1074,21 @@ static void
>  do_monitor(struct jsonrpc *rpc, const char *database,
>             int argc, char *argv[])
>  {
> -    do_monitor__(rpc, database, OVSDB_MONITOR_V1, argc, argv);
> +    do_monitor__(rpc, database, OVSDB_MONITOR_V1, false, argc, argv);
>  }
>
>  static void
>  do_monitor2(struct jsonrpc *rpc, const char *database,
>             int argc, char *argv[])
>  {
> -    do_monitor__(rpc, database, OVSDB_MONITOR_V2, argc, argv);
> +    do_monitor__(rpc, database, OVSDB_MONITOR_V2, false, argc, argv);
> +}
> +
> +static void
> +do_monitor_cond(struct jsonrpc *rpc, const char *database,
> +                int argc, char *argv[])
> +{
> +    do_monitor__(rpc, database, OVSDB_MONITOR_V2, true, argc, argv);
>  }
>
>  struct dump_table_aux {
> @@ -1329,6 +1362,7 @@ static const struct ovsdb_client_command
> all_commands[] = {
>      { "transact",           NEED_RPC,      1, 1,       do_transact },
>      { "monitor",            NEED_DATABASE, 1, INT_MAX, do_monitor },
>      { "monitor2",           NEED_DATABASE, 1, INT_MAX, do_monitor2 },
> +    { "monitor-cond",       NEED_DATABASE, 2, 3,       do_monitor_cond },
>      { "dump",               NEED_DATABASE, 0, INT_MAX, do_dump },
>      { "help",               NEED_NONE,     0, INT_MAX, do_help },
>
> diff --git a/tests/ovsdb-monitor.at b/tests/ovsdb-monitor.at
> index 0dbf5b0..9646a91 100644
> --- a/tests/ovsdb-monitor.at
> +++ b/tests/ovsdb-monitor.at
> @@ -44,6 +44,50 @@ m4_define([OVSDB_CHECK_MONITOR],
>     AT_CHECK([${PERL} $srcdir/ovsdb-monitor-sort.pl < output | ${PERL}
> $srcdir/uuidfilt.pl], [0], [$7], [ignore])
>     AT_CLEANUP])
>
> +# OVSDB_CHECK_MONITOR_COND(TITLE, SCHEMA, [PRE-MONITOR-TXN], DB, TABLE,
> +#                     TRANSACTIONS, OUTPUT, CONDITIONS, [COLUMNS],
> [KEYWORDS])
> +#
> +# Creates a database with the given SCHEMA, starts an ovsdb-server on
> +# that database, and runs each of the TRANSACTIONS (which should be a
> +# quoted list of quoted strings) against it with ovsdb-client one at a
> +# time.  COLUMNS, if specified, is passed to ovsdb-client as the set
> +# of columns and operations to select.
> +#
> +# Checks that the overall output is OUTPUT, but UUIDs in the output
> +# are replaced by markers of the form <N> where N is a number.  The
> +# first unique UUID is replaced by <0>, the next by <1>, and so on.
> +# If a given UUID appears more than once it is always replaced by the
> +# same marker.
> +#
> +# TITLE is provided to AT_SETUP and KEYWORDS to AT_KEYWORDS.
> +m4_define([OVSDB_CHECK_MONITOR_COND],
> +  [AT_SETUP([$1])
> +   AT_KEYWORDS([ovsdb server monitor monitor-cond positive $10])
> +   $2 > schema
> +   AT_CHECK([ovsdb-tool create db schema], [0], [stdout], [ignore])
> +   m4_foreach([txn], [$3],
> +     [AT_CHECK([ovsdb-tool transact db 'txn'], [0], [ignore], [ignore])])
> +   AT_CAPTURE_FILE([ovsdb-server-log])
> +   AT_CHECK([ovsdb-server --detach --no-chdir
> --pidfile="`pwd`"/server-pid --remote=punix:socket
> --unixctl="`pwd`"/unixctl --log-file="`pwd`"/ovsdb-server-log db >/dev/null
> 2>&1],
> +            [0], [], [])
> +   if test "$IS_WIN32" = "yes"; then
> +     AT_CHECK([ovsdb-client -vjsonrpc --pidfile="`pwd`"/client-pid -d
> json monitor-cond --format=csv unix:socket $4 $5 '[$8]' $9 > output &],
> +              [0], [ignore], [ignore], [kill `cat server-pid`])
> +     sleep 1
> +   else
> +     AT_CHECK([ ovsdb-client -vjsonrpc --detach --no-chdir
> --pidfile="`pwd`"/client-pid -d json monitor-cond --format=csv unix:socket
> $4 $5 '[$8]' $9 > output],
> +            [0], [ignore], [ignore], [kill `cat server-pid`])
> +   fi
> +   m4_foreach([txn], [$6],
> +     [AT_CHECK([ovsdb-client transact unix:socket 'txn'], [0],
> +                     [ignore], [ignore], [kill `cat server-pid
> client-pid`])])
> +   AT_CHECK([ovsdb-client transact unix:socket '[["$4"]]'], [0],
> +            [ignore], [ignore], [kill `cat server-pid client-pid`])
> +   AT_CHECK([ovs-appctl -t "`pwd`"/unixctl -e exit], [0], [ignore],
> [ignore])
> +   OVS_WAIT_UNTIL([test ! -e server-pid && test ! -e client-pid])
> +   AT_CHECK([${PERL} $srcdir/ovsdb-monitor-sort.pl < output | ${PERL}
> $srcdir/uuidfilt.pl], [0], [$7], [ignore])
> +   AT_CLEANUP])
> +
>  OVSDB_CHECK_MONITOR([monitor insert into empty table],
>    [ordinal_schema],
>    [],
> @@ -322,3 +366,137 @@ OVSDB_CHECK_MONITOR([monitor modify only],
>  <0>,old,"""five""",,"[""uuid"",""<1>""]"
>  ,new,"""FIVE""",5,"[""uuid"",""<2>""]"
>  ]], [!initial,!insert,!delete])
> +
> +AT_BANNER([ovsdb -- ovsdb-monitor-cond conditional monitor only some
> operations])
> +
> +OVSDB_CHECK_MONITOR_COND([monitor-cond empty condition],
> +  [ordinal_schema],
> +  [[[["ordinals",
> +      {"op": "insert",
> +       "table": "ordinals",
> +       "row": {"number": 0, "name": "zero"}},
> +      {"op": "insert",
> +       "table": "ordinals",
> +       "row": {"number": 1, "name": "one"}},
> +      {"op": "insert",
> +       "table": "ordinals",
> +       "row": {"number": 2, "name": "two"}}]]]],
> +  [ordinals], [ordinals],
> +  [[[["ordinals",
> +      {"op": "insert",
> +       "table": "ordinals",
> +       "row": {"number": 10, "name": "ten"}},
> +      {"op": "insert",
> +       "table": "ordinals",
> +       "row": {"number": 11, "name": "eleven"}}]]]],
> +  [[row,action,name,number,_version
> +<0>,initial,"""one""",1,"[""uuid"",""<1>""]"
> +<2>,initial,"""two""",2,"[""uuid"",""<3>""]"
> +<4>,initial,"""zero""",,"[""uuid"",""<5>""]"
> +
> +row,action,name,number,_version
> +<6>,insert,"""eleven""",11,"[""uuid"",""<7>""]"
> +<8>,insert,"""ten""",10,"[""uuid"",""<9>""]"
> +]],
> +  [[]])
> +
> +OVSDB_CHECK_MONITOR_COND([monitor-cond multiple conditions],
> +  [ordinal_schema],
> +  [[[["ordinals",
> +      {"op": "insert",
> +       "table": "ordinals",
> +       "row": {"number": 0, "name": "zero"}},
> +      {"op": "insert",
> +       "table": "ordinals",
> +       "row": {"number": 1, "name": "one"}},
> +      {"op": "insert",
> +       "table": "ordinals",
> +       "row": {"number": 2, "name": "two"}}]]]],
> +  [ordinals], [ordinals],
> +  [[[["ordinals",
> +      {"op": "insert",
> +       "table": "ordinals",
> +       "row": {"number": 10, "name": "ten"}},
> +      {"op": "insert",
> +       "table": "ordinals",
> +       "row": {"number": 11, "name": "eleven"}}]]]],
> +  [[row,action,name,number,_version
> +<0>,initial,"""one""",1,"[""uuid"",""<1>""]"
> +
> +row,action,name,number,_version
> +<2>,insert,"""ten""",10,"[""uuid"",""<3>""]"
> +]],
> +  [[["name","==","one"],["name","==","ten"]]])
> +
> +OVSDB_CHECK_MONITOR_COND([monitor-cond delete from populated table],
> +  [ordinal_schema],
> +  [[[["ordinals",
> +      {"op": "insert",
> +       "table": "ordinals",
> +       "row": {"number": 0, "name": "zero"}},
> +      {"op": "insert",
> +       "table": "ordinals",
> +       "row": {"number": 1, "name": "one"}},
> +      {"op": "insert",
> +       "table": "ordinals",
> +       "row": {"number": 2, "name": "two"}}]]]],
> +  [ordinals], [ordinals],
> +  [[[["ordinals",
> +      {"op": "delete",
> +       "table": "ordinals",
> +       "where": []}]]]],
> +  [[row,action,name,number,_version
> +<0>,initial,"""one""",1,"[""uuid"",""<1>""]"
> +
> +row,action,name,number,_version
> +<0>,delete,,,
> +]],
> +  [[["name","==","one"],["name","==","ten"]]])
> +
> +OVSDB_CHECK_MONITOR_COND([monitor-cond insert due to modify],
> +  [ordinal_schema],
> +  [[[["ordinals",
> +      {"op": "insert",
> +       "table": "ordinals",
> +       "row": {"number": 0, "name": "zero"}},
> +      {"op": "insert",
> +       "table": "ordinals",
> +       "row": {"number": 1, "name": "one"}},
> +      {"op": "insert",
> +       "table": "ordinals",
> +       "row": {"number": 2, "name": "two"}}]]]],
> +  [ordinals], [ordinals],
> +  [[[["ordinals",
> +      {"op": "update",
> +       "table": "ordinals",
> +       "where": [["name", "==", "one"]],
> +       "row": {"name": "ONE"}}]]]],
> +  [[row,action,name,number,_version
> +<0>,insert,"""ONE""",1,"[""uuid"",""<1>""]"
> +]],
> +  [[["name","==","ONE"]]],
> +  [!initial,!delete,!modify])
> +
> +OVSDB_CHECK_MONITOR_COND([monitor-cond delete due to modify],
> +  [ordinal_schema],
> +  [[[["ordinals",
> +      {"op": "insert",
> +       "table": "ordinals",
> +       "row": {"number": 0, "name": "zero"}},
> +      {"op": "insert",
> +       "table": "ordinals",
> +       "row": {"number": 1, "name": "one"}},
> +      {"op": "insert",
> +       "table": "ordinals",
> +       "row": {"number": 2, "name": "two"}}]]]],
> +  [ordinals], [ordinals],
> +  [[[["ordinals",
> +      {"op": "update",
> +       "table": "ordinals",
> +       "where": [["name", "==", "one"]],
> +       "row": {"name": "ONE"}}]]]],
> +  [[row,action,name,number,_version
> +<0>,delete,,,
> +]],
> +  [[["name","==","one"]]],
> +  [!initial,!insert,!modify])
> --
> 2.1.4
>
>
> _______________________________________________
> dev mailing list
> dev at openvswitch.org
> http://openvswitch.org/mailman/listinfo/dev
>



More information about the dev mailing list