-
Notifications
You must be signed in to change notification settings - Fork 47
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Adjusting checks of completionBits from SubordinateTransactionControl #17
Conversation
@@ -323,7 +323,7 @@ void rollbackLocal() throws SystemException { | |||
int oldVal; | |||
do { | |||
oldVal = completionBits.get(); | |||
if ((oldVal & BIT_PREPARE_OR_ROLLBACK) != 0) { | |||
if ((oldVal & BIT_PREPARE_OR_ROLLBACK) == 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Normally this bit is set when the transaction is either PREPARED or ROLLED_BACK. So if we do a rollback() when the transaction was already PREPARED or ROLLED_BACK, then we throw the exception.
In other words, these bits represent what states we've already reached, so that we know what state is valid to come next.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Which is to say that '!=' should be correct here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok, I see. I'm still not fully sure if I follow :)
(oldVal & BIT_PREPARE_OR_ROLLBACK) != 0)
says - if the current state is in prepare or rollback then throw an exception. But calling rollback could be from state where transaction was preapred. Ie. transaction.begin -> transation.prepare -> transaction.rollback
. I mean when transaction is prepared is fine to rollback it, what I'm missing here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought it was only valid to "forget" in this state. But if I'm wrong about that, then the entire check can be removed since either true or false are both OK.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All my other changes came from the feeling that rollbacking prepared transaction is fully ok. So I'm leaving other comments untouched till I understand how this behaves.
Btw. if this is ok then I need to find out fix on some different place and I need to think about it a little bit more.
@@ -337,7 +337,7 @@ void commitLocal() throws HeuristicRollbackException, RollbackException, Heurist | |||
int oldVal; | |||
do { | |||
oldVal = completionBits.get(); | |||
if ((oldVal & BIT_PREPARE_OR_ROLLBACK) != 0 || (oldVal & BIT_COMMIT_OR_FORGET) != 0) { | |||
if ((oldVal & BIT_PREPARE_OR_ROLLBACK) == 0 || (oldVal & BIT_COMMIT_OR_FORGET) != 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this case we want to keep '!=' because this essentially says, "If we have prepared or rolled back, or if we've committed or forgotten, throw the exception".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can probably skip the check here (and keep the CAS) if we want to just let commit() fail on its own.
@@ -361,7 +361,7 @@ public void rollback() throws XAException { | |||
int oldVal; | |||
do { | |||
oldVal = completionBits.get(); | |||
if ((oldVal & BIT_PREPARE_OR_ROLLBACK) != 0) { | |||
if ((oldVal & BIT_PREPARE_OR_ROLLBACK) == 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this case we keep the '!=' because we want to throw an exception if rollback() was called after prepare() or rollback().
@@ -509,7 +509,7 @@ public void commit(final boolean onePhase) throws XAException { | |||
int oldVal; | |||
do { | |||
oldVal = completionBits.get(); | |||
if (onePhase && (oldVal & BIT_PREPARE_OR_ROLLBACK) != 0 || (oldVal & BIT_COMMIT_OR_FORGET) != 0) { | |||
if ((onePhase && (oldVal & BIT_PREPARE_OR_ROLLBACK) != 0) || (oldVal & BIT_COMMIT_OR_FORGET) != 0 || (oldVal & BIT_PREPARE_OR_ROLLBACK) == 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This one is almost correct, I think, ignoring the useless extra ().
Transliterating:
if:
onePhase and we've already prepared/rolled back
or:
we've already committed
or:
we have not yet prepared
But the last check should be "or: !onePhase and we have not yet prepared". Otherwise, yes I think you found a real mistake in this one.
Since onePhase is compared in one sense in half the expression and the opposite sense in the other half, it's probably best written like this:
if ((oldVal & BIT_COMMIT_OR_FORGET) != 0 && onePhase ? (oldValue & BIT_PREPARE_OR_ROLLBACK) != 0 : (oldValue & BIT_PREPARE_OR_ROLLBACK) == 0) {
Since the sense of the latter flag check varies in relation to onePhase, it can be further simplified:
if ((oldVal & BIT_COMMIT_OR_FORGET) != 0 && onePhase == ((oldValue & BIT_PREPARE_OR_ROLLBACK) != 0)) {
Which transliterates as: "If we already committed/forgot, or whether we prepared is the same as onePhase, throw exception".
Given our conversation, I think that maybe all these checks are wrong and we can just remove completionBits completely. |
@dmlloyd ok, from my insight I think it could be fine to remove them. But maybe a check is worthy at some places. I mean for example is invalid to call commit when there is no onephase optimization and there was no prepare called. As I'm not all sure here but Narayana handles situations of execution in wrong context. As the call is delegated to it, the particular To summarize that somehow - are you ok for me change this PR to remove all the usage of Thanks |
b8c8b6e
to
4e30439
Compare
@dmlloyd per our discussion I removed the check bits code completely. Checked with inflow transaction processing and that works. |
This was agreed that is not needed anymore at this time. The checks, as they were defined, causes troubles on jca inflow transction processing (JBEAP-8993)
4e30439
to
65ef0e2
Compare
@dmlloyd what do you think, could this be part of 1.0.0.Beta19 release? You know I'm asking as my fix WFLY-8275 depends on it 😁 |
Hi @dmlloyd,
I think there is a wrong check in rollback method of JBossLocalTransactionProvider$Entry class.
What I can see from my testing and when looking to the code
rollback
method should change theif
to(oldVal & BIT_PREPARE_OR_ROLLBACK) == 0
- meaning throw InvalidStateException when transaction is not in prepared state.The other changes in this commit are not tested and they came only from my feeling. I would be happy if you can review this PR.