diff --git a/src/box/applier.cc b/src/box/applier.cc index a44347fe0bdbb147573fa4af4ad331e515667af1..8e219c0ac37edd45bbcf432d7c4c581aa60d624d 100644 --- a/src/box/applier.cc +++ b/src/box/applier.cc @@ -2694,6 +2694,16 @@ applier_delete(struct applier *applier) free(applier); } +void +applier_reload_uri(struct applier *applier) +{ + struct iostream_ctx io_ctx; + if (iostream_ctx_create(&io_ctx, IOSTREAM_CLIENT, &applier->uri) != 0) + diag_raise(); + iostream_ctx_destroy(&applier->io_ctx); + iostream_ctx_move(&applier->io_ctx, &io_ctx); +} + void applier_resume(struct applier *applier) { diff --git a/src/box/applier.h b/src/box/applier.h index 15c41ffe71a7731500b372700d2698dae58a639e..a16a782b3f5385021d7aa70149b4e86c99017ed4 100644 --- a/src/box/applier.h +++ b/src/box/applier.h @@ -316,6 +316,14 @@ applier_new(const struct uri *uri); void applier_delete(struct applier *applier); +/** + * Recreates the IO stream context from the applier's URI. + * + * Throws an exception on failure. + */ +void +applier_reload_uri(struct applier *applier); + /* * Resume execution of applier until \a state. */ diff --git a/src/box/box.cc b/src/box/box.cc index bdf603b8fec9d185d05b395e5456c452f22834d6..48f025d895469b030e4e33e61f2d1dddf1c211b9 100644 --- a/src/box/box.cc +++ b/src/box/box.cc @@ -1780,8 +1780,11 @@ box_set_replication(void) if (unchanged) { /* * No need to reconnect or sync in case the configuration is - * the same. + * the same. However, we should still reload the URIs because + * a URI parameter may store a path to a file (for example, + * an SSL certificate), which could change. */ + replicaset_reload_uris(); return; } /* diff --git a/src/box/replication.cc b/src/box/replication.cc index 606a3b07545a77114afc34d63810f6dafde2dab4..eee635ceefefbabae701df46704b49a6ac1c8754 100644 --- a/src/box/replication.cc +++ b/src/box/replication.cc @@ -1091,6 +1091,16 @@ replicaset_connect(const struct uri_set *uris, uri_set_copy(&replication_uris, uris); } +void +replicaset_reload_uris(void) +{ + replicaset_foreach(replica) { + struct applier *applier = replica->applier; + if (applier != NULL) + applier_reload_uri(applier); + } +} + bool replicaset_needs_rejoin(struct replica **master) { diff --git a/src/box/replication.h b/src/box/replication.h index dd0777fa3fc368626bfa9ae2592afab3140466e2..9f1014de78ca3c6be05496e926e3f69a88e2893f 100644 --- a/src/box/replication.h +++ b/src/box/replication.h @@ -585,6 +585,19 @@ void replicaset_connect(const struct uri_set *uris, bool connect_quorum, bool keep_connect); +/** + * Reload replica URIs. + * + * Called on reconfiguration in case the remote peer URIs are the same. + * A URI parameter may store a path to a file (for example, an SSL + * certificate), which could change, so we need to recreate appliers' + * IO stream contexts in this case. + * + * Throws an exception on failure. + */ +void +replicaset_reload_uris(void); + /** * Check if the current instance fell too much behind its * peers in the replica set and needs to be rebootstrapped. diff --git a/src/lib/core/iostream.c b/src/lib/core/iostream.c index f53a86906a0c95e51b35c1d45b9e0d1dfaab1835..ca3f92e228b871d0cb601b145a082b67280a84ae 100644 --- a/src/lib/core/iostream.c +++ b/src/lib/core/iostream.c @@ -98,15 +98,14 @@ iostream_ctx_create(struct iostream_ctx *ctx, enum iostream_mode mode, { assert(mode == IOSTREAM_SERVER || mode == IOSTREAM_CLIENT); ctx->mode = mode; + ctx->ssl = NULL; const char *transport = uri_param(uri, "transport", 0); if (transport != NULL) { if (strcmp(transport, "ssl") == 0) { ctx->ssl = ssl_iostream_ctx_new(mode, uri); if (ctx->ssl == NULL) goto err; - } else if (strcmp(transport, "plain") == 0) { - ctx->ssl = NULL; - } else { + } else if (strcmp(transport, "plain") != 0) { diag_set(IllegalParams, "Invalid transport: %s", transport); goto err; diff --git a/src/lib/core/iostream.h b/src/lib/core/iostream.h index 822d0c8d4c592414d1f27048c73a143a8ba73b06..31951cc2d2afd36486632cf390a8ce5e08cdefe0 100644 --- a/src/lib/core/iostream.h +++ b/src/lib/core/iostream.h @@ -265,6 +265,17 @@ iostream_ctx_clear(struct iostream_ctx *ctx) ctx->ssl = NULL; } +/** + * Move constructor: copies src to dst and clears src. + */ +static inline void +iostream_ctx_move(struct iostream_ctx *dst, struct iostream_ctx *src) +{ + assert(src->mode == IOSTREAM_CLIENT || src->mode == IOSTREAM_SERVER); + *dst = *src; + iostream_ctx_clear(src); +} + /** * Creates an IO stream context for the given mode and URI. * On success returns 0. On failure returns -1, sets diag,