2
0
mirror of https://github.com/openvswitch/ovs synced 2025-08-22 09:58:01 +00:00

ovsdb: add conditions utilities to support monitor_cond

Change ovsdb_condition to be a 3-element json array or a boolean value (see ovsdb-server
man page).
Conditions utilities will be used later for conditional monitoring.

Signed-off-by: Liran Schour <lirans@il.ibm.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
This commit is contained in:
Liran Schour 2016-07-18 11:45:50 +03:00 committed by Ben Pfaff
parent ec1eadce89
commit ae9cab378b
6 changed files with 334 additions and 22 deletions

View File

@ -52,7 +52,7 @@ ovsdb_function_to_string(enum ovsdb_function function)
return NULL; return NULL;
} }
static OVS_WARN_UNUSED_RESULT struct ovsdb_error * static struct ovsdb_error *
ovsdb_clause_from_json(const struct ovsdb_table_schema *ts, ovsdb_clause_from_json(const struct ovsdb_table_schema *ts,
const struct json *json, const struct json *json,
struct ovsdb_symbol_table *symtab, struct ovsdb_symbol_table *symtab,
@ -64,6 +64,18 @@ ovsdb_clause_from_json(const struct ovsdb_table_schema *ts,
const char *column_name; const char *column_name;
struct ovsdb_type type; struct ovsdb_type type;
if (json->type == JSON_TRUE || json->type == JSON_FALSE) {
clause->function =
json->type == JSON_TRUE ? OVSDB_F_TRUE : OVSDB_F_FALSE;
/* Column and arg fields are not being used with boolean functions.
* Use dummy values */
clause->column = ovsdb_table_schema_get_column(ts, "_uuid");
clause->index = clause->column->index;
ovsdb_datum_init_default(&clause->arg, &clause->column->type);
return NULL;
}
if (json->type != JSON_ARRAY if (json->type != JSON_ARRAY
|| json->u.array.n != 3 || json->u.array.n != 3
|| json->u.array.elems[0]->type != JSON_STRING || json->u.array.elems[0]->type != JSON_STRING
@ -79,6 +91,7 @@ ovsdb_clause_from_json(const struct ovsdb_table_schema *ts,
"No column %s in table %s.", "No column %s in table %s.",
column_name, ts->name); column_name, ts->name);
} }
clause->index = clause->column->index;
type = clause->column->type; type = clause->column->type;
function_name = json_string(array->elems[1]); function_name = json_string(array->elems[1]);
@ -109,7 +122,6 @@ ovsdb_clause_from_json(const struct ovsdb_table_schema *ts,
return error; return error;
} }
break; break;
case OVSDB_F_EQ: case OVSDB_F_EQ:
case OVSDB_F_NE: case OVSDB_F_NE:
break; break;
@ -126,6 +138,9 @@ ovsdb_clause_from_json(const struct ovsdb_table_schema *ts,
type.n_min = 0; type.n_min = 0;
} }
break; break;
case OVSDB_F_TRUE:
case OVSDB_F_FALSE:
OVS_NOT_REACHED();
} }
return ovsdb_datum_from_json(&clause->arg, &type, array->elems[2], symtab); return ovsdb_datum_from_json(&clause->arg, &type, array->elems[2], symtab);
} }
@ -164,6 +179,19 @@ compare_clauses_3way(const void *a_, const void *b_)
} }
} }
static int
compare_clauses_3way_with_data(const void *a_, const void *b_)
{
const struct ovsdb_clause *a = a_;
const struct ovsdb_clause *b = b_;
int res;
res = compare_clauses_3way(a, b);
return res ? res : ovsdb_datum_compare_3way(&a->arg,
&b->arg,
&a->column->type);
}
struct ovsdb_error * struct ovsdb_error *
ovsdb_condition_from_json(const struct ovsdb_table_schema *ts, ovsdb_condition_from_json(const struct ovsdb_table_schema *ts,
const struct json *json, const struct json *json,
@ -190,7 +218,7 @@ ovsdb_condition_from_json(const struct ovsdb_table_schema *ts,
/* A real database would have a query optimizer here. */ /* A real database would have a query optimizer here. */
qsort(cnd->clauses, cnd->n_clauses, sizeof *cnd->clauses, qsort(cnd->clauses, cnd->n_clauses, sizeof *cnd->clauses,
compare_clauses_3way); compare_clauses_3way_with_data);
return NULL; return NULL;
} }
@ -198,10 +226,15 @@ ovsdb_condition_from_json(const struct ovsdb_table_schema *ts,
static struct json * static struct json *
ovsdb_clause_to_json(const struct ovsdb_clause *clause) ovsdb_clause_to_json(const struct ovsdb_clause *clause)
{ {
return json_array_create_3( if (clause->function != OVSDB_F_TRUE &&
json_string_create(clause->column->name), clause->function != OVSDB_F_FALSE) {
json_string_create(ovsdb_function_to_string(clause->function)), return json_array_create_3(
ovsdb_datum_to_json(&clause->arg, &clause->column->type)); json_string_create(clause->column->name),
json_string_create(ovsdb_function_to_string(clause->function)),
ovsdb_datum_to_json(&clause->arg, &clause->column->type));
}
return json_boolean_create(clause->function == OVSDB_F_TRUE);
} }
struct json * struct json *
@ -218,13 +251,20 @@ ovsdb_condition_to_json(const struct ovsdb_condition *cnd)
} }
static bool static bool
ovsdb_clause_evaluate(const struct ovsdb_row *row, ovsdb_clause_evaluate(const struct ovsdb_datum *fields,
const struct ovsdb_clause *c) const struct ovsdb_clause *c,
unsigned int index_map[])
{ {
const struct ovsdb_datum *field = &row->fields[c->column->index]; const struct ovsdb_datum *field = &fields[index_map ?
index_map[c->column->index] :
c->column->index];
const struct ovsdb_datum *arg = &c->arg; const struct ovsdb_datum *arg = &c->arg;
const struct ovsdb_type *type = &c->column->type; const struct ovsdb_type *type = &c->column->type;
if (c->function == OVSDB_F_TRUE ||
c->function == OVSDB_F_FALSE) {
return c->function == OVSDB_F_TRUE;
}
if (ovsdb_type_is_optional_scalar(type) && field->n == 0) { if (ovsdb_type_is_optional_scalar(type) && field->n == 0) {
switch (c->function) { switch (c->function) {
case OVSDB_F_LT: case OVSDB_F_LT:
@ -237,6 +277,9 @@ ovsdb_clause_evaluate(const struct ovsdb_row *row,
case OVSDB_F_NE: case OVSDB_F_NE:
case OVSDB_F_EXCLUDES: case OVSDB_F_EXCLUDES:
return true; return true;
case OVSDB_F_TRUE:
case OVSDB_F_FALSE:
OVS_NOT_REACHED();
} }
} else if (ovsdb_type_is_scalar(type) } else if (ovsdb_type_is_scalar(type)
|| ovsdb_type_is_optional_scalar(type)) { || ovsdb_type_is_optional_scalar(type)) {
@ -257,6 +300,9 @@ ovsdb_clause_evaluate(const struct ovsdb_row *row,
return cmp >= 0; return cmp >= 0;
case OVSDB_F_GT: case OVSDB_F_GT:
return cmp > 0; return cmp > 0;
case OVSDB_F_TRUE:
case OVSDB_F_FALSE:
OVS_NOT_REACHED();
} }
} else { } else {
switch (c->function) { switch (c->function) {
@ -272,6 +318,8 @@ ovsdb_clause_evaluate(const struct ovsdb_row *row,
case OVSDB_F_LE: case OVSDB_F_LE:
case OVSDB_F_GE: case OVSDB_F_GE:
case OVSDB_F_GT: case OVSDB_F_GT:
case OVSDB_F_TRUE:
case OVSDB_F_FALSE:
OVS_NOT_REACHED(); OVS_NOT_REACHED();
} }
} }
@ -279,14 +327,24 @@ ovsdb_clause_evaluate(const struct ovsdb_row *row,
OVS_NOT_REACHED(); OVS_NOT_REACHED();
} }
static void
ovsdb_clause_clone(struct ovsdb_clause *new, struct ovsdb_clause *old)
{
new->function = old->function;
new->column = old->column;
ovsdb_datum_clone(&new->arg,
&old->arg,
&old->column->type);
}
bool bool
ovsdb_condition_evaluate(const struct ovsdb_row *row, ovsdb_condition_match_every_clause(const struct ovsdb_row *row,
const struct ovsdb_condition *cnd) const struct ovsdb_condition *cnd)
{ {
size_t i; size_t i;
for (i = 0; i < cnd->n_clauses; i++) { for (i = 0; i < cnd->n_clauses; i++) {
if (!ovsdb_clause_evaluate(row, &cnd->clauses[i])) { if (!ovsdb_clause_evaluate(row->fields, &cnd->clauses[i], NULL)) {
return false; return false;
} }
} }
@ -294,6 +352,25 @@ ovsdb_condition_evaluate(const struct ovsdb_row *row,
return true; return true;
} }
/* Returns true if condition evaluation of one of the clauses is
* true. index_map[] is an optional array that if exists indicates a mapping
* between indexing row_datum to the indexes in ovsdb_column */
bool
ovsdb_condition_match_any_clause(const struct ovsdb_datum *row_datum,
const struct ovsdb_condition *cnd,
unsigned int index_map[])
{
size_t i;
for (i = 0; i < cnd->n_clauses; i++) {
if (ovsdb_clause_evaluate(row_datum, &cnd->clauses[i], index_map)) {
return true;
}
}
return false;
}
void void
ovsdb_condition_destroy(struct ovsdb_condition *cnd) ovsdb_condition_destroy(struct ovsdb_condition *cnd)
{ {
@ -303,4 +380,87 @@ ovsdb_condition_destroy(struct ovsdb_condition *cnd)
ovsdb_clause_free(&cnd->clauses[i]); ovsdb_clause_free(&cnd->clauses[i]);
} }
free(cnd->clauses); free(cnd->clauses);
cnd->n_clauses = 0;
}
void
ovsdb_condition_init(struct ovsdb_condition *cnd)
{
cnd->clauses = NULL;
cnd->n_clauses = 0;
}
bool
ovsdb_condition_empty(const struct ovsdb_condition *cnd)
{
return cnd->n_clauses == 0;
}
int
ovsdb_condition_cmp_3way(const struct ovsdb_condition *a,
const struct ovsdb_condition *b)
{
size_t i;
int res;
if (a->n_clauses != b->n_clauses) {
return a->n_clauses < b->n_clauses ? -1 : 1;
}
/* We assume clauses are sorted */
for (i = 0; i < a->n_clauses; i++) {
res = (compare_clauses_3way_with_data(&a->clauses[i], &b->clauses[i]));
if (res != 0) {
return res;
}
}
return 0;
}
void
ovsdb_condition_clone(struct ovsdb_condition *to,
const struct ovsdb_condition *from)
{
size_t i;
to->clauses = xzalloc(from->n_clauses * sizeof *to->clauses);
for (i = 0; i < from->n_clauses; i++) {
ovsdb_clause_clone(&to->clauses[i], &from->clauses[i]);
}
to->n_clauses = from->n_clauses;
}
/* Return true if ovsdb_condition_match_any_clause() will return true on
* any row */
bool
ovsdb_condition_is_true(const struct ovsdb_condition *cond)
{
return (!cond->n_clauses ||
(cond->n_clauses >= 1 && (cond->clauses[0].function == OVSDB_F_TRUE)) ||
(cond->n_clauses >= 2 && (cond->clauses[1].function == OVSDB_F_TRUE)));
}
bool
ovsdb_condition_is_false(const struct ovsdb_condition *cond)
{
return ((cond->n_clauses == 1) &&
(cond->clauses[0].function == OVSDB_F_FALSE));
}
const struct ovsdb_column **
ovsdb_condition_get_columns(const struct ovsdb_condition *cond,
size_t *n_columns)
{
const struct ovsdb_column **columns;
size_t i;
columns = xmalloc(cond->n_clauses * sizeof *columns);
for (i = 0; i < cond->n_clauses; i++) {
columns[i] = cond->clauses[i].column;
}
*n_columns = i;
return columns;
} }

View File

@ -19,14 +19,18 @@
#include <stddef.h> #include <stddef.h>
#include "compiler.h" #include "compiler.h"
#include "ovsdb-data.h" #include "ovsdb-data.h"
#include "bitmap.h"
struct json; struct json;
struct ovsdb_table_schema; struct ovsdb_table_schema;
struct ovsdb_row; struct ovsdb_row;
/* These list is ordered in ascending order of the fraction of tables row that /* These list is ordered first with boolean functions and then in
* they are (heuristically) expected to leave in query results. */ * ascending order of the fraction of tables row that they are
* (heuristically) expected to leave in query results. */
#define OVSDB_FUNCTIONS \ #define OVSDB_FUNCTIONS \
OVSDB_FUNCTION(OVSDB_F_FALSE, "false") \
OVSDB_FUNCTION(OVSDB_F_TRUE, "true") \
OVSDB_FUNCTION(OVSDB_F_EQ, "==") \ OVSDB_FUNCTION(OVSDB_F_EQ, "==") \
OVSDB_FUNCTION(OVSDB_F_INCLUDES, "includes") \ OVSDB_FUNCTION(OVSDB_F_INCLUDES, "includes") \
OVSDB_FUNCTION(OVSDB_F_LE, "<=") \ OVSDB_FUNCTION(OVSDB_F_LE, "<=") \
@ -40,6 +44,7 @@ enum ovsdb_function {
#define OVSDB_FUNCTION(ENUM, NAME) ENUM, #define OVSDB_FUNCTION(ENUM, NAME) ENUM,
OVSDB_FUNCTIONS OVSDB_FUNCTIONS
#undef OVSDB_FUNCTION #undef OVSDB_FUNCTION
OVSDB_F_LAST = OVSDB_F_NE
}; };
struct ovsdb_error *ovsdb_function_from_string(const char *, struct ovsdb_error *ovsdb_function_from_string(const char *,
@ -50,6 +55,7 @@ const char *ovsdb_function_to_string(enum ovsdb_function);
struct ovsdb_clause { struct ovsdb_clause {
enum ovsdb_function function; enum ovsdb_function function;
const struct ovsdb_column *column; const struct ovsdb_column *column;
unsigned int index;
struct ovsdb_datum arg; struct ovsdb_datum arg;
}; };
@ -58,15 +64,38 @@ struct ovsdb_condition {
size_t n_clauses; size_t n_clauses;
}; };
#define OVSDB_CONDITION_INITIALIZER { NULL, 0 } #define OVSDB_CONDITION_INITIALIZER { NULL, 0}
void ovsdb_condition_init(struct ovsdb_condition *);
bool ovsdb_condition_empty(const struct ovsdb_condition *);
struct ovsdb_error *ovsdb_condition_from_json( struct ovsdb_error *ovsdb_condition_from_json(
const struct ovsdb_table_schema *, const struct ovsdb_table_schema *,
const struct json *, struct ovsdb_symbol_table *, const struct json *, struct ovsdb_symbol_table *,
struct ovsdb_condition *) OVS_WARN_UNUSED_RESULT; struct ovsdb_condition *) OVS_WARN_UNUSED_RESULT;
struct json *ovsdb_condition_to_json(const struct ovsdb_condition *); struct json *ovsdb_condition_to_json(const struct ovsdb_condition *);
void ovsdb_condition_destroy(struct ovsdb_condition *); void ovsdb_condition_destroy(struct ovsdb_condition *);
bool ovsdb_condition_evaluate(const struct ovsdb_row *, bool ovsdb_condition_match_every_clause(const struct ovsdb_row *,
const struct ovsdb_condition *); const struct ovsdb_condition *);
bool ovsdb_condition_match_any_clause(const struct ovsdb_datum *,
const struct ovsdb_condition *,
unsigned int index_map[]);
int ovsdb_condition_cmp_3way(const struct ovsdb_condition *a,
const struct ovsdb_condition *b);
void ovsdb_condition_clone(struct ovsdb_condition *to,
const struct ovsdb_condition *from);
bool ovsdb_condition_is_true(const struct ovsdb_condition *cond);
bool ovsdb_condition_is_false(const struct ovsdb_condition *cond);
const struct ovsdb_column **
ovsdb_condition_get_columns(const struct ovsdb_condition *cond,
size_t *n_columns);
static inline bool
ovsdb_condition_empty_or_match_any(const struct ovsdb_datum *row_datum,
const struct ovsdb_condition *cnd,
unsigned int index_map[])
{
return (ovsdb_condition_empty(cnd) ||
ovsdb_condition_match_any_clause(row_datum, cnd, index_map));
}
#endif /* ovsdb/condition.h */ #endif /* ovsdb/condition.h */

View File

@ -350,6 +350,12 @@ of 0 or 1 integer'' and ``set of 0 or 1 real''. These conditions
evaluate to false when the column is empty, and otherwise as described evaluate to false when the column is empty, and otherwise as described
in RFC 7047 for integer and real types. in RFC 7047 for integer and real types.
. .
.IP
<condition> is specified in Section 5.1 in the RFC with the following change:
A condition can be either a 3-element JSON array as described in the RFC or a
boolean value. In case of an empty array an implicit true boolean value will be
considered.
.
.SH "BUGS" .SH "BUGS"
. .
In Open vSwitch before version 2.4, when \fBovsdb\-server\fR sent In Open vSwitch before version 2.4, when \fBovsdb\-server\fR sent

View File

@ -34,7 +34,8 @@ ovsdb_query(struct ovsdb_table *table, const struct ovsdb_condition *cnd,
const struct ovsdb_row *row; const struct ovsdb_row *row;
row = ovsdb_table_get_row(table, &cnd->clauses[0].arg.keys[0].uuid); row = ovsdb_table_get_row(table, &cnd->clauses[0].arg.keys[0].uuid);
if (row && row->table == table && ovsdb_condition_evaluate(row, cnd)) { if (row && row->table == table &&
ovsdb_condition_match_every_clause(row, cnd)) {
output_row(row, aux); output_row(row, aux);
} }
} else { } else {
@ -42,7 +43,8 @@ ovsdb_query(struct ovsdb_table *table, const struct ovsdb_condition *cnd,
const struct ovsdb_row *row, *next; const struct ovsdb_row *row, *next;
HMAP_FOR_EACH_SAFE (row, next, hmap_node, &table->rows) { HMAP_FOR_EACH_SAFE (row, next, hmap_node, &table->rows) {
if (ovsdb_condition_evaluate(row, cnd) && !output_row(row, aux)) { if (ovsdb_condition_match_every_clause(row, cnd) &&
!output_row(row, aux)) {
break; break;
} }
} }

View File

@ -184,6 +184,18 @@ OVSDB_CHECK_POSITIVE([condition sorting],
["_uuid", "==", ["uuid", "d50e85c6-8ae7-4b16-b69e-4395928bd9be"]]]']], ["_uuid", "==", ["uuid", "d50e85c6-8ae7-4b16-b69e-4395928bd9be"]]]']],
[[[["_uuid","==",["uuid","d50e85c6-8ae7-4b16-b69e-4395928bd9be"]],["i","==",1],["i","includes",2],["i","<=",3],["i","<",4],["i",">=",5],["i",">",6],["i","excludes",7],["i","!=",8]]]]) [[[["_uuid","==",["uuid","d50e85c6-8ae7-4b16-b69e-4395928bd9be"]],["i","==",1],["i","includes",2],["i","<=",3],["i","<",4],["i",">=",5],["i",">",6],["i","excludes",7],["i","!=",8]]]])
OVSDB_CHECK_POSITIVE([boolean condition],
[[parse-conditions \
'{"columns": {"name": {"type": "string"}}}' \
'[true]']],
[[[true]]])
OVSDB_CHECK_POSITIVE([boolean condition],
[[parse-conditions \
'{"columns": {"name": {"type": "string"}}}' \
'[false]']],
[[[false]]])
OVSDB_CHECK_POSITIVE([evaluating null condition], OVSDB_CHECK_POSITIVE([evaluating null condition],
[[evaluate-conditions \ [[evaluate-conditions \
'{"columns": {"i": {"type": "integer"}}}' \ '{"columns": {"i": {"type": "integer"}}}' \
@ -657,3 +669,32 @@ condition 5: --T-
condition 6: -T-- condition 6: -T--
condition 7: T-TT condition 7: T-TT
condition 8: -T-T], [condition]) condition 8: -T-T], [condition])
OVSDB_CHECK_POSITIVE([evaluating false boolean condition],
[[evaluate-conditions-any \
'{"columns": {"i": {"type": "integer"}}}' \
'[[false,["i","==",1]]]' \
'[{"i": 0},
{"i": 1},
{"i": 2}']]],
[condition 0: -T-])
OVSDB_CHECK_POSITIVE([evaluating true boolean condition],
[[evaluate-conditions-any \
'{"columns": {"i": {"type": "integer"}}}' \
'[[true,["i","==",1]]]' \
'[{"i": 0},
{"i": 1},
{"i": 2}']]],
[condition 0: TTT])
OVSDB_CHECK_POSITIVE([compare condition],
[[compare-conditions \
'{"columns": {"i": {"type": "integer"}}}' \
'[[true,["i","==",1],["i","==",2],["i","==",3]],
[["i","==",1],["i","==",3],["i","==",2],true],
[["i","==",1]],
[["i",">=",1]]']]],
[condition 0-1: 0
condition 1-2: 1
condition 2-3: -1])

View File

@ -166,6 +166,12 @@ usage(void)
" parse each CONDITION on TABLE, and re-serialize\n" " parse each CONDITION on TABLE, and re-serialize\n"
" evaluate-conditions TABLE [CONDITION,...] [ROW,...]\n" " evaluate-conditions TABLE [CONDITION,...] [ROW,...]\n"
" test CONDITIONS on TABLE against each ROW, print results\n" " test CONDITIONS on TABLE against each ROW, print results\n"
" evaluate-conditions-any TABLE [CONDITION,...] [ROW,...]\n"
" test CONDITIONS to match any of the CONDITONS on TABLE\n"
" against each ROW, print results\n"
" compare-conditions TABLE [CONDITION,...]\n"
" mutually compare all of the CONDITION, print results for\n"
" each pair\n"
" parse-mutations TABLE MUTATION...\n" " parse-mutations TABLE MUTATION...\n"
" parse each MUTATION on TABLE, and re-serialize\n" " parse each MUTATION on TABLE, and re-serialize\n"
" execute-mutations TABLE [MUTATION,...] [ROW,...]\n" " execute-mutations TABLE [MUTATION,...] [ROW,...]\n"
@ -856,8 +862,11 @@ do_parse_conditions(struct ovs_cmdl_context *ctx)
exit(exit_code); exit(exit_code);
} }
#define OVSDB_CONDITION_EVERY 0
#define OVSDB_CONDITION_ANY 1
static void static void
do_evaluate_conditions(struct ovs_cmdl_context *ctx) do_evaluate_condition__(struct ovs_cmdl_context *ctx, int mode)
{ {
struct ovsdb_table_schema *ts; struct ovsdb_table_schema *ts;
struct ovsdb_table *table; struct ovsdb_table *table;
@ -905,7 +914,15 @@ do_evaluate_conditions(struct ovs_cmdl_context *ctx)
for (i = 0; i < n_conditions; i++) { for (i = 0; i < n_conditions; i++) {
printf("condition %2"PRIuSIZE":", i); printf("condition %2"PRIuSIZE":", i);
for (j = 0; j < n_rows; j++) { for (j = 0; j < n_rows; j++) {
bool result = ovsdb_condition_evaluate(rows[j], &conditions[i]); bool result;
if (mode == OVSDB_CONDITION_EVERY) {
result = ovsdb_condition_match_every_clause(rows[j],
&conditions[i]);
} else {
result = ovsdb_condition_match_any_clause(rows[j]->fields,
&conditions[i],
NULL);
}
if (j % 5 == 0) { if (j % 5 == 0) {
putchar(' '); putchar(' ');
} }
@ -925,6 +942,61 @@ do_evaluate_conditions(struct ovs_cmdl_context *ctx)
ovsdb_table_destroy(table); /* Also destroys 'ts'. */ ovsdb_table_destroy(table); /* Also destroys 'ts'. */
} }
static void
do_evaluate_conditions(struct ovs_cmdl_context *ctx)
{
do_evaluate_condition__(ctx, OVSDB_CONDITION_EVERY);
}
static void
do_evaluate_conditions_any(struct ovs_cmdl_context *ctx)
{
do_evaluate_condition__(ctx, OVSDB_CONDITION_ANY);
}
static void
do_compare_conditions(struct ovs_cmdl_context *ctx)
{
struct ovsdb_table_schema *ts;
struct ovsdb_table *table;
struct ovsdb_condition *conditions;
size_t n_conditions;
struct json *json;
size_t i;
/* Parse table schema, create table. */
json = unbox_json(parse_json(ctx->argv[1]));
check_ovsdb_error(ovsdb_table_schema_from_json(json, "mytable", &ts));
json_destroy(json);
table = ovsdb_table_create(ts);
/* Parse conditions. */
json = parse_json(ctx->argv[2]);
if (json->type != JSON_ARRAY) {
ovs_fatal(0, "CONDITION argument is not JSON array");
}
n_conditions = json->u.array.n;
conditions = xmalloc(n_conditions * sizeof *conditions);
for (i = 0; i < n_conditions; i++) {
check_ovsdb_error(ovsdb_condition_from_json(ts, json->u.array.elems[i],
NULL, &conditions[i]));
}
json_destroy(json);
for (i = 0; i < n_conditions - 1; i++) {
int res = ovsdb_condition_cmp_3way(&conditions[i], &conditions[i + 1]);
printf("condition %"PRIuSIZE"-%"PRIuSIZE": %d\n", i, i + 1, res);
}
for (i = 0; i < n_conditions; i++) {
ovsdb_condition_destroy(&conditions[i]);
}
free(conditions);
ovsdb_table_destroy(table); /* Also destroys 'ts'. */
}
static void static void
do_parse_mutations(struct ovs_cmdl_context *ctx) do_parse_mutations(struct ovs_cmdl_context *ctx)
{ {
@ -2311,6 +2383,8 @@ static struct ovs_cmdl_command all_commands[] = {
{ "compare-rows", NULL, 2, INT_MAX, do_compare_rows }, { "compare-rows", NULL, 2, INT_MAX, do_compare_rows },
{ "parse-conditions", NULL, 2, INT_MAX, do_parse_conditions }, { "parse-conditions", NULL, 2, INT_MAX, do_parse_conditions },
{ "evaluate-conditions", NULL, 3, 3, do_evaluate_conditions }, { "evaluate-conditions", NULL, 3, 3, do_evaluate_conditions },
{ "evaluate-conditions-any", NULL, 3, 3, do_evaluate_conditions_any },
{ "compare-conditions", NULL, 2, 2, do_compare_conditions },
{ "parse-mutations", NULL, 2, INT_MAX, do_parse_mutations }, { "parse-mutations", NULL, 2, INT_MAX, do_parse_mutations },
{ "execute-mutations", NULL, 3, 3, do_execute_mutations }, { "execute-mutations", NULL, 3, 3, do_execute_mutations },
{ "query", NULL, 3, 3, do_query }, { "query", NULL, 3, 3, do_query },