summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Pfaff <blp@ovn.org>2017-12-06 11:37:03 -0800
committerBen Pfaff <blp@ovn.org>2018-03-24 12:04:52 -0700
commit10621d795331a3ddddb3e96086a9fda7ad156efc (patch)
tree47f47725201b38e96d2ae1d68cdf3ba18ed03a73
parent6bb9b060d5b0f972461f0c061a865393611fd86a (diff)
downloadopenvswitch-10621d795331a3ddddb3e96086a9fda7ad156efc.tar.gz
ovsdb-server: Add new RPC "set_db_change_aware".
The _Server database recently added to ovsdb-server can be used to dump out information about databases, but monitoring updates to _Server is not yet very useful because for historical reasons ovsdb-server drops all of its OVSDB connections whenever databases are added or removed or otherwise change in some major way. It is not a good idea to change this behavior for all clients, because some of them rely on it, but this commit introduces a new RPC that allows clients that understand _Server to suppress the connection-closing behavior. Signed-off-by: Ben Pfaff <blp@ovn.org>
-rw-r--r--Documentation/ref/ovsdb-server.7.rst43
-rw-r--r--ovsdb/_server.xml34
-rw-r--r--ovsdb/jsonrpc-server.c195
-rw-r--r--ovsdb/jsonrpc-server.h4
-rw-r--r--ovsdb/ovsdb-client.c28
-rw-r--r--ovsdb/ovsdb-server.c9
-rw-r--r--tests/ovsdb-server.at40
7 files changed, 299 insertions, 54 deletions
diff --git a/Documentation/ref/ovsdb-server.7.rst b/Documentation/ref/ovsdb-server.7.rst
index cc625f601..2ed392fee 100644
--- a/Documentation/ref/ovsdb-server.7.rst
+++ b/Documentation/ref/ovsdb-server.7.rst
@@ -146,6 +146,19 @@ notifications (see below) to the request, it must be unique among all active
monitors. ``ovsdb-server`` rejects attempt to create two monitors with the
same identifier.
+4.1.7 Monitor Cancellation
+--------------------------
+
+When a database monitored by a session is removed, and database change
+awareness is enabled for the session (see Section 4.1.16), the database server
+spontaneously cancels all monitors (including conditional monitors described in
+Section 4.1.12) for the removed database. For each canceled monitor, it issues
+a notification in the following form::
+
+ "method": "monitor_canceled"
+ "params": [<json-value>]
+ "id": null
+
4.1.12 Monitor_cond
-------------------
@@ -371,6 +384,36 @@ The response object contains the following members::
running OVSDB server process. A fresh UUID is generated when the process
restarts.
+4.1.16 Database Change Awareness
+--------------------------------
+
+RFC 7047 does not provide a way for a client to find out about some kinds of
+configuration changes, such as about databases added or removed while a client
+is connected to the server, or databases changing between read/write and
+read-only due to a transition between active and backup roles. Traditionally,
+``ovsdb-server`` disconnects all of its clients when this happens, because this
+prompts a well-written client to reassess what is available from the server
+when it reconnects.
+
+OVS 2.9 provides a way for clients to keep track of these kinds of changes, by
+monitoring the ``Database`` table in the ``_Server`` database introduced in
+this release (see ``ovsdb-server(5)`` for details). By itself, this does not
+suppress ``ovsdb-server`` disconnection behavior, because a client might
+monitor this database without understanding its special semantics. Instead,
+``ovsdb-server`` provides a special request::
+
+ "method": "set_db_change_aware"
+ "params": [<boolean>]
+ "id": <nonnull-json-value>
+
+If the boolean in the request is true, it suppresses the connection-closing
+behavior for the current connection, and false restores the default behavior.
+The reply is always the same::
+
+ "result": {}
+ "error": null
+ "id": same "id" as request
+
5.1 Notation
------------
diff --git a/ovsdb/_server.xml b/ovsdb/_server.xml
index a55beb9bd..559939ced 100644
--- a/ovsdb/_server.xml
+++ b/ovsdb/_server.xml
@@ -13,6 +13,40 @@
one row per database. As its database configuration and status changes,
the server automatically and immediately updates the table to match.
</p>
+
+ <p>
+ The OVSDB protocol specified in RFC 7047 does not provide a way for an
+ OVSDB client to find out about some kinds of configuration changes, such
+ as about databases added or removed while a client is connected to the
+ server, or databases changing between read/write and read-only due to a
+ transition between active and backup roles. This table provides a
+ solution: clients can monitor the table's contents to find out about
+ important changes.
+ </p>
+
+ <p>
+ Traditionally, <code>ovsdb-server</code> disconnects all of its clients
+ when a significant configuration change occurs, because this prompts a
+ well-written client to reassess what is available from the server when it
+ reconnects. Because this table provides an alternative and more
+ efficient way to find out about those changes, OVS 2.9 also introduces
+ the <code>set_db_change_aware</code> RPC, documented in
+ <code>ovsdb-server</code>(7), to allow clients to suppress this
+ disconnection behavior.
+ </p>
+
+ <p>
+ When a database is removed from the server, in addition to
+ <code>Database</code> table updates, the server sends <code>cancel</code>
+ messages, as described in RFC 7047 section 4.1.4, in reply to outstanding
+ transactions for the removed database. The server also cancels any
+ outstanding monitoring initiated by <code>monitor</code> or
+ <code>monitor_cond</code> requested on the removed database, sending the
+ <code>monitor_canceled</code> RPC described in
+ <code>ovsdb-server</code>(7). Only clients that disable disconnection
+ with <code>set_db_change_aware</code> receive these messages.
+ </p>
+
<p>
Clients can use the <code>_uuid</code> column in this table as a
generation number. The server generates a fresh <code>_uuid</code> every
diff --git a/ovsdb/jsonrpc-server.c b/ovsdb/jsonrpc-server.c
index 75ff98f78..d6d2ad4c6 100644
--- a/ovsdb/jsonrpc-server.c
+++ b/ovsdb/jsonrpc-server.c
@@ -57,12 +57,15 @@ static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
/* Sessions. */
static struct ovsdb_jsonrpc_session *ovsdb_jsonrpc_session_create(
struct ovsdb_jsonrpc_remote *, struct jsonrpc_session *, bool);
+static void ovsdb_jsonrpc_session_preremove_db(struct ovsdb_jsonrpc_remote *,
+ struct ovsdb *);
static void ovsdb_jsonrpc_session_run_all(struct ovsdb_jsonrpc_remote *);
static void ovsdb_jsonrpc_session_wait_all(struct ovsdb_jsonrpc_remote *);
static void ovsdb_jsonrpc_session_get_memory_usage_all(
const struct ovsdb_jsonrpc_remote *, struct simap *usage);
static void ovsdb_jsonrpc_session_close_all(struct ovsdb_jsonrpc_remote *);
-static void ovsdb_jsonrpc_session_reconnect_all(struct ovsdb_jsonrpc_remote *);
+static void ovsdb_jsonrpc_session_reconnect_all(struct ovsdb_jsonrpc_remote *,
+ bool force);
static void ovsdb_jsonrpc_session_set_all_options(
struct ovsdb_jsonrpc_remote *, const struct ovsdb_jsonrpc_options *);
static bool ovsdb_jsonrpc_active_session_get_status(
@@ -83,6 +86,8 @@ static void ovsdb_jsonrpc_trigger_create(struct ovsdb_jsonrpc_session *,
static struct ovsdb_jsonrpc_trigger *ovsdb_jsonrpc_trigger_find(
struct ovsdb_jsonrpc_session *, const struct json *id, size_t hash);
static void ovsdb_jsonrpc_trigger_complete(struct ovsdb_jsonrpc_trigger *);
+static void ovsdb_jsonrpc_trigger_preremove_db(struct ovsdb_jsonrpc_session *,
+ struct ovsdb *);
static void ovsdb_jsonrpc_trigger_complete_all(struct ovsdb_jsonrpc_session *);
static void ovsdb_jsonrpc_trigger_complete_done(
struct ovsdb_jsonrpc_session *);
@@ -99,6 +104,8 @@ static struct jsonrpc_msg *ovsdb_jsonrpc_monitor_cancel(
struct ovsdb_jsonrpc_session *,
struct json_array *params,
const struct json *request_id);
+static void ovsdb_jsonrpc_monitor_preremove_db(struct ovsdb_jsonrpc_session *,
+ struct ovsdb *);
static void ovsdb_jsonrpc_monitor_remove_all(struct ovsdb_jsonrpc_session *);
static void ovsdb_jsonrpc_monitor_flush_all(struct ovsdb_jsonrpc_session *);
static bool ovsdb_jsonrpc_monitor_needs_flush(struct ovsdb_jsonrpc_session *);
@@ -157,34 +164,25 @@ ovsdb_jsonrpc_server_create(bool read_only)
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);
-
+ ovsdb_jsonrpc_server_reconnect(svr, false);
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
+/* Removes 'db' from the set of databases served out by 'svr'. */
+void
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);
+ struct shash_node *node;
+ SHASH_FOR_EACH (node, &svr->remotes) {
+ struct ovsdb_jsonrpc_remote *remote = node->data;
+
+ ovsdb_jsonrpc_session_preremove_db(remote, db);
+ }
+
+ ovsdb_jsonrpc_server_reconnect(svr, false);
- return ovsdb_server_remove_db(&svr->up, db);
+ ovsdb_server_remove_db(&svr->up, db);
}
void
@@ -333,17 +331,20 @@ ovsdb_jsonrpc_server_free_remote_status(
free(status->locks_lost);
}
-/* Forces all of the JSON-RPC sessions managed by 'svr' to disconnect and
- * reconnect. */
+/* Makes all of the JSON-RPC sessions managed by 'svr' disconnect. (They will
+ * then generally reconnect.).
+ *
+ * If 'force' is true, disconnects all sessions. Otherwise, disconnects only
+ * sesions that aren't database change aware. */
void
-ovsdb_jsonrpc_server_reconnect(struct ovsdb_jsonrpc_server *svr)
+ovsdb_jsonrpc_server_reconnect(struct ovsdb_jsonrpc_server *svr, bool force)
{
struct shash_node *node;
SHASH_FOR_EACH (node, &svr->remotes) {
struct ovsdb_jsonrpc_remote *remote = node->data;
- ovsdb_jsonrpc_session_reconnect_all(remote);
+ ovsdb_jsonrpc_session_reconnect_all(remote, force);
}
}
@@ -353,7 +354,7 @@ ovsdb_jsonrpc_server_set_read_only(struct ovsdb_jsonrpc_server *svr,
{
if (svr->read_only != read_only) {
svr->read_only = read_only;
- ovsdb_jsonrpc_server_reconnect(svr);
+ ovsdb_jsonrpc_server_reconnect(svr, false);
}
}
@@ -426,6 +427,20 @@ struct ovsdb_jsonrpc_session {
struct ovsdb_session up;
struct ovsdb_jsonrpc_remote *remote;
+ /* RFC 7047 does not contemplate how to alert clients to changes to the set
+ * of databases, e.g. databases that are added or removed while the
+ * database server is running. Traditionally, ovsdb-server disconnects all
+ * of its clients when this happens; a well-written client will reassess
+ * what is available from the server upon reconnection.
+ *
+ * OVS 2.9 introduces a way for clients to monitor changes to the databases
+ * being served, through the Database table in the _Server database that
+ * OVSDB adds in this version. ovsdb-server suppresses the connection
+ * close for clients that identify themselves as taking advantage of this
+ * mechanism. When this member is true, it indicates that the client
+ * requested such suppression. */
+ bool db_change_aware;
+
/* Triggers. */
struct hmap triggers; /* Hmap of "struct ovsdb_jsonrpc_trigger"s. */
@@ -472,6 +487,20 @@ ovsdb_jsonrpc_session_create(struct ovsdb_jsonrpc_remote *remote,
return s;
}
+/* Database 'db' is about to be removed from the database server. To prepare,
+ * this function removes all references to 'db' from 'remote'. */
+static void
+ovsdb_jsonrpc_session_preremove_db(struct ovsdb_jsonrpc_remote *remote,
+ struct ovsdb *db)
+{
+ struct ovsdb_jsonrpc_session *s;
+
+ LIST_FOR_EACH (s, node, &remote->sessions) {
+ ovsdb_jsonrpc_monitor_preremove_db(s, db);
+ ovsdb_jsonrpc_trigger_preremove_db(s, db);
+ }
+}
+
static void
ovsdb_jsonrpc_session_close(struct ovsdb_jsonrpc_session *s)
{
@@ -600,17 +629,23 @@ ovsdb_jsonrpc_session_close_all(struct ovsdb_jsonrpc_remote *remote)
}
}
-/* Forces all of the JSON-RPC sessions managed by 'remote' to disconnect and
- * reconnect. */
+/* Makes all of the JSON-RPC sessions managed by 'remote' disconnect. (They
+ * will then generally reconnect.).
+ *
+ * If 'force' is true, disconnects all sessions. Otherwise, disconnects only
+ * sesions that aren't database change aware. */
static void
-ovsdb_jsonrpc_session_reconnect_all(struct ovsdb_jsonrpc_remote *remote)
+ovsdb_jsonrpc_session_reconnect_all(struct ovsdb_jsonrpc_remote *remote,
+ bool force)
{
struct ovsdb_jsonrpc_session *s, *next;
LIST_FOR_EACH_SAFE (s, next, node, &remote->sessions) {
- jsonrpc_session_force_reconnect(s->js);
- if (!jsonrpc_session_is_alive(s->js)) {
- ovsdb_jsonrpc_session_close(s);
+ if (force || !s->db_change_aware) {
+ jsonrpc_session_force_reconnect(s->js);
+ if (!jsonrpc_session_is_alive(s->js)) {
+ ovsdb_jsonrpc_session_close(s);
+ }
}
}
}
@@ -853,6 +888,17 @@ ovsdb_jsonrpc_session_unlock__(struct ovsdb_lock_waiter *waiter)
}
static struct jsonrpc_msg *
+syntax_error_reply(const struct jsonrpc_msg *request, const char *details)
+{
+ struct ovsdb_error *error = ovsdb_syntax_error(
+ request->params, NULL, "%s: %s", request->method, details);
+ struct jsonrpc_msg *msg = jsonrpc_create_error(ovsdb_error_to_json(error),
+ request->id);
+ ovsdb_error_destroy(error);
+ return msg;
+}
+
+static struct jsonrpc_msg *
ovsdb_jsonrpc_session_unlock(struct ovsdb_jsonrpc_session *s,
struct jsonrpc_msg *request)
{
@@ -866,24 +912,21 @@ ovsdb_jsonrpc_session_unlock(struct ovsdb_jsonrpc_session *s,
error = ovsdb_jsonrpc_session_parse_lock_name(request, &lock_name);
if (error) {
- goto error;
+ return jsonrpc_create_error(ovsdb_error_to_json_free(error),
+ request->id);
}
/* Report error if this session has not issued a "lock" or "steal" for this
* lock. */
waiter = ovsdb_session_get_lock_waiter(&s->up, lock_name);
if (!waiter) {
- error = ovsdb_syntax_error(
- request->params, NULL, "\"unlock\" without \"lock\" or \"steal\"");
- goto error;
+ return syntax_error_reply(request,
+ "\"unlock\" without \"lock\" or \"steal\"");
}
ovsdb_jsonrpc_session_unlock__(waiter);
return jsonrpc_create_reply(json_object_create(), request->id);
-
-error:
- return jsonrpc_create_error(ovsdb_error_to_json_free(error), request->id);
}
static struct jsonrpc_msg *
@@ -897,6 +940,21 @@ execute_transaction(struct ovsdb_jsonrpc_session *s, struct ovsdb *db,
return NULL;
}
+static struct jsonrpc_msg *
+ovsdb_jsonrpc_session_set_db_change_aware(struct ovsdb_jsonrpc_session *s,
+ const struct jsonrpc_msg *request)
+{
+ const struct json_array *params = json_array(request->params);
+ if (params->n != 1
+ || (params->elems[0]->type != JSON_TRUE &&
+ params->elems[0]->type != JSON_FALSE)) {
+ return syntax_error_reply(request, "true or false parameter expected");
+ }
+
+ s->db_change_aware = json_boolean(params->elems[0]);
+ return jsonrpc_create_reply(json_object_create(), request->id);
+}
+
static void
ovsdb_jsonrpc_session_got_request(struct ovsdb_jsonrpc_session *s,
struct jsonrpc_msg *request)
@@ -957,6 +1015,8 @@ ovsdb_jsonrpc_session_got_request(struct ovsdb_jsonrpc_session *s,
reply = ovsdb_jsonrpc_session_lock(s, request, OVSDB_LOCK_STEAL);
} else if (!strcmp(request->method, "unlock")) {
reply = ovsdb_jsonrpc_session_unlock(s, request);
+ } else if (!strcmp(request->method, "set_db_change_aware")) {
+ reply = ovsdb_jsonrpc_session_set_db_change_aware(s, request);
} else if (!strcmp(request->method, "echo")) {
reply = jsonrpc_create_reply(json_clone(request->params), request->id);
} else {
@@ -1092,14 +1152,34 @@ ovsdb_jsonrpc_trigger_complete(struct ovsdb_jsonrpc_trigger *t)
}
static void
-ovsdb_jsonrpc_trigger_complete_all(struct ovsdb_jsonrpc_session *s)
+ovsdb_jsonrpc_trigger_remove__(struct ovsdb_jsonrpc_session *s,
+ struct ovsdb *db)
{
struct ovsdb_jsonrpc_trigger *t, *next;
HMAP_FOR_EACH_SAFE (t, next, hmap_node, &s->triggers) {
- ovsdb_jsonrpc_trigger_complete(t);
+ if (!db || t->trigger.db == db) {
+ ovsdb_jsonrpc_trigger_complete(t);
+ }
}
}
+/* Database 'db' is about to be removed from the database server. To prepare,
+ * this function removes all references from triggers in 's' to 'db'. */
+static void
+ovsdb_jsonrpc_trigger_preremove_db(struct ovsdb_jsonrpc_session *s,
+ struct ovsdb *db)
+{
+ ovs_assert(db);
+ ovsdb_jsonrpc_trigger_remove__(s, db);
+}
+
+/* Removes all triggers from 's'. */
+static void
+ovsdb_jsonrpc_trigger_complete_all(struct ovsdb_jsonrpc_session *s)
+{
+ ovsdb_jsonrpc_trigger_remove__(s, NULL);
+}
+
static void
ovsdb_jsonrpc_trigger_complete_done(struct ovsdb_jsonrpc_session *s)
{
@@ -1519,15 +1599,42 @@ ovsdb_jsonrpc_monitor_cancel(struct ovsdb_jsonrpc_session *s,
}
static void
-ovsdb_jsonrpc_monitor_remove_all(struct ovsdb_jsonrpc_session *s)
+ovsdb_jsonrpc_monitor_remove__(struct ovsdb_jsonrpc_session *s,
+ struct ovsdb *db)
{
struct ovsdb_jsonrpc_monitor *m, *next;
HMAP_FOR_EACH_SAFE (m, next, node, &s->monitors) {
- ovsdb_jsonrpc_monitor_destroy(m);
+ if (!db || m->db == db) {
+ if (db && jsonrpc_session_is_connected(s->js)
+ && s->db_change_aware) {
+ struct jsonrpc_msg *notify = jsonrpc_create_notify(
+ "monitor_canceled",
+ json_array_create_1(json_clone(m->monitor_id)));
+ ovsdb_jsonrpc_session_send(s, notify);
+ }
+ ovsdb_jsonrpc_monitor_destroy(m);
+ }
}
}
+/* Database 'db' is about to be removed from the database server. To prepare,
+ * this function removes all references from monitors in 's' to 'db'. */
+static void
+ovsdb_jsonrpc_monitor_preremove_db(struct ovsdb_jsonrpc_session *s,
+ struct ovsdb *db)
+{
+ ovs_assert(db);
+ ovsdb_jsonrpc_monitor_remove__(s, db);
+}
+
+/* Cancels all monitors in 's'. */
+static void
+ovsdb_jsonrpc_monitor_remove_all(struct ovsdb_jsonrpc_session *s)
+{
+ ovsdb_jsonrpc_monitor_remove__(s, NULL);
+}
+
static struct json *
ovsdb_jsonrpc_monitor_compose_update(struct ovsdb_jsonrpc_monitor *m,
bool initial)
diff --git a/ovsdb/jsonrpc-server.h b/ovsdb/jsonrpc-server.h
index 2be4bbc01..fe7d8e202 100644
--- a/ovsdb/jsonrpc-server.h
+++ b/ovsdb/jsonrpc-server.h
@@ -27,7 +27,7 @@ struct uuid;
struct ovsdb_jsonrpc_server *ovsdb_jsonrpc_server_create(bool read_only);
bool ovsdb_jsonrpc_server_add_db(struct ovsdb_jsonrpc_server *,
struct ovsdb *);
-bool ovsdb_jsonrpc_server_remove_db(struct ovsdb_jsonrpc_server *,
+void ovsdb_jsonrpc_server_remove_db(struct ovsdb_jsonrpc_server *,
struct ovsdb *);
void ovsdb_jsonrpc_server_destroy(struct ovsdb_jsonrpc_server *);
@@ -64,7 +64,7 @@ bool ovsdb_jsonrpc_server_get_remote_status(
void ovsdb_jsonrpc_server_free_remote_status(
struct ovsdb_jsonrpc_remote_status *);
-void ovsdb_jsonrpc_server_reconnect(struct ovsdb_jsonrpc_server *);
+void ovsdb_jsonrpc_server_reconnect(struct ovsdb_jsonrpc_server *, bool force);
void ovsdb_jsonrpc_server_run(struct ovsdb_jsonrpc_server *);
void ovsdb_jsonrpc_server_wait(struct ovsdb_jsonrpc_server *);
diff --git a/ovsdb/ovsdb-client.c b/ovsdb/ovsdb-client.c
index 3dfe543a3..bd1c5fdc2 100644
--- a/ovsdb/ovsdb-client.c
+++ b/ovsdb/ovsdb-client.c
@@ -75,6 +75,13 @@ struct ovsdb_client_command {
/* --timestamp: Print a timestamp before each update on "monitor" command? */
static bool timestamp;
+/* --db-change-aware, --no-db-change-aware: Enable db_change_aware feature for
+ * "monitor" command?
+ *
+ * (This option is undocumented because it is expected to be useful only for
+ * testing that the db_change_aware feature actually works.) */
+static int db_change_aware;
+
/* --force: Ignore schema differences for "restore" command? */
static bool force;
@@ -201,6 +208,8 @@ parse_options(int argc, char *argv[])
{"timestamp", no_argument, NULL, OPT_TIMESTAMP},
{"force", no_argument, NULL, OPT_FORCE},
{"timeout", required_argument, NULL, 't'},
+ {"db-change-aware", no_argument, &db_change_aware, 1},
+ {"no-db-change-aware", no_argument, &db_change_aware, 0},
VLOG_LONG_OPTIONS,
DAEMON_LONG_OPTIONS,
#ifdef HAVE_OPENSSL
@@ -1034,7 +1043,6 @@ do_monitor__(struct jsonrpc *rpc, const char *database,
const char *table_name = argv[0];
struct unixctl_server *unixctl;
struct ovsdb_schema *schema;
- struct jsonrpc_msg *request;
struct json *monitor, *monitor_requests, *request_id;
bool exiting = false;
bool blocked = false;
@@ -1102,11 +1110,29 @@ do_monitor__(struct jsonrpc *rpc, const char *database,
free(nodes);
}
+ if (db_change_aware) {
+ struct jsonrpc_msg *request = jsonrpc_create_request(
+ "set_db_change_aware",
+ json_array_create_1(json_boolean_create(true)),
+ NULL);
+ struct jsonrpc_msg *reply;
+ int error = jsonrpc_transact_block(rpc, request, &reply);
+ if (error) {
+ ovs_fatal(error, "%s: error setting db_change_aware", server);
+ }
+ if (reply->type == JSONRPC_ERROR) {
+ ovs_fatal(0, "%s: set_db_change_aware failed (%s)",
+ server, json_to_string(reply->error, 0));
+ }
+ jsonrpc_msg_destroy(reply);
+ }
+
monitor = json_array_create_3(json_string_create(database),
json_null_create(), monitor_requests);
const char *method = version == OVSDB_MONITOR_V2 ? "monitor_cond"
: "monitor";
+ struct jsonrpc_msg *request;
request = jsonrpc_create_request(method, monitor, NULL);
request_id = json_clone(request->id);
jsonrpc_send(rpc, request);
diff --git a/ovsdb/ovsdb-server.c b/ovsdb/ovsdb-server.c
index b9830f807..1e36b2795 100644
--- a/ovsdb/ovsdb-server.c
+++ b/ovsdb/ovsdb-server.c
@@ -1240,7 +1240,7 @@ ovsdb_server_disable_monitor_cond(struct unixctl_conn *conn,
struct ovsdb_jsonrpc_server *jsonrpc = jsonrpc_;
ovsdb_jsonrpc_disable_monitor_cond();
- ovsdb_jsonrpc_server_reconnect(jsonrpc);
+ ovsdb_jsonrpc_server_reconnect(jsonrpc, true);
unixctl_command_reply(conn, NULL);
}
@@ -1298,7 +1298,7 @@ ovsdb_server_reconnect(struct unixctl_conn *conn, int argc OVS_UNUSED,
const char *argv[] OVS_UNUSED, void *jsonrpc_)
{
struct ovsdb_jsonrpc_server *jsonrpc = jsonrpc_;
- ovsdb_jsonrpc_server_reconnect(jsonrpc);
+ ovsdb_jsonrpc_server_reconnect(jsonrpc, true);
unixctl_command_reply(conn, NULL);
}
@@ -1400,10 +1400,9 @@ ovsdb_server_add_database(struct unixctl_conn *conn, int argc OVS_UNUSED,
static void
remove_db(struct server_config *config, struct shash_node *node)
{
- struct db *db;
+ struct db *db = node->data;
- db = node->data;
- ovs_assert(ovsdb_jsonrpc_server_remove_db(config->jsonrpc, db->db));
+ ovsdb_jsonrpc_server_remove_db(config->jsonrpc, db->db);
close_db(db);
shash_delete(config->all_dbs, node);
diff --git a/tests/ovsdb-server.at b/tests/ovsdb-server.at
index 0b28b677f..2786cbbf3 100644
--- a/tests/ovsdb-server.at
+++ b/tests/ovsdb-server.at
@@ -169,14 +169,31 @@ AT_CLEANUP
AT_SETUP([ovsdb-server/add-db and remove-db])
AT_KEYWORDS([ovsdb server positive])
-on_exit 'kill `cat ovsdb-server.pid`'
+on_exit 'kill `cat *.pid`'
ordinal_schema > schema1
constraint_schema > schema2
AT_CHECK([ovsdb-tool create db1 schema1], [0], [ignore], [ignore])
AT_CHECK([ovsdb-tool create db2 schema2], [0], [ignore], [ignore])
# Start ovsdb-server with just a single database - db1.
-AT_CHECK([ovsdb-server --detach --no-chdir --pidfile --remote=punix:db.sock db1], [0])
+AT_CHECK([ovsdb-server -vfile -vvlog:off --log-file --detach --no-chdir --pidfile --remote=punix:db.sock db1], [0])
+CHECK_DBS([ordinals
+])
+
+# Remove the database.
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/remove-db ordinals], [0])
+CHECK_DBS([])
+
+# Start monitoring processes.
+AT_CHECK([ovsdb-client --detach --pidfile=ovsdb-client-1.pid --no-db-change-aware --no-headings monitor _Server Database name > db-change-unaware.stdout 2> db-change-unaware.stderr])
+AT_CHECK([ovsdb-client --detach --pidfile=ovsdb-client-2.pid --db-change-aware --no-headings monitor _Server Database name > db-change-aware.stdout 2> db-change-aware.stderr])
+AT_CAPTURE_FILE([db-change-unaware.stdout])
+AT_CAPTURE_FILE([db-change-unaware.stderr])
+AT_CAPTURE_FILE([db-change-aware.stdout])
+AT_CAPTURE_FILE([db-change-aware.stderr])
+
+# Add the first database back.
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/add-db db1], [0])
CHECK_DBS([ordinals
])
@@ -243,6 +260,25 @@ AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/add-db db2], [0])
CHECK_DBS([constraints
])
AT_CHECK([ovsdb-client list-tables unix:db.sock constraints], [0], [ignore], [ignore])
+
+# Check the monitoring results.
+AT_CHECK([uuidfilt db-change-aware.stdout], [0], [dnl
+<0> initial _Server
+
+<1> insert ordinals
+
+<2> insert constraints
+
+<1> delete ordinals
+
+<2> delete constraints
+
+<3> insert constraints
+])
+AT_CHECK([uuidfilt db-change-unaware.stdout], [0], [dnl
+<0> initial _Server
+])
+
OVS_APP_EXIT_AND_WAIT([ovsdb-server])
AT_CLEANUP