[ovs-dev] [PATCH monitor_cond V4 07/17] ovsdb: enable jsonrpc-server to service "monitor_cond_update" request

Liran Schour lirans at il.ibm.com
Thu Feb 18 11:46:45 UTC 2016


ovsdb-server now accepts "monitor_cond_update" request. On conditions update
we compose update notification according to the current state of the
database (do not use of cahnges list). We assume that seesion is flushed when
composing update after conditon_update().
Sees ovsdb-server (1) man page for details of monitor_cond_update.

Signed-off-by: Liran Schour <lirans at il.ibm.com>

---
v3->v4:
* Do not use changes list on condition update, compose update message directly
  from ovsdb_table

v2->v3:
* ovsdb_monitor_table_condition_update() accepts only single json condition
* Allow non-monitored columns in cond_update.
* Flush monitor session after monitor_cond_update to guarantee empty changes list
* Bug fix: use json cache when all condition are empty
* Simplify inserting row change to changes lists
---
 ovsdb/jsonrpc-server.c | 152 ++++++++++++++++++++++++++++++--
 ovsdb/monitor.c        | 230 ++++++++++++++++++++++++++++++++++++++++---------
 ovsdb/monitor.h        |  23 +++--
 3 files changed, 350 insertions(+), 55 deletions(-)

diff --git a/ovsdb/jsonrpc-server.c b/ovsdb/jsonrpc-server.c
index eaa44b6..9e1769d 100644
--- a/ovsdb/jsonrpc-server.c
+++ b/ovsdb/jsonrpc-server.c
@@ -87,6 +87,10 @@ static void ovsdb_jsonrpc_trigger_complete_done(
 static struct jsonrpc_msg *ovsdb_jsonrpc_monitor_create(
     struct ovsdb_jsonrpc_session *, struct ovsdb *, struct json *params,
     enum ovsdb_monitor_version, const struct json *request_id);
+static struct jsonrpc_msg *ovsdb_jsonrpc_monitor_cond_update(
+    struct ovsdb_jsonrpc_session *s,
+    struct json *params,
+    const struct json *request_id);
 static struct jsonrpc_msg *ovsdb_jsonrpc_monitor_cancel(
     struct ovsdb_jsonrpc_session *,
     struct json_array *params,
@@ -400,7 +404,8 @@ static void ovsdb_jsonrpc_session_wait(struct ovsdb_jsonrpc_session *);
 static void ovsdb_jsonrpc_session_get_memory_usage(
     const struct ovsdb_jsonrpc_session *, struct simap *usage);
 static void ovsdb_jsonrpc_session_got_request(struct ovsdb_jsonrpc_session *,
-                                             struct jsonrpc_msg *);
+                                              struct jsonrpc_msg *,
+                                              bool *);
 static void ovsdb_jsonrpc_session_got_notify(struct ovsdb_jsonrpc_session *,
                                              struct jsonrpc_msg *);
 
@@ -456,13 +461,14 @@ ovsdb_jsonrpc_session_run(struct ovsdb_jsonrpc_session *s)
 
     if (!jsonrpc_session_get_backlog(s->js)) {
         struct jsonrpc_msg *msg;
+        bool needs_flush = false;
 
         ovsdb_jsonrpc_monitor_flush_all(s);
 
         msg = jsonrpc_session_recv(s->js);
         if (msg) {
             if (msg->type == JSONRPC_REQUEST) {
-                ovsdb_jsonrpc_session_got_request(s, msg);
+                ovsdb_jsonrpc_session_got_request(s, msg, &needs_flush);
             } else if (msg->type == JSONRPC_NOTIFY) {
                 ovsdb_jsonrpc_session_got_notify(s, msg);
             } else {
@@ -473,6 +479,9 @@ ovsdb_jsonrpc_session_run(struct ovsdb_jsonrpc_session *s)
                 jsonrpc_msg_destroy(msg);
             }
         }
+        if (needs_flush) {
+            ovsdb_jsonrpc_monitor_flush_all(s);
+        }
     }
     return jsonrpc_session_is_alive(s->js) ? 0 : ETIMEDOUT;
 }
@@ -832,10 +841,12 @@ execute_transaction(struct ovsdb_jsonrpc_session *s, struct ovsdb *db,
 
 static void
 ovsdb_jsonrpc_session_got_request(struct ovsdb_jsonrpc_session *s,
-                                  struct jsonrpc_msg *request)
+                                  struct jsonrpc_msg *request,
+                                  bool *needs_flush)
 {
     struct jsonrpc_msg *reply;
 
+    *needs_flush = false;
     if (!strcmp(request->method, "transact")) {
         struct ovsdb *db = ovsdb_jsonrpc_lookup_db(s, request, &reply);
         if (!reply) {
@@ -852,6 +863,10 @@ ovsdb_jsonrpc_session_got_request(struct ovsdb_jsonrpc_session *s,
             reply = ovsdb_jsonrpc_monitor_create(s, db, request->params,
                                                  version, request->id);
         }
+    } else if (!strcmp(request->method, "monitor_cond_update")) {
+        reply = ovsdb_jsonrpc_monitor_cond_update(s, request->params,
+                                                  request->id);
+        *needs_flush = true;
     } else if (!strcmp(request->method, "monitor_cancel")) {
         reply = ovsdb_jsonrpc_monitor_cancel(s, json_array(request->params),
                                              request->id);
@@ -1041,6 +1056,7 @@ struct ovsdb_jsonrpc_monitor {
     struct ovsdb_monitor *dbmon;
     uint64_t unflushed;         /* The first transaction that has not been
                                        flushed to the jsonrpc remote client. */
+    bool cond_updated;
     enum ovsdb_monitor_version version;
     struct ovsdb_monitor_session_condition *condition;/* Session's condition */
 };
@@ -1204,6 +1220,7 @@ ovsdb_jsonrpc_monitor_create(struct ovsdb_jsonrpc_session *s, struct ovsdb *db,
         m->condition = ovsdb_monitor_session_condition_create();
     }
     m->unflushed = 0;
+    m->cond_updated = false;
     m->version = version;
     hmap_insert(&s->monitors, &m->node, json_hash(monitor_id, 0));
     m->monitor_id = json_clone(monitor_id);
@@ -1285,6 +1302,123 @@ error:
     return jsonrpc_create_error(json, request_id);
 }
 
+static struct ovsdb_error *
+ovsdb_jsonrpc_parse_monitor_cond_update_request(
+                                struct ovsdb_jsonrpc_monitor *m,
+                                const struct ovsdb_table *table,
+                                const struct json *cond_update_req)
+{
+    const struct ovsdb_table_schema *ts = table->schema;
+    const struct json *condition, *columns;
+    struct ovsdb_parser parser;
+    struct ovsdb_error *error;
+
+    ovsdb_parser_init(&parser, cond_update_req, "table %s", ts->name);
+    columns = ovsdb_parser_member(&parser, "columns", OP_ARRAY | OP_OPTIONAL);
+    condition = ovsdb_parser_member(&parser, "where", OP_ARRAY | OP_OPTIONAL);
+
+    error = ovsdb_parser_finish(&parser);
+    if (error) {
+        return error;
+    }
+
+    if (columns) {
+        error = ovsdb_syntax_error(cond_update_req, NULL, "changing columns "
+                                   "is unsupported");
+        return error;
+    }
+    error = ovsdb_monitor_table_condition_update(m->dbmon, m->condition, table,
+                                                 condition);
+
+    return error;
+}
+
+static struct jsonrpc_msg *
+ovsdb_jsonrpc_monitor_cond_update(struct ovsdb_jsonrpc_session *s,
+                                  struct json *params,
+                                  const struct json *request_id)
+{
+    struct ovsdb_error *error;
+    struct ovsdb_jsonrpc_monitor *m;
+    struct json *monitor_cond_update_reqs;
+    struct shash_node *node;
+    struct json *json;
+
+    if (json_array(params)->n != 3) {
+        error = ovsdb_syntax_error(params, NULL, "invalid parameters");
+        goto error;
+    }
+
+    m = ovsdb_jsonrpc_monitor_find(s, params->u.array.elems[0]);
+    if (!m) {
+        error = ovsdb_syntax_error(request_id, NULL,
+                                   "unknown monitor session");
+        goto error;
+    }
+
+    monitor_cond_update_reqs = params->u.array.elems[2];
+    if (monitor_cond_update_reqs->type != JSON_OBJECT) {
+        error =
+            ovsdb_syntax_error(NULL, NULL,
+                               "monitor-cond-change-requests must be object");
+        goto error;
+    }
+
+    SHASH_FOR_EACH (node, json_object(monitor_cond_update_reqs)) {
+        const struct ovsdb_table *table;
+        const struct json *mr_value;
+        size_t i;
+
+        table = ovsdb_get_table(m->db, node->name);
+        if (!table) {
+            error = ovsdb_syntax_error(NULL, NULL,
+                                       "no table named %s", node->name);
+            goto error;
+        }
+        if (!ovsdb_monitor_table_exists(m->dbmon, table)) {
+            error = ovsdb_syntax_error(NULL, NULL,
+                                       "no table named %s in monitor session",
+                                       node->name);
+            goto error;
+        }
+
+        mr_value = node->data;
+        if (mr_value->type == JSON_ARRAY) {
+            const struct json_array *array = &mr_value->u.array;
+
+            for (i = 0; i < array->n; i++) {
+                error = ovsdb_jsonrpc_parse_monitor_cond_update_request(
+                                            m, table, array->elems[i]);
+                if (error) {
+                    goto error;
+                }
+            }
+        } else {
+            error = ovsdb_syntax_error(
+                       NULL, NULL,
+                       "table %s no monitor-cond-change JSON array",
+                       node->name);
+            goto error;
+        }
+    }
+
+    m->cond_updated = true;
+
+    /* Change monitor id */
+    hmap_remove(&s->monitors, &m->node);
+    json_destroy(m->monitor_id);
+    m->monitor_id = json_clone(params->u.array.elems[1]);
+    hmap_insert(&s->monitors, &m->node, json_hash(m->monitor_id, 0));
+
+    return jsonrpc_create_reply(json_object_create(), request_id);
+
+error:
+
+    json = ovsdb_error_to_json(error);
+    ovsdb_error_destroy(error);
+    return jsonrpc_create_error(json, request_id);
+}
+
 static struct jsonrpc_msg *
 ovsdb_jsonrpc_monitor_cancel(struct ovsdb_jsonrpc_session *s,
                              struct json_array *params,
@@ -1321,8 +1455,14 @@ static struct json *
 ovsdb_jsonrpc_monitor_compose_update(struct ovsdb_jsonrpc_monitor *m,
                                      bool initial)
 {
-    return ovsdb_monitor_get_update(m->dbmon, initial, &m->unflushed,
-                                    m->condition, m->version);
+    struct json * json = ovsdb_monitor_get_update(m->dbmon, initial,
+                                                  m->cond_updated,
+                                                  &m->unflushed,
+                                                  m->condition,
+                                                  m->version);
+
+    m->cond_updated = false;
+    return json;
 }
 
 static bool
@@ -1331,7 +1471,7 @@ ovsdb_jsonrpc_monitor_needs_flush(struct ovsdb_jsonrpc_session *s)
     struct ovsdb_jsonrpc_monitor *m;
 
     HMAP_FOR_EACH (m, node, &s->monitors) {
-        if (ovsdb_monitor_needs_flush(m->dbmon, m->unflushed)) {
+        if (m->cond_updated || ovsdb_monitor_needs_flush(m->dbmon, m->unflushed)) {
             return true;
         }
     }
diff --git a/ovsdb/monitor.c b/ovsdb/monitor.c
index 75331a2..56036e8 100644
--- a/ovsdb/monitor.c
+++ b/ovsdb/monitor.c
@@ -155,11 +155,17 @@ struct ovsdb_monitor_table {
     struct hmap changes;
 };
 
+enum ovsdb_monitor_row_type {
+    OVSDB_ROW,
+    OVSDB_MONITOR_ROW
+};
+
 typedef struct json *
 (*compose_row_update_cb_func)
     (const struct ovsdb_monitor_table *mt,
      const struct ovsdb_monitor_session_condition * condition,
-     const struct ovsdb_monitor_row *row,
+     enum ovsdb_monitor_row_type row_type,
+     const void *,
      bool initial, unsigned long int *changed);
 
 static void ovsdb_monitor_destroy(struct ovsdb_monitor *dbmon);
@@ -498,6 +504,13 @@ ovsdb_monitor_condition_bind(struct ovsdb_monitor *dbmon,
     }
 }
 
+bool
+ovsdb_monitor_table_exists(struct ovsdb_monitor *m,
+                           const struct ovsdb_table *table)
+{
+    return shash_find_data(&m->tables, table->schema->name);
+}
+
 /* Check for duplicated column names. Return the first
  * duplicated column's name if found. Otherwise return
  * NULL.  */
@@ -709,11 +722,71 @@ ovsdb_monitor_get_table_conditions(
     return true;
 }
 
+struct ovsdb_error *
+ovsdb_monitor_table_condition_update(
+                            struct ovsdb_monitor *dbmon,
+                            struct ovsdb_monitor_session_condition *condition,
+                            const struct ovsdb_table *table,
+                            const struct json *cond_json)
+{
+    struct ovsdb_monitor_table_condition *mtc =
+        shash_find_data(&condition->tables, table->schema->name);
+    struct ovsdb_error *error;
+    struct ovsdb_condition cond = OVSDB_CONDITION_INITIALIZER;
+
+    if (!condition) {
+        return NULL;
+    }
+
+    error = ovsdb_condition_from_json(table->schema, cond_json,
+                                      NULL, &cond);
+    if (error) {
+        return error;
+    }
+    ovsdb_condition_destroy(&mtc->new_condition);
+    ovsdb_condition_clone(&mtc->new_condition, &cond);
+    ovsdb_condition_destroy(&cond);
+    ovsdb_monitor_condition_add_columns(dbmon,
+                                        table,
+                                        &mtc->new_condition);
+
+    return NULL;
+}
+
+static void
+ovsdb_monitor_table_condition_updated(struct ovsdb_monitor_table *mt,
+                    struct ovsdb_monitor_session_condition *condition)
+{
+    struct ovsdb_monitor_table_condition *mtc =
+        shash_find_data(&condition->tables, mt->table->schema->name);
+
+    if (mtc) {
+        /* If conditional monitoring - set old condition to new condition */
+        if (ovsdb_condition_cmp(&mtc->old_condition, &mtc->new_condition)) {
+            if (ovsdb_condition_is_true(&mtc->new_condition)) {
+                mtc->cond_mode = MTC_MODE_TRUE;
+                if (!ovsdb_condition_is_true(&mtc->old_condition)) {
+                    condition->n_true_cnd++;
+                }
+            } else {
+                mtc->cond_mode = MTC_MODE_FULL;
+                if (ovsdb_condition_is_true(&mtc->old_condition)) {
+                    condition->n_true_cnd--;
+                }
+            }
+            ovsdb_condition_destroy(&mtc->old_condition);
+            ovsdb_condition_clone(&mtc->old_condition, &mtc->new_condition);
+            ovsdb_monitor_session_condition_set_mode(condition);
+        }
+    }
+}
+
 static enum ovsdb_monitor_selection
 ovsdb_monitor_row_update_type_condition(
                       const struct ovsdb_monitor_table *mt,
                       const struct ovsdb_monitor_session_condition *condition,
                       bool initial,
+                      enum ovsdb_monitor_row_type row_type,
                       const struct ovsdb_datum *old,
                       const struct ovsdb_datum *new)
 {
@@ -728,11 +801,15 @@ ovsdb_monitor_row_update_type_condition(
         bool old_cond = !old ? false
             : ovsdb_condition_evaluate_or_datum(old,
                                                 old_condition,
-                                                mt->columns_index_map);
+                                                row_type == OVSDB_MONITOR_ROW ?
+                                                mt->columns_index_map :
+                                                NULL);
         bool new_cond = !new ? false
             : ovsdb_condition_evaluate_or_datum(new,
                                                 new_condition,
-                                                mt->columns_index_map);
+                                                row_type == OVSDB_MONITOR_ROW ?
+                                                mt->columns_index_map :
+                                                NULL);
 
         if (!old_cond && !new_cond) {
             type = OJMS_NONE;
@@ -763,7 +840,9 @@ ovsdb_monitor_row_update_type_condition(
 
 static bool
 ovsdb_monitor_row_skip_update(const struct ovsdb_monitor_table *mt,
-                              const struct ovsdb_monitor_row *row,
+                              enum ovsdb_monitor_row_type row_type,
+                              const struct ovsdb_datum *old,
+                              const struct ovsdb_datum *new,
                               enum ovsdb_monitor_selection type,
                               unsigned long int *changed)
 {
@@ -778,7 +857,8 @@ ovsdb_monitor_row_skip_update(const struct ovsdb_monitor_table *mt,
         memset(changed, 0, bitmap_n_bytes(mt->n_columns));
         for (i = 0; i < mt->n_columns; i++) {
             const struct ovsdb_column *c = mt->columns[i].column;
-            if (!ovsdb_datum_equals(&row->old[i], &row->new[i], &c->type)) {
+            size_t index = row_type == OVSDB_ROW ? c->index : i;
+            if (!ovsdb_datum_equals(&old[index], &new[index], &c->type)) {
                 bitmap_set1(changed, i);
                 n_changes++;
             }
@@ -806,16 +886,19 @@ static struct json *
 ovsdb_monitor_compose_row_update(
     const struct ovsdb_monitor_table *mt,
     const struct ovsdb_monitor_session_condition *condition OVS_UNUSED,
-    const struct ovsdb_monitor_row *row,
+    enum ovsdb_monitor_row_type row_type OVS_UNUSED,
+    const void *_row,
     bool initial, unsigned long int *changed)
 {
+    const struct ovsdb_monitor_row *row = _row;
     enum ovsdb_monitor_selection type;
     struct json *old_json, *new_json;
     struct json *row_json;
     size_t i;
 
+    ovs_assert(row_type == OVSDB_MONITOR_ROW);
     type = ovsdb_monitor_row_update_type(initial, row->old, row->new);
-    if (ovsdb_monitor_row_skip_update(mt, row, type, changed)) {
+    if (ovsdb_monitor_row_skip_update(mt, row_type, row->old, row->new, type, changed)) {
         return NULL;
     }
 
@@ -859,7 +942,7 @@ ovsdb_monitor_compose_row_update(
  * for 'row' within * 'mt', or NULL if no row update should be sent.
  *
  * The caller should specify 'initial' as true if the returned JSON is
- * going to be used as part of the initial reply to a "monitor2" request,
+ * going to be used as part of the initial reply to a "monitor_cond" request,
  * false if it is going to be used as part of an "update2" notification.
  *
  * 'changed' must be a scratch buffer for internal use that is at least
@@ -868,16 +951,25 @@ static struct json *
 ovsdb_monitor_compose_row_update2(
     const struct ovsdb_monitor_table *mt,
     const struct ovsdb_monitor_session_condition *condition,
-    const struct ovsdb_monitor_row *row,
+    enum ovsdb_monitor_row_type row_type,
+    const void *_row,
     bool initial, unsigned long int *changed)
 {
     enum ovsdb_monitor_selection type;
     struct json *row_update2, *diff_json;
+    const struct ovsdb_datum *old, *new;
     size_t i;
 
+    if (row_type == OVSDB_MONITOR_ROW) {
+        old = ((const struct ovsdb_monitor_row *)_row)->old;;
+        new = ((const struct ovsdb_monitor_row *)_row)->new;
+    } else {
+        old = new = ((const struct ovsdb_row *)_row)->fields;
+    }
+
     type = ovsdb_monitor_row_update_type_condition(mt, condition, initial,
-                                                   row->old, row->new);
-    if (ovsdb_monitor_row_skip_update(mt, row, type, changed)) {
+                                                   row_type, old, new);
+    if (ovsdb_monitor_row_skip_update(mt, row_type, old, new, type, changed)) {
         return NULL;
     }
 
@@ -890,7 +982,7 @@ ovsdb_monitor_compose_row_update2(
 
         for (i = 0; i < mt->n_columns; i++) {
             const struct ovsdb_monitor_column *c = &mt->columns[i];
-
+            size_t index = row_type == OVSDB_ROW ? c->column->index : i;
             if (!c->monitored || !(type & c->select))  {
                 /* We don't care about this type of change for this
                  * particular column (but we will care about it for some
@@ -905,15 +997,15 @@ ovsdb_monitor_compose_row_update2(
                     continue;
                 }
 
-                ovsdb_datum_diff(&diff ,&row->old[i], &row->new[i],
+                ovsdb_datum_diff(&diff ,&old[index], &new[index],
                                         &c->column->type);
                 json_object_put(diff_json, c->column->name,
                                 ovsdb_datum_to_json(&diff, &c->column->type));
                 ovsdb_datum_destroy(&diff, &c->column->type);
             } else {
-                if (!ovsdb_datum_is_default(&row->new[i], &c->column->type)) {
+                if (!ovsdb_datum_is_default(&new[index], &c->column->type)) {
                     json_object_put(diff_json, c->column->name,
-                                    ovsdb_datum_to_json(&row->new[i],
+                                    ovsdb_datum_to_json(&new[index],
                                                         &c->column->type));
                 }
             }
@@ -942,6 +1034,29 @@ ovsdb_monitor_max_columns(struct ovsdb_monitor *dbmon)
     return max_columns;
 }
 
+static void
+ovsdb_monitor_add_json_row(struct json **json, const char *table_name,
+                           struct json **table_json, struct json *row_json,
+                           const struct uuid *row_uuid)
+{
+    char uuid[UUID_LEN + 1];
+
+    /* Create JSON object for transaction overall. */
+    if (!*json) {
+        *json = json_object_create();
+    }
+
+    /* Create JSON object for transaction on this table. */
+    if (!*table_json) {
+        *table_json = json_object_create();
+        json_object_put(*json, table_name, *table_json);
+    }
+
+    /* Add JSON row to JSON table. */
+    snprintf(uuid, sizeof uuid, UUID_FMT, UUID_ARGS(row_uuid));
+    json_object_put(*table_json, uuid, row_json);
+}
+
 /* Constructs and returns JSON for a <table-updates> object (as described in
  * RFC 7047) for all the outstanding changes within 'monitor', starting from
  * 'transaction'.  */
@@ -988,24 +1103,11 @@ ovsdb_monitor_compose_update(
 
             HMAP_FOR_EACH_SAFE (row, next, hmap_node, &changes->rows) {
                 struct json *row_json;
-
-                row_json = (*row_update)(mt, condition, row, initial, changed);
+                row_json = (*row_update)(mt, condition, OVSDB_MONITOR_ROW, row,
+                                         initial, changed);
                 if (row_json) {
-                    char uuid[UUID_LEN + 1];
-
-                    /* Create JSON object for transaction overall. */
-                    if (!json) {
-                        json = json_object_create();
-                    }
-                    /* Create JSON object for transaction on this table. */
-                    if (!table_json) {
-                        table_json = json_object_create();
-                        json_object_put(json, mt->table->schema->name, table_json);
-                    }
-
-                    /* Add JSON row to JSON table. */
-                    snprintf(uuid, sizeof uuid, UUID_FMT, UUID_ARGS(&row->uuid));
-                    json_object_put(table_json, uuid, row_json);
+                    ovsdb_monitor_add_json_row(&json, mt->table->schema->name,
+                                               &table_json, row_json, &row->uuid);
                 }
             }
             if (!mtc || !mtc->cond_mode) {
@@ -1018,9 +1120,44 @@ ovsdb_monitor_compose_update(
     return json;
 }
 
+static struct json*
+ovsdb_monitor_compose_all_rows_update(
+                    struct ovsdb_monitor *dbmon,
+                    struct ovsdb_monitor_session_condition *condition)
+{
+    struct shash_node *node;
+    struct json *json = NULL;
+    size_t max_columns = ovsdb_monitor_max_columns(dbmon);
+    unsigned long int *changed = xmalloc(bitmap_n_bytes(max_columns));
+
+    SHASH_FOR_EACH (node, &dbmon->tables) {
+        struct ovsdb_monitor_table *mt = node->data;
+        struct ovsdb_row *row;
+        struct json *table_json = NULL;
+
+        HMAP_FOR_EACH (row, hmap_node, &mt->table->rows) {
+            struct json *row_json;
+
+            row_json = ovsdb_monitor_compose_row_update2(mt, condition,
+                                                         OVSDB_ROW, row,
+                                                         false, changed);
+            if (row_json) {
+                ovsdb_monitor_add_json_row(&json, mt->table->schema->name,
+                                           &table_json, row_json,
+                                           ovsdb_row_get_uuid(row));
+            }
+        }
+        ovsdb_monitor_table_condition_updated(mt, condition);
+    }
+    free(changed);
+
+    return json;
+}
+
 /* Returns JSON for a <table-updates> object (as described in RFC 7047)
  * for all the outstanding changes within 'monitor' that starts from
- * '*unflushed' transaction id.
+ * '*unflushed'.
+ * If cond_updated is true all rows in the db that match conditions will be sent.
  *
  * The caller should specify 'initial' as true if the returned JSON is going to
  * be used as part of the initial reply to a "monitor" request, false if it is
@@ -1028,8 +1165,9 @@ ovsdb_monitor_compose_update(
 struct json *
 ovsdb_monitor_get_update(
              struct ovsdb_monitor *dbmon,
-             bool initial, uint64_t *unflushed,
-             const struct ovsdb_monitor_session_condition *condition,
+             bool initial, bool cond_updated,
+             uint64_t *unflushed,
+             struct ovsdb_monitor_session_condition *condition,
              enum ovsdb_monitor_version version)
 {
     struct ovsdb_monitor_json_cache_node *cache_node = NULL;
@@ -1038,20 +1176,28 @@ ovsdb_monitor_get_update(
     uint64_t prev_txn = *unflushed;
     uint64_t next_txn = dbmon->n_transactions + 1;
 
+    /* In case that conditon was updated, assert that monitor session is flushed */
+    ovs_assert(cond_updated ? *unflushed == dbmon->n_transactions + 1 : true);
+
     /* Return a clone of cached json if one exists. Otherwise,
      * generate a new one and add it to the cache.  */
-    if (!condition || !condition->conditional) {
+    if (!condition || (!condition->conditional && !cond_updated)) {
         cache_node = ovsdb_monitor_json_cache_search(&dbmon->json_cache, version, prev_txn);
     }
     if (cache_node) {
         json = cache_node->json ? json_clone(cache_node->json) : NULL;
     } else {
-        json = ovsdb_monitor_compose_update(dbmon, initial, prev_txn,
-                                            condition,
-                                            version);
+        if (!cond_updated) {
+            json = ovsdb_monitor_compose_update(dbmon, initial, prev_txn,
+                                                condition,
+                                                version);
 
-        if (!condition || !condition->conditional) {
-            ovsdb_monitor_json_cache_insert(&dbmon->json_cache, version, prev_txn, json);
+            if (!condition || !condition->conditional) {
+                ovsdb_monitor_json_cache_insert(&dbmon->json_cache, version, prev_txn, json);
+            }
+        } else {
+            json =
+                ovsdb_monitor_compose_all_rows_update(dbmon, condition);
         }
     }
 
@@ -1245,10 +1391,8 @@ ovsdb_monitor_change_cb(const struct ovsdb_row *old,
 void
 ovsdb_monitor_get_initial(const struct ovsdb_monitor *dbmon)
 {
-    struct ovsdb_monitor_aux aux;
     struct shash_node *node;
 
-    ovsdb_monitor_init_aux(&aux, dbmon);
     SHASH_FOR_EACH (node, &dbmon->tables) {
         struct ovsdb_monitor_table *mt = node->data;
 
diff --git a/ovsdb/monitor.h b/ovsdb/monitor.h
index 0c61aff..07cb0be 100644
--- a/ovsdb/monitor.h
+++ b/ovsdb/monitor.h
@@ -57,6 +57,10 @@ void ovsdb_monitor_remove_jsonrpc_monitor(struct ovsdb_monitor *dbmon,
 void ovsdb_monitor_add_table(struct ovsdb_monitor *m,
                              const struct ovsdb_table *table);
 
+bool
+ovsdb_monitor_table_exists(struct ovsdb_monitor *m,
+                           const struct ovsdb_table *table);
+
 void ovsdb_monitor_add_column(struct ovsdb_monitor *dbmon,
                               const struct ovsdb_table *table,
                               const struct ovsdb_column *column,
@@ -67,12 +71,12 @@ const char * OVS_WARN_UNUSED_RESULT
 ovsdb_monitor_table_check_duplicates(struct ovsdb_monitor *,
                           const struct ovsdb_table *);
 
-struct json *ovsdb_monitor_get_update(
-               struct ovsdb_monitor *dbmon,
-               bool initial,
-               uint64_t *unflushed_transaction,
-               const struct ovsdb_monitor_session_condition *condition,
-               enum ovsdb_monitor_version version);
+struct json *ovsdb_monitor_get_update(struct ovsdb_monitor *dbmon,
+                                      bool initial,
+                                      bool cond_updated,
+                                      uint64_t *unflushed_transaction,
+                                      struct ovsdb_monitor_session_condition *condition,
+                                      enum ovsdb_monitor_version version);
 
 void ovsdb_monitor_table_add_select(struct ovsdb_monitor *dbmon,
                                     const struct ovsdb_table *table,
@@ -101,4 +105,11 @@ void
 ovsdb_monitor_condition_bind(struct ovsdb_monitor *dbmon,
                              struct ovsdb_monitor_session_condition *cond);
 
+struct ovsdb_error *
+ovsdb_monitor_table_condition_update(
+                           struct ovsdb_monitor *dbmon,
+                           struct ovsdb_monitor_session_condition *condition,
+                           const struct ovsdb_table *table,
+                           const struct json *cond_json);
+
 #endif
-- 
2.1.4





More information about the dev mailing list