From: Vladimir Davydov <vdavydov.dev@gmail.com> To: kostja@tarantool.org Cc: tarantool-patches@freelists.org Subject: [PATCH 4/6] txn: do not require space id for nop requests Date: Wed, 13 Jun 2018 19:10:36 +0300 [thread overview] Message-ID: <4dfddcb3838385c88cbfdf51d52ef112f56cf130.1528906027.git.vdavydov.dev@gmail.com> (raw) In-Reply-To: <cover.1528906027.git.vdavydov.dev@gmail.com> In-Reply-To: <cover.1528906027.git.vdavydov.dev@gmail.com> Currently, IPROTO_NOP can only be generated by a before_replace trigger, when it returns the old tuple thus turning the original operation into a NOP. In such a case we know the space id and we write it to the request body. This allows us to dispatch NOP requests via DML route. As a part of replica local spaces feature, we will substitute requests operating on local spaces with NOP in relay in order to promote vclock on replicas without actual data modification. Since space_id is stored in request body, sending it to replicas would mean decoding the request body in relay, which is an overkill. To avoid that, let's separate NOP and DML paths and remove space_id from NOP requests. Needed for #3443 --- src/box/box.cc | 5 ++ src/box/iproto_constants.c | 2 +- src/box/request.c | 2 +- src/box/txn.c | 99 ++++++++++++++++++++++++++-------------- src/box/txn.h | 12 +++++ test/box/before_replace.result | 4 +- test/box/before_replace.test.lua | 2 +- 7 files changed, 86 insertions(+), 40 deletions(-) diff --git a/src/box/box.cc b/src/box/box.cc index c1d15644..8248cc77 100644 --- a/src/box/box.cc +++ b/src/box/box.cc @@ -277,6 +277,11 @@ apply_row(struct xstream *stream, struct xrow_header *row) (void) stream; struct request request; xrow_decode_dml_xc(row, &request, dml_request_key_map(row->type)); + if (request.type == IPROTO_NOP) { + if (txn_commit_nop(&request) != 0) + diag_raise(); + return; + } struct space *space = space_cache_find_xc(request.space_id); if (process_rw(&request, space, NULL) != 0) { say_error("error applying row: %s", request_str(&request)); diff --git a/src/box/iproto_constants.c b/src/box/iproto_constants.c index 3adb7cd4..5c1d3a31 100644 --- a/src/box/iproto_constants.c +++ b/src/box/iproto_constants.c @@ -121,7 +121,7 @@ const uint64_t iproto_body_key_map[IPROTO_TYPE_STAT_MAX] = { bit(SPACE_ID) | bit(OPS) | bit(TUPLE), /* UPSERT */ 0, /* CALL */ 0, /* reserved */ - bit(SPACE_ID), /* NOP */ + 0, /* NOP */ }; #undef bit diff --git a/src/box/request.c b/src/box/request.c index fda54a18..6633153c 100644 --- a/src/box/request.c +++ b/src/box/request.c @@ -50,7 +50,6 @@ request_create_from_tuple(struct request *request, struct space *space, struct tuple *old_tuple, struct tuple *new_tuple) { memset(request, 0, sizeof(*request)); - request->space_id = space->def->id; if (old_tuple == new_tuple) { /* @@ -61,6 +60,7 @@ request_create_from_tuple(struct request *request, struct space *space, return 0; } + request->space_id = space->def->id; if (new_tuple == NULL) { uint32_t size, key_size; const char *data = tuple_data_range(old_tuple, &size); diff --git a/src/box/txn.c b/src/box/txn.c index e25c0e0e..362030a9 100644 --- a/src/box/txn.c +++ b/src/box/txn.c @@ -71,9 +71,9 @@ txn_add_redo(struct txn_stmt *stmt, struct request *request) return 0; } -/** Initialize a new stmt object within txn. */ +/** Allocate a new txn statement. */ static struct txn_stmt * -txn_stmt_new(struct txn *txn) +txn_stmt_new(void) { struct txn_stmt *stmt; stmt = region_alloc_object(&fiber()->gc, struct txn_stmt); @@ -89,12 +89,6 @@ txn_stmt_new(struct txn *txn) stmt->new_tuple = NULL; stmt->engine_savepoint = NULL; stmt->row = NULL; - - /* Set the savepoint for statement rollback. */ - txn->sub_stmt_begin[txn->in_sub_stmt] = stailq_last(&txn->stmts); - txn->in_sub_stmt++; - - stailq_add_tail_entry(&txn->stmts, stmt, next); return stmt; } @@ -106,13 +100,15 @@ txn_rollback_to_svp(struct txn *txn, struct stailq_entry *svp) stailq_cut_tail(&txn->stmts, svp, &rollback); stailq_reverse(&rollback); stailq_foreach_entry(stmt, &rollback, next) { - engine_rollback_statement(txn->engine, txn, stmt); + if (stmt->space != NULL) { + engine_rollback_statement(txn->engine, txn, stmt); + stmt->space = NULL; + } if (stmt->row != NULL) { assert(txn->n_rows > 0); txn->n_rows--; stmt->row = NULL; } - stmt->space = NULL; } } @@ -145,7 +141,6 @@ int txn_begin_in_engine(struct engine *engine, struct txn *txn) { if (txn->engine == NULL) { - assert(stailq_empty(&txn->stmts)); txn->engine = engine; return engine_begin(engine, txn); } else if (txn->engine != engine) { @@ -179,11 +174,17 @@ txn_begin_stmt(struct space *space) if (txn_begin_in_engine(engine, txn) != 0) goto fail; - struct txn_stmt *stmt = txn_stmt_new(txn); + struct txn_stmt *stmt = txn_stmt_new(); if (stmt == NULL) goto fail; stmt->space = space; + /* Set the savepoint for statement rollback. */ + txn->sub_stmt_begin[txn->in_sub_stmt] = stailq_last(&txn->stmts); + txn->in_sub_stmt++; + + stailq_add_tail_entry(&txn->stmts, stmt, next); + if (engine_begin_statement(engine, txn) != 0) { txn_rollback_stmt(); return NULL; @@ -238,6 +239,35 @@ fail: return -1; } +int +txn_commit_nop(struct request *request) +{ + assert(request->header != NULL); + + struct txn *txn = in_txn(); + if (txn == NULL) { + txn = txn_begin(true); + if (txn == NULL) + return -1; + } + + struct txn_stmt *stmt = txn_stmt_new(); + if (stmt == NULL) + goto fail; + if (txn_add_redo(stmt, request) != 0) + goto fail; + + txn->n_rows++; + stailq_add_tail_entry(&txn->stmts, stmt, next); + + if (txn->is_autocommit && txn->in_sub_stmt == 0) + return txn_commit(txn); + return 0; +fail: + if (txn->is_autocommit && txn->in_sub_stmt == 0) + txn_rollback(); + return -1; +} static int64_t txn_write_to_wal(struct txn *txn) @@ -287,32 +317,31 @@ txn_commit(struct txn *txn) { assert(txn == in_txn()); - assert(stailq_empty(&txn->stmts) || txn->engine); - /* Do transaction conflict resolving */ - if (txn->engine) { - if (engine_prepare(txn->engine, txn) != 0) - goto fail; + if (txn->engine != NULL && + engine_prepare(txn->engine, txn) != 0) + goto fail; - if (txn->n_rows > 0) { - txn->signature = txn_write_to_wal(txn); - if (txn->signature < 0) - goto fail; - } - /* - * The transaction is in the binary log. No action below - * may throw. In case an error has happened, there is - * no other option but terminate. - */ - if (txn->has_triggers && - trigger_run(&txn->on_commit, txn) != 0) { - diag_log(); - unreachable(); - panic("commit trigger failed"); - } + if (txn->n_rows > 0) { + txn->signature = txn_write_to_wal(txn); + if (txn->signature < 0) + goto fail; + } + /* + * The transaction is in the binary log. No action below + * may throw. In case an error has happened, there is + * no other option but terminate. + */ + if (txn->has_triggers && + trigger_run(&txn->on_commit, txn) != 0) { + diag_log(); + unreachable(); + panic("commit trigger failed"); + } + if (txn->engine != NULL) engine_commit(txn->engine, txn); - } + TRASH(txn); /** Free volatile txn memory. */ fiber_gc(); @@ -470,7 +499,7 @@ box_txn_rollback_to_savepoint(box_txn_savepoint_t *svp) } struct txn_stmt *stmt = svp->stmt == NULL ? NULL : stailq_entry(svp->stmt, struct txn_stmt, next); - if (stmt != NULL && stmt->space == NULL) { + if (stmt != NULL && stmt->space == NULL && stmt->row == NULL) { /* * The statement at which this savepoint was * created has been rolled back. diff --git a/src/box/txn.h b/src/box/txn.h index f3d690be..b61adc33 100644 --- a/src/box/txn.h +++ b/src/box/txn.h @@ -253,6 +253,18 @@ void txn_rollback_stmt(); /** + * Commit a no-op request. + * + * A no-op request does not affect any space, but it + * promotes vclock and is written to WAL. + * + * This function can be called both as a part of an + * independent transaction and in autocommit mode. + */ +int +txn_commit_nop(struct request *request); + +/** * Raise an error if this is a multi-statement * transaction: DDL can not be part of a multi-statement * transaction and must be run in autocommit mode. diff --git a/test/box/before_replace.result b/test/box/before_replace.result index 4f47b9fa..2b6c1801 100644 --- a/test/box/before_replace.result +++ b/test/box/before_replace.result @@ -660,9 +660,9 @@ row.HEADER.type --- - NOP ... -row.BODY.space_id == s.id +#row.BODY --- -- true +- 0 ... -- gh-3128 before_replace with run_triggers s2 = box.schema.space.create("test2") diff --git a/test/box/before_replace.test.lua b/test/box/before_replace.test.lua index 22733c1d..9b4f49cf 100644 --- a/test/box/before_replace.test.lua +++ b/test/box/before_replace.test.lua @@ -221,7 +221,7 @@ path = fio.pathjoin(box.cfg.wal_dir, string.format('%020d.xlog', box.info.lsn - fun, param, state = xlog.pairs(path) state, row = fun(param, state) row.HEADER.type -row.BODY.space_id == s.id +#row.BODY -- gh-3128 before_replace with run_triggers s2 = box.schema.space.create("test2") -- 2.11.0
next prev parent reply other threads:[~2018-06-13 16:10 UTC|newest] Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top 2018-06-13 16:10 [PATCH 0/6] Introduce replica local spaces Vladimir Davydov 2018-06-13 16:10 ` [PATCH 1/6] txn: remove unused C++ wrappers Vladimir Davydov 2018-06-27 17:08 ` Konstantin Osipov 2018-06-13 16:10 ` [PATCH 2/6] xrow: fix ret code on decode failure Vladimir Davydov 2018-06-27 17:29 ` Konstantin Osipov 2018-06-13 16:10 ` [PATCH 3/6] iproto: fix IPROTO_SERVER_IS_RO key code Vladimir Davydov 2018-06-27 17:48 ` Konstantin Osipov 2018-06-13 16:10 ` Vladimir Davydov [this message] 2018-06-27 17:45 ` [PATCH 4/6] txn: do not require space id for nop requests Konstantin Osipov 2018-06-28 9:13 ` Vladimir Davydov 2018-06-28 10:23 ` Konstantin Osipov 2018-06-28 10:35 ` Vladimir Davydov 2018-06-28 10:54 ` Konstantin Osipov 2018-06-28 11:10 ` Vladimir Davydov 2018-06-13 16:10 ` [PATCH 5/6] xrow: make NOP requests bodiless Vladimir Davydov 2018-06-27 17:49 ` Konstantin Osipov 2018-06-13 16:10 ` [PATCH 6/6] Introduce replica local spaces Vladimir Davydov 2018-06-13 21:26 ` [tarantool-patches] " Vladislav Shpilevoy 2018-06-27 18:24 ` Konstantin Osipov 2018-06-27 18:27 ` 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=4dfddcb3838385c88cbfdf51d52ef112f56cf130.1528906027.git.vdavydov.dev@gmail.com \ --to=vdavydov.dev@gmail.com \ --cc=kostja@tarantool.org \ --cc=tarantool-patches@freelists.org \ --subject='Re: [PATCH 4/6] txn: do not require space id for nop requests' \ /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