Olav,
I'm glad you noticed this. The relative state of a Record object is
always CommittedVisible. It was never associated wioth a transaction.
Just a committed record read from the database. We might as well save
time and report that directly. Try this;
State Transaction::getRelativeState(Record* record, uint32 flags)
{
+ if (!record->isVersion())
+ return CommittedVisible;
+
blockingRecord = record;
State state = getRelativeState(record->getTransaction(),
record->getTransactionId(), flags);
blockingRecord = NULL;
return state;
}
Olav Sandstaa wrote:
> Hi Kevin,
>
> After applying your patch for Bug #40893 "Falcon concurrent unlock can
> cause invalid fetches" I found another issue with the use of
> Transaction::getRelativeState() that I first thought had to be wrong but
> which might be correct anyway. It would be good to get your comment on it.
>
> It is related to the following code:
>
> State Transaction::getRelativeState(Transaction *transaction, TransId
> transId, uint32 flags)
> {
> if (transactionId == transId)
> return Us;
>
> // A record may still have the transId even after the trans itself
> has been deleted.
> if (!transaction)
> {
> // All calls to getRelativeState are for the purpose of writing.
> // So only ConsistentRead can get CommittedInvisible.
>
> if (IS_CONSISTENT_READ(isolationLevel))
> {
> // If the transaction is no longer around, and the record is,
> // then it must be committed.
>
> if (transactionId < transId)
> return CommittedInvisible;
>
> // Be sure it was not active when we started.
>
> for (int n = 0; n < numberStates; ++n)
> if (states [n].transactionId == transId)
> return CommittedInvisible;
> }
>
> return CommittedVisible;
> }
>
>
> After your fix I had hoped that we no longer should see cases where we
> use the states array in the last for-loop. But with the debug code I had
> in my code tree we were still executing that code (but not the return
> statement). So I wondered why....
>
> It turns out that the case where this code is executed happens when we
> call Transaction::getRelativeState(Transaction*...) and the transaction
> argument is NULL and the transId is 0. This seems to happen when we
> calls Transaction::getReleativeState(Record* ) and the record argument
> is a Record object, not a RecordVersion object.
>
> When this is the case, Transaction::getRelativeState() will always
> return CommittedVisible (which is likely the correct value). Still from
> reading the above code it is a bit hard to imagine that it is supposed
> to work when both transaction==NULL and transId==0 (and could easily be
> a source for introducing unintended changes if someone decided to change
> the order of the logic).
>
> At least this puzzled me, so is it correct use of
> Transaction::getTransaction(NULL, 0, flags) in this case?
>
> Olav
>
>
>