[ovs-dev] [PATCH monitor_cond V5 05/18] ovsdb: enable JSON cache for none conditional monitored tables

Liran Schour lirans at il.ibm.com
Fri Mar 4 08:09:00 UTC 2016


This patch enables JSON cache of none conditional monitored tables to reduce
computation on sessions with mixed tables (true and none true conditions).

Signed-off-by: Liran Schour <lirans at il.ibm.com>
---
 ovsdb/monitor.c | 140 ++++++++++++++++++++++++++++++++++----------------------
 1 file changed, 86 insertions(+), 54 deletions(-)

diff --git a/ovsdb/monitor.c b/ovsdb/monitor.c
index 0192abf..afba8f2 100644
--- a/ovsdb/monitor.c
+++ b/ovsdb/monitor.c
@@ -38,6 +38,7 @@
 #include "monitor.h"
 #include "openvswitch/vlog.h"
 
+VLOG_DEFINE_THIS_MODULE(ovsdb_monitor);
 
 static const struct ovsdb_replica_class ovsdb_jsonrpc_replica_class;
 static struct hmap ovsdb_monitors = HMAP_INITIALIZER(&ovsdb_monitors);
@@ -50,10 +51,16 @@ struct ovsdb_monitor_session_condition {
                               *   "struct ovsdb_monitor_table_condition *"s. */
 };
 
+enum monitor_table_condition_mode {
+    MTC_MODE_TRUE,    /* monitor all rows in table */
+    MTC_MODE_FULL,    /* full conditional monitoring */
+};
+
 /* Monitored table session's conditions */
 struct ovsdb_monitor_table_condition {
     const struct ovsdb_table *table;
     struct ovsdb_monitor_table *mt;
+    enum monitor_table_condition_mode cond_mode;
     struct ovsdb_condition old_condition;
     struct ovsdb_condition new_condition;
 };
@@ -142,6 +149,8 @@ struct ovsdb_monitor_table {
      * ovsdb_monitor_row. It is used for condition evaluation */
     unsigned int *columns_index_map;
 
+    /* Contains "ovsdb_monitor_json_cache_node"s.*/
+    struct hmap json_cache;
     /* Contains 'ovsdb_monitor_changes' indexed by 'transaction'. */
     struct hmap changes;
 };
@@ -175,14 +184,14 @@ json_cache_hash(enum ovsdb_monitor_version version, uint64_t from_txn)
 }
 
 static struct ovsdb_monitor_json_cache_node *
-ovsdb_monitor_json_cache_search(const struct ovsdb_monitor *dbmon,
+ovsdb_monitor_json_cache_search(const struct hmap *json_cache,
                                 enum ovsdb_monitor_version version,
                                 uint64_t from_txn)
 {
     struct ovsdb_monitor_json_cache_node *node;
     uint32_t hash = json_cache_hash(version, from_txn);
 
-    HMAP_FOR_EACH_WITH_HASH(node, hmap_node, hash, &dbmon->json_cache) {
+    HMAP_FOR_EACH_WITH_HASH(node, hmap_node, hash, json_cache) {
         if (node->from_txn == from_txn && node->version == version) {
             return node;
         }
@@ -192,7 +201,7 @@ ovsdb_monitor_json_cache_search(const struct ovsdb_monitor *dbmon,
 }
 
 static void
-ovsdb_monitor_json_cache_insert(struct ovsdb_monitor *dbmon,
+ovsdb_monitor_json_cache_insert(struct hmap *json_cache,
                                 enum ovsdb_monitor_version version,
                                 uint64_t from_txn, struct json *json)
 {
@@ -205,16 +214,16 @@ ovsdb_monitor_json_cache_insert(struct ovsdb_monitor *dbmon,
     node->from_txn = from_txn;
     node->json = json ? json_clone(json) : NULL;
 
-    hmap_insert(&dbmon->json_cache, &node->hmap_node, hash);
+    hmap_insert(json_cache, &node->hmap_node, hash);
 }
 
 static void
-ovsdb_monitor_json_cache_flush(struct ovsdb_monitor *dbmon)
+ovsdb_monitor_json_cache_flush(struct hmap *json_cache)
 {
     struct ovsdb_monitor_json_cache_node *node, *next;
 
-    HMAP_FOR_EACH_SAFE(node, next, hmap_node, &dbmon->json_cache) {
-        hmap_remove(&dbmon->json_cache, &node->hmap_node);
+    HMAP_FOR_EACH_SAFE(node, next, hmap_node, json_cache) {
+        hmap_remove(json_cache, &node->hmap_node);
         json_destroy(node->json);
         free(node);
     }
@@ -395,6 +404,7 @@ ovsdb_monitor_add_table(struct ovsdb_monitor *m,
     mt->dbmon = m;
     shash_add(&m->tables, table->schema->name, mt);
     hmap_init(&mt->changes);
+    hmap_init(&mt->json_cache);
     mt->columns_index_map =
         xmalloc(sizeof(unsigned int) * shash_count(&table->schema->columns));
     for (i = 0; i < shash_count(&table->schema->columns); i++) {
@@ -415,7 +425,7 @@ ovsdb_monitor_add_column(struct ovsdb_monitor *dbmon,
 
     mt = shash_find_data(&dbmon->tables, table->schema->name);
 
-    /* Check duplication only for non-monitored columns */
+    /* Check duplication only for unmonitored columns */
     if (!monitored) {
         for (i = 0; i < mt->n_columns; i++) {
             if (mt->columns[i].column == column) {
@@ -671,6 +681,8 @@ ovsdb_monitor_table_condition_set(
     if (ovsdb_condition_is_true(&mtc->old_condition)) {
         condition->n_true_cnd++;
         ovsdb_monitor_session_condition_set_mode(condition);
+    } else {
+        mtc->cond_mode = MTC_MODE_FULL;
     }
 
     return NULL;
@@ -940,46 +952,71 @@ ovsdb_monitor_compose_update(
                       struct ovsdb_monitor *dbmon,
                       bool initial, uint64_t transaction,
                       const struct ovsdb_monitor_session_condition *condition,
-                      compose_row_update_cb_func row_update)
+                      enum ovsdb_monitor_version version)
 {
     struct shash_node *node;
     struct json *json;
     size_t max_columns = ovsdb_monitor_max_columns(dbmon);
     unsigned long int *changed = xmalloc(bitmap_n_bytes(max_columns));
+    compose_row_update_cb_func row_update = version == OVSDB_MONITOR_V1 ?
+        ovsdb_monitor_compose_row_update : ovsdb_monitor_compose_row_update2;
 
     json = NULL;
     SHASH_FOR_EACH (node, &dbmon->tables) {
         struct ovsdb_monitor_table *mt = node->data;
+        struct ovsdb_monitor_table_condition *mtc = condition ?
+            shash_find_data(&condition->tables, node->name) : NULL;
+        struct ovsdb_monitor_json_cache_node *cache_node = NULL;
         struct ovsdb_monitor_row *row, *next;
         struct ovsdb_monitor_changes *changes;
         struct json *table_json = NULL;
 
-        changes = ovsdb_monitor_table_find_changes(mt, transaction);
-        if (!changes) {
-            continue;
+        if (!mtc || !mtc->cond_mode) {
+            cache_node = ovsdb_monitor_json_cache_search(&mt->json_cache,
+                                                         version, transaction);
         }
-
-        HMAP_FOR_EACH_SAFE (row, next, hmap_node, &changes->rows) {
-            struct json *row_json;
-
-            row_json = (*row_update)(mt, condition, row, initial, changed);
-            if (row_json) {
-                char uuid[UUID_LEN + 1];
-
-                /* Create JSON object for transaction overall. */
+        if (cache_node) {
+            table_json = cache_node->json ?
+                json_clone(cache_node->json) : NULL;
+            if (table_json) {
                 if (!json) {
                     json = json_object_create();
                 }
+                json_object_put(json, mt->table->schema->name, table_json);
+            }
+        } else {
+            changes = ovsdb_monitor_table_find_changes(mt, transaction);
+            if (!changes) {
+                continue;
+            }
 
-                /* 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);
+            HMAP_FOR_EACH_SAFE (row, next, hmap_node, &changes->rows) {
+                struct json *row_json;
+
+                row_json = (*row_update)(mt, condition, 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);
                 }
-
-                /* Add JSON row to JSON table. */
-                snprintf(uuid, sizeof uuid, UUID_FMT, UUID_ARGS(&row->uuid));
-                json_object_put(table_json, uuid, row_json);
+            }
+            if (!mtc || !mtc->cond_mode) {
+                ovsdb_monitor_json_cache_insert(&mt->json_cache, version,
+                                                transaction, table_json);
             }
         }
     }
@@ -1011,26 +1048,19 @@ ovsdb_monitor_get_update(
     /* Return a clone of cached json if one exists. Otherwise,
      * generate a new one and add it to the cache.  */
     if (!condition || !condition->conditional) {
-        cache_node = ovsdb_monitor_json_cache_search(dbmon, version,
-                                                     unflushed);
+        cache_node = ovsdb_monitor_json_cache_search(&dbmon->json_cache,
+                                                     version, unflushed);
     }
     if (cache_node) {
         json = cache_node->json ? json_clone(cache_node->json) : NULL;
     } else {
-        if (version == OVSDB_MONITOR_V1) {
-            json =
-               ovsdb_monitor_compose_update(dbmon, initial, unflushed,
-                                            condition,
-                                            ovsdb_monitor_compose_row_update);
-        } else {
-            ovs_assert(version == OVSDB_MONITOR_V2);
-            json =
-               ovsdb_monitor_compose_update(dbmon, initial, unflushed,
+        json = ovsdb_monitor_compose_update(dbmon, initial, unflushed,
                                             condition,
-                                            ovsdb_monitor_compose_row_update2);
-        }
+                                            version);
+
         if (!condition || !condition->conditional) {
-            ovsdb_monitor_json_cache_insert(dbmon, version, unflushed, json);
+            ovsdb_monitor_json_cache_insert(&dbmon->json_cache, version,
+                                            unflushed, json);
         }
     }
 
@@ -1201,19 +1231,21 @@ ovsdb_monitor_change_cb(const struct ovsdb_row *old,
     }
     mt = aux->mt;
 
-    HMAP_FOR_EACH(changes, hmap_node, &mt->changes) {
-        enum ovsdb_monitor_changes_efficacy efficacy;
-        enum ovsdb_monitor_selection type;
+    enum ovsdb_monitor_selection type =
+        ovsdb_monitor_row_update_type(false, old, new);
+    enum ovsdb_monitor_changes_efficacy efficacy =
+        ovsdb_monitor_changes_classify(type, mt, changed);
 
-        type = ovsdb_monitor_row_update_type(false, old, new);
-        efficacy = ovsdb_monitor_changes_classify(type, mt, changed);
+    if (efficacy == OVSDB_CHANGES_REQUIRE_EXTERNAL_UPDATE) {
+        ovsdb_monitor_json_cache_flush(&mt->json_cache);
+    }
+    HMAP_FOR_EACH(changes, hmap_node, &mt->changes) {
         if (efficacy > OVSDB_CHANGES_NO_EFFECT) {
             ovsdb_monitor_changes_update(old, new, mt, changes);
         }
-
-        if (aux->efficacy < efficacy) {
-            aux->efficacy = efficacy;
-        }
+    }
+    if (aux->efficacy < efficacy) {
+        aux->efficacy = efficacy;
     }
 
     return true;
@@ -1384,7 +1416,7 @@ ovsdb_monitor_destroy(struct ovsdb_monitor *dbmon)
         hmap_remove(&ovsdb_monitors, &dbmon->hmap_node);
     }
 
-    ovsdb_monitor_json_cache_flush(dbmon);
+    ovsdb_monitor_json_cache_flush(&dbmon->json_cache);
     hmap_destroy(&dbmon->json_cache);
 
     SHASH_FOR_EACH (node, &dbmon->tables) {
@@ -1429,7 +1461,7 @@ ovsdb_monitor_commit(struct ovsdb_replica *replica,
         /* Nothing.  */
         break;
     case  OVSDB_CHANGES_REQUIRE_EXTERNAL_UPDATE:
-        ovsdb_monitor_json_cache_flush(m);
+        ovsdb_monitor_json_cache_flush(&m->json_cache);
         break;
     }
 
-- 
2.1.4





More information about the dev mailing list