@@ -181,6 +181,8 @@ lib_libopenvswitch_la_SOURCES = \
lib/ovsdb-idl.h \
lib/ovsdb-map-op.c \
lib/ovsdb-map-op.h \
+ lib/ovsdb-condition.h \
+ lib/ovsdb-condition.c \
lib/ovsdb-parser.c \
lib/ovsdb-parser.h \
lib/ovsdb-types.c \
new file mode 100644
@@ -0,0 +1,47 @@
+/* Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Nicira, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <config.h>
+
+#include <string.h>
+#include "ovsdb-error.h"
+#include "ovsdb-condition.h"
+
+struct ovsdb_error *
+ovsdb_function_from_string(const char *name, enum ovsdb_function *function)
+{
+#define OVSDB_FUNCTION(ENUM, NAME) \
+ if (!strcmp(name, NAME)) { \
+ *function = ENUM; \
+ return NULL; \
+ }
+ OVSDB_FUNCTIONS;
+#undef OVSDB_FUNCTION
+
+ return ovsdb_syntax_error(NULL, "unknown function",
+ "No function named %s.", name);
+}
+
+const char *
+ovsdb_function_to_string(enum ovsdb_function function)
+{
+ switch (function) {
+#define OVSDB_FUNCTION(ENUM, NAME) case ENUM: return NAME;
+ OVSDB_FUNCTIONS;
+#undef OVSDB_FUNCTION
+ }
+
+ return NULL;
+}
new file mode 100644
@@ -0,0 +1,45 @@
+/* Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014, 2015 Nicira, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef OVSDB_LIB_CONDITION_H
+#define OVSDB_LIB_CONDITION_H 1
+
+/* These list is ordered first with boolean functions and then in
+ * ascending order of the fraction of tables row that they are
+ * (heuristically) expected to leave in query results. */
+#define OVSDB_FUNCTIONS \
+ OVSDB_FUNCTION(OVSDB_F_FALSE, "false") \
+ OVSDB_FUNCTION(OVSDB_F_TRUE, "true") \
+ OVSDB_FUNCTION(OVSDB_F_EQ, "==") \
+ OVSDB_FUNCTION(OVSDB_F_INCLUDES, "includes") \
+ OVSDB_FUNCTION(OVSDB_F_LE, "<=") \
+ OVSDB_FUNCTION(OVSDB_F_LT, "<") \
+ OVSDB_FUNCTION(OVSDB_F_GE, ">=") \
+ OVSDB_FUNCTION(OVSDB_F_GT, ">") \
+ OVSDB_FUNCTION(OVSDB_F_EXCLUDES, "excludes") \
+ OVSDB_FUNCTION(OVSDB_F_NE, "!=")
+
+enum ovsdb_function {
+#define OVSDB_FUNCTION(ENUM, NAME) ENUM,
+ OVSDB_FUNCTIONS
+#undef OVSDB_FUNCTION
+ OVSDB_F_LAST = OVSDB_F_NE
+};
+
+struct ovsdb_error * ovsdb_function_from_string(const char *name,
+ enum ovsdb_function *function);
+const char * ovsdb_function_to_string(enum ovsdb_function function);
+
+#endif /* ovsdb-condition.h */
@@ -73,6 +73,8 @@ struct ovsdb_idl_table {
struct ovsdb_idl *idl; /* Containing idl. */
unsigned int change_seqno[OVSDB_IDL_CHANGE_MAX];
struct ovs_list track_list; /* Tracked rows (ovsdb_idl_row.track_node). */
+ struct ovsdb_idl_condition condition;
+ bool cond_changed;
};
struct ovsdb_idl_class {
@@ -108,6 +108,7 @@ struct ovsdb_idl {
/* Transaction support. */
struct ovsdb_idl_txn *txn;
struct hmap outstanding_txns;
+ bool cond_changed;
};
struct ovsdb_idl_txn {
@@ -211,6 +212,9 @@ static struct ovsdb_idl_table *
ovsdb_idl_table_from_class(const struct ovsdb_idl *,
const struct ovsdb_idl_table_class *);
static bool ovsdb_idl_track_is_set(struct ovsdb_idl_table *table);
+static void ovsdb_idl_send_cond_change(struct ovsdb_idl *idl);
+static void ovsdb_idl_condition_init(struct ovsdb_idl_condition *cnd,
+ const struct ovsdb_idl_table_class *tc);
/* Creates and returns a connection to database 'remote', which should be in a
* form acceptable to jsonrpc_session_open(). The connection will maintain an
@@ -269,8 +273,11 @@ ovsdb_idl_create(const char *remote, const struct ovsdb_idl_class *class,
= table->change_seqno[OVSDB_IDL_CHANGE_MODIFY]
= table->change_seqno[OVSDB_IDL_CHANGE_DELETE] = 0;
table->idl = idl;
+ ovsdb_idl_condition_init(&table->condition, tc);
+ table->cond_changed = false;
}
+ idl->cond_changed = false;
idl->state_seqno = UINT_MAX;
idl->request_id = NULL;
idl->schema = NULL;
@@ -373,6 +380,9 @@ ovsdb_idl_run(struct ovsdb_idl *idl)
int i;
ovs_assert(!idl->txn);
+
+ ovsdb_idl_send_cond_change(idl);
+
jsonrpc_session_run(idl->session);
for (i = 0; jsonrpc_session_is_connected(idl->session) && i < 50; i++) {
struct jsonrpc_msg *msg;
@@ -700,6 +710,190 @@ ovsdb_idl_add_table(struct ovsdb_idl *idl,
OVS_NOT_REACHED();
}
+static struct json *
+ovsdb_idl_clause_to_json(const struct ovsdb_idl_clause *clause)
+{
+ if (clause->function != OVSDB_F_TRUE &&
+ clause->function != OVSDB_F_FALSE) {
+ const char *function = ovsdb_function_to_string(clause->function);
+
+ return json_array_create_3(json_string_create(clause->column->name),
+ json_string_create(function),
+ ovsdb_datum_to_json(&clause->arg,
+ &clause->column->type));
+ }
+
+ return json_boolean_create(clause->function == OVSDB_F_TRUE ?
+ true : false);
+}
+
+static void
+ovsdb_idl_clause_free(struct ovsdb_idl_clause *clause)
+{
+ if (clause->function != OVSDB_F_TRUE &&
+ clause->function != OVSDB_F_FALSE) {
+ ovsdb_datum_destroy(&clause->arg, &clause->column->type);
+ }
+
+ ovs_list_remove(&clause->node);
+ free(clause);
+}
+
+void
+ovsdb_idl_condition_reset(struct ovsdb_idl *idl,
+ const struct ovsdb_idl_table_class *tc)
+{
+ struct ovsdb_idl_clause *c, *next;
+ struct ovsdb_idl_table *table = ovsdb_idl_table_from_class(idl, tc);
+
+ LIST_FOR_EACH_SAFE (c, next, node, &table->condition.clauses) {
+ ovs_list_remove(&c->node);
+ ovsdb_idl_clause_free(c);
+ }
+ idl->cond_changed = table->cond_changed = true;
+}
+
+static void
+ovsdb_idl_condition_init(struct ovsdb_idl_condition *cnd,
+ const struct ovsdb_idl_table_class *tc)
+{
+ cnd->tc = tc;
+ ovs_list_init(&cnd->clauses);
+}
+
+void ovsdb_idl_condition_add_clause(struct ovsdb_idl *idl,
+ const struct ovsdb_idl_table_class *tc,
+ enum ovsdb_function function,
+ const struct ovsdb_idl_column *column,
+ struct ovsdb_datum *arg)
+{
+ struct ovsdb_idl_table *table = ovsdb_idl_table_from_class(idl, tc);
+ struct ovsdb_idl_clause *clause = xzalloc(sizeof *clause);
+ const struct ovsdb_type *type = NULL;
+ struct ovsdb_idl_clause *c;
+
+ LIST_FOR_EACH(c, node, &table->condition.clauses) {
+ if (c->function == function &&
+ (!column || (c->column == column &&
+ ovsdb_datum_equals(&c->arg,
+ arg, &column->type)))) {
+ return;
+ }
+ }
+
+ ovs_list_init(&clause->node);
+ clause->function = function;
+ clause->column = column;
+ if (column) {
+ type = &column->type;
+ } else {
+ type = &ovsdb_type_boolean;
+ }
+ ovsdb_datum_clone(&clause->arg, arg, type);
+ ovs_list_push_back(&table->condition.clauses, &clause->node);
+ idl->cond_changed = table->cond_changed = true;
+ poll_immediate_wake();
+}
+
+void ovsdb_idl_condition_remove_clause(struct ovsdb_idl *idl,
+ const struct ovsdb_idl_table_class *tc,
+ enum ovsdb_function function,
+ const struct ovsdb_idl_column *column,
+ struct ovsdb_datum *arg)
+{
+ struct ovsdb_idl_clause *c, *next;
+ struct ovsdb_idl_table *table = ovsdb_idl_table_from_class(idl, tc);
+
+ LIST_FOR_EACH_SAFE(c, next, node, &table->condition.clauses) {
+ if (c->function == function &&
+ (!column || (c->column == column &&
+ ovsdb_datum_equals(&c->arg,
+ arg, &column->type)))) {
+ ovsdb_idl_clause_free(c);
+ idl->cond_changed = table->cond_changed = true;
+ return;
+ }
+ }
+}
+
+static struct json *
+ovsdb_idl_condition_to_json(const struct ovsdb_idl_condition *cnd)
+{
+ struct json **clauses;
+ size_t i = 0, n_clauses = ovs_list_size(&cnd->clauses);
+ struct ovsdb_idl_clause *c;
+
+ clauses = xmalloc(n_clauses * sizeof *clauses);
+ LIST_FOR_EACH (c, node, &cnd->clauses) {
+ clauses[i++] = ovsdb_idl_clause_to_json(c);
+ }
+
+ return json_array_create(clauses, n_clauses);
+}
+
+static struct json*
+ovsdb_idl_create_cond_change_req(struct ovsdb_idl_table *table)
+{
+ const struct ovsdb_idl_condition *cond = &table->condition;
+ struct json *monitor_cond_change_request = json_object_create();
+ struct json *cond_json = ovsdb_idl_condition_to_json(cond);
+
+ json_object_put(monitor_cond_change_request, "where", cond_json);
+
+ return monitor_cond_change_request;
+}
+
+static void
+ovsdb_idl_send_cond_change(struct ovsdb_idl *idl)
+{
+ int i;
+ char uuid[UUID_LEN + 1];
+ struct json *params, *json_uuid;
+ struct jsonrpc_msg *request;
+
+ if (!idl->cond_changed || !jsonrpc_session_is_connected(idl->session) ||
+ idl->state != IDL_S_MONITORING_COND) {
+ return;
+ }
+
+ struct json *monitor_cond_change_requests = NULL;
+
+ for (i = 0; i < idl->class->n_tables; i++) {
+ struct ovsdb_idl_table *table = &idl->tables[i];
+
+ if (table->cond_changed) {
+ struct json *req = ovsdb_idl_create_cond_change_req(table);
+ if (req) {
+ if (!monitor_cond_change_requests) {
+ monitor_cond_change_requests = json_object_create();
+ }
+ json_object_put(monitor_cond_change_requests,
+ table->class->name,
+ json_array_create_1(req));
+ }
+ table->cond_changed = false;
+ }
+ }
+
+ /* Send request if not empty. */
+ if (monitor_cond_change_requests) {
+ snprintf(uuid, sizeof uuid, UUID_FMT,
+ UUID_ARGS(&idl->uuid));
+ json_uuid = json_string_create(uuid);
+
+ /* Create a new uuid */
+ uuid_generate(&idl->uuid);
+ snprintf(uuid, sizeof uuid, UUID_FMT,
+ UUID_ARGS(&idl->uuid));
+ params = json_array_create_3(json_uuid, json_string_create(uuid),
+ monitor_cond_change_requests);
+
+ request = jsonrpc_create_request("monitor_cond_change", params, NULL);
+ jsonrpc_session_send(idl->session, request);
+ }
+ idl->cond_changed = false;
+}
+
/* Turns off OVSDB_IDL_ALERT for 'column' in 'idl'.
*
* This function should be called between ovsdb_idl_create() and the first call
@@ -997,9 +1191,9 @@ ovsdb_idl_send_monitor_request__(struct ovsdb_idl *idl,
schema = parse_schema(idl->schema);
monitor_requests = json_object_create();
for (i = 0; i < idl->class->n_tables; i++) {
- const struct ovsdb_idl_table *table = &idl->tables[i];
+ struct ovsdb_idl_table *table = &idl->tables[i];
const struct ovsdb_idl_table_class *tc = table->class;
- struct json *monitor_request, *columns;
+ struct json *monitor_request, *columns, *where;
const struct sset *table_schema;
size_t j;
@@ -1037,6 +1231,12 @@ ovsdb_idl_send_monitor_request__(struct ovsdb_idl *idl,
monitor_request = json_object_create();
json_object_put(monitor_request, "columns", columns);
+ if (!strcmp(method, "monitor_cond") && table->cond_changed &&
+ ovs_list_size(&table->condition.clauses) > 0) {
+ where = ovsdb_idl_condition_to_json(&table->condition);
+ json_object_put(monitor_request, "where", where);
+ table->cond_changed = false;
+ }
json_object_put(monitor_requests, tc->name, monitor_request);
}
}
@@ -1051,6 +1251,7 @@ ovsdb_idl_send_monitor_request__(struct ovsdb_idl *idl,
json_string_create(uuid), monitor_requests),
&idl->request_id);
jsonrpc_session_send(idl->session, msg);
+ idl->cond_changed = false;
}
static void
@@ -38,6 +38,9 @@
#include <stdint.h>
#include "compiler.h"
#include "ovsdb-types.h"
+#include "ovsdb-data.h"
+#include "openvswitch/list.h"
+#include "ovsdb-condition.h"
struct json;
struct ovsdb_datum;
@@ -45,6 +48,7 @@ struct ovsdb_idl_class;
struct ovsdb_idl_row;
struct ovsdb_idl_column;
struct ovsdb_idl_table_class;
+struct ovsdb_idl_condition;
struct uuid;
struct ovsdb_idl *ovsdb_idl_create(const char *remote,
@@ -299,4 +303,29 @@ void ovsdb_idl_loop_destroy(struct ovsdb_idl_loop *);
struct ovsdb_idl_txn *ovsdb_idl_loop_run(struct ovsdb_idl_loop *);
void ovsdb_idl_loop_commit_and_wait(struct ovsdb_idl_loop *);
+struct ovsdb_idl_condition {
+ const struct ovsdb_idl_table_class *tc;
+ struct ovs_list clauses;
+};
+
+struct ovsdb_idl_clause {
+ struct ovs_list node;
+ enum ovsdb_function function;
+ const struct ovsdb_idl_column *column;
+ struct ovsdb_datum arg;
+};
+
+void ovsdb_idl_condition_reset(struct ovsdb_idl *idl,
+ const struct ovsdb_idl_table_class *tc);
+void ovsdb_idl_condition_add_clause(struct ovsdb_idl *idl,
+ const struct ovsdb_idl_table_class *tc,
+ enum ovsdb_function function,
+ const struct ovsdb_idl_column *column,
+ struct ovsdb_datum *arg);
+void ovsdb_idl_condition_remove_clause(struct ovsdb_idl *idl,
+ const struct ovsdb_idl_table_class *tc,
+ enum ovsdb_function function,
+ const struct ovsdb_idl_column *column,
+ struct ovsdb_datum *arg);
+
#endif /* ovsdb-idl.h */
@@ -20,38 +20,12 @@
#include "compiler.h"
#include "ovsdb-data.h"
#include "bitmap.h"
+#include "ovsdb-condition.h"
struct json;
struct ovsdb_table_schema;
struct ovsdb_row;
-/* These list is ordered first with boolean functions and then in
- * ascending order of the fraction of tables row that they are
- * (heuristically) expected to leave in query results. */
-#define OVSDB_FUNCTIONS \
- OVSDB_FUNCTION(OVSDB_F_FALSE, "false") \
- OVSDB_FUNCTION(OVSDB_F_TRUE, "true") \
- OVSDB_FUNCTION(OVSDB_F_EQ, "==") \
- OVSDB_FUNCTION(OVSDB_F_INCLUDES, "includes") \
- OVSDB_FUNCTION(OVSDB_F_LE, "<=") \
- OVSDB_FUNCTION(OVSDB_F_LT, "<") \
- OVSDB_FUNCTION(OVSDB_F_GE, ">=") \
- OVSDB_FUNCTION(OVSDB_F_GT, ">") \
- OVSDB_FUNCTION(OVSDB_F_EXCLUDES, "excludes") \
- OVSDB_FUNCTION(OVSDB_F_NE, "!=")
-
-enum ovsdb_function {
-#define OVSDB_FUNCTION(ENUM, NAME) ENUM,
- OVSDB_FUNCTIONS
-#undef OVSDB_FUNCTION
- OVSDB_F_LAST = OVSDB_F_NE
-};
-
-struct ovsdb_error *ovsdb_function_from_string(const char *,
- enum ovsdb_function *)
- OVS_WARN_UNUSED_RESULT;
-const char *ovsdb_function_to_string(enum ovsdb_function);
-
struct ovsdb_clause {
enum ovsdb_function function;
const struct ovsdb_column *column;
@@ -229,11 +229,38 @@ bool %(s)s_is_updated(const struct %(s)s *, enum %(s)s_column_id);
print
for columnName, column in sorted(table.columns.iteritems()):
- if column.type.is_map():
+ if column.type.is_map():
print 'void %(s)s_update_%(c)s_setkey(const struct %(s)s *, ' % {'s': structName, 'c': columnName},
print '%(coltype)s, %(valtype)s);' % {'coltype':column.type.key.toCType(prefix), 'valtype':column.type.value.toCType(prefix)}
print 'void %(s)s_update_%(c)s_delkey(const struct %(s)s *, ' % {'s': structName, 'c': columnName},
- print '%(coltype)s);' % {'coltype':column.type.key.toCType(prefix)}
+ print '%(coltype)s);' % {'coltype':column.type.key.toCType(prefix)},
+
+ print 'void %(s)s_add_clause_%(c)s(struct ovsdb_idl *idl, enum ovsdb_function function,' % {'s': structName, 'c': columnName},
+ if column.type.is_smap():
+ args = ['const struct smap *']
+ else:
+ comment, members = cMembers(prefix, tableName, columnName,
+ column, True)
+ args = ['%(type)s%(name)s' % member for member in members]
+ print '%s);' % ', '.join(args)
+
+ print 'void %s_add_clause_true(struct ovsdb_idl *idl);' % structName
+ print 'void %s_add_clause_false(struct ovsdb_idl *idl);' % structName
+
+ print
+ for columnName, column in sorted(table.columns.iteritems()):
+ print 'void %(s)s_remove_clause_%(c)s(struct ovsdb_idl *idl, enum ovsdb_function function,' % {'s': structName, 'c': columnName},
+ if column.type.is_smap():
+ args = ['const struct smap *']
+ else:
+ comment, members = cMembers(prefix, tableName, columnName,
+ column, True)
+ args = ['%(type)s%(name)s' % member for member in members]
+ print '%s);' % ', '.join(args)
+
+ print 'void %s_remove_clause_true(struct ovsdb_idl *idl);' % structName
+ print 'void %s_remove_clause_false(struct ovsdb_idl *idl);' % structName
+
print
# Table indexes.
@@ -828,6 +855,339 @@ void
'C': columnName.upper()}
# End Update/Delete of partial maps
+ # Add clause functions.
+ for columnName, column in sorted(table.columns.iteritems()):
+ type = column.type
+
+ comment, members = cMembers(prefix, tableName, columnName,
+ column, True)
+
+ if type.is_smap():
+ print comment
+ print """void
+%(s)s_add_clause_%(c)s(struct ovsdb_idl *idl, enum ovsdb_function function, const struct smap *%(c)s)
+{
+ struct ovsdb_datum datum;
+
+ ovs_assert(inited);
+ if (%(c)s) {
+ struct smap_node *node;
+ size_t i;
+
+ datum.n = smap_count(%(c)s);
+ datum.keys = xmalloc(datum.n * sizeof *datum.keys);
+ datum.values = xmalloc(datum.n * sizeof *datum.values);
+
+ i = 0;
+ SMAP_FOR_EACH (node, %(c)s) {
+ datum.keys[i].string = xstrdup(node->key);
+ datum.values[i].string = xstrdup(node->value);
+ i++;
+ }
+ ovsdb_datum_sort_unique(&datum, OVSDB_TYPE_STRING, OVSDB_TYPE_STRING);
+ } else {
+ ovsdb_datum_init_empty(&datum);
+ }
+
+ ovsdb_idl_condition_add_clause(idl,
+ &%(p)stable_classes[%(P)sTABLE_%(T)s],
+ function,
+ &%(s)s_columns[%(S)s_COL_%(C)s],
+ &datum);
+}
+""" % {'t': tableName,
+ 'T': tableName.upper(),
+ 'p': prefix,
+ 'P': prefix.upper(),
+ 's': structName,
+ 'S': structName.upper(),
+ 'c': columnName,
+ 'C': columnName.upper()}
+ continue
+
+ keyVar = members[0]['name']
+ nVar = None
+ valueVar = None
+ if type.value:
+ valueVar = members[1]['name']
+ if len(members) > 2:
+ nVar = members[2]['name']
+ else:
+ if len(members) > 1:
+ nVar = members[1]['name']
+
+ print comment
+ print 'void'
+ print '%(s)s_add_clause_%(c)s(struct ovsdb_idl *idl, enum ovsdb_function function, %(args)s)' % \
+ {'s': structName, 'c': columnName,
+ 'args': ', '.join(['%(type)s%(name)s' % m for m in members])}
+ print "{"
+ print " struct ovsdb_datum datum;"
+ if type.n_min == 1 and type.n_max == 1:
+ print " union ovsdb_atom key;"
+ if type.value:
+ print " union ovsdb_atom value;"
+ print
+ print " ovs_assert(inited);"
+ print " datum.n = 1;"
+ print " datum.keys = &key;"
+ print " " + type.key.assign_c_value_casting_away_const("key.%s" % type.key.type.to_string(), keyVar)
+ if type.value:
+ print " datum.values = &value;"
+ print " "+ type.value.assign_c_value_casting_away_const("value.%s" % type.value.type.to_string(), valueVar)
+ else:
+ print " datum.values = NULL;"
+ elif type.is_optional_pointer():
+ print " union ovsdb_atom key;"
+ print
+ print " ovs_assert(inited);"
+ print " if (%s) {" % keyVar
+ print " datum.n = 1;"
+ print " datum.keys = &key;"
+ print " " + type.key.assign_c_value_casting_away_const("key.%s" % type.key.type.to_string(), keyVar)
+ print " } else {"
+ print " datum.n = 0;"
+ print " datum.keys = NULL;"
+ print " }"
+ print " datum.values = NULL;"
+ elif type.n_max == 1:
+ print " union ovsdb_atom key;"
+ print
+ print " ovs_assert(inited);"
+ print " if (%s) {" % nVar
+ print " datum.n = 1;"
+ print " datum.keys = &key;"
+ print " " + type.key.assign_c_value_casting_away_const("key.%s" % type.key.type.to_string(), "*" + keyVar)
+ print " } else {"
+ print " datum.n = 0;"
+ print " datum.keys = NULL;"
+ print " }"
+ print " datum.values = NULL;"
+ else:
+ print " size_t i;"
+ print
+ print " ovs_assert(inited);"
+ print " datum.n = %s;" % nVar
+ print " datum.keys = %s ? xmalloc(%s * sizeof *datum.keys) : NULL;" % (nVar, nVar)
+ if type.value:
+ print " datum.values = xmalloc(%s * sizeof *datum.values);" % nVar
+ else:
+ print " datum.values = NULL;"
+ print " for (i = 0; i < %s; i++) {" % nVar
+ print " " + type.key.copyCValue("datum.keys[i].%s" % type.key.type.to_string(), "%s[i]" % keyVar)
+ if type.value:
+ print " " + type.value.copyCValue("datum.values[i].%s" % type.value.type.to_string(), "%s[i]" % valueVar)
+ print " }"
+ if type.value:
+ valueType = type.value.toAtomicType()
+ else:
+ valueType = "OVSDB_TYPE_VOID"
+ print " ovsdb_datum_sort_unique(&datum, %s, %s);" % (
+ type.key.toAtomicType(), valueType)
+
+ print""" ovsdb_idl_condition_add_clause(idl, &%(p)stable_classes[%(P)sTABLE_%(T)s],
+ function,
+ &%(s)s_columns[%(S)s_COL_%(C)s],
+ &datum);
+}""" % {'t': tableName,
+ 'T': tableName.upper(),
+ 'p': prefix,
+ 'P': prefix.upper(),
+ 's': structName,
+ 'S': structName.upper(),
+ 'c': columnName,
+ 'C': columnName.upper()}
+
+ print """void
+%(s)s_add_clause_false(struct ovsdb_idl *idl)
+{
+ struct ovsdb_datum datum;
+
+ ovsdb_datum_init_empty(&datum);
+ ovsdb_idl_condition_add_clause(idl, &%(p)stable_classes[%(P)sTABLE_%(T)s], OVSDB_F_FALSE, NULL, &datum);
+}""" % {'s': structName,
+ 'T': tableName.upper(),
+ 'p': prefix,
+ 'P': prefix.upper()}
+
+ print """void
+%(s)s_add_clause_true(struct ovsdb_idl *idl)
+{
+ struct ovsdb_datum datum;
+
+ ovsdb_datum_init_empty(&datum);
+ ovsdb_idl_condition_add_clause(idl, &%(p)stable_classes[%(P)sTABLE_%(T)s], OVSDB_F_TRUE, NULL, &datum);
+}""" % {'s': structName,
+ 'T': tableName.upper(),
+ 'p': prefix,
+ 'P': prefix.upper()}
+
+ # Remove clause functions.
+ for columnName, column in sorted(table.columns.iteritems()):
+ type = column.type
+
+ comment, members = cMembers(prefix, tableName, columnName,
+ column, True)
+
+ if type.is_smap():
+ print comment
+ print """void
+%(s)s_remove_clause_%(c)s(struct ovsdb_idl *idl, enum ovsdb_function function, const struct smap *%(c)s)
+{
+ struct ovsdb_datum datum;
+
+ ovs_assert(inited);
+ if (%(c)s) {
+ struct smap_node *node;
+ size_t i;
+
+ datum.n = smap_count(%(c)s);
+ datum.keys = xmalloc(datum.n * sizeof *datum.keys);
+ datum.values = xmalloc(datum.n * sizeof *datum.values);
+
+ i = 0;
+ SMAP_FOR_EACH (node, %(c)s) {
+ datum.keys[i].string = xstrdup(node->key);
+ datum.values[i].string = xstrdup(node->value);
+ i++;
+ }
+ ovsdb_datum_sort_unique(&datum, OVSDB_TYPE_STRING, OVSDB_TYPE_STRING);
+ } else {
+ ovsdb_datum_init_empty(&datum);
+ }
+
+ ovsdb_idl_condition_remove_clause(idl, &%(p)stable_classes[%(P)sTABLE_%(T)s],
+ function,
+ &%(s)s_columns[%(S)s_COL_%(C)s],
+ &datum);
+}
+""" % {'t': tableName,
+ 'T': tableName.upper(),
+ 'p': prefix,
+ 'P': prefix.upper(),
+ 's': structName,
+ 'S': structName.upper(),
+ 'c': columnName,
+ 'C': columnName.upper()}
+ continue
+
+ keyVar = members[0]['name']
+ nVar = None
+ valueVar = None
+ if type.value:
+ valueVar = members[1]['name']
+ if len(members) > 2:
+ nVar = members[2]['name']
+ else:
+ if len(members) > 1:
+ nVar = members[1]['name']
+
+ print comment
+ print 'void'
+ print '%(s)s_remove_clause_%(c)s(struct ovsdb_idl *idl, enum ovsdb_function function, %(args)s)' % \
+ {'s': structName, 'c': columnName,
+ 'args': ', '.join(['%(type)s%(name)s' % m for m in members])}
+ print "{"
+ print " struct ovsdb_datum datum;"
+ if type.n_min == 1 and type.n_max == 1:
+ print " union ovsdb_atom key;"
+ if type.value:
+ print " union ovsdb_atom value;"
+ print
+ print " ovs_assert(inited);"
+ print " datum.n = 1;"
+ print " datum.keys = &key;"
+ print " " + type.key.assign_c_value_casting_away_const("key.%s" % type.key.type.to_string(), keyVar)
+ if type.value:
+ print " datum.values = &value;"
+ print " "+ type.value.assign_c_value_casting_away_const("value.%s" % type.value.type.to_string(), valueVar)
+ else:
+ print " datum.values = NULL;"
+ elif type.is_optional_pointer():
+ print " union ovsdb_atom key;"
+ print
+ print " ovs_assert(inited);"
+ print " if (%s) {" % keyVar
+ print " datum.n = 1;"
+ print " datum.keys = &key;"
+ print " " + type.key.assign_c_value_casting_away_const("key.%s" % type.key.type.to_string(), keyVar)
+ print " } else {"
+ print " datum.n = 0;"
+ print " datum.keys = NULL;"
+ print " }"
+ print " datum.values = NULL;"
+ elif type.n_max == 1:
+ print " union ovsdb_atom key;"
+ print
+ print " ovs_assert(inited);"
+ print " if (%s) {" % nVar
+ print " datum.n = 1;"
+ print " datum.keys = &key;"
+ print " " + type.key.assign_c_value_casting_away_const("key.%s" % type.key.type.to_string(), "*" + keyVar)
+ print " } else {"
+ print " datum.n = 0;"
+ print " datum.keys = NULL;"
+ print " }"
+ print " datum.values = NULL;"
+ else:
+ print " size_t i;"
+ print
+ print " ovs_assert(inited);"
+ print " datum.n = %s;" % nVar
+ print " datum.keys = %s ? xmalloc(%s * sizeof *datum.keys) : NULL;" % (nVar, nVar)
+ if type.value:
+ print " datum.values = xmalloc(%s * sizeof *datum.values);" % nVar
+ else:
+ print " datum.values = NULL;"
+ print " for (i = 0; i < %s; i++) {" % nVar
+ print " " + type.key.copyCValue("datum.keys[i].%s" % type.key.type.to_string(), "%s[i]" % keyVar)
+ if type.value:
+ print " " + type.value.copyCValue("datum.values[i].%s" % type.value.type.to_string(), "%s[i]" % valueVar)
+ print " }"
+ if type.value:
+ valueType = type.value.toAtomicType()
+ else:
+ valueType = "OVSDB_TYPE_VOID"
+ print " ovsdb_datum_sort_unique(&datum, %s, %s);" % (
+ type.key.toAtomicType(), valueType)
+
+ print""" ovsdb_idl_condition_remove_clause(idl, &%(p)stable_classes[%(P)sTABLE_%(T)s],
+ function,
+ &%(s)s_columns[%(S)s_COL_%(C)s],
+ &datum);
+}""" % {'t': tableName,
+ 'T': tableName.upper(),
+ 'p': prefix,
+ 'P': prefix.upper(),
+ 's': structName,
+ 'S': structName.upper(),
+ 'c': columnName,
+ 'C': columnName.upper()}
+
+ print """void
+%(s)s_remove_clause_false(struct ovsdb_idl *idl)
+{
+ struct ovsdb_datum datum;
+
+ ovsdb_datum_init_empty(&datum);
+ ovsdb_idl_condition_remove_clause(idl, &%(p)stable_classes[%(P)sTABLE_%(T)s], OVSDB_F_FALSE, NULL, &datum);
+}""" % {'s': structName,
+ 'T': tableName.upper(),
+ 'p': prefix,
+ 'P': prefix.upper()}
+
+ print """void
+%(s)s_remove_clause_true(struct ovsdb_idl *idl)
+{
+ struct ovsdb_datum datum;
+
+ ovsdb_datum_init_empty(&datum);
+ ovsdb_idl_condition_remove_clause(idl, &%(p)stable_classes[%(P)sTABLE_%(T)s], OVSDB_F_TRUE, NULL, &datum);
+}""" % {'s': structName,
+ 'T': tableName.upper(),
+ 'p': prefix,
+ 'P': prefix.upper(),}
+
# Table columns.
print "\nstruct ovsdb_idl_column %s_columns[%s_N_COLUMNS];" % (
structName, structName.upper())
@@ -144,6 +144,7 @@ class Idl(object):
table.rows = {}
table.idl = self
table.condition = []
+ table.cond_changed = False
def close(self):
"""Closes the connection to the database. The IDL will no longer
@@ -170,6 +171,8 @@ class Idl(object):
for changes in self.change_seqno."""
assert not self.txn
initial_change_seqno = self.change_seqno
+
+ self.send_cond_change()
self._session.run()
i = 0
while i < 50:
@@ -252,18 +255,32 @@ class Idl(object):
return initial_change_seqno != self.change_seqno
- def cond_change(self, table_name, cond):
+ def send_cond_change(self):
+ if not self._session.is_connected():
+ return
+
+ for table in six.itervalues(self.tables):
+ if table.cond_changed:
+ self.__send_cond_change(table, table.condition)
+ table.cond_changed = False
+
+ def cond_change(self, table_name, add_cmd, cond):
"""Change conditions for this IDL session. If session is not already
connected, add condtion to table and submit it on send_monitor_request.
Otherwise send monitor_cond_change method with the requested
changes."""
+
table = self.tables.get(table_name)
if not table:
raise error.Error('Unknown table "%s"' % table_name)
- if self._session.is_connected():
- self.__send_cond_change(table, cond)
+
+ if add_cmd:
+ table.condition += cond
else:
- table.condition = cond
+ for c in cond:
+ table.condition.remove(c)
+
+ table.cond_changed = True
def wait(self, poller):
"""Arranges for poller.block() to wake up when self.run() has something
@@ -401,9 +418,10 @@ class Idl(object):
(column not in self.readonly[table.name])):
columns.append(column)
monitor_requests[table.name] = {"columns": columns}
- if method == "monitor_cond" and table.condition:
+ if method == "monitor_cond" and table.cond_changed and \
+ table.condition:
monitor_requests[table.name]["where"] = table.condition
- table.condition = None
+ table.cond_change = False
msg = ovs.jsonrpc.Message.create_request(
method, [self._db.name, str(self.uuid), monitor_requests])
@@ -389,6 +389,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 add simple [false]' \
+ 'condition remove simple [false]']],
+ [[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 add simple [false]' \
+ 'condition add 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 add simple [false]' \
+ 'condition add 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 add simple [false]' \
+ 'condition add 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 add simple [false]' \
+ 'condition add simple [["i","==",1],["i","==",2]]' \
+ 'condition remove simple [["i","==",1]]' \
+ '["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 add simple [false];condition add link1 [false];condition add link2 [false]' \
+ 'condition add simple [["i","==",1]]' \
+ 'condition add link1 [["i","==",0]]' \
+ 'condition add 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",
@@ -2145,6 +2145,208 @@ 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 *idl, bool add_cmd,
+ struct json *json)
+{
+ const char *c;
+ struct ovsdb_error *error;
+ enum ovsdb_function function;
+
+ if (json->type == JSON_TRUE) {
+ add_cmd ? idltest_simple_add_clause_true(idl) :
+ idltest_simple_remove_clause_true(idl);
+ return;
+ } else if (json->type == JSON_FALSE) {
+ add_cmd ? idltest_simple_add_clause_false(idl) :
+ idltest_simple_remove_clause_false(idl);
+ 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_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")) {
+ add_cmd ? idltest_simple_add_clause_b(idl, function,
+ json_boolean(json->u.array.elems[2])) :
+ idltest_simple_remove_clause_b(idl, function,
+ json_boolean(json->u.array.elems[2]));
+ } else if (!strcmp(c, "i")) {
+ add_cmd ? idltest_simple_add_clause_i(idl, function,
+ json_integer(json->u.array.elems[2])) :
+ idltest_simple_remove_clause_i(idl, function,
+ json_integer(json->u.array.elems[2]));
+ } else if (!strcmp(c, "s")) {
+ add_cmd ? idltest_simple_add_clause_s(idl, function,
+ json_string(json->u.array.elems[2])) :
+ idltest_simple_remove_clause_s(idl, 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]));
+ }
+ add_cmd ? idltest_simple_add_clause_u(idl, function, uuid) :
+ idltest_simple_remove_clause_u(idl, function, uuid);
+ } else if (!strcmp(c, "r")) {
+ add_cmd ? idltest_simple_add_clause_r(idl, function,
+ json_real(json->u.array.elems[2])) :
+ idltest_simple_remove_clause_r(idl, 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 *idl, bool add_cmd,
+ struct json *json)
+{
+ const char *c;
+ struct ovsdb_error *error;
+ enum ovsdb_function function;
+
+ if (json->type == JSON_TRUE) {
+ add_cmd ? idltest_link1_add_clause_true(idl) :
+ idltest_link1_remove_clause_true(idl);
+ return;
+ } else if (json->type == JSON_FALSE) {
+ add_cmd ? idltest_link1_add_clause_false(idl) :
+ idltest_link1_remove_clause_false(idl);
+ 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_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")) {
+ add_cmd ? idltest_link1_add_clause_i(idl, function,
+ json_integer(json->u.array.elems[2])) :
+ idltest_link1_remove_clause_i(idl, 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 *idl, bool add_cmd, struct json *json)
+{
+ const char *c;
+ struct ovsdb_error *error;
+ enum ovsdb_function function;
+
+ if (json->type == JSON_TRUE) {
+ add_cmd ? idltest_link2_add_clause_true(idl) :
+ idltest_link2_remove_clause_true(idl);
+ return;
+ } else if (json->type == JSON_FALSE) {
+ add_cmd ? idltest_link2_add_clause_false(idl) :
+ idltest_link2_remove_clause_false(idl);
+ 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_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")) {
+ add_cmd ? idltest_link2_add_clause_i(idl, function,
+ json_integer(json->u.array.elems[2])) :
+ idltest_link2_remove_clause_i(idl, 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;
+ bool add_cmd = false;
+
+ for (cmd = strtok_r(commands, ";", &save_ptr1); cmd;
+ cmd = strtok_r(NULL, ";", &save_ptr1)) {
+ if (strstr(cmd, "condition add")) {
+ cmd += strlen("condition add ");
+ add_cmd = true;
+ } else if (strstr(cmd, "condition remove")) {
+ cmd += strlen("condition remove ");
+ } else {
+ ovs_fatal(0, "condition command should be add or remove");
+ }
+
+ char *save_ptr2 = NULL;
+ char *table_name = strtok_r(cmd, " ", &save_ptr2);
+ struct json *json = parse_json(save_ptr2);
+ 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_reset(idl, tc);
+
+ for (i = 0; i < json->u.array.n; i++) {
+ if (!strcmp(table_name, "simple")) {
+ parse_simple_json_clause(idl, add_cmd, json->u.array.elems[i]);
+ } else if (!strcmp(table_name, "link1")) {
+ parse_link1_json_clause(idl, add_cmd, json->u.array.elems[i]);
+ } else if (!strcmp(table_name, "link2")) {
+ parse_link2_json_clause(idl, add_cmd, json->u.array.elems[i]);
+ }
+ }
+ }
+}
+
static void
do_idl(struct ovs_cmdl_context *ctx)
{
@@ -2183,7 +2385,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;
@@ -2217,6 +2426,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,27 @@ 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 "):]
+ if "add" in command:
+ add_cmd = True
+ command = command[len("add "):]
+ else:
+ add_cmd = False
+ command = command[len("remove "):]
+
+ 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_change(table, add_cmd, cond)
+
def do_idl(schema_file, remote, *commands):
schema_helper = ovs.db.idl.SchemaHelper(schema_file)
if commands and commands[0].startswith("?"):
@@ -422,6 +443,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 +475,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 to IDL API that allows the user to add and remove clauses on a table's condition iteratively. IDL maintain tables condition and send monitor_cond_change to the server upon condition change. Add tests for conditional monitoring to IDL. Signed-off-by: Liran Schour <lirans@il.ibm.com> --- lib/automake.mk | 2 + lib/ovsdb-condition.c | 47 ++++++ lib/ovsdb-condition.h | 45 ++++++ lib/ovsdb-idl-provider.h | 2 + lib/ovsdb-idl.c | 205 +++++++++++++++++++++++++- lib/ovsdb-idl.h | 29 ++++ ovsdb/condition.h | 28 +--- ovsdb/ovsdb-idlc.in | 364 ++++++++++++++++++++++++++++++++++++++++++++++- python/ovs/db/idl.py | 30 +++- tests/ovsdb-idl.at | 136 ++++++++++++++++++ tests/test-ovsdb.c | 214 +++++++++++++++++++++++++++- tests/test-ovsdb.py | 34 +++++ 12 files changed, 1098 insertions(+), 38 deletions(-) create mode 100644 lib/ovsdb-condition.c create mode 100644 lib/ovsdb-condition.h