@@ -912,17 +912,40 @@ ovsdb_cs_db_get_table(struct ovsdb_cs_db *db, const char *table)
return t;
}
+static void
+ovsdb_cs_db_destroy_table(struct ovsdb_cs_db_table *table,
+ struct ovsdb_cs_db *db)
+{
+ json_destroy(table->ack_cond);
+ json_destroy(table->req_cond);
+ json_destroy(table->new_cond);
+ hmap_remove(&db->tables, &table->hmap_node);
+ free(table->name);
+ free(table);
+}
+
+/* Destroy a given ovsdb_cs_db_table according to the table name. */
+void
+ovsdb_cs_clear_condition(struct ovsdb_cs *cs, const char *table)
+{
+ uint32_t hash = hash_string(table, 0);
+ struct ovsdb_cs_db *db = &cs->data;
+
+ struct ovsdb_cs_db_table *t;
+ HMAP_FOR_EACH_WITH_HASH (t, hmap_node, hash, &db->tables) {
+ if (!strcmp(t->name, table)) {
+ ovsdb_cs_db_destroy_table(t, db);
+ return;
+ }
+ }
+}
+
static void
ovsdb_cs_db_destroy_tables(struct ovsdb_cs_db *db)
{
struct ovsdb_cs_db_table *table;
HMAP_FOR_EACH_SAFE (table, hmap_node, &db->tables) {
- json_destroy(table->ack_cond);
- json_destroy(table->req_cond);
- json_destroy(table->new_cond);
- hmap_remove(&db->tables, &table->hmap_node);
- free(table->name);
- free(table);
+ ovsdb_cs_db_destroy_table(table, db);
}
hmap_destroy(&db->tables);
}
@@ -144,6 +144,7 @@ void ovsdb_cs_set_probe_interval(const struct ovsdb_cs *, int probe_interval);
unsigned int ovsdb_cs_set_condition(struct ovsdb_cs *, const char *table,
const struct json *condition);
unsigned int ovsdb_cs_get_condition_seqno(const struct ovsdb_cs *);
+void ovsdb_cs_clear_condition(struct ovsdb_cs *, const char *table);
/* Database change awareness. */
void ovsdb_cs_set_db_change_aware(struct ovsdb_cs *, bool set_db_change_aware);
@@ -130,6 +130,9 @@ struct ovsdb_idl_table {
* or not. */
struct ovs_list indexes; /* Contains "struct ovsdb_idl_index"s */
struct ovs_list track_list; /* Tracked rows (ovsdb_idl_row.track_node). */
+
+ struct ovsdb_idl_condition req_cond; /* User requested monitor
+ * condition. */
};
struct ovsdb_idl_class {
@@ -99,6 +99,7 @@ struct ovsdb_idl {
struct ovs_list rows_to_reparse; /* Stores rows that might need to be
* re-parsed due to insertion of a
* referenced row. */
+ bool server_schema_received;
};
static struct ovsdb_cs_ops ovsdb_idl_cs_ops;
@@ -205,6 +206,19 @@ static void ovsdb_idl_add_to_indexes(const struct ovsdb_idl_row *);
static void ovsdb_idl_remove_from_indexes(const struct ovsdb_idl_row *);
static int ovsdb_idl_try_commit_loop_txn(struct ovsdb_idl_loop *loop,
bool *may_need_wakeup);
+static void
+ovsdb_idl_condition_clone(struct ovsdb_idl_condition *dest,
+ const struct ovsdb_idl_condition *source);
+static void
+ovsdb_idl_create_req_condition(struct ovsdb_idl *,
+ const struct ovsdb_idl_table_class *,
+ const struct ovsdb_idl_condition *);
+static void ovsdb_idl_destroy_req_condition(struct ovsdb_idl_table *);
+static bool ovsdb_idl_condition_is_set(struct ovsdb_idl_condition *);
+static unsigned int
+ovsdb_idl_set_condition__(struct ovsdb_idl *,
+ const struct ovsdb_idl_table_class *,
+ const struct ovsdb_idl_condition *);
static void add_tracked_change_for_references(struct ovsdb_idl_row *);
@@ -266,6 +280,7 @@ ovsdb_idl_create_unconnected(const struct ovsdb_idl_class *class,
.txn = NULL,
.outstanding_txns = HMAP_INITIALIZER(&idl->outstanding_txns),
.verify_write_only = false,
+ .server_schema_received = false,
.deleted_untracked_rows
= OVS_LIST_INITIALIZER(&idl->deleted_untracked_rows),
.rows_to_reparse
@@ -298,6 +313,7 @@ ovsdb_idl_create_unconnected(const struct ovsdb_idl_class *class,
= table->change_seqno[OVSDB_IDL_CHANGE_DELETE] = 0;
table->idl = idl;
table->in_server_schema = false;
+ ovsdb_idl_condition_init(&table->req_cond);
shash_init(&table->schema_columns);
}
@@ -311,6 +327,7 @@ ovsdb_idl_create_unconnected(const struct ovsdb_idl_class *class,
void
ovsdb_idl_set_remote(struct ovsdb_idl *idl, const char *remote, bool retry)
{
+ idl->server_schema_received = false;
ovsdb_cs_set_remote(idl->cs, remote, retry);
}
@@ -372,6 +389,7 @@ ovsdb_idl_destroy(struct ovsdb_idl *idl)
ovsdb_idl_schema_columns_clear(&table->schema_columns);
shash_destroy(&table->schema_columns);
+ ovsdb_idl_destroy_req_condition(table);
hmap_destroy(&table->rows);
free(table->modes);
@@ -784,6 +802,7 @@ static struct json *
ovsdb_idl_compose_monitor_request(const struct json *schema_json, void *idl_)
{
struct ovsdb_idl *idl = idl_;
+ idl->server_schema_received = true;
struct shash *schema = ovsdb_cs_parse_schema(schema_json);
struct json *monitor_requests = json_object_create();
@@ -842,6 +861,7 @@ ovsdb_idl_compose_monitor_request(const struct json *schema_json, void *idl_)
idl->class_->database, table->class_->name);
json_destroy(columns);
table->in_server_schema = false;
+ ovsdb_cs_clear_condition(idl->cs, table->class_->name);
continue;
} else if (schema && table_schema) {
table->in_server_schema = true;
@@ -852,6 +872,14 @@ ovsdb_idl_compose_monitor_request(const struct json *schema_json, void *idl_)
json_object_put(monitor_requests, tc->name,
json_array_create_1(monitor_request));
}
+
+ if (!table->in_server_schema) {
+ ovsdb_cs_clear_condition(idl->cs, table->class_->name);
+ } else if (ovsdb_idl_condition_is_set(&table->req_cond)) {
+ /* Update the monitor condition request according to the
+ * db schema. */
+ ovsdb_idl_set_condition__(idl, tc, &table->req_cond);
+ }
}
ovsdb_cs_free_schema(schema);
@@ -1156,6 +1184,45 @@ ovsdb_idl_condition_add_clause__(struct ovsdb_idl_condition *condition,
hmap_insert(&condition->clauses, &clause->hmap_node, hash);
}
+static void
+ovsdb_idl_destroy_req_condition(struct ovsdb_idl_table *table)
+{
+ ovsdb_idl_condition_destroy(&table->req_cond);
+}
+
+static bool
+ovsdb_idl_condition_is_set(struct ovsdb_idl_condition *condition)
+{
+ return !hmap_is_empty(&condition->clauses) || condition->is_true;
+}
+
+static void
+ovsdb_idl_condition_clone(struct ovsdb_idl_condition *dest,
+ const struct ovsdb_idl_condition *source)
+{
+ ovsdb_idl_condition_init(dest);
+
+ struct ovsdb_idl_clause *clause;
+ HMAP_FOR_EACH (clause, hmap_node, &source->clauses) {
+ uint32_t hash = ovsdb_idl_clause_hash(clause);
+ ovsdb_idl_condition_add_clause__(dest, clause, hash);
+ }
+ dest->is_true = source->is_true;
+}
+
+static void
+ovsdb_idl_create_req_condition(struct ovsdb_idl *idl,
+ const struct ovsdb_idl_table_class *tc,
+ const struct ovsdb_idl_condition *condition)
+{
+ struct ovsdb_idl_table *table = shash_find_data(&idl->table_by_name,
+ tc->name);
+ if (table) {
+ ovsdb_idl_destroy_req_condition(table);
+ ovsdb_idl_condition_clone(&table->req_cond, condition);
+ }
+}
+
/* Adds a clause to the condition for replicating the table with class 'tc' in
* 'idl'.
*
@@ -1234,6 +1301,17 @@ ovsdb_idl_condition_to_json(const struct ovsdb_idl_condition *cnd)
return json_array_create(clauses, n);
}
+static unsigned int
+ovsdb_idl_set_condition__(struct ovsdb_idl *idl,
+ const struct ovsdb_idl_table_class *tc,
+ const struct ovsdb_idl_condition *condition)
+{
+ struct json *cond_json = ovsdb_idl_condition_to_json(condition);
+ unsigned int seqno = ovsdb_cs_set_condition(idl->cs, tc->name, cond_json);
+ json_destroy(cond_json);
+ return seqno;
+}
+
/* Sets the replication condition for 'tc' in 'idl' to 'condition' and
* arranges to send the new condition to the database server.
*
@@ -1245,9 +1323,29 @@ ovsdb_idl_set_condition(struct ovsdb_idl *idl,
const struct ovsdb_idl_table_class *tc,
const struct ovsdb_idl_condition *condition)
{
- struct json *cond_json = ovsdb_idl_condition_to_json(condition);
- unsigned int seqno = ovsdb_cs_set_condition(idl->cs, tc->name, cond_json);
- json_destroy(cond_json);
+ struct ovsdb_idl_condition filter_cond =
+ OVSDB_IDL_CONDITION_INIT(&filter_cond);
+
+ if (idl->server_schema_received && hmap_count(&condition->clauses)) {
+ struct ovsdb_idl_clause *clause;
+ HMAP_FOR_EACH (clause, hmap_node, &condition->clauses) {
+ if (ovsdb_idl_server_has_column(idl, clause->column)) {
+ uint32_t hash = ovsdb_idl_clause_hash(clause);
+ ovsdb_idl_condition_add_clause__(&filter_cond, clause, hash);
+ }
+ }
+ if (hmap_is_empty(&filter_cond.clauses)) {
+ return 0; /* FIXME */
+ }
+ condition = &filter_cond;
+ }
+
+ unsigned int seqno = ovsdb_idl_set_condition__(idl, tc, condition);
+ ovsdb_idl_create_req_condition(idl, tc, &filter_cond);
+ if (hmap_count(&filter_cond.clauses)) {
+ ovsdb_idl_condition_destroy(&filter_cond);
+ }
+
return seqno;
}
@@ -2722,6 +2722,9 @@ unix:socket2 remote has col id in table simple7, type: string
--- remote unix:socket2 done ---
], [stderr])
+# Check we do not have any errors related to conditional monitoring.
+AT_CHECK([grep -q "received error, error={\"details\":\"no table named link2\",\"error\":\"syntax error\"}" stderr], [1])
+
OVSDB_SERVER_SHUTDOWN
AT_CLEANUP
@@ -3596,6 +3596,12 @@ do_idl_table_column_check(struct ovs_cmdl_context *ctx)
ovsdb_idl_set_remote(idl, ctx->argv[r], true);
ovsdb_idl_force_reconnect(idl);
+ struct ovsdb_idl_condition cond_link2 =
+ OVSDB_IDL_CONDITION_INIT(&cond_link2);
+ idltest_link2_add_clause_i(&cond_link2, OVSDB_F_EQ, 1);
+
+ idltest_link2_set_condition(idl, &cond_link2);
+
/* Wait for update. */
for (;;) {
ovsdb_idl_run(idl);
@@ -3661,6 +3667,8 @@ do_idl_table_column_check(struct ovs_cmdl_context *ctx)
type ? ", type: " : "", type ? type_s : "");
free(type_s);
+ ovsdb_idl_condition_destroy(&cond_link2);
+
printf("--- remote %s done ---\n", ctx->argv[r]);
}
Store the user monitor condition request in pre-json format in ovsdb_idl_table in order to use it in ovsdb_idl_compose_monitor_request routine and create a monitor condition request based on the tables/columns available in db-schema. Reported-at: https://issues.redhat.com/browse/FDP-3114 Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi@redhat.com> --- Changes in v2: - Add missing unit-test. - squash with patch 'ovsdb: Add ovsdb_cs_clear_condition routine to remove stable ovsdb_cs_db_table entries.'. - fix the error condition reported by Ilya. - Remove unnecessary ovsdb_cs_db_sync_condition() in ovsdb_cs_send_monitor_request(). - cosmetics. --- lib/ovsdb-cs.c | 35 ++++++++++--- lib/ovsdb-cs.h | 1 + lib/ovsdb-idl-provider.h | 3 ++ lib/ovsdb-idl.c | 104 +++++++++++++++++++++++++++++++++++++-- tests/ovsdb-idl.at | 3 ++ tests/test-ovsdb.c | 8 +++ 6 files changed, 145 insertions(+), 9 deletions(-)