@@ -353,6 +353,142 @@ OVSDB_CHECK_IDL([simple idl, destroy without commit or abort],
004: done
]])
+OVSDB_CHECK_IDL([simple idl, conditional, false condition],
+ [['["idltest",
+ {"op": "insert",
+ "table": "simple",
+ "row": {"i": 1,
+ "r": 2.0,
+ "b": true}}]']],
+ [['condition simple [false]' \
+ 'condition simple []']],
+ [[000: change conditions
+001: empty
+002: change conditions
+003: i=1 r=2 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
+004: done
+]])
+
+OVSDB_CHECK_IDL([simple idl, conditional, true condition],
+ [['["idltest",
+ {"op": "insert",
+ "table": "simple",
+ "row": {"i": 1,
+ "r": 2.0,
+ "b": true}}]']],
+ [['condition simple [false]' \
+ 'condition simple [true]']],
+ [[000: change conditions
+001: empty
+002: change conditions
+003: i=1 r=2 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
+004: done
+]])
+
+OVSDB_CHECK_IDL([simple idl, conditional, multiple clauses in condition],
+ [['["idltest",
+ {"op": "insert",
+ "table": "simple",
+ "row": {"i": 1,
+ "r": 2.0,
+ "b": true}},
+ {"op": "insert",
+ "table": "simple",
+ "row": {"i": 2,
+ "r": 3.0,
+ "b": true}}]']],
+ [['condition simple [false]' \
+ 'condition simple [["i","==",1],["i","==",2]]']],
+ [[000: change conditions
+001: empty
+002: change conditions
+003: i=1 r=2 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
+003: i=2 r=3 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<2>
+004: done
+]])
+
+OVSDB_CHECK_IDL([simple idl, conditional, modify as insert due to condition],
+ [['["idltest",
+ {"op": "insert",
+ "table": "simple",
+ "row": {"i": 1,
+ "r": 2.0,
+ "b": true}}]']],
+ [['condition simple [false]' \
+ 'condition simple [["i","==",1]]']],
+ [[000: change conditions
+001: empty
+002: change conditions
+003: i=1 r=2 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
+004: done
+]])
+
+OVSDB_CHECK_IDL([simple idl, conditional, modify as delete due to condition],
+ [['["idltest",
+ {"op": "insert",
+ "table": "simple",
+ "row": {"i": 1,
+ "r": 2.0,
+ "b": true}}]']],
+ [['condition simple [false]' \
+ 'condition simple [["i","==",1]]' \
+ 'condition simple [["i","==",2]]' \
+ '["idltest",
+ {"op": "insert",
+ "table": "simple",
+ "row": {"i": 2,
+ "r": 3.0,
+ "b": true}}]']],
+ [[000: change conditions
+001: empty
+002: change conditions
+003: i=1 r=2 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
+004: change conditions
+005: empty
+006: {"error":null,"result":[{"uuid":["uuid","<2>"]}]}
+007: i=2 r=3 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<2>
+008: done
+]])
+
+OVSDB_CHECK_IDL([simple idl, conditional, multiple tables],
+ [['["idltest",
+ {"op": "insert",
+ "table": "simple",
+ "row": {"i": 1,
+ "r": 2.0,
+ "b": true}},
+ {"op": "insert",
+ "table": "link1",
+ "row": {"i": 0, "k": ["named-uuid", "self"]},
+ "uuid-name": "self"},
+ {"op": "insert",
+ "table": "link2",
+ "row": {"i": 2},
+ "uuid-name": "row0"}]']],
+ [['condition simple [false];condition link1 [false];condition link2 [false]' \
+ 'condition simple [["i","==",1]]' \
+ 'condition link1 [["i","==",0]]' \
+ 'condition link2 [["i","==",3]]' \
+ '+["idltest",
+ {"op": "insert",
+ "table": "link2",
+ "row": {"i": 3},
+ "uuid-name": "row0"}]']],
+ [[000: change conditions
+001: empty
+002: change conditions
+003: i=1 r=2 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
+004: change conditions
+005: i=0 k=0 ka=[] l2= uuid=<2>
+005: i=1 r=2 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
+006: change conditions
+007: {"error":null,"result":[{"uuid":["uuid","<3>"]}]}
+008: i=0 k=0 ka=[] l2= uuid=<2>
+008: i=1 r=2 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
+008: i=3 l1= uuid=<3>
+009: done
+]])
+
OVSDB_CHECK_IDL([self-linking idl, consistent ops],
[],
[['["idltest",
@@ -2141,6 +2141,187 @@ idl_set(struct ovsdb_idl *idl, char *commands, int step)
ovsdb_idl_txn_destroy(txn);
}
+static const struct ovsdb_idl_table_class *
+find_table_class(const char *name)
+{
+ if (!strcmp(name, "simple")) {
+ return &idltest_table_simple;
+ } else if (!strcmp(name, "link1")) {
+ return &idltest_table_link1;
+ } else if (!strcmp(name, "link2")) {
+ return &idltest_table_link2;
+ }
+ return NULL;
+}
+
+static void
+parse_simple_json_clause(struct ovsdb_idl_condition *cnd, struct json *json)
+{
+ const char *c;
+ struct ovsdb_error *error;
+ enum ovsdb_idl_function function;
+
+ if (json->type == JSON_TRUE) {
+ idltest_simple_add_clause_true(cnd);
+ return;
+ } else if (json->type == JSON_FALSE) {
+ idltest_simple_add_clause_false(cnd);
+ return;
+ }
+ if (json->type != JSON_ARRAY || json->u.array.n != 3) {
+ ovs_fatal(0, "Error parsing condition");
+ }
+
+ c = json_string(json->u.array.elems[0]);
+ error = ovsdb_idl_function_from_string(
+ json_string(json->u.array.elems[1]),
+ &function);
+ if (error) {
+ ovs_fatal(0, "Error parsing clause function %s",
+ json_string(json->u.array.elems[1]));
+ }
+
+ /* add clause according to column */
+ if (!strcmp(c, "b")) {
+ idltest_simple_add_clause_b(cnd, function,
+ json_boolean(json->u.array.elems[2]));
+ } else if (!strcmp(c, "i")) {
+ idltest_simple_add_clause_i(cnd, function,
+ json_integer(json->u.array.elems[2]));
+ } else if (!strcmp(c, "s")) {
+ idltest_simple_add_clause_s(cnd, function,
+ json_string(json->u.array.elems[2]));
+ } else if (!strcmp(c, "u")) {
+ struct uuid uuid;
+ if (!uuid_from_string(&uuid,
+ json_string(json->u.array.elems[2]))) {
+ ovs_fatal(0, "\"%s\" is not a valid UUID",
+ json_string(json->u.array.elems[2]));
+ }
+ idltest_simple_add_clause_u(cnd, function, uuid);
+ } else if (!strcmp(c, "r")) {
+ idltest_simple_add_clause_r(cnd, function,
+ json_real(json->u.array.elems[2]));
+ } else {
+ ovs_fatal(0, "Unsupported columns name %s", c);
+ }
+}
+
+static void
+parse_link1_json_clause(struct ovsdb_idl_condition *cnd, struct json *json)
+{
+ const char *c;
+ struct ovsdb_error *error;
+ enum ovsdb_idl_function function;
+
+ if (json->type == JSON_TRUE) {
+ idltest_link1_add_clause_true(cnd);
+ return;
+ } else if (json->type == JSON_FALSE) {
+ idltest_link1_add_clause_false(cnd);
+ return;
+ }
+ if (json->type != JSON_ARRAY || json->u.array.n != 3) {
+ ovs_fatal(0, "Error parsing condition");
+ }
+
+ c = json_string(json->u.array.elems[0]);
+ error = ovsdb_idl_function_from_string(
+ json_string(json->u.array.elems[1]),
+ &function);
+ if (error) {
+ ovs_fatal(0, "Error parsing clause function %s",
+ json_string(json->u.array.elems[1]));
+ }
+
+ /* add clause according to column */
+ if (!strcmp(c, "i")) {
+ idltest_link1_add_clause_i(cnd, function,
+ json_integer(json->u.array.elems[2]));
+ } else {
+ ovs_fatal(0, "Unsupported columns name %s", c);
+ }
+}
+
+static void
+parse_link2_json_clause(struct ovsdb_idl_condition *cnd, struct json *json)
+{
+ const char *c;
+ struct ovsdb_error *error;
+ enum ovsdb_idl_function function;
+
+ if (json->type == JSON_TRUE) {
+ idltest_link2_add_clause_true(cnd);
+ return;
+ } else if (json->type == JSON_FALSE) {
+ idltest_link2_add_clause_false(cnd);
+ return;
+ }
+ if (json->type != JSON_ARRAY || json->u.array.n != 3) {
+ ovs_fatal(0, "Error parsing condition");
+ }
+
+ c = json_string(json->u.array.elems[0]);
+ error = ovsdb_idl_function_from_string(
+ json_string(json->u.array.elems[1]),
+ &function);
+ if (error) {
+ ovs_fatal(0, "Error parsing clause function %s",
+ json_string(json->u.array.elems[1]));
+ }
+
+ /* add clause according to column */
+ if (!strcmp(c, "i")) {
+ idltest_link2_add_clause_i(cnd, function,
+ json_integer(json->u.array.elems[2]));
+ } else {
+ ovs_fatal(0, "Unsupported columns name %s", c);
+ }
+}
+
+static void
+update_conditions(struct ovsdb_idl *idl, char *commands)
+{
+ char *cmd, *save_ptr1 = NULL;
+ const struct ovsdb_idl_table_class *tc;
+
+ for (cmd = strtok_r(commands, ";", &save_ptr1); cmd;
+ cmd = strtok_r(NULL, ";", &save_ptr1)) {
+ cmd += strlen("condition ");
+ char *save_ptr2 = NULL;
+ char *table_name = strtok_r(cmd, " ", &save_ptr2);
+ struct json *json = parse_json(save_ptr2);
+ struct ovsdb_idl_condition cnd;
+ int i;
+
+ if (json->type != JSON_ARRAY) {
+ ovs_fatal(0, "condition should be an array");
+ }
+
+ tc = find_table_class(table_name);
+ if (!tc) {
+ ovs_fatal(0, "Table %s does not exist", table_name);
+ }
+
+ ovsdb_idl_condition_init(&cnd, tc);
+
+ for (i = 0; i < json->u.array.n; i++) {
+ if (!strcmp(table_name, "simple")) {
+ parse_simple_json_clause(&cnd, json->u.array.elems[i]);
+ } else if (!strcmp(table_name, "link1")) {
+ parse_link1_json_clause(&cnd, json->u.array.elems[i]);
+ } else if (!strcmp(table_name, "link2")) {
+ parse_link2_json_clause(&cnd, json->u.array.elems[i]);
+ }
+ }
+
+ if (!ovsdb_idl_cond_update(idl, &cnd)) {
+ ovs_fatal(0, "Error update conditions");
+ }
+ ovsdb_idl_condition_destroy(&cnd);
+ }
+}
+
static void
do_idl(struct ovs_cmdl_context *ctx)
{
@@ -2179,7 +2360,14 @@ do_idl(struct ovs_cmdl_context *ctx)
setvbuf(stdout, NULL, _IONBF, 0);
symtab = ovsdb_symbol_table_create();
- for (i = 2; i < ctx->argc; i++) {
+ if (ctx->argc > 2 && strstr(ctx->argv[2], "condition ")) {
+ update_conditions(idl, ctx->argv[2]);
+ printf("%03d: change conditions\n", step++);
+ i = 3;
+ } else {
+ i = 2;
+ }
+ for (; i < ctx->argc; i++) {
char *arg = ctx->argv[i];
struct jsonrpc_msg *request, *reply;
@@ -2213,6 +2401,9 @@ do_idl(struct ovs_cmdl_context *ctx)
if (!strcmp(arg, "reconnect")) {
printf("%03d: reconnect\n", step++);
ovsdb_idl_force_reconnect(idl);
+ } else if (strstr(arg, "condition ")) {
+ update_conditions(idl, arg);
+ printf("%03d: change conditions\n", step++);
} else if (arg[0] != '[') {
idl_set(idl, arg, step++);
} else {
@@ -391,6 +391,20 @@ def idl_set(idl, commands, step):
sys.stdout.flush()
+def update_condition(idl, commands):
+ commands = commands.split(";")
+ for command in commands:
+ command = command[len("condition "):]
+ command = command.split(" ")
+ if(len(command) != 2):
+ sys.stderr.write("Error parsong condition %s\n" % command)
+ sys.exit(1)
+
+ table = command[0]
+ cond = ovs.json.from_string(command[1])
+ idl.cond_update(table, cond)
+
+
def do_idl(schema_file, remote, *commands):
schema_helper = ovs.db.idl.SchemaHelper(schema_file)
if commands and commands[0].startswith("?"):
@@ -422,6 +436,14 @@ def do_idl(schema_file, remote, *commands):
symtab = {}
seqno = 0
step = 0
+
+ commands = list(commands)
+ if len(commands) >= 1 and "condition" in commands[0]:
+ update_condition(idl, commands.pop(0))
+ sys.stdout.write("%03d: change conditions\n" % step)
+ sys.stdout.flush()
+ step += 1
+
for command in commands:
if command.startswith("+"):
# The previous transaction didn't change anything.
@@ -446,6 +468,11 @@ def do_idl(schema_file, remote, *commands):
sys.stdout.flush()
step += 1
idl.force_reconnect()
+ elif "condition" in command:
+ update_condition(idl, command)
+ sys.stdout.write("%03d: change conditions\n" % step)
+ sys.stdout.flush()
+ step += 1
elif not command.startswith("["):
idl_set(idl, command, step)
step += 1
Add tests for conditional monitoring to IDL. Signed-off-by: Liran Schour <lirans@il.ibm.com> --- tests/ovsdb-idl.at | 136 ++++++++++++++++++++++++++++++++++++ tests/test-ovsdb.c | 193 +++++++++++++++++++++++++++++++++++++++++++++++++++- tests/test-ovsdb.py | 27 ++++++++ 3 files changed, 355 insertions(+), 1 deletion(-)