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