On Wed, 7 May 2014 18:44:13 -0400, "Claudio Valderrama C."
<[email protected]>
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