diff --git a/src/box/box.cc b/src/box/box.cc index 511df83e207766035c2f1d038202c19483c3e00e..1525da8eb1224f2d6dc5636b96185bc3bd2ef5ac 100644 --- a/src/box/box.cc +++ b/src/box/box.cc @@ -1135,15 +1135,24 @@ box_set_replication_anon(void) } -void +int box_clear_synchro_queue(bool try_wait) { + /* A guard to block multiple simultaneous function invocations. */ + static bool in_clear_synchro_queue = false; + if (in_clear_synchro_queue) { + diag_set(ClientError, ER_UNSUPPORTED, "clear_synchro_queue", + "simultaneous invocations"); + return -1; + } if (!is_box_configured || txn_limbo_is_empty(&txn_limbo)) - return; + return 0; uint32_t former_leader_id = txn_limbo.owner_id; assert(former_leader_id != REPLICA_ID_NIL); if (former_leader_id == instance_id) - return; + return 0; + + in_clear_synchro_queue = true; if (try_wait) { /* Wait until pending confirmations/rollbacks reach us. */ @@ -1184,6 +1193,9 @@ box_clear_synchro_queue(bool try_wait) txn_limbo_force_empty(&txn_limbo, confirm_lsn); assert(txn_limbo_is_empty(&txn_limbo)); } + + in_clear_synchro_queue = false; + return 0; } void diff --git a/src/box/box.h b/src/box/box.h index 12b1a459c493ca5e7944f6f756458cac22bf4066..b68047a9556dbb149614db80becf20ea321acccc 100644 --- a/src/box/box.h +++ b/src/box/box.h @@ -268,7 +268,7 @@ extern "C" { typedef struct tuple box_tuple_t; -void +int box_clear_synchro_queue(bool try_wait); /* box_select is private and used only by FFI */ diff --git a/src/box/lua/ctl.c b/src/box/lua/ctl.c index bb4841994116242d9fa639e24d6af3d5564c1b8f..b44474b124dc9cfa68b032037f2f7df46d07fa2a 100644 --- a/src/box/lua/ctl.c +++ b/src/box/lua/ctl.c @@ -83,8 +83,8 @@ lbox_ctl_on_schema_init(struct lua_State *L) static int lbox_ctl_clear_synchro_queue(struct lua_State *L) { - (void) L; - box_clear_synchro_queue(true); + if (box_clear_synchro_queue(true) != 0) + return luaT_error(L); return 0; } diff --git a/src/box/raft.c b/src/box/raft.c index 8f32a96628b8b64cbec6f551e1a958b734e94c55..1942df95241f3e8bc0a912a88645570a4e2459be 100644 --- a/src/box/raft.c +++ b/src/box/raft.c @@ -89,9 +89,14 @@ box_raft_update_synchro_queue(struct raft *raft) * If the node became a leader, it means it will ignore all records from * all the other nodes, and won't get late CONFIRM messages anyway. Can * clear the queue without waiting for confirmations. + * It's alright that the user may have called clear_synchro_queue + * manually. In this case the call below will exit immediately and we'll + * simply log a warning. */ - if (raft->state == RAFT_STATE_LEADER) - box_clear_synchro_queue(false); + if (raft->state == RAFT_STATE_LEADER) { + if (box_clear_synchro_queue(false) != 0) + diag_log(); + } } static int