ovsdb-monitor: rename jsonrpc_monitor_compose_table_update()
[cascardo/ovs.git] / ovsdb / monitor.c
index a1aeb5f..0898808 100644 (file)
@@ -47,8 +47,14 @@ static const struct ovsdb_replica_class ovsdb_jsonrpc_replica_class;
 struct ovsdb_monitor {
     struct ovsdb_replica replica;
     struct shash tables;     /* Holds "struct ovsdb_monitor_table"s. */
-    struct ovsdb_jsonrpc_monitor *jsonrpc_monitor;
+    struct ovs_list jsonrpc_monitors;  /* Contains "jsonrpc_monitor_node"s. */
     struct ovsdb *db;
+    uint64_t n_transactions;      /* Count number of committed transactions. */
+};
+
+struct jsonrpc_monitor_node {
+    struct ovsdb_jsonrpc_monitor *jsonrpc_monitor;
+    struct ovs_list node;
 };
 
 /* A particular column being monitored. */
@@ -82,6 +88,8 @@ struct ovsdb_monitor_table {
     struct hmap changes;
 };
 
+static void ovsdb_monitor_destroy(struct ovsdb_monitor *dbmon);
+
 static int
 compare_ovsdb_monitor_column(const void *a_, const void *b_)
 {
@@ -199,15 +207,21 @@ ovsdb_monitor_create(struct ovsdb *db,
                      struct ovsdb_jsonrpc_monitor *jsonrpc_monitor)
 {
     struct ovsdb_monitor *dbmon;
+    struct jsonrpc_monitor_node *jm;
 
     dbmon = xzalloc(sizeof *dbmon);
 
     ovsdb_replica_init(&dbmon->replica, &ovsdb_jsonrpc_replica_class);
     ovsdb_add_replica(db, &dbmon->replica);
-    dbmon->jsonrpc_monitor = jsonrpc_monitor;
+    list_init(&dbmon->jsonrpc_monitors);
     dbmon->db = db;
+    dbmon->n_transactions = 0;
     shash_init(&dbmon->tables);
 
+    jm = xzalloc(sizeof *jm);
+    jm->jsonrpc_monitor = jsonrpc_monitor;
+    list_push_back(&dbmon->jsonrpc_monitors, &jm->node);
+
     return dbmon;
 }
 
@@ -364,14 +378,16 @@ ovsdb_monitor_compose_row_update(
  * be used as part of the initial reply to a "monitor" request, false if it is
  * going to be used as part of an "update" notification. */
 struct json *
-ovsdb_monitor_compose_table_update(
-    const struct ovsdb_monitor *dbmon, bool initial)
+ovsdb_monitor_compose_update(const struct ovsdb_monitor *dbmon,
+                             bool initial, uint64_t *unflushed)
 {
     struct shash_node *node;
     unsigned long int *changed;
     struct json *json;
     size_t max_columns;
 
+    *unflushed = dbmon->n_transactions + 1;
+
     max_columns = 0;
     SHASH_FOR_EACH (node, &dbmon->tables) {
         struct ovsdb_monitor_table *mt = node->data;
@@ -420,18 +436,11 @@ ovsdb_monitor_compose_table_update(
 }
 
 bool
-ovsdb_monitor_needs_flush(struct ovsdb_monitor *dbmon)
+ovsdb_monitor_needs_flush(struct ovsdb_monitor *dbmon,
+                          uint64_t next_transaction)
 {
-    struct shash_node *node;
-
-    SHASH_FOR_EACH (node, &dbmon->tables) {
-        struct ovsdb_monitor_table *mt = node->data;
-
-        if (!hmap_is_empty(&mt->changes)) {
-            return true;
-        }
-    }
-    return false;
+    ovs_assert(next_transaction <= dbmon->n_transactions + 1);
+    return (next_transaction <= dbmon->n_transactions);
 }
 
 void
@@ -505,12 +514,11 @@ ovsdb_monitor_change_cb(const struct ovsdb_row *old,
     return true;
 }
 
-struct json *
+void
 ovsdb_monitor_get_initial(const struct ovsdb_monitor *dbmon)
 {
     struct ovsdb_monitor_aux aux;
     struct shash_node *node;
-    struct json *json;
 
     ovsdb_monitor_init_aux(&aux, dbmon);
     SHASH_FOR_EACH (node, &dbmon->tables) {
@@ -524,11 +532,34 @@ ovsdb_monitor_get_initial(const struct ovsdb_monitor *dbmon)
             }
         }
     }
-    json = ovsdb_monitor_compose_table_update(dbmon, true);
-    return json ? json : json_object_create();
 }
 
 void
+ovsdb_monitor_remove_jsonrpc_monitor(struct ovsdb_monitor *dbmon,
+                   struct ovsdb_jsonrpc_monitor *jsonrpc_monitor)
+{
+    struct jsonrpc_monitor_node *jm;
+
+    /* Find and remove the jsonrpc monitor from the list.  */
+    LIST_FOR_EACH(jm, node, &dbmon->jsonrpc_monitors) {
+        if (jm->jsonrpc_monitor == jsonrpc_monitor) {
+            list_remove(&jm->node);
+            free(jm);
+
+            /* Destroy ovsdb monitor if this is the last user.  */
+            if (list_is_empty(&dbmon->jsonrpc_monitors)) {
+                ovsdb_monitor_destroy(dbmon);
+            }
+
+            return;
+        };
+    }
+
+    /* Should never reach here. jsonrpc_monitor should be on the list.  */
+    OVS_NOT_REACHED();
+}
+
+static void
 ovsdb_monitor_destroy(struct ovsdb_monitor *dbmon)
 {
     struct shash_node *node;
@@ -562,6 +593,7 @@ ovsdb_monitor_commit(struct ovsdb_replica *replica,
 
     ovsdb_monitor_init_aux(&aux, m);
     ovsdb_txn_for_each_change(txn, ovsdb_monitor_change_cb, &aux);
+    m->n_transactions++;
 
     return NULL;
 }
@@ -570,9 +602,14 @@ static void
 ovsdb_monitor_destroy_callback(struct ovsdb_replica *replica)
 {
     struct ovsdb_monitor *dbmon = ovsdb_monitor_cast(replica);
-    struct ovsdb_jsonrpc_monitor *m = dbmon->jsonrpc_monitor;
+    struct jsonrpc_monitor_node *jm, *next;
 
-    ovsdb_jsonrpc_monitor_destroy(m);
+    /* Delete all front end monitors. Removing the last front
+     * end monitor will also destroy the corresponding 'ovsdb_monitor'.
+     * ovsdb monitor will also be destroied.  */
+    LIST_FOR_EACH_SAFE(jm, next, node, &dbmon->jsonrpc_monitors) {
+        ovsdb_jsonrpc_monitor_destroy(jm->jsonrpc_monitor);
+    }
 }
 
 static const struct ovsdb_replica_class ovsdb_jsonrpc_replica_class = {