From 01cb7d0bf5a761d47cf89cc60358458e2e77fc7f Mon Sep 17 00:00:00 2001 From: Maxim Orlov Date: Mon, 20 Mar 2023 18:23:55 +0300 Subject: [PATCH v58 3/3] Make use FullTransactionId in 2PC filenames Switch from using TransactionId to FullTransactionId in naming of 2PC files. Transaction state file in the pg_twophase directory now have extra 8 bytes in the name to address an epoch of a given xid. Author: Maxim Orlov Discussion: https://postgr.es/m/CAJ7c6TPDOYBYrnCAeyndkBktO0WG2xSdYduTF0nxq%2BvfkmTF5Q%40mail.gmail.com --- src/backend/access/transam/twophase.c | 50 ++++++++++++++++++++++++--- 1 file changed, 45 insertions(+), 5 deletions(-) diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c index 068e59bec0..e103ffb6d3 100644 --- a/src/backend/access/transam/twophase.c +++ b/src/backend/access/transam/twophase.c @@ -941,8 +941,46 @@ TwoPhaseGetDummyProc(TransactionId xid, bool lock_held) /* State file support */ /************************************************************************/ -#define TwoPhaseFilePath(path, xid) \ - snprintf(path, MAXPGPATH, TWOPHASE_DIR "/%08X", xid) +/* + * Compute the FullTransactionId for the given TransactionId. + * + * The wrap logic is safe here because the span of active xids cannot exceed one + * epoch at any given time. + */ +static inline FullTransactionId +AdjustToFullTransactionId(TransactionId xid) +{ + FullTransactionId nextFullXid; + TransactionId nextXid; + uint32 epoch; + + Assert(TransactionIdIsValid(xid)); + + LWLockAcquire(XidGenLock, LW_SHARED); + nextFullXid = ShmemVariableCache->nextXid; + LWLockRelease(XidGenLock); + + nextXid = XidFromFullTransactionId(nextFullXid); + epoch = EpochFromFullTransactionId(nextFullXid); + if (unlikely(xid > nextXid)) + { + /* Wraparound occured, must be from a prev epoch. */ + Assert(epoch > 0); + epoch--; + } + + return FullTransactionIdFromEpochAndXid(epoch, xid); +} + +static inline int +TwoPhaseFilePath(char *path, TransactionId xid) +{ + FullTransactionId fxid = AdjustToFullTransactionId(xid); + + return snprintf(path, MAXPGPATH, TWOPHASE_DIR "/%08X%08X", + EpochFromFullTransactionId(fxid), + XidFromFullTransactionId(fxid)); +} /* * 2PC state file format: @@ -1881,13 +1919,15 @@ restoreTwoPhaseData(void) cldir = AllocateDir(TWOPHASE_DIR); while ((clde = ReadDir(cldir, TWOPHASE_DIR)) != NULL) { - if (strlen(clde->d_name) == 8 && - strspn(clde->d_name, "0123456789ABCDEF") == 8) + if (strlen(clde->d_name) == 16 && + strspn(clde->d_name, "0123456789ABCDEF") == 16) { TransactionId xid; + FullTransactionId fxid; char *buf; - xid = (TransactionId) strtoul(clde->d_name, NULL, 16); + fxid = FullTransactionIdFromU64(strtou64(clde->d_name, NULL, 16)); + xid = XidFromFullTransactionId(fxid); buf = ProcessTwoPhaseBuffer(xid, InvalidXLogRecPtr, true, false, false); -- 2.41.0