Message ID | 20180618183650.17439-1-blp@ovn.org |
---|---|
State | Accepted |
Headers | show |
Series | [ovs-dev,v2,1/2] ovsdb-idl: New function ovsdb_idl_create_unconnected(). | expand |
Better late than never Acked-by: Mark Michelson <mmichels@redhat.com> On 06/18/2018 02:36 PM, Ben Pfaff wrote: > 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@ovn.org> > --- > v1->v2: No change. > > 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 e0991f940f79..86e28d810603 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. */ > @@ -365,18 +366,6 @@ static void ovsdb_idl_destroy_indexes(struct ovsdb_idl_table *); > 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) > @@ -443,13 +432,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; > @@ -471,14 +485,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); > + } > } > } > > @@ -588,7 +626,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 { > @@ -601,7 +639,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); > @@ -619,7 +657,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 > @@ -787,6 +827,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); > @@ -826,6 +871,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); > } > @@ -892,7 +940,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 > @@ -900,7 +950,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, > @@ -918,7 +970,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; > } > > @@ -930,10 +982,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) { > @@ -949,7 +998,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 > @@ -4006,7 +4057,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))) { > @@ -4696,7 +4748,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 ea18b22f5480..382981cb44c6 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 *); > >
Thanks. I applied this series to master. On Thu, Jul 26, 2018 at 04:56:32PM -0400, Mark Michelson wrote: > Better late than never > > Acked-by: Mark Michelson <mmichels@redhat.com> > > On 06/18/2018 02:36 PM, Ben Pfaff wrote: > >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@ovn.org> > >--- > >v1->v2: No change. > > > > 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 e0991f940f79..86e28d810603 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. */ > >@@ -365,18 +366,6 @@ static void ovsdb_idl_destroy_indexes(struct ovsdb_idl_table *); > > 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) > >@@ -443,13 +432,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; > >@@ -471,14 +485,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); > >+ } > > } > > } > >@@ -588,7 +626,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 { > >@@ -601,7 +639,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); > >@@ -619,7 +657,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 > >@@ -787,6 +827,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); > >@@ -826,6 +871,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); > > } > >@@ -892,7 +940,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 > >@@ -900,7 +950,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, > >@@ -918,7 +970,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; > > } > >@@ -930,10 +982,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) { > >@@ -949,7 +998,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 > >@@ -4006,7 +4057,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))) { > >@@ -4696,7 +4748,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 ea18b22f5480..382981cb44c6 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 *); > > >
diff --git a/lib/ovsdb-idl.c b/lib/ovsdb-idl.c index e0991f940f79..86e28d810603 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. */ @@ -365,18 +366,6 @@ static void ovsdb_idl_destroy_indexes(struct ovsdb_idl_table *); 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) @@ -443,13 +432,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; @@ -471,14 +485,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); + } } } @@ -588,7 +626,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 { @@ -601,7 +639,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); @@ -619,7 +657,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 @@ -787,6 +827,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); @@ -826,6 +871,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); } @@ -892,7 +940,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 @@ -900,7 +950,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, @@ -918,7 +970,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; } @@ -930,10 +982,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) { @@ -949,7 +998,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 @@ -4006,7 +4057,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))) { @@ -4696,7 +4748,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 ea18b22f5480..382981cb44c6 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 *);
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@ovn.org> --- v1->v2: No change. lib/ovsdb-idl.c | 118 +++++++++++++++++++++++++++++++++++++++++--------------- lib/ovsdb-idl.h | 2 + 2 files changed, 88 insertions(+), 32 deletions(-)