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 <[email protected]> --- 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 _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
