[Tarantool-patches] [PATCH 11/13] wal: introduce JOURNAL_ENTRY_ERR_CASCADE

Vladislav Shpilevoy v.shpilevoy at tarantool.org
Sat Jun 12 00:56:07 MSK 2021


A transaction in WAL thread could be rolled back not only due to
an IO error. But also if there was a cascading rollback in
progress.

The patch makes such case use a special error code turned into its
own diag when it reaches the TX thread. Usage of ER_WAL_IO wasn't
correct here.

Part of #6027
---
 src/box/journal.c |  3 +++
 src/box/journal.h |  5 +++++
 src/box/txn.h     |  1 +
 src/box/wal.c     | 17 ++++++++++++++---
 4 files changed, 23 insertions(+), 3 deletions(-)

diff --git a/src/box/journal.c b/src/box/journal.c
index 32c3e4bd7..7de149080 100644
--- a/src/box/journal.c
+++ b/src/box/journal.c
@@ -49,6 +49,9 @@ diag_set_journal_res_detailed(const char *file, unsigned line, int64_t res)
 	case JOURNAL_ENTRY_ERR_IO:
 		diag_set_detailed(file, line, ClientError, ER_WAL_IO);
 		return;
+	case JOURNAL_ENTRY_ERR_CASCADE:
+		diag_set_detailed(file, line, ClientError, ER_CASCADE_ROLLBACK);
+		return;
 	}
 	panic("Journal result code %lld can't be converted to an error "
 	      "at %s:%u", (long long)res, file, line);
diff --git a/src/box/journal.h b/src/box/journal.h
index 18767176e..857245779 100644
--- a/src/box/journal.h
+++ b/src/box/journal.h
@@ -49,6 +49,11 @@ enum {
 	JOURNAL_ENTRY_ERR_UNKNOWN = -1,
 	/** Tried to be written, but something happened related to IO. */
 	JOURNAL_ENTRY_ERR_IO = -2,
+	/**
+	 * Rollback because there is a not finished rollback of a previous
+	 * entry.
+	 */
+	JOURNAL_ENTRY_ERR_CASCADE = -3,
 	/**
 	 * Anchor for the structs built on top of journal entry so as they
 	 * could introduce their own unique errors. Set to a big value in
diff --git a/src/box/txn.h b/src/box/txn.h
index 037865ac6..7638854a7 100644
--- a/src/box/txn.h
+++ b/src/box/txn.h
@@ -110,6 +110,7 @@ enum {
 	 */
 	TXN_SIGNATURE_UNKNOWN = JOURNAL_ENTRY_ERR_UNKNOWN,
 	TXN_SIGNATURE_IO = JOURNAL_ENTRY_ERR_IO,
+	TXN_SIGNATURE_CASCADE = JOURNAL_ENTRY_ERR_CASCADE,
 	/**
 	 * The default signature value for failed transactions.
 	 * Indicates either write failure or any other failure
diff --git a/src/box/wal.c b/src/box/wal.c
index f59cc9113..8543c4a08 100644
--- a/src/box/wal.c
+++ b/src/box/wal.c
@@ -1036,6 +1036,7 @@ wal_write_to_disk(struct cmsg *msg)
 {
 	struct wal_writer *writer = &wal_writer_singleton;
 	struct wal_msg *wal_msg = (struct wal_msg *) msg;
+	int err_code = JOURNAL_ENTRY_ERR_UNKNOWN;
 	struct stailq_entry *last_committed = NULL;
 	struct journal_entry *entry;
 	struct error *error;
@@ -1059,16 +1060,19 @@ wal_write_to_disk(struct cmsg *msg)
 
 	if (writer->is_in_rollback) {
 		/* We're rolling back a failed write. */
+		err_code = JOURNAL_ENTRY_ERR_CASCADE;
 		goto done;
 	}
 
 	/* Xlog is only rotated between queue processing  */
 	if (wal_opt_rotate(writer) != 0) {
+		err_code = JOURNAL_ENTRY_ERR_IO;
 		goto done;
 	}
 
 	/* Ensure there's enough disk space before writing anything. */
 	if (wal_fallocate(writer, wal_msg->approx_len) != 0) {
+		err_code = JOURNAL_ENTRY_ERR_IO;
 		goto done;
 	}
 
@@ -1104,8 +1108,10 @@ wal_write_to_disk(struct cmsg *msg)
 		entry->res = vclock_sum(&vclock_diff) +
 			     vclock_sum(&writer->vclock);
 		rc = xlog_write_entry(l, entry);
-		if (rc < 0)
+		if (rc < 0) {
+			err_code = JOURNAL_ENTRY_ERR_IO;
 			goto done;
+		}
 		if (rc > 0) {
 			writer->checkpoint_wal_size += rc;
 			last_committed = &entry->fifo;
@@ -1114,8 +1120,10 @@ wal_write_to_disk(struct cmsg *msg)
 		/* rc == 0: the write is buffered in xlog_tx */
 	}
 	rc = xlog_flush(l);
-	if (rc < 0)
+	if (rc < 0) {
+		err_code= JOURNAL_ENTRY_ERR_IO;
 		goto done;
+	}
 
 	writer->checkpoint_wal_size += rc;
 	last_committed = stailq_last(&wal_msg->commit);
@@ -1167,12 +1175,15 @@ done:
 	stailq_cut_tail(&wal_msg->commit, last_committed, &rollback);
 
 	if (!stailq_empty(&rollback)) {
+		assert(err_code != JOURNAL_ENTRY_ERR_UNKNOWN);
 		/* Update status of the successfully committed requests. */
 		stailq_foreach_entry(entry, &rollback, fifo)
-			entry->res = JOURNAL_ENTRY_ERR_IO;
+			entry->res = err_code;
 		/* Rollback unprocessed requests */
 		stailq_concat(&wal_msg->rollback, &rollback);
 		wal_begin_rollback();
+	} else {
+		assert(err_code == JOURNAL_ENTRY_ERR_UNKNOWN);
 	}
 	fiber_gc();
 	wal_notify_watchers(writer, WAL_EVENT_WRITE);
-- 
2.24.3 (Apple Git-128)



More information about the Tarantool-patches mailing list