diff --git a/src/box/applier.cc b/src/box/applier.cc index 299c2b9faa258d8db0380e313c306f7b712b9240..cd16893804a1b3d18a8f7fcd1b7aefa866d09c6f 100644 --- a/src/box/applier.cc +++ b/src/box/applier.cc @@ -788,7 +788,9 @@ applier_wait_snapshot(struct applier *applier) * Used to initialize the replica's initial * vclock in bootstrap_from_master() */ - xrow_decode_vclock_xc(&row, instance_vclock); + struct vclock vclock; + xrow_decode_vclock_xc(&row, &vclock); + box_init_instance_vclock(&vclock); } coio_read_xrow(io, ibuf, &row); @@ -844,7 +846,9 @@ applier_wait_snapshot(struct applier *applier) * vclock yet, do it now. In 1.7+ * this vclock is not used. */ - xrow_decode_vclock_xc(&row, instance_vclock); + struct vclock vclock; + xrow_decode_vclock_xc(&row, &vclock); + box_init_instance_vclock(&vclock); } break; /* end of stream */ } else if (iproto_type_is_error(row.type)) { diff --git a/src/box/box.cc b/src/box/box.cc index 5cabd6b576a0ca2cb2f471a7dbd209800675eeed..2141c50bc5036a9c97128e64a6c226e48b1a0af5 100644 --- a/src/box/box.cc +++ b/src/box/box.cc @@ -125,7 +125,7 @@ struct rlist box_on_shutdown_trigger_list = struct event *box_on_shutdown_event = NULL; const struct vclock *box_vclock = instance_vclock; -struct vclock *instance_vclock = &instance_vclock_storage; +const struct vclock *instance_vclock = &instance_vclock_storage; const char *box_auth_type; @@ -5107,7 +5107,12 @@ bootstrap_from_master(struct replica *master) return false; } assert(applier->state == APPLIER_READY); - + /* + * In case of rejoin the vclock could be already set to send it in the + * ballot and for other global things. Make it unset again so the + * applier could "init" it again. + */ + vclock_clear(&instance_vclock_storage); say_info("bootstrapping replica from %s at %s", tt_uuid_str(&master->uuid), sio_strfaddr(&applier->addr, applier->addr_len)); @@ -6103,6 +6108,14 @@ box_init(void) sizeof(struct sync_trigger_data)); } +void +box_init_instance_vclock(const struct vclock *vclock) +{ + if (vclock_is_set(&instance_vclock_storage)) + panic("Instance vclock can be initialized only once"); + vclock_copy(&instance_vclock_storage, vclock); +} + /** Shutdown box storage i.e. stop parts that need TX loop running. */ static void box_storage_shutdown() diff --git a/src/box/box.h b/src/box/box.h index b73f78e7f5a21f52d2b6daecd4e99f55434f6b4e..f3a069a7da1c9dbb538e074a363c60eac62a83bc 100644 --- a/src/box/box.h +++ b/src/box/box.h @@ -70,7 +70,7 @@ extern const struct vclock *box_vclock; * recovery this vclock points to the end of WAL, not to the current recovery * position. */ -extern struct vclock *instance_vclock; +extern const struct vclock *instance_vclock; /** * Name of the authentication method that is currently used on @@ -118,6 +118,18 @@ extern bool box_is_force_recovery; void box_init(void); +/** + * Set instance's vclock to the given value. Works only if the instance vclock + * isn't already set. It must be initialized manually and explicitly this way + * when the instance boots from a snapshot - snapshot rows have no LSNs, so + * setting the instance vclock manually is the only way. + * + * It has to be a "public" API of box, because the snapshot can be remote, i.e. + * coming from the applier. + */ +void +box_init_instance_vclock(const struct vclock *vclock); + /** Shutdown box storage i.e. stop parts that need TX loop running. */ void box_shutdown(void);