From 243c207a5fd02a5d0eb8e232741b8f98adb8ceb0 Mon Sep 17 00:00:00 2001 From: mechanik20051988 <mechanik20051988@tarantool.org> Date: Mon, 20 Sep 2021 16:06:39 +0300 Subject: [PATCH] txn: rework txn_on_yield trigger We are going to implement timeout for transaction, after which it will be rolled back. The timeout starts counting from the moment of the first yield. Previously `txn_on_yield` trigger installed only in case when engine does not support yields for transactions. Now it is installed when transaction is created, but if transaction supports yields it doesn't do anything. In the following patches, we will use this trigger to start the transaction timeout countdown. Part of #6177 --- src/box/txn.c | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/src/box/txn.c b/src/box/txn.c index e7fc81683b..3785545d93 100644 --- a/src/box/txn.c +++ b/src/box/txn.c @@ -307,7 +307,8 @@ txn_begin(void) memtx_tx_register_tx(txn); txn->fiber = NULL; fiber_set_txn(fiber(), txn); - /* fiber_on_yield is initialized by engine on demand */ + trigger_create(&txn->fiber_on_yield, txn_on_yield, NULL, NULL); + trigger_add(&fiber()->on_yield, &txn->fiber_on_yield); trigger_create(&txn->fiber_on_stop, txn_on_stop, NULL, NULL); trigger_add(&fiber()->on_stop, &txn->fiber_on_stop); /* @@ -757,8 +758,7 @@ txn_prepare(struct txn *txn) assert(rlist_empty(&txn->conflicted_by_list)); trigger_clear(&txn->fiber_on_stop); - if (!txn_has_flag(txn, TXN_CAN_YIELD)) - trigger_clear(&txn->fiber_on_yield); + trigger_clear(&txn->fiber_on_yield); txn->start_tm = ev_monotonic_now(loop()); txn->status = TXN_PREPARED; @@ -986,8 +986,7 @@ txn_rollback(struct txn *txn) assert(txn->signature != TXN_SIGNATURE_UNKNOWN); txn->status = TXN_ABORTED; trigger_clear(&txn->fiber_on_stop); - if (!txn_has_flag(txn, TXN_CAN_YIELD)) - trigger_clear(&txn->fiber_on_yield); + trigger_clear(&txn->fiber_on_yield); txn_complete_fail(txn); fiber_set_txn(fiber(), NULL); } @@ -1016,13 +1015,10 @@ txn_can_yield(struct txn *txn, bool set) { assert(txn == in_txn()); bool could = txn_has_flag(txn, TXN_CAN_YIELD); - if (set && !could) { + if (set) { txn_set_flags(txn, TXN_CAN_YIELD); - trigger_clear(&txn->fiber_on_yield); - } else if (!set && could) { + } else { txn_clear_flags(txn, TXN_CAN_YIELD); - trigger_create(&txn->fiber_on_yield, txn_on_yield, NULL, NULL); - trigger_add(&fiber()->on_yield, &txn->fiber_on_yield); } return could; } @@ -1255,9 +1251,10 @@ txn_on_yield(struct trigger *trigger, void *event) (void) event; struct txn *txn = in_txn(); assert(txn != NULL); - assert(!txn_has_flag(txn, TXN_CAN_YIELD)); - txn_rollback_to_svp(txn, NULL); - txn_set_flags(txn, TXN_IS_ABORTED_BY_YIELD); + if (!txn_has_flag(txn, TXN_CAN_YIELD)) { + txn_rollback_to_svp(txn, NULL); + txn_set_flags(txn, TXN_IS_ABORTED_BY_YIELD); + } return 0; } @@ -1267,10 +1264,8 @@ txn_detach(void) struct txn *txn = in_txn(); if (txn == NULL) return NULL; - if (!txn_has_flag(txn, TXN_CAN_YIELD)) { - txn_on_yield(NULL, NULL); - trigger_clear(&txn->fiber_on_yield); - } + txn_on_yield(NULL, NULL); + trigger_clear(&txn->fiber_on_yield); trigger_clear(&txn->fiber_on_stop); fiber_set_txn(fiber(), NULL); return txn; @@ -1282,4 +1277,6 @@ txn_attach(struct txn *txn) assert(txn != NULL); assert(!in_txn()); fiber_set_txn(fiber(), txn); + trigger_add(&fiber()->on_yield, &txn->fiber_on_yield); + trigger_add(&fiber()->on_stop, &txn->fiber_on_stop); } -- GitLab