recRollback could be on a record that was deleted and is now being
rolled back. So at least this state is valid as well. What others???
This may be a possibility! This is a temporary state that could be
repalacing recDeleted while it is added to the transaction. I surveyed
the calls to Transaction::addRecord where this is set. Sometimes it
occurs before the record shows up on the recordLeaf for others to see
(Table::insert or validateAndInsert) before addRecord() is called.
Sometimes it is the other way around. If we make it standard procedure
to add new record versions to the transaction first, before inserting
into the record tree, then we could be sure that no other thread will
find it in checkUniqueRecordVersion() or duplicateKey().
This is always a new record, so it should always haveData.
Happens during ~RecordVersion(). That means the useCount is zero.
It may be possible for a checkUniqueRecordVersion or duplicateKey() to
be traversing a chain at the same time as a scavengeSavepoint(). But it
looks like syncPrior is held exclusively during the time the savepoint
records are being bypassed and the last one scavenged receives
recEndChain. So I guess this cannot happen, currently. :)
Christopher Powers wrote:
> This has to be most annoying assert in Falcon, next to the 'active'
> asserts in the Record class.
> Historically, this asserted because hasRecord() failed to thaw the
> record, leaving the record state as 'recChilled'. In this case, however,
> dup->state is 'recRollback'.
> Do you think we should we check for 'recRollback', too?
> bool Table::checkUniqueRecordVersion(...)
> for (Record *dup = rec; dup; dup = dup->getPriorVersion())
> if (dup == record)
> continue; // Check next record version
> // Get the record's transaction state. Don't wait yet.
> state = transaction->getRelativeState(dup, DO_NOT_WAIT);
> // Check for a deleted record or a record lock
> if (!dup->hasRecord())
> // If the record is a lock record, keep looking for a dup.
> if (dup->state == recLock)
> continue; // Next record version.
> // The record has been deleted.
>>>> ASSERT(dup->state == recDeleted); <<<
> switch (state)
> case CommittedVisible: