Tarantool development patches archive
 help / color / mirror / Atom feed
From: Cyrill Gorcunov <gorcunov@gmail.com>
To: tml <tarantool-patches@dev.tarantool.org>
Subject: [Tarantool-patches] [PATCH 3/3] box/txn: clear fiber storage right before journal_write
Date: Thu, 27 Feb 2020 17:16:28 +0300	[thread overview]
Message-ID: <20200227141628.13782-4-gorcunov@gmail.com> (raw)
In-Reply-To: <20200227141628.13782-1-gorcunov@gmail.com>

Otherwise any previous attempts to rollback the transaction
will triggers assert since rollback action requires the
fiber to carry txn in the fiber->storage.txn. To make
sure the rollback works as expected we inject journal
allocation error to happen.

There are some nonobvious moments to be clarified. Both
asyncronous and synchronous commits are using async commit
engine. And journal_entry_complete is critical for both:
it handles success writes and rollback on failures.

On sync commits (txn_commit) we simply call fiber_yield
and wait until we're woken up by journal_entry_complete
to proceed. In turn txn_commit_async doesn't wait for
commit to happen but leaves journal entry to commit
later (for this reason the fiber->storage.txn is set
to null).

Fixes #4776

Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
---
 src/box/journal.c        |  6 ++++++
 src/box/txn.c            |  2 +-
 src/lib/core/errinj.h    |  3 ++-
 test/box/errinj.result   | 20 ++++++++++++++++++++
 test/box/errinj.test.lua |  7 +++++++
 5 files changed, 36 insertions(+), 2 deletions(-)

diff --git a/src/box/journal.c b/src/box/journal.c
index 11e78990d..9633e2af3 100644
--- a/src/box/journal.c
+++ b/src/box/journal.c
@@ -29,6 +29,7 @@
  * SUCH DAMAGE.
  */
 #include "journal.h"
+#include "errinj.h"
 #include <small/region.h>
 #include <diag.h>
 
@@ -62,6 +63,11 @@ journal_entry_new(size_t n_rows, struct region *region,
 	size_t size = (sizeof(struct journal_entry) +
 		       sizeof(entry->rows[0]) * n_rows);
 
+	ERROR_INJECT(ERRINJ_JOURNAL_NEW, {
+		diag_set(OutOfMemory, 0, "region", "journal_entry");
+		return NULL;
+	});
+
 	entry = region_aligned_alloc(region, size,
 				     alignof(struct journal_entry));
 	if (entry == NULL) {
diff --git a/src/box/txn.c b/src/box/txn.c
index 9e2888c09..8b10c0965 100644
--- a/src/box/txn.c
+++ b/src/box/txn.c
@@ -520,6 +520,7 @@ txn_write_to_wal(struct txn *txn)
 	assert(local_row == remote_row + txn->n_new_rows);
 
 	/* Send the entry to the journal. */
+	fiber_set_txn(fiber(), NULL);
 	if (journal_write(req) < 0) {
 		diag_set(ClientError, ER_WAL_IO);
 		diag_log();
@@ -583,7 +584,6 @@ txn_commit_async(struct txn *txn)
 		fiber_set_txn(fiber(), NULL);
 		return 0;
 	}
-	fiber_set_txn(fiber(), NULL);
 	return txn_write_to_wal(txn);
 }
 
diff --git a/src/lib/core/errinj.h b/src/lib/core/errinj.h
index ed0cba903..08ea47f2e 100644
--- a/src/lib/core/errinj.h
+++ b/src/lib/core/errinj.h
@@ -136,7 +136,8 @@ struct errinj {
 	_(ERRINJ_SWIM_FD_ONLY, ERRINJ_BOOL, {.bparam = false}) \
 	_(ERRINJ_DYN_MODULE_COUNT, ERRINJ_INT, {.iparam = 0}) \
 	_(ERRINJ_FIBER_MADVISE, ERRINJ_BOOL, {.bparam = false}) \
-	_(ERRINJ_FIBER_MPROTECT, ERRINJ_INT, {.iparam = -1})
+	_(ERRINJ_FIBER_MPROTECT, ERRINJ_INT, {.iparam = -1}) \
+	_(ERRINJ_JOURNAL_NEW, ERRINJ_BOOL, {.bparam = false})
 
 ENUM0(errinj_id, ERRINJ_LIST);
 extern struct errinj errinjs[];
diff --git a/test/box/errinj.result b/test/box/errinj.result
index daa27ed24..927f86402 100644
--- a/test/box/errinj.result
+++ b/test/box/errinj.result
@@ -54,6 +54,7 @@ evals
   - ERRINJ_HTTP_RESPONSE_ADD_WAIT: false
   - ERRINJ_INDEX_ALLOC: false
   - ERRINJ_IPROTO_TX_DELAY: false
+  - ERRINJ_JOURNAL_NEW: false
   - ERRINJ_LOG_ROTATE: false
   - ERRINJ_MEMTX_DELAY_GC: false
   - ERRINJ_PORT_DUMP: false
@@ -134,6 +135,25 @@ errinj.set("ERRINJ_TESTING", false)
 ---
 - ok
 ...
+-- Check journal entries allocation failure
+errinj.set("ERRINJ_JOURNAL_NEW", true)
+---
+- ok
+...
+space:insert{1}
+---
+- error: Failed to allocate 0 bytes in region for journal_entry
+...
+space:get{1}
+---
+...
+errinj.set("ERRINJ_JOURNAL_NEW", false)
+---
+- ok
+...
+space:truncate()
+---
+...
 -- Check how well we handle a failed log write
 errinj.set("ERRINJ_WAL_IO", true)
 ---
diff --git a/test/box/errinj.test.lua b/test/box/errinj.test.lua
index 01d2b68df..f007e97f6 100644
--- a/test/box/errinj.test.lua
+++ b/test/box/errinj.test.lua
@@ -30,6 +30,13 @@ errinj.set("ERRINJ_TESTING", true)
 space:select{222444}
 errinj.set("ERRINJ_TESTING", false)
 
+-- Check journal entries allocation failure
+errinj.set("ERRINJ_JOURNAL_NEW", true)
+space:insert{1}
+space:get{1}
+errinj.set("ERRINJ_JOURNAL_NEW", false)
+space:truncate()
+
 -- Check how well we handle a failed log write
 errinj.set("ERRINJ_WAL_IO", true)
 space:insert{1}
-- 
2.20.1

  parent reply	other threads:[~2020-02-27 14:17 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-02-27 14:16 [Tarantool-patches] [PATCH 0/3] box/txn: fix assert in txn_rollback Cyrill Gorcunov
2020-02-27 14:16 ` [Tarantool-patches] [PATCH 1/3] box/txn: rename txn_write to txn_commit_async Cyrill Gorcunov
2020-02-27 14:16 ` [Tarantool-patches] [PATCH 2/3] box/txn: log error explicitly in txn_commit Cyrill Gorcunov
2020-02-27 14:16 ` Cyrill Gorcunov [this message]
2020-02-27 19:47   ` [Tarantool-patches] [PATCH 3/3] box/txn: clear fiber storage right before journal_write Kirill Yukhin
2020-02-27 20:20     ` Cyrill Gorcunov
2020-02-27 20:27       ` Kirill Yukhin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200227141628.13782-4-gorcunov@gmail.com \
    --to=gorcunov@gmail.com \
    --cc=tarantool-patches@dev.tarantool.org \
    --subject='Re: [Tarantool-patches] [PATCH 3/3] box/txn: clear fiber storage right before journal_write' \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox