SnapshotData SnapshotAnyData = {HeapTupleSatisfiesAny};
/* local functions */
-static bool XidVisibleInSnapshot(TransactionId xid, Snapshot snapshot, bool known_committed, TransactionIdStatus *hintstatus);
+static bool XidVisibleInSnapshot(TransactionId xid, Snapshot snapshot,
+ TransactionIdStatus *hintstatus);
+static bool CommittedXidVisibleInSnapshot(TransactionId xid, Snapshot snapshot);
static bool IsMovedTupleVisible(HeapTuple htup, Buffer buffer);
/*
}
else
{
- visible = XidVisibleInSnapshot(HeapTupleHeaderGetRawXmin(tuple), snapshot, false, &hintstatus);
+ visible = XidVisibleInSnapshot(HeapTupleHeaderGetRawXmin(tuple), snapshot, &hintstatus);
if (hintstatus == XID_COMMITTED)
SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
if (TransactionIdIsCurrentTransactionId(xmax))
return false;
- visible = XidVisibleInSnapshot(xmax, snapshot, false, &hintstatus);
+ visible = XidVisibleInSnapshot(xmax, snapshot, &hintstatus);
if (!visible)
{
/* it must have aborted or crashed */
return false;
}
- visible = XidVisibleInSnapshot(HeapTupleHeaderGetRawXmax(tuple), snapshot, false, &hintstatus);
+ visible = XidVisibleInSnapshot(HeapTupleHeaderGetRawXmax(tuple), snapshot, &hintstatus);
if (hintstatus == XID_ABORTED)
{
/* it must have aborted or crashed */
else
{
visible = XidVisibleInSnapshot(HeapTupleHeaderGetXmin(tuple),
- snapshot, false, &hintstatus);
+ snapshot, &hintstatus);
if (hintstatus == XID_COMMITTED)
SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
HeapTupleHeaderGetRawXmin(tuple));
/* xmin is committed, but maybe not according to our snapshot */
if (!HeapTupleHeaderXminFrozen(tuple))
{
- visible = XidVisibleInSnapshot(HeapTupleHeaderGetRawXmin(tuple), snapshot,
- true, &hintstatus);
- if (hintstatus == XID_COMMITTED)
- {
- SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
- HeapTupleHeaderGetRawXmin(tuple));
- }
- if (hintstatus == XID_ABORTED)
- {
- SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
- InvalidTransactionId);
- }
+ visible = CommittedXidVisibleInSnapshot(HeapTupleHeaderGetRawXmin(tuple), snapshot);
if (!visible)
return false; /* treat as still in progress */
}
return false; /* deleted before scan started */
}
- visible = XidVisibleInSnapshot(xmax, snapshot, false, &hintstatus);
+ visible = XidVisibleInSnapshot(xmax, snapshot, &hintstatus);
if (visible)
return false; /* updating transaction committed */
else
}
visible = XidVisibleInSnapshot(HeapTupleHeaderGetRawXmax(tuple),
- snapshot, false, &hintstatus);
+ snapshot, &hintstatus);
if (hintstatus == XID_COMMITTED)
{
/* xmax transaction committed */
/* it must have aborted or crashed */
SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
InvalidTransactionId);
- return true;
}
+ if (!visible)
+ return true; /* treat as still in progress */
}
else
{
/* xmax is committed, but maybe not according to our snapshot */
- visible = XidVisibleInSnapshot(HeapTupleHeaderGetRawXmax(tuple), snapshot,
- false, &hintstatus);
+ visible = CommittedXidVisibleInSnapshot(HeapTupleHeaderGetRawXmax(tuple), snapshot);
if (!visible)
return true; /* treat as still in progress */
}
return false;
}
-
/*
* HeapTupleSatisfiesVacuum
*
*/
static bool
XidVisibleInSnapshot(TransactionId xid, Snapshot snapshot,
- bool known_committed, TransactionIdStatus *hintstatus)
+ TransactionIdStatus *hintstatus)
{
CommitSeqNo csn;
- elog(DEBUG1, "XidVisibleInSnapshot %u, %u:%u",
- xid, snapshot->xmin, snapshot->xmax);
-
*hintstatus = XID_INPROGRESS;
- /*
- * Make a quick range check to eliminate most XIDs without looking at the
- * CSN log.
- */
- if (known_committed && TransactionIdPrecedes(xid, snapshot->xmin))
- {
- *hintstatus = XID_COMMITTED;
- return true;
- }
-
/*
* Any xid >= xmax is in-progress (or aborted, but we don't distinguish
- * that here.
+ * that here).
+ *
+ * We can't do anything useful with xmin, because the xmin only tells us
+ * whether we see it as completed. We have to check the transaction log to
+ * see if the transaction committed or aborted, in any case.
*/
if (TransactionIdFollowsOrEquals(xid, snapshot->xmax))
return false;
}
}
+/*
+ * CommittedXidVisibleInSnapshot
+ * Is the given XID visible according to the snapshot?
+ *
+ * This is the same as XidVisibleInSnapshot, but the caller knows that the
+ * given XID committed. The only question is whether it's visible to our
+ * snapshot or not.
+ */
+static bool
+CommittedXidVisibleInSnapshot(TransactionId xid, Snapshot snapshot)
+{
+ CommitSeqNo csn;
+
+ /*
+ * Make a quick range check to eliminate most XIDs without looking at the
+ * CSN log.
+ */
+ if (TransactionIdPrecedes(xid, snapshot->xmin))
+ return true;
+
+ /*
+ * Any xid >= xmax is in-progress (or aborted, but we don't distinguish
+ * that here.
+ */
+ if (TransactionIdFollowsOrEquals(xid, snapshot->xmax))
+ return false;
+
+ csn = TransactionIdGetCommitSeqNo(xid);
+
+ if (!COMMITSEQNO_IS_COMMITTED(csn))
+ {
+ elog(WARNING, "transaction %u was hinted as committed, but was not marked as committed in the transaction log", xid);
+ /*
+ * We have contradicting evidence on whether the transaction committed or
+ * not. Let's assume that it did. That seems better than erroring out.
+ */
+ return true;
+ }
+
+ if (csn < snapshot->snapshotcsn)
+ return true;
+ else
+ return false;
+}
+
+
/*
* Is the tuple really only locked? That is, is it not updated?
*
* it's not "this" transaction. Do a normal visibility check using the
* snapshot.
*/
- else if (!XidVisibleInSnapshot(xmin, snapshot, false, &hintstatus))
+ else if (!XidVisibleInSnapshot(xmin, snapshot, &hintstatus))
{
return false;
}
* it's not "this" transaction. Do a normal visibility check using the
* snapshot.
*/
- if (XidVisibleInSnapshot(xmax, snapshot, false, &hintstatus))
+ if (XidVisibleInSnapshot(xmax, snapshot, &hintstatus))
return false;
else
return true;