On Wed, 7 May 2014 18:44:13 -0400, "Claudio Valderrama C." <cva...@usa.net> wrote: >> As the value of RDB$TRANSACTION_STATE is modified, I assume >> this code (or >> something very similar) is actually called, but then the `else` branch >> shown above. What does TRA_prepare2 mean here? Note that the specific >> scenario that triggered my question is a transaction recovery >> case, where >> the transaction is reconnected: transaction was prepared, but not >> committed/rolled back, then the connection was >> abandoned/destroyed; new >> connections recovers transaction and commits (or rolls back). > > MET_prepare() writes a record in RDB$TRANSACTIONS and as Vlad said, > TRA_prepare() calls MET... only if you pass a text: > > TRA_prepare: > // Functional desc: Put a transaction into limbo > .... > if (msg && length) > { > MET_prepare(tdbb, transaction, length, msg); > transaction->tra_flags |= TRA_prepare2; > } > > TRA_prepare2 is the indication that you are signaling all members of a > distributed transaction "pay attention, we are going to commit this > multi-connection mess". > > In other words, when you prepare a 2PC txn, you have the sequence: > - jrd.cpp's JTransaction::prepare_tra() (prepare a txn for commit, first > phase of 2PC) > - jrd.cpp's prepare_tra() > - TRA_prepare() > - MET_prepare() -> writes to rdb$transactions and activates TRA_prepare2 > but > it's called only if you passed a message to TRA_prepare().
Which I do. > Now, when you commit or rollback: > Only with the flags TRA_prepare2 or TRA_reconnected activated, TRA_commit > does > MET_update_transaction(tdbb, transaction, true); > and TRA_rollback does > MET_update_transaction(tdbb, transaction, false); > > then we reach the code I showed in the previous letter: > > void MET_update_transaction(thread_db* tdbb, > jrd_tra* transaction, const bool do_commit) > { > .... > if (do_commit && (transaction->tra_flags & TRA_prepare2)) > ERASE X > else > { > MODIFY X > X.RDB$TRANSACTION_STATE = do_commit ? > RDB$TRANSACTIONS.RDB$TRANSACTION_STATE.COMMITTED : > RDB$TRANSACTIONS.RDB$TRANSACTION_STATE.ROLLED_BACK; > END_MODIFY > } > > Now it's evident what Vlad said: no message when preparing to commit > implies > no TRA_prepare2 activated and in turn, it means the deletion won't happen. > There will be only an update. > The code is consistent. However if you're managing the 2PC trick in other > ways, we can allow the deletion (commenting the protection code is one > line), but how can we be sure you're deleting only what belongs to your > distributed transaction? Well I did add a message on prepare, but the specific problem I am referring to is on commit/rollback of a reconnected transaction, so TRA_prepare2 is not (no longer) set. Thanks for all the information. I will see if I can come up with a solution for Firebird 3 without needing RDB$TRANSACTIONS to be unprotected, but doesn't - potentially - degenerate to iterating over a list of thousands if not millions of transaction records when recovering a distributed transaction. Mark ------------------------------------------------------------------------------ Is your legacy SCM system holding you back? Join Perforce May 7 to find out: • 3 signs your SCM is hindering your productivity • Requirements for releasing software faster • Expert tips and advice for migrating your SCM now http://p.sf.net/sfu/perforce Firebird-Devel mailing list, web interface at https://lists.sourceforge.net/lists/listinfo/firebird-devel