Revert "jsonrpc-server: Disconnect connections that queue too much data."
[sliver-openvswitch.git] / ovsdb / jsonrpc-server.c
index 8e1c030..a81648b 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009, 2010, 2011, 2012 Nicira, Inc.
+/* Copyright (c) 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -17,7 +17,6 @@
 
 #include "jsonrpc-server.h"
 
-#include <assert.h>
 #include <errno.h>
 
 #include "bitmap.h"
@@ -128,9 +127,36 @@ ovsdb_jsonrpc_server_create(void)
 bool
 ovsdb_jsonrpc_server_add_db(struct ovsdb_jsonrpc_server *svr, struct ovsdb *db)
 {
+    /* The OVSDB protocol doesn't have a way to notify a client that a
+     * database has been added.  If some client tried to use the database
+     * that we're adding and failed, then forcing it to reconnect seems like
+     * a reasonable way to make it try again.
+     *
+     * If this is too big of a hammer in practice, we could be more selective,
+     * e.g. disconnect only connections that actually tried to use a database
+     * with 'db''s name. */
+    ovsdb_jsonrpc_server_reconnect(svr);
+
     return ovsdb_server_add_db(&svr->up, db);
 }
 
+/* Removes 'db' from the set of databases served out by 'svr'.  Returns
+ * true if successful, false if there is no database associated with 'db'. */
+bool
+ovsdb_jsonrpc_server_remove_db(struct ovsdb_jsonrpc_server *svr,
+                               struct ovsdb *db)
+{
+    /* There might be pointers to 'db' from 'svr', such as monitors or
+     * outstanding transactions.  Disconnect all JSON-RPC connections to avoid
+     * accesses to freed memory.
+     *
+     * If this is too big of a hammer in practice, we could be more selective,
+     * e.g. disconnect only connections that actually reference 'db'. */
+    ovsdb_jsonrpc_server_reconnect(svr);
+
+    return ovsdb_server_remove_db(&svr->up, db);
+}
+
 void
 ovsdb_jsonrpc_server_destroy(struct ovsdb_jsonrpc_server *svr)
 {
@@ -199,7 +225,7 @@ ovsdb_jsonrpc_server_add_remote(struct ovsdb_jsonrpc_server *svr,
 
     error = jsonrpc_pstream_open(name, &listener, options->dscp);
     if (error && error != EAFNOSUPPORT) {
-        VLOG_ERR_RL(&rl, "%s: listen failed: %s", name, strerror(error));
+        VLOG_ERR_RL(&rl, "%s: listen failed: %s", name, ovs_strerror(error));
         return NULL;
     }
 
@@ -211,7 +237,7 @@ ovsdb_jsonrpc_server_add_remote(struct ovsdb_jsonrpc_server *svr,
     shash_add(&svr->remotes, name, remote);
 
     if (!listener) {
-        ovsdb_jsonrpc_session_create(remote, jsonrpc_session_open(name));
+        ovsdb_jsonrpc_session_create(remote, jsonrpc_session_open(name, true));
     }
     return remote;
 }
@@ -290,7 +316,7 @@ ovsdb_jsonrpc_server_run(struct ovsdb_jsonrpc_server *svr)
             } else if (error != EAGAIN) {
                 VLOG_WARN_RL(&rl, "%s: accept failed: %s",
                              pstream_get_name(remote->listener),
-                             strerror(error));
+                             ovs_strerror(error));
             }
         }
 
@@ -385,9 +411,13 @@ ovsdb_jsonrpc_session_close(struct ovsdb_jsonrpc_session *s)
 {
     ovsdb_jsonrpc_monitor_remove_all(s);
     ovsdb_jsonrpc_session_unlock_all(s);
+    ovsdb_jsonrpc_trigger_complete_all(s);
+
+    hmap_destroy(&s->monitors);
+    hmap_destroy(&s->triggers);
+
     jsonrpc_session_close(s->js);
     list_remove(&s->node);
-    ovsdb_session_destroy(&s->up);
     s->remote->server->n_sessions--;
     ovsdb_session_destroy(&s->up);
     free(s);
@@ -527,7 +557,7 @@ ovsdb_jsonrpc_session_set_all_options(
         error = pstream_set_dscp(remote->listener, options->dscp);
         if (error) {
             VLOG_ERR("%s: set_dscp failed %s",
-                     pstream_get_name(remote->listener), strerror(error));
+                     pstream_get_name(remote->listener), ovs_strerror(error));
         } else {
             remote->dscp = options->dscp;
         }
@@ -552,6 +582,10 @@ ovsdb_jsonrpc_session_get_status(const struct ovsdb_jsonrpc_remote *remote,
     struct reconnect_stats rstats;
     struct ds locks_held, locks_waiting, locks_lost;
 
+    status->bound_port = (remote->listener
+                          ? pstream_get_bound_port(remote->listener)
+                          : htons(0));
+
     if (list_is_empty(&remote->sessions)) {
         return false;
     }
@@ -1292,7 +1326,7 @@ ovsdb_jsonrpc_monitor_remove_all(struct ovsdb_jsonrpc_session *s)
 static struct ovsdb_jsonrpc_monitor *
 ovsdb_jsonrpc_monitor_cast(struct ovsdb_replica *replica)
 {
-    assert(replica->class == &ovsdb_jsonrpc_replica_class);
+    ovs_assert(replica->class == &ovsdb_jsonrpc_replica_class);
     return CONTAINER_OF(replica, struct ovsdb_jsonrpc_monitor, replica);
 }