Replace all uses of strerror() by ovs_strerror(), for thread safety.
[sliver-openvswitch.git] / ovsdb / jsonrpc-server.c
index febc351..4cba4d9 100644 (file)
@@ -129,9 +129,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)
 {
@@ -200,7 +227,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;
     }
 
@@ -291,7 +318,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));
             }
         }
 
@@ -572,7 +599,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;
         }
@@ -597,6 +624,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;
     }