acinclude.m4: Reorganize checks for kernel identifiers.
[sliver-openvswitch.git] / ovsdb / jsonrpc-server.c
index 6f2a656..84243d5 100644 (file)
@@ -20,6 +20,7 @@
 #include <assert.h>
 #include <errno.h>
 
+#include "bitmap.h"
 #include "column.h"
 #include "json.h"
 #include "jsonrpc.h"
@@ -100,6 +101,18 @@ ovsdb_jsonrpc_server_create(struct ovsdb *db)
     return server;
 }
 
+void
+ovsdb_jsonrpc_server_destroy(struct ovsdb_jsonrpc_server *svr)
+{
+    struct shash_node *node, *next;
+
+    SHASH_FOR_EACH_SAFE (node, next, &svr->remotes) {
+        ovsdb_jsonrpc_server_del_remote(node);
+    }
+    shash_destroy(&svr->remotes);
+    free(svr);
+}
+
 /* Sets 'svr''s current set of remotes to the names in 'new_remotes'.  The data
  * values in 'new_remotes' are ignored.
  *
@@ -131,7 +144,7 @@ ovsdb_jsonrpc_server_add_remote(struct ovsdb_jsonrpc_server *svr,
     struct pstream *listener;
     int error;
 
-    error = pstream_open(name, &listener);
+    error = jsonrpc_pstream_open(name, &listener);
     if (error && error != EAFNOSUPPORT) {
         VLOG_ERR_RL(&rl, "%s: listen failed: %s", name, strerror(error));
         return;
@@ -334,6 +347,48 @@ ovsdb_jsonrpc_session_close_all(struct ovsdb_jsonrpc_remote *remote)
     }
 }
 
+static const char *
+get_db_name(const struct ovsdb_jsonrpc_session *s)
+{
+    return s->remote->server->db->schema->name;
+}
+
+static struct jsonrpc_msg *
+ovsdb_jsonrpc_check_db_name(const struct ovsdb_jsonrpc_session *s,
+                            const struct jsonrpc_msg *request)
+{
+    struct json_array *params;
+    const char *want_db_name;
+    const char *have_db_name;
+    struct ovsdb_error *error;
+    struct jsonrpc_msg *reply;
+
+    params = json_array(request->params);
+    if (!params->n || params->elems[0]->type != JSON_STRING) {
+        error = ovsdb_syntax_error(
+            request->params, NULL,
+            "%s request params must begin with <db-name>", request->method);
+        goto error;
+    }
+
+    want_db_name = params->elems[0]->u.string;
+    have_db_name = get_db_name(s);
+    if (strcmp(want_db_name, have_db_name)) {
+        error = ovsdb_syntax_error(
+            request->params, "unknown database",
+            "%s request specifies unknown database %s",
+            request->method, want_db_name);
+        goto error;
+    }
+
+    return NULL;
+
+error:
+    reply = jsonrpc_create_reply(ovsdb_error_to_json(error), request->id);
+    ovsdb_error_destroy(error);
+    return reply;
+}
+
 static struct jsonrpc_msg *
 execute_transaction(struct ovsdb_jsonrpc_session *s,
                     struct jsonrpc_msg *request)
@@ -352,16 +407,30 @@ ovsdb_jsonrpc_session_got_request(struct ovsdb_jsonrpc_session *s,
     struct jsonrpc_msg *reply;
 
     if (!strcmp(request->method, "transact")) {
-        reply = execute_transaction(s, request);
+        reply = ovsdb_jsonrpc_check_db_name(s, request);
+        if (!reply) {
+            reply = execute_transaction(s, request);
+        }
     } else if (!strcmp(request->method, "monitor")) {
-        reply = jsonrpc_create_reply(
-            ovsdb_jsonrpc_monitor_create(s, request->params), request->id);
+        reply = ovsdb_jsonrpc_check_db_name(s, request);
+        if (!reply) {
+            reply = jsonrpc_create_reply(
+                ovsdb_jsonrpc_monitor_create(s, request->params), request->id);
+        }
     } else if (!strcmp(request->method, "monitor_cancel")) {
         reply = ovsdb_jsonrpc_monitor_cancel(s, json_array(request->params),
                                              request->id);
     } else if (!strcmp(request->method, "get_schema")) {
+        reply = ovsdb_jsonrpc_check_db_name(s, request);
+        if (!reply) {
+            reply = jsonrpc_create_reply(
+                ovsdb_schema_to_json(s->remote->server->db->schema),
+                request->id);
+        }
+    } else if (!strcmp(request->method, "list_dbs")) {
         reply = jsonrpc_create_reply(
-            ovsdb_schema_to_json(s->remote->server->db->schema), request->id);
+            json_array_create_1(json_string_create(get_db_name(s))),
+            request->id);
     } else if (!strcmp(request->method, "echo")) {
         reply = jsonrpc_create_reply(json_clone(request->params), request->id);
     } else {
@@ -577,12 +646,12 @@ ovsdb_jsonrpc_monitor_create(struct ovsdb_jsonrpc_session *s,
     struct shash_node *node;
     struct json *json;
 
-    if (json_array(params)->n != 2) {
+    if (json_array(params)->n != 3) {
         error = ovsdb_syntax_error(params, NULL, "invalid parameters");
         goto error;
     }
-    monitor_id = params->u.array.elems[0];
-    monitor_requests = params->u.array.elems[1];
+    monitor_id = params->u.array.elems[1];
+    monitor_requests = params->u.array.elems[2];
     if (monitor_requests->type != JSON_OBJECT) {
         error = ovsdb_syntax_error(monitor_requests, NULL,
                                    "monitor-requests must be object");
@@ -736,6 +805,7 @@ struct ovsdb_jsonrpc_monitor_aux {
 static bool
 ovsdb_jsonrpc_monitor_change_cb(const struct ovsdb_row *old,
                                 const struct ovsdb_row *new,
+                                const unsigned long int *changed,
                                 void *aux_)
 {
     struct ovsdb_jsonrpc_monitor_aux *aux = aux_;
@@ -773,14 +843,13 @@ ovsdb_jsonrpc_monitor_change_cb(const struct ovsdb_row *old,
     for (i = 0; i < aux->mt->columns.n_columns; i++) {
         const struct ovsdb_column *column = aux->mt->columns.columns[i];
         unsigned int idx = column->index;
-        bool changed = false;
+        bool column_changed = false;
 
         if (type == OJMS_MODIFY) {
-            changed = !ovsdb_datum_equals(&old->fields[idx],
-                                          &new->fields[idx], &column->type);
-            n_changed += changed;
+            column_changed = bitmap_is_set(changed, idx);
+            n_changed += column_changed;
         }
-        if (changed || type == OJMS_DELETE) {
+        if (column_changed || type == OJMS_DELETE) {
             if (!old_json) {
                 old_json = json_object_create();
             }
@@ -847,7 +916,8 @@ ovsdb_jsonrpc_monitor_init_aux(struct ovsdb_jsonrpc_monitor_aux *aux,
 
 static struct ovsdb_error *
 ovsdb_jsonrpc_monitor_commit(struct ovsdb_replica *replica,
-                             const struct ovsdb_txn *txn, bool durable UNUSED)
+                             const struct ovsdb_txn *txn,
+                             bool durable OVS_UNUSED)
 {
     struct ovsdb_jsonrpc_monitor *m = ovsdb_jsonrpc_monitor_cast(replica);
     struct ovsdb_jsonrpc_monitor_aux aux;
@@ -882,7 +952,7 @@ ovsdb_jsonrpc_monitor_get_initial(const struct ovsdb_jsonrpc_monitor *m)
 
             HMAP_FOR_EACH (row, struct ovsdb_row, hmap_node,
                            &mt->table->rows) {
-                ovsdb_jsonrpc_monitor_change_cb(NULL, row, &aux);
+                ovsdb_jsonrpc_monitor_change_cb(NULL, row, NULL, &aux);
             }
         }
     }