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:
&#149; 3 signs your SCM is hindering your productivity
&#149; Requirements for releasing software faster
&#149; 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

Reply via email to