Jim and everybody else,
As I mentioned in was working on removing the last parts of the old
dependency manager and had one issue left (famous last word :-) ). This
issue is related to Transaction::getRelativeState().
Some background: The new dependency manager stores the event counter for
(a) when the transaction became active and (b) when the transaction
committed in the transaction object. These two event numbers is then
used for comparing the relative state of active and committed
transactions. Using these instead of the old dependency manager allows
me to remove (a) the dependency counter for each transaction and (b) the
states array with pointers to all transactions that where active at the
start of a given transaction.
The issue:
The code for the first part of Transaction::getRelativeState() looks
like this:
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;
}
The issue is related to when the pointer to the transaction argument is
NULL:
1) Not having a reference to the transaction makes it hard(er) to
compare the state of two different transactions since the one we are
going to compare state against is "not there". For the old dependency
manager this was easy since it has the states array of all active
transactions available also after these transactions possibly are
deleted (see the for loop above). But with the new dependency manager we
should be able to remove this state array....
I have a working solution for this: By including the commit
transition event number in every RecordVersion object (I set this in
Transaction::commit()) makes it possible to compare this record against
this transaction's start event. The code replacing the above for loop
looks approximately like this:
if (transEndEvent_of_recordObject > startEvent)
{
fprintf(stderr, "T::getRelativeState: %d: NEW:
CommittedInvisible: end=%d start=%d\n", transactionId, transEndEvent,
startEvent);
return CommittedInvisible;
}
The test for this is simple but I do not like to having to include
the commit event in record versions if I do not have to do so. Anyone
having a suggestion for a better solution?
2) Comments in the code above seems to suggest that the reason for not
having the pointer to the transaction object is due to that the
transaction object has been deleted and it assumes that the transaction
has been committed. In my testing this seems not like it is an correct
assumption, in most cases when the transaction pointer is NULL the
transaction is actually still in Active state. Questions:
a) Are the comments in the code wrong? Or
b) The code is wrong? And
c) Why do we not have the transaction pointer pointing to the
transaction if it is still active
or (d) I have I introduced some error that causes this?
Any comments or feedback is appreciated.
Olav