if (!HEAP_XMAX_IS_LOCKED_ONLY(oldtup.t_data->t_infomask))
update_xact = HeapTupleGetUpdateXid(oldtup.t_data);
- /* there was no UPDATE in the MultiXact; or it aborted. */
+ /*
+ * There was no UPDATE in the MultiXact; or it aborted. No
+ * TransactionIdIsInProgress() call needed here, since we called
+ * MultiXactIdWait() above.
+ */
if (!TransactionIdIsValid(update_xact) ||
TransactionIdDidAbort(update_xact))
can_continue = true;
* Given a multixact Xmax and corresponding infomask, which does not have the
* HEAP_XMAX_LOCK_ONLY bit set, obtain and return the Xid of the updating
* transaction.
+ *
+ * Caller is expected to check the status of the updating transaction, if
+ * necessary.
*/
static TransactionId
MultiXactIdGetUpdateXid(TransactionId xmax, uint16 t_infomask)
for (i = 0; i < nmembers; i++)
{
/* Ignore lockers */
- if (members[i].status == MultiXactStatusForKeyShare ||
- members[i].status == MultiXactStatusForShare ||
- members[i].status == MultiXactStatusForNoKeyUpdate ||
- members[i].status == MultiXactStatusForUpdate)
+ if (!ISUPDATE_from_mxstatus(members[i].status))
continue;
- /* ignore aborted transactions */
- if (TransactionIdDidAbort(members[i].xid))
- continue;
- /* there should be at most one non-aborted updater */
+ /* there can be at most one updater */
Assert(update_xact == InvalidTransactionId);
- Assert(members[i].status == MultiXactStatusNoKeyUpdate ||
- members[i].status == MultiXactStatusUpdate);
update_xact = members[i].xid;
#ifndef USE_ASSERT_CHECKING
TransactionId xmax;
xmax = HeapTupleGetUpdateXid(tuple);
- if (!TransactionIdIsValid(xmax))
- return true;
+
+ /* not LOCKED_ONLY, so it has to have an xmax */
+ Assert(TransactionIdIsValid(xmax));
/* updating subtransaction must have aborted */
if (!TransactionIdIsCurrentTransactionId(xmax))
return true;
xmax = HeapTupleGetUpdateXid(tuple);
- if (!TransactionIdIsValid(xmax))
- return true;
+
+ /* not LOCKED_ONLY, so it has to have an xmax */
+ Assert(TransactionIdIsValid(xmax));
+
if (TransactionIdIsCurrentTransactionId(xmax))
return false;
if (TransactionIdIsInProgress(xmax))
return true;
if (TransactionIdDidCommit(xmax))
return false;
+ /* it must have aborted or crashed */
return true;
}
TransactionId xmax;
xmax = HeapTupleGetUpdateXid(tuple);
- if (!TransactionIdIsValid(xmax))
- return HeapTupleMayBeUpdated;
+
+ /* not LOCKED_ONLY, so it has to have an xmax */
+ Assert(TransactionIdIsValid(xmax));
/* updating subtransaction must have aborted */
if (!TransactionIdIsCurrentTransactionId(xmax))
}
xmax = HeapTupleGetUpdateXid(tuple);
- if (!TransactionIdIsValid(xmax))
- {
- if (MultiXactIdIsRunning(HeapTupleHeaderGetRawXmax(tuple)))
- return HeapTupleBeingUpdated;
- SetHintBits(tuple, buffer, HEAP_XMAX_INVALID, InvalidTransactionId);
- return HeapTupleMayBeUpdated;
- }
+ /* not LOCKED_ONLY, so it has to have an xmax */
+ Assert(TransactionIdIsValid(xmax));
if (TransactionIdIsCurrentTransactionId(xmax))
{
return HeapTupleInvisible; /* updated before scan started */
}
- if (MultiXactIdIsRunning(HeapTupleHeaderGetRawXmax(tuple)))
+ if (TransactionIdIsInProgress(xmax))
return HeapTupleBeingUpdated;
if (TransactionIdDidCommit(xmax))
return HeapTupleUpdated;
+
+ /* no member, even just a locker, alive anymore */
+ if (!MultiXactIdIsRunning(HeapTupleHeaderGetRawXmax(tuple)))
+ SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
+ InvalidTransactionId);
+
/* it must have aborted or crashed */
- SetHintBits(tuple, buffer, HEAP_XMAX_INVALID, InvalidTransactionId);
return HeapTupleMayBeUpdated;
}
TransactionId xmax;
xmax = HeapTupleGetUpdateXid(tuple);
- if (!TransactionIdIsValid(xmax))
- return true;
+
+ /* not LOCKED_ONLY, so it has to have an xmax */
+ Assert(TransactionIdIsValid(xmax));
/* updating subtransaction must have aborted */
if (!TransactionIdIsCurrentTransactionId(xmax))
return true;
xmax = HeapTupleGetUpdateXid(tuple);
- if (!TransactionIdIsValid(xmax))
- return true;
+
+ /* not LOCKED_ONLY, so it has to have an xmax */
+ Assert(TransactionIdIsValid(xmax));
+
if (TransactionIdIsCurrentTransactionId(xmax))
return false;
if (TransactionIdIsInProgress(xmax))
}
if (TransactionIdDidCommit(xmax))
return false;
+ /* it must have aborted or crashed */
return true;
}
TransactionId xmax;
xmax = HeapTupleGetUpdateXid(tuple);
- if (!TransactionIdIsValid(xmax))
- return true;
+
+ /* not LOCKED_ONLY, so it has to have an xmax */
+ Assert(TransactionIdIsValid(xmax));
/* updating subtransaction must have aborted */
if (!TransactionIdIsCurrentTransactionId(xmax))
Assert(!HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask));
xmax = HeapTupleGetUpdateXid(tuple);
- if (!TransactionIdIsValid(xmax))
- return true;
+
+ /* not LOCKED_ONLY, so it has to have an xmax */
+ Assert(TransactionIdIsValid(xmax));
+
if (TransactionIdIsCurrentTransactionId(xmax))
{
if (HeapTupleHeaderGetCmax(tuple) >= snapshot->curcid)
return true; /* treat as still in progress */
return false;
}
+ /* it must have aborted or crashed */
return true;
}
Assert(!HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask));
xmax = HeapTupleGetUpdateXid(tuple);
- if (!TransactionIdIsValid(xmax))
- return HEAPTUPLE_LIVE;
+
+ /* not LOCKED_ONLY, so it has to have an xmax */
+ Assert(TransactionIdIsValid(xmax));
+
if (TransactionIdIsInProgress(xmax))
return HEAPTUPLE_DELETE_IN_PROGRESS;
else if (TransactionIdDidCommit(xmax))
Assert(!(tuple->t_infomask & HEAP_XMAX_COMMITTED));
xmax = HeapTupleGetUpdateXid(tuple);
- if (!TransactionIdIsValid(xmax))
- return HEAPTUPLE_LIVE;
+
+ /* not LOCKED_ONLY, so it has to have an xmax */
+ Assert(TransactionIdIsValid(xmax));
+
/* multi is not running -- updating xact cannot be */
Assert(!TransactionIdIsInProgress(xmax));
if (TransactionIdDidCommit(xmax))
else
return HEAPTUPLE_DEAD;
}
- else
- {
- /*
- * Not in Progress, Not Committed, so either Aborted or crashed.
- */
- SetHintBits(tuple, buffer, HEAP_XMAX_INVALID, InvalidTransactionId);
- return HEAPTUPLE_LIVE;
- }
/*
- * Deleter committed, but perhaps it was recent enough that some open
- * transactions could still see the tuple.
+ * Not in Progress, Not Committed, so either Aborted or crashed.
+ * Remove the Xmax.
*/
-
- /* Otherwise, it's dead and removable */
- return HEAPTUPLE_DEAD;
+ SetHintBits(tuple, buffer, HEAP_XMAX_INVALID, InvalidTransactionId);
+ return HEAPTUPLE_LIVE;
}
if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED))
/* ... but if it's a multi, then perhaps the updating Xid aborted. */
xmax = HeapTupleGetUpdateXid(tuple);
- if (!TransactionIdIsValid(xmax)) /* shouldn't happen .. */
- return true;
+
+ /* not LOCKED_ONLY, so it has to have an xmax */
+ Assert(TransactionIdIsValid(xmax));
if (TransactionIdIsCurrentTransactionId(xmax))
return false;