xl_heap_freeze_tuple *frz, bool *totally_frozen_p)
{
bool changed = false;
- bool freeze_xmax = false;
+ bool xmax_already_frozen = false;
+ bool xmin_frozen;
+ bool freeze_xmax;
TransactionId xid;
- bool totally_frozen = true;
frz->frzflags = 0;
frz->t_infomask2 = tuple->t_infomask2;
/* Process xmin */
xid = HeapTupleHeaderGetXmin(tuple);
+ xmin_frozen = ((xid == FrozenTransactionId) ||
+ HeapTupleHeaderXminFrozen(tuple));
if (TransactionIdIsNormal(xid))
{
if (TransactionIdPrecedes(xid, relfrozenxid))
frz->t_infomask |= HEAP_XMIN_FROZEN;
changed = true;
+ xmin_frozen = true;
}
- else
- totally_frozen = false;
}
/*
relfrozenxid, relminmxid,
cutoff_xid, cutoff_multi, &flags);
- if (flags & FRM_INVALIDATE_XMAX)
- freeze_xmax = true;
- else if (flags & FRM_RETURN_IS_XID)
+ freeze_xmax = (flags & FRM_INVALIDATE_XMAX);
+
+ if (flags & FRM_RETURN_IS_XID)
{
/*
* NB -- some of these transformations are only valid because we
if (flags & FRM_MARK_COMMITTED)
frz->t_infomask |= HEAP_XMAX_COMMITTED;
changed = true;
- totally_frozen = false;
}
else if (flags & FRM_RETURN_IS_MULTI)
{
frz->xmax = newxmax;
changed = true;
- totally_frozen = false;
- }
- else
- {
- Assert(flags & FRM_NOOP);
}
}
else if (TransactionIdIsNormal(xid))
freeze_xmax = true;
}
else
- totally_frozen = false;
+ freeze_xmax = false;
}
+ else if ((tuple->t_infomask & HEAP_XMAX_INVALID) ||
+ !TransactionIdIsValid(HeapTupleHeaderGetRawXmax(tuple)))
+ {
+ freeze_xmax = false;
+ xmax_already_frozen = true;
+ }
+ else
+ ereport(ERROR,
+ (errcode(ERRCODE_DATA_CORRUPTED),
+ errmsg_internal("found xmax %u (infomask 0x%04x) not frozen, not multi, not normal",
+ xid, tuple->t_infomask)));
if (freeze_xmax)
{
+ Assert(!xmax_already_frozen);
+
frz->xmax = InvalidTransactionId;
/*
}
}
- *totally_frozen_p = totally_frozen;
+ *totally_frozen_p = (xmin_frozen &&
+ (freeze_xmax || xmax_already_frozen));
return changed;
}