[ovs-dev] [PATCH v2 1/2] ovsdb-idl: New function ovsdb_idl_create_unconnected().

Ben Pfaff blp at ovn.org
Wed May 9 21:13:20 UTC 2018


This new function makes it possible to create an instance of the IDL
without connecting it to a remote OVSDB server.  The caller can then
connect and disconnect using ovsdb_idl_set_remote(); the ability to
disconnect is a new feature.

With this patch, the ovsdb_idl 'session' member can be null whereas
previously it was always nonnull.  The scattered changes throughout
ovsdb-idl are to cope with this new possibility.

An upcoming patch will introduce the first user of this new feature.

Signed-off-by: Ben Pfaff <blp at ovn.org>
---
 lib/ovsdb-idl.c | 118 +++++++++++++++++++++++++++++++++++++++++---------------
 lib/ovsdb-idl.h |   2 +
 2 files changed, 88 insertions(+), 32 deletions(-)

diff --git a/lib/ovsdb-idl.c b/lib/ovsdb-idl.c
index 9b99375da70a..ab864eb02d57 100644
--- a/lib/ovsdb-idl.c
+++ b/lib/ovsdb-idl.c
@@ -233,6 +233,7 @@ struct ovsdb_idl {
      * function currently returns then the session has reconnected and the
      * state machine must restart.  */
     struct jsonrpc_session *session; /* Connection to the server. */
+    char *remote;                    /* 'session' remote name. */
     enum ovsdb_idl_state state;      /* Current session state. */
     unsigned int state_seqno;        /* See above. */
     struct json *request_id;         /* JSON ID for request awaiting reply. */
@@ -369,18 +370,6 @@ static void
 static void ovsdb_idl_add_to_indexes(const struct ovsdb_idl_row *);
 static void ovsdb_idl_remove_from_indexes(const struct ovsdb_idl_row *);
 
-static void
-ovsdb_idl_open_session(struct ovsdb_idl *idl, const char *remote, bool retry)
-{
-    ovs_assert(!idl->data.txn);
-    jsonrpc_session_close(idl->session);
-
-    struct svec remotes = SVEC_EMPTY_INITIALIZER;
-    ovsdb_session_parse_remote(remote, &remotes, &idl->cid);
-    idl->session = jsonrpc_session_open_multiple(&remotes, retry);
-    svec_destroy(&remotes);
-}
-
 static void
 ovsdb_idl_db_init(struct ovsdb_idl_db *db, const struct ovsdb_idl_class *class,
                   struct ovsdb_idl *parent, bool monitor_everything_by_default)
@@ -447,13 +436,38 @@ ovsdb_idl_db_init(struct ovsdb_idl_db *db, const struct ovsdb_idl_class *class,
 struct ovsdb_idl *
 ovsdb_idl_create(const char *remote, const struct ovsdb_idl_class *class,
                  bool monitor_everything_by_default, bool retry)
+{
+    struct ovsdb_idl *idl = ovsdb_idl_create_unconnected(
+        class, monitor_everything_by_default);
+    ovsdb_idl_set_remote(idl, remote, retry);
+    return idl;
+}
+
+/* Creates and returns a connection to an in-memory replica of the remote
+ * database whose schema is described by 'class'.  (Ordinarily 'class' is
+ * compiled from an OVSDB schema automatically by ovsdb-idlc.)
+ *
+ * Use ovsdb_idl_set_remote() to configure the database to which to connect.
+ * Until a remote is configured, no data can be retrieved.
+ *
+ * If 'monitor_everything_by_default' is true, then everything in the remote
+ * database will be replicated by default.  ovsdb_idl_omit() and
+ * ovsdb_idl_omit_alert() may be used to selectively drop some columns from
+ * monitoring.
+ *
+ * If 'monitor_everything_by_default' is false, then no columns or tables will
+ * be replicated by default.  ovsdb_idl_add_column() and ovsdb_idl_add_table()
+ * must be used to choose some columns or tables to replicate.
+ */
+struct ovsdb_idl *
+ovsdb_idl_create_unconnected(const struct ovsdb_idl_class *class,
+                             bool monitor_everything_by_default)
 {
     struct ovsdb_idl *idl;
 
     idl = xzalloc(sizeof *idl);
     ovsdb_idl_db_init(&idl->server, &serverrec_idl_class, idl, true);
     ovsdb_idl_db_init(&idl->data, class, idl, monitor_everything_by_default);
-    ovsdb_idl_open_session(idl, remote, retry);
     idl->state_seqno = UINT_MAX;
     idl->request_id = NULL;
     idl->leader_only = true;
@@ -475,14 +489,38 @@ ovsdb_idl_create(const char *remote, const struct ovsdb_idl_class *class,
     return idl;
 }
 
-/* Changes the remote and creates a new session. */
+/* Changes the remote and creates a new session.
+ *
+ * If 'retry' is true, the connection to the remote will automatically retry
+ * when it fails.  If 'retry' is false, the connection is one-time. */
 void
-ovsdb_idl_set_remote(struct ovsdb_idl *idl, const char *remote,
-                     bool retry)
+ovsdb_idl_set_remote(struct ovsdb_idl *idl, const char *remote, bool retry)
 {
-    if (idl) {
-        ovsdb_idl_open_session(idl, remote, retry);
-        idl->state_seqno = UINT_MAX;
+    if (idl
+        && ((remote != NULL) != (idl->remote != NULL)
+            || (remote && idl->remote && strcmp(remote, idl->remote)))) {
+        ovs_assert(!idl->data.txn);
+
+        /* Close the old session, if any. */
+        if (idl->session) {
+            jsonrpc_session_close(idl->session);
+            idl->session = NULL;
+
+            free(idl->remote);
+            idl->remote = NULL;
+        }
+
+        /* Open new session, if any. */
+        if (remote) {
+            struct svec remotes = SVEC_EMPTY_INITIALIZER;
+            ovsdb_session_parse_remote(remote, &remotes, &idl->cid);
+            idl->session = jsonrpc_session_open_multiple(&remotes, retry);
+            svec_destroy(&remotes);
+
+            idl->state_seqno = UINT_MAX;
+
+            idl->remote = xstrdup(remote);
+        }
     }
 }
 
@@ -592,7 +630,7 @@ ovsdb_idl_state_to_string(enum ovsdb_idl_state state)
 static void
 ovsdb_idl_retry_at(struct ovsdb_idl *idl, const char *where)
 {
-    if (jsonrpc_session_get_n_remotes(idl->session) > 1) {
+    if (idl->session && jsonrpc_session_get_n_remotes(idl->session) > 1) {
         ovsdb_idl_force_reconnect(idl);
         ovsdb_idl_transition_at(idl, IDL_S_RETRY, where);
     } else {
@@ -605,7 +643,7 @@ ovsdb_idl_transition_at(struct ovsdb_idl *idl, enum ovsdb_idl_state new_state,
                         const char *where)
 {
     VLOG_DBG("%s: %s -> %s at %s",
-             jsonrpc_session_get_name(idl->session),
+             idl->session ? jsonrpc_session_get_name(idl->session) : "void",
              ovsdb_idl_state_to_string(idl->state),
              ovsdb_idl_state_to_string(new_state),
              where);
@@ -623,7 +661,9 @@ ovsdb_idl_send_request(struct ovsdb_idl *idl, struct jsonrpc_msg *request)
 {
     json_destroy(idl->request_id);
     idl->request_id = json_clone(request->id);
-    jsonrpc_session_send(idl->session, request);
+    if (idl->session) {
+        jsonrpc_session_send(idl->session, request);
+    }
 }
 
 static void
@@ -791,6 +831,11 @@ ovsdb_idl_process_msg(struct ovsdb_idl *idl, struct jsonrpc_msg *msg)
 void
 ovsdb_idl_run(struct ovsdb_idl *idl)
 {
+    if (!idl->session) {
+        ovsdb_idl_txn_abort_all(idl);
+        return;
+    }
+
     int i;
 
     ovs_assert(!idl->data.txn);
@@ -830,6 +875,9 @@ ovsdb_idl_run(struct ovsdb_idl *idl)
 void
 ovsdb_idl_wait(struct ovsdb_idl *idl)
 {
+    if (!idl->session) {
+        return;
+    }
     jsonrpc_session_wait(idl->session);
     jsonrpc_session_recv_wait(idl->session);
 }
@@ -896,7 +944,9 @@ ovsdb_idl_has_ever_connected(const struct ovsdb_idl *idl)
 void
 ovsdb_idl_enable_reconnect(struct ovsdb_idl *idl)
 {
-    jsonrpc_session_enable_reconnect(idl->session);
+    if (idl->session) {
+        jsonrpc_session_enable_reconnect(idl->session);
+    }
 }
 
 /* Forces 'idl' to drop its connection to the database and reconnect.  In the
@@ -904,7 +954,9 @@ ovsdb_idl_enable_reconnect(struct ovsdb_idl *idl)
 void
 ovsdb_idl_force_reconnect(struct ovsdb_idl *idl)
 {
-    jsonrpc_session_force_reconnect(idl->session);
+    if (idl->session) {
+        jsonrpc_session_force_reconnect(idl->session);
+    }
 }
 
 /* Some IDL users should only write to write-only columns.  Furthermore,
@@ -922,7 +974,7 @@ ovsdb_idl_verify_write_only(struct ovsdb_idl *idl)
 bool
 ovsdb_idl_is_alive(const struct ovsdb_idl *idl)
 {
-    return jsonrpc_session_is_alive(idl->session) &&
+    return idl->session && jsonrpc_session_is_alive(idl->session) &&
            idl->state != IDL_S_ERROR;
 }
 
@@ -934,10 +986,7 @@ ovsdb_idl_is_alive(const struct ovsdb_idl *idl)
 int
 ovsdb_idl_get_last_error(const struct ovsdb_idl *idl)
 {
-    int err;
-
-    err = jsonrpc_session_get_last_error(idl->session);
-
+    int err = idl->session ? jsonrpc_session_get_last_error(idl->session) : 0;
     if (err) {
         return err;
     } else if (idl->state == IDL_S_ERROR) {
@@ -953,7 +1002,9 @@ ovsdb_idl_get_last_error(const struct ovsdb_idl *idl)
 void
 ovsdb_idl_set_probe_interval(const struct ovsdb_idl *idl, int probe_interval)
 {
-    jsonrpc_session_set_probe_interval(idl->session, probe_interval);
+    if (idl->session) {
+        jsonrpc_session_set_probe_interval(idl->session, probe_interval);
+    }
 }
 
 static size_t
@@ -4095,7 +4146,8 @@ ovsdb_idl_txn_commit(struct ovsdb_idl_txn *txn)
     if (!any_updates) {
         txn->status = TXN_UNCHANGED;
         json_destroy(operations);
-    } else if (!jsonrpc_session_send(
+    } else if (txn->db->idl->session
+               && !jsonrpc_session_send(
                    txn->db->idl->session,
                    jsonrpc_create_request(
                        "transact", operations, &txn->request_id))) {
@@ -4785,7 +4837,9 @@ ovsdb_idl_set_lock(struct ovsdb_idl *idl, const char *lock_name)
         if (!msg) {
             break;
         }
-        jsonrpc_session_send(idl->session, msg);
+        if (idl->session) {
+            jsonrpc_session_send(idl->session, msg);
+        }
     }
 }
 
diff --git a/lib/ovsdb-idl.h b/lib/ovsdb-idl.h
index 2f5655227ac1..85e35d06844a 100644
--- a/lib/ovsdb-idl.h
+++ b/lib/ovsdb-idl.h
@@ -60,6 +60,8 @@ struct ovsdb_idl *ovsdb_idl_create(const char *remote,
                                    const struct ovsdb_idl_class *,
                                    bool monitor_everything_by_default,
                                    bool retry);
+struct ovsdb_idl *ovsdb_idl_create_unconnected(
+    const struct ovsdb_idl_class *, bool monitor_everything_by_default);
 void ovsdb_idl_set_remote(struct ovsdb_idl *, const char *, bool);
 void ovsdb_idl_destroy(struct ovsdb_idl *);
 
-- 
2.16.1



More information about the dev mailing list