From: Georgy Kirichenko <georgy@tarantool.org> To: tarantool-patches@freelists.org Cc: Georgy Kirichenko <georgy@tarantool.org> Subject: [tarantool-patches] [PATCH 01/10] Introduce a txn memory region Date: Fri, 19 Apr 2019 15:43:57 +0300 [thread overview] Message-ID: <578b5150bc489f2839387f8b95c8068e6649d455.1555677159.git.georgy@tarantool.org> (raw) In-Reply-To: <cover.1555677159.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 | 2 +- src/box/sql/vdbe.c | 2 +- src/box/txn.c | 71 +++++++++++++++++++++++++++++------- src/box/txn.h | 2 + test/box/misc.result | 2 +- test/engine/savepoint.result | 2 +- test/sql/savepoints.result | 6 +-- 7 files changed, 66 insertions(+), 21 deletions(-) diff --git a/src/box/errcode.h b/src/box/errcode.h index 3f8cb8e0e..a273826b3 100644 --- a/src/box/errcode.h +++ b/src/box/errcode.h @@ -166,7 +166,7 @@ struct errcode_record { /*111 */_(ER_WRONG_SPACE_OPTIONS, "Wrong space options (field %u): %s") \ /*112 */_(ER_UNSUPPORTED_INDEX_FEATURE, "Index '%s' (%s) of space '%s' (%s) does not support %s") \ /*113 */_(ER_VIEW_IS_RO, "View '%s' is read-only") \ - /*114 */_(ER_SAVEPOINT_NO_TRANSACTION, "Can not set a savepoint in absence of active transaction") \ + /*114 */_(ER_NO_TRANSACTION, "No active transaction") \ /*115 */_(ER_SYSTEM, "%s") \ /*116 */_(ER_LOADING, "Instance bootstrap hasn't finished yet") \ /*117 */_(ER_CONNECTION_TO_SELF, "Connection to self") \ diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c index ed7bf8870..9fc70980c 100644 --- a/src/box/sql/vdbe.c +++ b/src/box/sql/vdbe.c @@ -3017,7 +3017,7 @@ case OP_Savepoint: { if (psql_txn == NULL) { assert(!box_txn()); - diag_set(ClientError, ER_SAVEPOINT_NO_TRANSACTION); + diag_set(ClientError, ER_NO_TRANSACTION); rc = SQL_TARANTOOL_ERROR; goto abort_due_to_error; } diff --git a/src/box/txn.c b/src/box/txn.c index d51bfc67a..815199645 100644 --- a/src/box/txn.c +++ b/src/box/txn.c @@ -37,6 +37,9 @@ double too_long_threshold; +/* Txn cache. */ +static struct stailq txn_cache = {NULL, &txn_cache.first}; + 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,50 @@ 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. + */ +inline static struct txn * +txn_new() +{ + if (!stailq_empty(&txn_cache)) + return stailq_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; + } + assert(region_used(®ion) == sizeof(*txn)); + txn->region = region; + return txn; +} + +/* + * Free txn memory and return it to a cache. + */ +inline static void +txn_free(struct txn *txn) +{ + /* Truncate region up to struct txn size. */ + region_truncate(&txn->region, sizeof(struct txn)); + stailq_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 +288,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 +430,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 +470,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 +558,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)); } @@ -535,11 +578,11 @@ box_txn_savepoint() { struct txn *txn = in_txn(); if (txn == NULL) { - diag_set(ClientError, ER_SAVEPOINT_NO_TRANSACTION); + diag_set(ClientError, ER_NO_TRANSACTION); 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), @@ -558,7 +601,7 @@ box_txn_rollback_to_savepoint(box_txn_savepoint_t *svp) { struct txn *txn = in_txn(); if (txn == NULL) { - diag_set(ClientError, ER_SAVEPOINT_NO_TRANSACTION); + diag_set(ClientError, ER_NO_TRANSACTION); return -1; } struct txn_stmt *stmt = svp->stmt == NULL ? NULL : diff --git a/src/box/txn.h b/src/box/txn.h index 747b38db3..fe8a299f2 100644 --- a/src/box/txn.h +++ b/src/box/txn.h @@ -132,6 +132,8 @@ struct autoinc_id_entry { }; struct txn { + struct stailq_entry 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 a1f7a0990..d7d76d87e 100644 --- a/test/box/misc.result +++ b/test/box/misc.result @@ -443,7 +443,7 @@ t; 111: box.error.WRONG_SPACE_OPTIONS 112: box.error.UNSUPPORTED_INDEX_FEATURE 113: box.error.VIEW_IS_RO - 114: box.error.SAVEPOINT_NO_TRANSACTION + 114: box.error.NO_TRANSACTION 115: box.error.SYSTEM 116: box.error.LOADING 117: box.error.CONNECTION_TO_SELF diff --git a/test/engine/savepoint.result b/test/engine/savepoint.result index b3a918de0..86a2d0be2 100644 --- a/test/engine/savepoint.result +++ b/test/engine/savepoint.result @@ -14,7 +14,7 @@ s1 = nil ... s1 = box.savepoint() --- -- error: Can not set a savepoint in absence of active transaction +- error: No active transaction ... box.rollback_to_savepoint(s1) --- diff --git a/test/sql/savepoints.result b/test/sql/savepoints.result index 2f943bd9b..bb4a296fa 100644 --- a/test/sql/savepoints.result +++ b/test/sql/savepoints.result @@ -14,15 +14,15 @@ box.execute('pragma sql_default_engine=\''..engine..'\'') -- box.execute('SAVEPOINT t1;'); --- -- error: Can not set a savepoint in absence of active transaction +- error: No active transaction ... box.execute('RELEASE SAVEPOINT t1;'); --- -- error: Can not set a savepoint in absence of active transaction +- error: No active transaction ... box.execute('ROLLBACK TO SAVEPOINT t1;'); --- -- error: Can not set a savepoint in absence of active transaction +- error: No active transaction ... box.begin() box.execute('SAVEPOINT t1;') box.execute('RELEASE SAVEPOINT t1;') box.commit(); --- -- 2.21.0
next prev parent reply other threads:[~2019-04-19 12:44 UTC|newest] Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top 2019-04-19 12:43 [tarantool-patches] [PATCH 00/10] Transaction refactoring Georgy Kirichenko 2019-04-19 12:43 ` Georgy Kirichenko [this message] 2019-04-24 18:20 ` [tarantool-patches] Re: [PATCH 01/10] Introduce a txn memory region Konstantin Osipov 2019-04-19 12:43 ` [tarantool-patches] [PATCH 02/10] Alloc journal entry on " Georgy Kirichenko 2019-04-24 18:21 ` [tarantool-patches] " Konstantin Osipov 2019-04-19 12:43 ` [tarantool-patches] [PATCH 03/10] Encode a dml statement to a transaction " Georgy Kirichenko 2019-04-24 18:28 ` [tarantool-patches] " Konstantin Osipov 2019-04-19 12:44 ` [tarantool-patches] [PATCH 04/10] Get rid of autocommit from a txn structure Georgy Kirichenko 2019-04-24 19:07 ` [tarantool-patches] " Konstantin Osipov 2019-04-19 12:44 ` [tarantool-patches] [PATCH 05/10] Get rid of fiber_gc from txn_rollback Georgy Kirichenko 2019-04-24 19:12 ` [tarantool-patches] " Konstantin Osipov 2019-04-19 12:44 ` [tarantool-patches] [PATCH 06/10] Require for txn in case of txn_begin_stmt/txn_rollback_stmt Georgy Kirichenko 2019-04-24 19:13 ` [tarantool-patches] " Konstantin Osipov 2019-04-19 12:44 ` [tarantool-patches] [PATCH 07/10] Remove fiber from a journal_entry structure Georgy Kirichenko 2019-04-24 19:16 ` [tarantool-patches] " Konstantin Osipov 2019-04-19 12:44 ` [tarantool-patches] [PATCH 08/10] Use mempool to alloc wal messages Georgy Kirichenko 2019-04-24 19:18 ` [tarantool-patches] " Konstantin Osipov 2019-04-19 12:44 ` [tarantool-patches] [PATCH 09/10] Enable asyncronous wal writes Georgy Kirichenko 2019-04-24 19:19 ` [tarantool-patches] " Konstantin Osipov 2019-04-19 12:44 ` [tarantool-patches] [PATCH 10/10] Introduce asynchronous txn commit Georgy Kirichenko 2019-04-24 19:20 ` [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=578b5150bc489f2839387f8b95c8068e6649d455.1555677159.git.georgy@tarantool.org \ --to=georgy@tarantool.org \ --cc=tarantool-patches@freelists.org \ --subject='Re: [tarantool-patches] [PATCH 01/10] 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