From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Date: Wed, 27 Mar 2019 14:48:32 +0300 From: Vladimir Davydov Subject: Re: [tarantool-patches] [PATCH v3 4/5] Transaction support for applier Message-ID: <20190327114832.z6znrtcup4pdlxja@esperanza> References: <2d06385bd5d62551ce1132d3d5c937d417ea9e66.1553255718.git.georgy@tarantool.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <2d06385bd5d62551ce1132d3d5c937d417ea9e66.1553255718.git.georgy@tarantool.org> To: Georgy Kirichenko Cc: tarantool-patches@freelists.org List-ID: On Fri, Mar 22, 2019 at 03:06:09PM +0300, Georgy Kirichenko wrote: > +/** > + * Apply all rows in the rows queue as a single transaction. > + * > + * Return 0 for success or -1 in case of an error. > + */ > +static int > +applier_apply_tx(struct stailq *rows) > +{ > + int res = 0; > + struct txn *txn = txn_begin(false); > + struct applier_tx_row *item; > + if (txn == NULL) > + diag_raise(); Just one thing - mixing retval and exceptions to propagate errors doesn't look good. Besides you won't release the latch in case of an exception (see below). Please replace with 'return -1'. > + stailq_foreach_entry(item, rows, next) { > + struct xrow_header *row = &item->row; > + res = apply_row(row); > + if (res != 0) { > + struct error *e = diag_last_error(diag_get()); > + /* > + * In case of ER_TUPLE_FOUND error and enabled > + * replication_skip_conflict configuration > + * option, skip applying the foreign row and > + * replace it with NOP in the local write ahead > + * log. > + */ > + if (e->type == &type_ClientError && > + box_error_code(e) == ER_TUPLE_FOUND && > + replication_skip_conflict) { > + diag_clear(diag_get()); > + row->type = IPROTO_NOP; > + row->bodycnt = 0; > + res = apply_row(row); > + } > + } > + if (res != 0) > + break; > + } > + if (res == 0) > + res = txn_commit(txn); > + else > + txn_rollback(); > + return res; > +} > @@ -594,33 +724,11 @@ applier_subscribe(struct applier *applier) > * that belong to the same server id. > */ > latch_lock(latch); > - if (vclock_get(&replicaset.vclock, row.replica_id) < row.lsn) { > - int res = apply_row(&row); > - if (res != 0) { > - struct error *e = diag_last_error(diag_get()); > - /* > - * In case of ER_TUPLE_FOUND error and enabled > - * replication_skip_conflict configuration > - * option, skip applying the foreign row and > - * replace it with NOP in the local write ahead > - * log. > - */ > - if (e->type == &type_ClientError && > - box_error_code(e) == ER_TUPLE_FOUND && > - replication_skip_conflict) { > - diag_clear(diag_get()); > - struct xrow_header nop; > - nop.type = IPROTO_NOP; > - nop.bodycnt = 0; > - nop.replica_id = row.replica_id; > - nop.lsn = row.lsn; > - res = apply_row(&nop); > - } > - } > - if (res != 0) { > - latch_unlock(latch); > - diag_raise(); > - } > + if (vclock_get(&replicaset.vclock, first_row->replica_id) < > + first_row->lsn && > + applier_apply_tx(&rows) != 0) { > + latch_unlock(latch); > + diag_raise(); > } > latch_unlock(latch); >