aboutsummaryrefslogtreecommitdiff
path: root/src/include/access/transam.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/include/access/transam.h')
-rw-r--r--src/include/access/transam.h43
1 files changed, 43 insertions, 0 deletions
diff --git a/src/include/access/transam.h b/src/include/access/transam.h
index 0cab8653f1b..7d82cd2eb56 100644
--- a/src/include/access/transam.h
+++ b/src/include/access/transam.h
@@ -370,6 +370,49 @@ FullTransactionIdNewer(FullTransactionId a, FullTransactionId b)
return b;
}
+/*
+ * Compute FullTransactionId for the given TransactionId, assuming xid was
+ * between [oldestXid, nextXid] at the time when TransamVariables->nextXid was
+ * nextFullXid. When adding calls, evaluate what prevents xid from preceding
+ * oldestXid if SetTransactionIdLimit() runs between the collection of xid and
+ * the collection of nextFullXid.
+ */
+static inline FullTransactionId
+FullTransactionIdFromAllowableAt(FullTransactionId nextFullXid,
+ TransactionId xid)
+{
+ uint32 epoch;
+
+ /* Special transaction ID. */
+ if (!TransactionIdIsNormal(xid))
+ return FullTransactionIdFromEpochAndXid(0, xid);
+
+ Assert(TransactionIdPrecedesOrEquals(xid,
+ XidFromFullTransactionId(nextFullXid)));
+
+ /*
+ * The 64 bit result must be <= nextFullXid, since nextFullXid hadn't been
+ * issued yet when xid was in the past. The xid must therefore be from
+ * the epoch of nextFullXid or the epoch before. We know this because we
+ * must remove (by freezing) an XID before assigning the XID half an epoch
+ * ahead of it.
+ *
+ * The unlikely() branch hint is dubious. It's perfect for the first 2^32
+ * XIDs of a cluster's life. Right at 2^32 XIDs, misprediction shoots to
+ * 100%, then improves until perfection returns 2^31 XIDs later. Since
+ * current callers pass relatively-recent XIDs, expect >90% prediction
+ * accuracy overall. This favors average latency over tail latency.
+ */
+ epoch = EpochFromFullTransactionId(nextFullXid);
+ if (unlikely(xid > XidFromFullTransactionId(nextFullXid)))
+ {
+ Assert(epoch != 0);
+ epoch--;
+ }
+
+ return FullTransactionIdFromEpochAndXid(epoch, xid);
+}
+
#endif /* FRONTEND */
#endif /* TRANSAM_H */