From: Georgy Kirichenko <georgy@tarantool.org>
To: tarantool-patches@freelists.org
Cc: Georgy Kirichenko <georgy@tarantool.org>
Subject: [tarantool-patches] [PATCH 1/2] Introduce a txn memory region
Date: Wed, 10 Apr 2019 10:22:25 +0300 [thread overview]
Message-ID: <75597e590276ca833b38aec0bee1f008f081271d.1554880565.git.georgy@tarantool.org> (raw)
In-Reply-To: <cover.1554880565.git.georgy@tarantool.org>
Attach a separate memory region for each txn structure in order to store
all txn internal data until the transaction finished. This patch is a
preparation to detach a txn from a fiber and a fiber gc storage.
Prerequisites: #1254
---
src/box/errcode.h | 1 +
src/box/txn.c | 66 ++++++++++++++++++++++++++++++++++++--------
src/box/txn.h | 2 ++
test/box/misc.result | 1 +
4 files changed, 58 insertions(+), 12 deletions(-)
diff --git a/src/box/errcode.h b/src/box/errcode.h
index 3f8cb8e0e..bd1a684ab 100644
--- a/src/box/errcode.h
+++ b/src/box/errcode.h
@@ -246,6 +246,7 @@ struct errcode_record {
/*191 */_(ER_SQL_PARSER_LIMIT, "%s %d exceeds the limit (%d)") \
/*192 */_(ER_INDEX_DEF_UNSUPPORTED, "%s are prohibited in an index definition") \
/*193 */_(ER_CK_DEF_UNSUPPORTED, "%s are prohibited in a CHECK constraint definition") \
+ /*194 */_(ER_NO_TRANSACTION, "No active transaction") \
/*
* !IMPORTANT! Please follow instructions at start of the file
diff --git a/src/box/txn.c b/src/box/txn.c
index d51bfc67a..be5e209b6 100644
--- a/src/box/txn.c
+++ b/src/box/txn.c
@@ -37,6 +37,9 @@
double too_long_threshold;
+/* Txn cache. */
+static struct rlist txn_cache = RLIST_HEAD_INITIALIZER(txn_cache);
+
static inline void
fiber_set_txn(struct fiber *fiber, struct txn *txn)
{
@@ -44,7 +47,7 @@ fiber_set_txn(struct fiber *fiber, struct txn *txn)
}
static int
-txn_add_redo(struct txn_stmt *stmt, struct request *request)
+txn_add_redo(struct txn *txn, struct txn_stmt *stmt, struct request *request)
{
stmt->row = request->header;
if (request->header != NULL)
@@ -52,7 +55,7 @@ txn_add_redo(struct txn_stmt *stmt, struct request *request)
/* Create a redo log row for Lua requests */
struct xrow_header *row;
- row = region_alloc_object(&fiber()->gc, struct xrow_header);
+ row = region_alloc_object(&txn->region, struct xrow_header);
if (row == NULL) {
diag_set(OutOfMemory, sizeof(*row),
"region", "struct xrow_header");
@@ -77,7 +80,7 @@ static struct txn_stmt *
txn_stmt_new(struct txn *txn)
{
struct txn_stmt *stmt;
- stmt = region_alloc_object(&fiber()->gc, struct txn_stmt);
+ stmt = region_alloc_object(&txn->region, struct txn_stmt);
if (stmt == NULL) {
diag_set(OutOfMemory, sizeof(*stmt),
"region", "struct txn_stmt");
@@ -134,16 +137,49 @@ txn_rollback_to_svp(struct txn *txn, struct stailq_entry *svp)
}
}
+/*
+ * Return a txn from cache or create a new one if cache is empty.
+ */
+static struct txn *
+txn_new()
+{
+ if (!rlist_empty(&txn_cache))
+ return rlist_shift_entry(&txn_cache, struct txn, list);
+
+ /* Create a region. */
+ struct region region;
+ region_create(®ion, &cord()->slabc);
+
+ /* Place txn structure on the region. */
+ struct txn *txn = region_alloc_object(®ion, struct txn);
+ if (txn == NULL) {
+ diag_set(OutOfMemory, sizeof(*txn), "region", "struct txn");
+ return NULL;
+ }
+ txn->region = region;
+ return txn;
+}
+
+/*
+ * Free txn memory and return it to a cache.
+ */
+static void
+txn_free(struct txn *txn)
+{
+ /* Truncate region up to struct txn size. */
+ region_truncate(&txn->region, sizeof(struct txn));
+ rlist_add(&txn_cache, &txn->list);
+}
+
struct txn *
txn_begin(bool is_autocommit)
{
static int64_t tsn = 0;
assert(! in_txn());
- struct txn *txn = region_alloc_object(&fiber()->gc, struct txn);
- if (txn == NULL) {
- diag_set(OutOfMemory, sizeof(*txn), "region", "struct txn");
+ struct txn *txn = txn_new();
+ if (txn == NULL)
return NULL;
- }
+
/* Initialize members explicitly to save time on memset() */
stailq_create(&txn->stmts);
txn->n_new_rows = 0;
@@ -251,7 +287,7 @@ txn_commit_stmt(struct txn *txn, struct request *request)
* stmt->space can be NULL for IRPOTO_NOP.
*/
if (stmt->space == NULL || !space_is_temporary(stmt->space)) {
- if (txn_add_redo(stmt, request) != 0)
+ if (txn_add_redo(txn, stmt, request) != 0)
goto fail;
assert(stmt->row != NULL);
if (stmt->row->replica_id == 0) {
@@ -393,8 +429,8 @@ txn_commit(struct txn *txn)
stailq_foreach_entry(stmt, &txn->stmts, next)
txn_stmt_unref_tuples(stmt);
- TRASH(txn);
fiber_set_txn(fiber(), NULL);
+ txn_free(txn);
return 0;
fail:
txn_rollback();
@@ -433,10 +469,10 @@ txn_rollback()
stailq_foreach_entry(stmt, &txn->stmts, next)
txn_stmt_unref_tuples(stmt);
- TRASH(txn);
/** Free volatile txn memory. */
fiber_gc();
fiber_set_txn(fiber(), NULL);
+ txn_free(txn);
}
void
@@ -521,12 +557,18 @@ box_txn_rollback()
void *
box_txn_alloc(size_t size)
{
+ struct txn *txn = in_txn();
+ if (txn == NULL) {
+ /* There are no transaction yet - return an error. */
+ diag_set(ClientError, ER_NO_TRANSACTION);
+ return NULL;
+ }
union natural_align {
void *p;
double lf;
long l;
};
- return region_aligned_alloc(&fiber()->gc, size,
+ return region_aligned_alloc(&txn->region, size,
alignof(union natural_align));
}
@@ -539,7 +581,7 @@ box_txn_savepoint()
return NULL;
}
struct txn_savepoint *svp =
- (struct txn_savepoint *) region_alloc_object(&fiber()->gc,
+ (struct txn_savepoint *) region_alloc_object(&txn->region,
struct txn_savepoint);
if (svp == NULL) {
diag_set(OutOfMemory, sizeof(*svp),
diff --git a/src/box/txn.h b/src/box/txn.h
index 747b38db3..84c82af92 100644
--- a/src/box/txn.h
+++ b/src/box/txn.h
@@ -132,6 +132,8 @@ struct autoinc_id_entry {
};
struct txn {
+ struct rlist list;
+ struct region region;
/**
* A sequentially growing transaction id, assigned when
* a transaction is initiated. Used to identify
diff --git a/test/box/misc.result b/test/box/misc.result
index e2b618c9c..be3cbde37 100644
--- a/test/box/misc.result
+++ b/test/box/misc.result
@@ -522,6 +522,7 @@ t;
191: box.error.SQL_PARSER_LIMIT
192: box.error.INDEX_DEF_UNSUPPORTED
193: box.error.CK_DEF_UNSUPPORTED
+ 194: box.error.NO_TRANSACTION
...
test_run:cmd("setopt delimiter ''");
---
--
2.21.0
next prev parent reply other threads:[~2019-04-10 7:22 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-04-10 7:22 [tarantool-patches] [PATCH 0/2] Transaction refactoring Georgy Kirichenko
2019-04-10 7:22 ` Georgy Kirichenko [this message]
2019-04-10 10:11 ` [tarantool-patches] Re: [PATCH 1/2] Introduce a txn memory region Konstantin Osipov
2019-04-10 7:22 ` [tarantool-patches] [PATCH 2/2] Get rid of aurocommit from a txn structure Georgy Kirichenko
2019-04-11 6:43 ` [tarantool-patches] " Konstantin Osipov
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=75597e590276ca833b38aec0bee1f008f081271d.1554880565.git.georgy@tarantool.org \
--to=georgy@tarantool.org \
--cc=tarantool-patches@freelists.org \
--subject='Re: [tarantool-patches] [PATCH 1/2] Introduce a txn memory region' \
/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