From 8af31945cdc9031a3212d87659b201b5c62ed61a Mon Sep 17 00:00:00 2001 From: Maxim Orlov Date: Fri, 27 Feb 2026 16:59:51 +0300 Subject: [PATCH 3/3] WIP - make clog 64 bit --- src/backend/access/rmgrdesc/clogdesc.c | 6 +- src/backend/access/transam/clog.c | 204 ++++++++++---------- src/backend/access/transam/transam.c | 26 ++- src/backend/access/transam/twophase.c | 8 +- src/backend/access/transam/varsup.c | 10 +- src/backend/commands/indexcmds.c | 2 +- src/backend/commands/vacuum.c | 12 +- src/backend/storage/ipc/procarray.c | 58 +++--- src/backend/storage/lmgr/lock.c | 4 +- src/backend/storage/lmgr/proc.c | 8 +- src/bin/pg_verifybackup/t/003_corruption.pl | 2 +- src/include/access/clog.h | 15 +- src/include/access/transam.h | 1 + src/include/storage/proc.h | 6 +- src/test/recovery/t/003_recovery_targets.pl | 12 ++ 15 files changed, 210 insertions(+), 164 deletions(-) diff --git a/src/backend/access/rmgrdesc/clogdesc.c b/src/backend/access/rmgrdesc/clogdesc.c index 022376045d..138bc2fce1 100644 --- a/src/backend/access/rmgrdesc/clogdesc.c +++ b/src/backend/access/rmgrdesc/clogdesc.c @@ -35,8 +35,10 @@ clog_desc(StringInfo buf, XLogReaderState *record) xl_clog_truncate xlrec; memcpy(&xlrec, rec, sizeof(xl_clog_truncate)); - appendStringInfo(buf, "page %" PRId64 "; oldestXact %u", - xlrec.pageno, xlrec.oldestXact); + appendStringInfo(buf, "page %" PRId64 "; oldestXact %u%u", + xlrec.pageno, + EpochFromFullTransactionId(xlrec.oldestXact), + XidFromFullTransactionId(xlrec.oldestXact)); } } diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 3de650a18d..660dbe6e11 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -79,27 +79,27 @@ * 0xFFFFFFFF/CLOG_XACTS_PER_PAGE. */ static inline int64 -TransactionIdToPage(TransactionId xid) +FullTransactionIdToPage(FullTransactionId fxid) { - return xid / (int64) CLOG_XACTS_PER_PAGE; + return U64FromFullTransactionId(fxid) / (int64) CLOG_XACTS_PER_PAGE; } static inline int -TransactionIdToPgIndex(TransactionId xid) +FullTransactionIdToPgIndex(FullTransactionId fxid) { - return xid % (TransactionId) CLOG_XACTS_PER_PAGE; + return U64FromFullTransactionId(fxid) % (uint64) CLOG_XACTS_PER_PAGE; } static inline int -TransactionIdToByte(TransactionId xid) +FullTransactionIdToByte(FullTransactionId fxid) { - return TransactionIdToPgIndex(xid) / CLOG_XACTS_PER_BYTE; + return FullTransactionIdToPgIndex(fxid) / CLOG_XACTS_PER_BYTE; } static inline int -TransactionIdToBIndex(TransactionId xid) +FullTransactionIdToBIndex(FullTransactionId fxid) { - return xid % (TransactionId) CLOG_XACTS_PER_BYTE; + return U64FromFullTransactionId(fxid) % (uint64) CLOG_XACTS_PER_BYTE; } /* We store the latest async LSN for each group of transactions */ @@ -107,10 +107,17 @@ TransactionIdToBIndex(TransactionId xid) #define CLOG_LSNS_PER_PAGE (CLOG_XACTS_PER_PAGE / CLOG_XACTS_PER_LSN_GROUP) static inline int -GetLSNIndex(int slotno, TransactionId xid) +GetLSNIndex(int slotno, FullTransactionId fxid) { return slotno * CLOG_LSNS_PER_PAGE + - TransactionIdToPgIndex(xid) / CLOG_XACTS_PER_LSN_GROUP; + FullTransactionIdToPgIndex(fxid) / CLOG_XACTS_PER_LSN_GROUP; +} + +static inline FullTransactionId +AdjustToFullTransactionId(TransactionId xid) +{ + Assert(TransactionIdIsValid(xid)); + return FullTransactionIdFromAllowableAt(ReadNextFullTransactionId(), xid); } /* @@ -129,20 +136,22 @@ static SlruCtlData XactCtlData; static bool CLOGPagePrecedes(int64 page1, int64 page2); -static void WriteTruncateXlogRec(int64 pageno, TransactionId oldestXact, +static void WriteTruncateXlogRec(int64 pageno, FullTransactionId oldestXact, Oid oldestXactDb); -static void TransactionIdSetPageStatus(TransactionId xid, int nsubxids, +static void TransactionIdSetPageStatus(FullTransactionId fxid, int nsubxids, TransactionId *subxids, XidStatus status, XLogRecPtr lsn, int64 pageno, bool all_xact_same_page); -static void TransactionIdSetStatusBit(TransactionId xid, XidStatus status, +static void TransactionIdSetStatusBit(FullTransactionId fxid, XidStatus status, XLogRecPtr lsn, int slotno); static void set_status_by_pages(int nsubxids, TransactionId *subxids, XidStatus status, XLogRecPtr lsn); -static bool TransactionGroupUpdateXidStatus(TransactionId xid, +static bool TransactionGroupUpdateXidStatus(FullTransactionId fxid, XidStatus status, XLogRecPtr lsn, int64 pageno); -static void TransactionIdSetPageStatusInternal(TransactionId xid, int nsubxids, - TransactionId *subxids, XidStatus status, +static void TransactionIdSetPageStatusInternal(FullTransactionId fxid, + int nsubxids, + TransactionId *subxids, + XidStatus status, XLogRecPtr lsn, int64 pageno); @@ -196,11 +205,12 @@ static void TransactionIdSetPageStatusInternal(TransactionId xid, int nsubxids, * cache yet. */ void -TransactionIdSetTreeStatus(TransactionId xid, int nsubxids, +TransactionIdSetTreeStatus(FullTransactionId fxid, int nsubxids, TransactionId *subxids, XidStatus status, XLogRecPtr lsn) { - int64 pageno = TransactionIdToPage(xid); /* get page of parent */ + int64 pageno = FullTransactionIdToPage(fxid); /* get page of parent */ int i; + FullTransactionId next; Assert(status == TRANSACTION_STATUS_COMMITTED || status == TRANSACTION_STATUS_ABORTED); @@ -209,9 +219,14 @@ TransactionIdSetTreeStatus(TransactionId xid, int nsubxids, * See how many subxids, if any, are on the same page as the parent, if * any. */ + next = ReadNextFullTransactionId(); for (i = 0; i < nsubxids; i++) { - if (TransactionIdToPage(subxids[i]) != pageno) + FullTransactionId subfxid = FullTransactionIdFromAllowableAt(next, + subxids[i]); + int64 subxid_pageno = FullTransactionIdToPage(subfxid); + + if (subxid_pageno != pageno) break; } @@ -223,7 +238,7 @@ TransactionIdSetTreeStatus(TransactionId xid, int nsubxids, /* * Set the parent and all subtransactions in a single call */ - TransactionIdSetPageStatus(xid, nsubxids, subxids, status, lsn, + TransactionIdSetPageStatus(fxid, nsubxids, subxids, status, lsn, pageno, true); } else @@ -249,9 +264,9 @@ TransactionIdSetTreeStatus(TransactionId xid, int nsubxids, * Now set the parent and subtransactions on same page as the parent, * if any */ - pageno = TransactionIdToPage(xid); - TransactionIdSetPageStatus(xid, nsubxids_on_first_page, subxids, status, - lsn, pageno, false); + pageno = FullTransactionIdToPage(fxid); + TransactionIdSetPageStatus(fxid, nsubxids_on_first_page, subxids, + status, lsn, pageno, false); /* * Now work through the rest of the subxids one clog page at a time, @@ -273,7 +288,8 @@ static void set_status_by_pages(int nsubxids, TransactionId *subxids, XidStatus status, XLogRecPtr lsn) { - int64 pageno = TransactionIdToPage(subxids[0]); + FullTransactionId fxid = AdjustToFullTransactionId(subxids[0]); + int64 pageno = FullTransactionIdToPage(fxid); int offset = 0; int i = 0; @@ -286,14 +302,15 @@ set_status_by_pages(int nsubxids, TransactionId *subxids, do { - nextpageno = TransactionIdToPage(subxids[i]); + fxid = AdjustToFullTransactionId(subxids[i]); + nextpageno = FullTransactionIdToPage(fxid); if (nextpageno != pageno) break; num_on_page++; i++; } while (i < nsubxids); - TransactionIdSetPageStatus(InvalidTransactionId, + TransactionIdSetPageStatus(InvalidFullTransactionId, num_on_page, subxids + offset, status, lsn, pageno, false); offset = i; @@ -306,7 +323,7 @@ set_status_by_pages(int nsubxids, TransactionId *subxids, * entries on a single page. Atomic only on this page. */ static void -TransactionIdSetPageStatus(TransactionId xid, int nsubxids, +TransactionIdSetPageStatus(FullTransactionId fxid, int nsubxids, TransactionId *subxids, XidStatus status, XLogRecPtr lsn, int64 pageno, bool all_xact_same_page) @@ -334,7 +351,7 @@ TransactionIdSetPageStatus(TransactionId xid, int nsubxids, * sub-XIDs and all of the XIDs for which we're adjusting clog should be * on the same page. Check those conditions, too. */ - if (all_xact_same_page && xid == MyProc->xid && + if (all_xact_same_page && FullTransactionIdEquals(fxid, MyProc->xid) && nsubxids <= THRESHOLD_SUBTRANS_CLOG_OPT && nsubxids == MyProc->subxidStatus.count && (nsubxids == 0 || @@ -350,12 +367,12 @@ TransactionIdSetPageStatus(TransactionId xid, int nsubxids, if (LWLockConditionalAcquire(lock, LW_EXCLUSIVE)) { /* Got the lock without waiting! Do the update. */ - TransactionIdSetPageStatusInternal(xid, nsubxids, subxids, status, + TransactionIdSetPageStatusInternal(fxid, nsubxids, subxids, status, lsn, pageno); LWLockRelease(lock); return; } - else if (TransactionGroupUpdateXidStatus(xid, status, lsn, pageno)) + else if (TransactionGroupUpdateXidStatus(fxid, status, lsn, pageno)) { /* Group update mechanism has done the work. */ return; @@ -366,7 +383,7 @@ TransactionIdSetPageStatus(TransactionId xid, int nsubxids, /* Group update not applicable, or couldn't accept this page number. */ LWLockAcquire(lock, LW_EXCLUSIVE); - TransactionIdSetPageStatusInternal(xid, nsubxids, subxids, status, + TransactionIdSetPageStatusInternal(fxid, nsubxids, subxids, status, lsn, pageno); LWLockRelease(lock); } @@ -377,7 +394,7 @@ TransactionIdSetPageStatus(TransactionId xid, int nsubxids, * We don't do any locking here; caller must handle that. */ static void -TransactionIdSetPageStatusInternal(TransactionId xid, int nsubxids, +TransactionIdSetPageStatusInternal(FullTransactionId fxid, int nsubxids, TransactionId *subxids, XidStatus status, XLogRecPtr lsn, int64 pageno) { @@ -386,7 +403,8 @@ TransactionIdSetPageStatusInternal(TransactionId xid, int nsubxids, Assert(status == TRANSACTION_STATUS_COMMITTED || status == TRANSACTION_STATUS_ABORTED || - (status == TRANSACTION_STATUS_SUB_COMMITTED && !TransactionIdIsValid(xid))); + (status == TRANSACTION_STATUS_SUB_COMMITTED && + !FullTransactionIdIsValid(fxid))); Assert(LWLockHeldByMeInMode(SimpleLruGetBankLock(XactCtl, pageno), LW_EXCLUSIVE)); @@ -400,7 +418,7 @@ TransactionIdSetPageStatusInternal(TransactionId xid, int nsubxids, * we think. */ slotno = SimpleLruReadPage(XactCtl, pageno, !XLogRecPtrIsValid(lsn), - xid); + XidFromFullTransactionId(fxid)); /* * Set the main transaction id, if any. @@ -411,29 +429,40 @@ TransactionIdSetPageStatusInternal(TransactionId xid, int nsubxids, * could break atomicity, so we subcommit the subxids first before we mark * the top-level commit. */ - if (TransactionIdIsValid(xid)) + if (FullTransactionIdIsValid(fxid)) { /* Subtransactions first, if needed ... */ if (status == TRANSACTION_STATUS_COMMITTED) { + FullTransactionId next = ReadNextFullTransactionId(); + for (i = 0; i < nsubxids; i++) { - Assert(XactCtl->shared->page_number[slotno] == TransactionIdToPage(subxids[i])); - TransactionIdSetStatusBit(subxids[i], + FullTransactionId subxid = + FullTransactionIdFromAllowableAt(next, subxids[i]); + int64 subxid_pageno PG_USED_FOR_ASSERTS_ONLY = + FullTransactionIdToPage(subxid); + + Assert(XactCtl->shared->page_number[slotno] == subxid_pageno); + TransactionIdSetStatusBit(subxid, TRANSACTION_STATUS_SUB_COMMITTED, lsn, slotno); } } /* ... then the main transaction */ - TransactionIdSetStatusBit(xid, status, lsn, slotno); + TransactionIdSetStatusBit(fxid, status, lsn, slotno); } /* Set the subtransactions */ for (i = 0; i < nsubxids; i++) { - Assert(XactCtl->shared->page_number[slotno] == TransactionIdToPage(subxids[i])); - TransactionIdSetStatusBit(subxids[i], status, lsn, slotno); + FullTransactionId subfxid = AdjustToFullTransactionId(subxids[i]); + int64 subxid_pageno PG_USED_FOR_ASSERTS_ONLY; + + subxid_pageno = FullTransactionIdToPage(subfxid); + Assert(XactCtl->shared->page_number[slotno] == subxid_pageno); + TransactionIdSetStatusBit(subfxid, status, lsn, slotno); } XactCtl->shared->page_dirty[slotno] = true; @@ -455,7 +484,7 @@ TransactionIdSetPageStatusInternal(TransactionId xid, int nsubxids, * number we need to update differs from those processes already waiting. */ static bool -TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, +TransactionGroupUpdateXidStatus(FullTransactionId fxid, XidStatus status, XLogRecPtr lsn, int64 pageno) { volatile PROC_HDR *procglobal = ProcGlobal; @@ -466,14 +495,14 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, LWLock *prevlock = NULL; /* We should definitely have an XID whose status needs to be updated. */ - Assert(TransactionIdIsValid(xid)); + Assert(FullTransactionIdIsValid(fxid)); /* * Prepare to add ourselves to the list of processes needing a group XID * status update. */ proc->clogGroupMember = true; - proc->clogGroupMemberXid = xid; + proc->clogGroupMemberXid = fxid; proc->clogGroupMemberXidStatus = status; proc->clogGroupMemberPage = pageno; proc->clogGroupMemberLsn = lsn; @@ -675,15 +704,16 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * Caller must hold the corresponding SLRU bank lock, will be held at exit. */ static void -TransactionIdSetStatusBit(TransactionId xid, XidStatus status, XLogRecPtr lsn, int slotno) +TransactionIdSetStatusBit(FullTransactionId fxid, XidStatus status, + XLogRecPtr lsn, int slotno) { - int byteno = TransactionIdToByte(xid); - int bshift = TransactionIdToBIndex(xid) * CLOG_BITS_PER_XACT; + int byteno = FullTransactionIdToByte(fxid); + int bshift = FullTransactionIdToBIndex(fxid) * CLOG_BITS_PER_XACT; char *byteptr; char byteval; char curval; - Assert(XactCtl->shared->page_number[slotno] == TransactionIdToPage(xid)); + Assert(XactCtl->shared->page_number[slotno] == FullTransactionIdToPage(fxid)); Assert(LWLockHeldByMeInMode(SimpleLruGetBankLock(XactCtl, XactCtl->shared->page_number[slotno]), LW_EXCLUSIVE)); @@ -726,7 +756,7 @@ TransactionIdSetStatusBit(TransactionId xid, XidStatus status, XLogRecPtr lsn, i */ if (XLogRecPtrIsValid(lsn)) { - int lsnindex = GetLSNIndex(slotno, xid); + int lsnindex = GetLSNIndex(slotno, fxid); if (XactCtl->shared->group_lsn[lsnindex] < lsn) XactCtl->shared->group_lsn[lsnindex] = lsn; @@ -749,11 +779,11 @@ TransactionIdSetStatusBit(TransactionId xid, XidStatus status, XLogRecPtr lsn, i * for most uses; TransactionLogFetch() in transam.c is the intended caller. */ XidStatus -TransactionIdGetStatus(TransactionId xid, XLogRecPtr *lsn) +TransactionIdGetStatus(FullTransactionId fxid, XLogRecPtr *lsn) { - int64 pageno = TransactionIdToPage(xid); - int byteno = TransactionIdToByte(xid); - int bshift = TransactionIdToBIndex(xid) * CLOG_BITS_PER_XACT; + int64 pageno = FullTransactionIdToPage(fxid); + int byteno = FullTransactionIdToByte(fxid); + int bshift = FullTransactionIdToBIndex(fxid) * CLOG_BITS_PER_XACT; int slotno; int lsnindex; char *byteptr; @@ -761,12 +791,13 @@ TransactionIdGetStatus(TransactionId xid, XLogRecPtr *lsn) /* lock is acquired by SimpleLruReadPage_ReadOnly */ - slotno = SimpleLruReadPage_ReadOnly(XactCtl, pageno, xid); + slotno = SimpleLruReadPage_ReadOnly(XactCtl, pageno, + XidFromFullTransactionId(fxid)); byteptr = XactCtl->shared->page_buffer[slotno] + byteno; status = (*byteptr >> bshift) & CLOG_XACT_BITMASK; - lsnindex = GetLSNIndex(slotno, xid); + lsnindex = GetLSNIndex(slotno, fxid); *lsn = XactCtl->shared->group_lsn[lsnindex]; LWLockRelease(SimpleLruGetBankLock(XactCtl, pageno)); @@ -827,8 +858,8 @@ CLOGShmemInit(void) XactCtl->PagePrecedes = CLOGPagePrecedes; SimpleLruInit(XactCtl, "transaction", CLOGShmemBuffers(), CLOG_LSNS_PER_PAGE, "pg_xact", LWTRANCHE_XACT_BUFFER, - LWTRANCHE_XACT_SLRU, SYNC_HANDLER_CLOG, false); - SlruPagePrecedesUnitTests(XactCtl, CLOG_XACTS_PER_PAGE); + LWTRANCHE_XACT_SLRU, SYNC_HANDLER_CLOG, true); + /* doesn't meet criteria for unit tests */ } /* @@ -860,8 +891,7 @@ BootStrapCLOG(void) void StartupCLOG(void) { - TransactionId xid = XidFromFullTransactionId(TransamVariables->nextXid); - int64 pageno = TransactionIdToPage(xid); + int64 pageno = FullTransactionIdToPage(TransamVariables->nextXid); /* * Initialize our idea of the latest page number. @@ -875,8 +905,9 @@ StartupCLOG(void) void TrimCLOG(void) { - TransactionId xid = XidFromFullTransactionId(TransamVariables->nextXid); - int64 pageno = TransactionIdToPage(xid); + FullTransactionId fxid = TransamVariables->nextXid; + TransactionId xid = XidFromFullTransactionId(fxid); + int64 pageno = FullTransactionIdToPage(fxid); LWLock *lock = SimpleLruGetBankLock(XactCtl, pageno); LWLockAcquire(lock, LW_EXCLUSIVE); @@ -893,10 +924,10 @@ TrimCLOG(void) * nextXid is exactly at a page boundary; and it's likely that the * "current" page doesn't exist yet in that case.) */ - if (TransactionIdToPgIndex(xid) != 0) + if (FullTransactionIdToPgIndex(fxid) != 0) { - int byteno = TransactionIdToByte(xid); - int bshift = TransactionIdToBIndex(xid) * CLOG_BITS_PER_XACT; + int byteno = FullTransactionIdToByte(fxid); + int bshift = FullTransactionIdToBIndex(fxid) * CLOG_BITS_PER_XACT; int slotno; char *byteptr; @@ -940,7 +971,7 @@ CheckPointCLOG(void) * in shared memory. */ void -ExtendCLOG(TransactionId newestXact) +ExtendCLOG(FullTransactionId newestXact) { int64 pageno; LWLock *lock; @@ -949,11 +980,11 @@ ExtendCLOG(TransactionId newestXact) * No work except at first XID of a page. But beware: just after * wraparound, the first XID of page zero is FirstNormalTransactionId. */ - if (TransactionIdToPgIndex(newestXact) != 0 && - !TransactionIdEquals(newestXact, FirstNormalTransactionId)) + if (FullTransactionIdToPgIndex(newestXact) != 0 && + !FullTransactionIdEquals(newestXact, FirstNormalFullTransactionId)) return; - pageno = TransactionIdToPage(newestXact); + pageno = FullTransactionIdToPage(newestXact); lock = SimpleLruGetBankLock(XactCtl, pageno); LWLockAcquire(lock, LW_EXCLUSIVE); @@ -982,15 +1013,13 @@ ExtendCLOG(TransactionId newestXact) * the XLOG flush unless we have confirmed that there is a removable segment. */ void -TruncateCLOG(TransactionId oldestXact, Oid oldestxid_datoid) +TruncateCLOG(FullTransactionId oldestXact, Oid oldestxid_datoid) { - int64 cutoffPage; - /* * The cutoff point is the start of the segment containing oldestXact. We * pass the *page* containing oldestXact to SimpleLruTruncate. */ - cutoffPage = TransactionIdToPage(oldestXact); + int64 cutoffPage = FullTransactionIdToPage(oldestXact); /* Check to see if there's any files that could be removed */ if (!SlruScanDirectory(XactCtl, SlruScanDirCbReportPresence, &cutoffPage)) @@ -1003,7 +1032,7 @@ TruncateCLOG(TransactionId oldestXact, Oid oldestxid_datoid) * It's only necessary to do this if we will actually truncate away clog * pages. */ - AdvanceOldestClogXid(oldestXact); + AdvanceOldestClogXid(XidFromFullTransactionId(oldestXact)); /* * Write XLOG record and flush XLOG to disk. We record the oldest xid @@ -1020,35 +1049,11 @@ TruncateCLOG(TransactionId oldestXact, Oid oldestxid_datoid) /* * Decide whether a CLOG page number is "older" for truncation purposes. - * - * We need to use comparison of TransactionIds here in order to do the right - * thing with wraparound XID arithmetic. However, TransactionIdPrecedes() - * would get weird about permanent xact IDs. So, offset both such that xid1, - * xid2, and xid2 + CLOG_XACTS_PER_PAGE - 1 are all normal XIDs; this offset - * is relevant to page 0 and to the page preceding page 0. - * - * The page containing oldestXact-2^31 is the important edge case. The - * portion of that page equaling or following oldestXact-2^31 is expendable, - * but the portion preceding oldestXact-2^31 is not. When oldestXact-2^31 is - * the first XID of a page and segment, the entire page and segment is - * expendable, and we could truncate the segment. Recognizing that case would - * require making oldestXact, not just the page containing oldestXact, - * available to this callback. The benefit would be rare and small, so we - * don't optimize that edge case. */ static bool CLOGPagePrecedes(int64 page1, int64 page2) { - TransactionId xid1; - TransactionId xid2; - - xid1 = ((TransactionId) page1) * CLOG_XACTS_PER_PAGE; - xid1 += FirstNormalTransactionId + 1; - xid2 = ((TransactionId) page2) * CLOG_XACTS_PER_PAGE; - xid2 += FirstNormalTransactionId + 1; - - return (TransactionIdPrecedes(xid1, xid2) && - TransactionIdPrecedes(xid1, xid2 + CLOG_XACTS_PER_PAGE - 1)); + return page1 < page2; } @@ -1059,7 +1064,8 @@ CLOGPagePrecedes(int64 page1, int64 page2) * in TruncateCLOG(). */ static void -WriteTruncateXlogRec(int64 pageno, TransactionId oldestXact, Oid oldestXactDb) +WriteTruncateXlogRec(int64 pageno, FullTransactionId oldestXact, + Oid oldestXactDb) { XLogRecPtr recptr; xl_clog_truncate xlrec; @@ -1098,7 +1104,7 @@ clog_redo(XLogReaderState *record) memcpy(&xlrec, XLogRecGetData(record), sizeof(xl_clog_truncate)); - AdvanceOldestClogXid(xlrec.oldestXact); + AdvanceOldestClogXid(XidFromFullTransactionId(xlrec.oldestXact)); SimpleLruTruncate(XactCtl, xlrec.pageno); } diff --git a/src/backend/access/transam/transam.c b/src/backend/access/transam/transam.c index 682182fb4a..065807697e 100644 --- a/src/backend/access/transam/transam.c +++ b/src/backend/access/transam/transam.c @@ -53,6 +53,7 @@ TransactionLogFetch(TransactionId transactionId) { XidStatus xidstatus; XLogRecPtr xidlsn; + FullTransactionId fxid; /* * Before going to the commit log manager, check our single item cache to @@ -73,10 +74,13 @@ TransactionLogFetch(TransactionId transactionId) return TRANSACTION_STATUS_ABORTED; } + fxid = FullTransactionIdFromAllowableAt(ReadNextFullTransactionId(), + transactionId); + /* * Get the transaction status. */ - xidstatus = TransactionIdGetStatus(transactionId, &xidlsn); + xidstatus = TransactionIdGetStatus(fxid, &xidlsn); /* * Cache it, but DO NOT cache status for unfinished or sub-committed @@ -239,7 +243,10 @@ TransactionIdDidAbort(TransactionId transactionId) void TransactionIdCommitTree(TransactionId xid, int nxids, TransactionId *xids) { - TransactionIdSetTreeStatus(xid, nxids, xids, + FullTransactionId fxid = + FullTransactionIdFromAllowableAt(ReadNextFullTransactionId(), xid); + + TransactionIdSetTreeStatus(fxid, nxids, xids, TRANSACTION_STATUS_COMMITTED, InvalidXLogRecPtr); } @@ -252,7 +259,10 @@ void TransactionIdAsyncCommitTree(TransactionId xid, int nxids, TransactionId *xids, XLogRecPtr lsn) { - TransactionIdSetTreeStatus(xid, nxids, xids, + FullTransactionId fxid = + FullTransactionIdFromAllowableAt(ReadNextFullTransactionId(), xid); + + TransactionIdSetTreeStatus(fxid, nxids, xids, TRANSACTION_STATUS_COMMITTED, lsn); } @@ -269,7 +279,10 @@ TransactionIdAsyncCommitTree(TransactionId xid, int nxids, TransactionId *xids, void TransactionIdAbortTree(TransactionId xid, int nxids, TransactionId *xids) { - TransactionIdSetTreeStatus(xid, nxids, xids, + FullTransactionId fxid = + FullTransactionIdFromAllowableAt(ReadNextFullTransactionId(), xid); + + TransactionIdSetTreeStatus(fxid, nxids, xids, TRANSACTION_STATUS_ABORTED, InvalidXLogRecPtr); } @@ -318,6 +331,7 @@ XLogRecPtr TransactionIdGetCommitLSN(TransactionId xid) { XLogRecPtr result; + FullTransactionId fxid; /* * Currently, all uses of this function are for xids that were just @@ -332,10 +346,12 @@ TransactionIdGetCommitLSN(TransactionId xid) if (!TransactionIdIsNormal(xid)) return InvalidXLogRecPtr; + fxid = FullTransactionIdFromAllowableAt(ReadNextFullTransactionId(), xid); + /* * Get the transaction status. */ - (void) TransactionIdGetStatus(xid, &result); + (void) TransactionIdGetStatus(fxid, &result); return result; } diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c index e4340b5964..3622eed3b5 100644 --- a/src/backend/access/transam/twophase.c +++ b/src/backend/access/transam/twophase.c @@ -438,7 +438,6 @@ MarkAsPreparingGuts(GlobalTransaction gxact, FullTransactionId fxid, { PGPROC *proc; int i; - TransactionId xid = XidFromFullTransactionId(fxid); Assert(LWLockHeldByMeInMode(TwoPhaseStateLock, LW_EXCLUSIVE)); @@ -458,10 +457,10 @@ MarkAsPreparingGuts(GlobalTransaction gxact, FullTransactionId fxid, { Assert(AmStartupProcess() || !IsPostmasterEnvironment); /* GetLockConflicts() uses this to specify a wait on the XID */ - proc->vxid.lxid = xid; + proc->vxid.lxid = XidFromFullTransactionId(fxid); proc->vxid.procNumber = INVALID_PROC_NUMBER; } - proc->xid = xid; + proc->xid = fxid; Assert(proc->xmin == InvalidTransactionId); proc->delayChkptFlags = 0; proc->statusFlags = 0; @@ -778,7 +777,8 @@ pg_prepared_xact(PG_FUNCTION_ARGS) * Form tuple with appropriate data. */ - values[0] = TransactionIdGetDatum(proc->xid); + values[0] = TransactionIdGetDatum(XidFromFullTransactionId(proc->xid)); + /* XXX: cosider adding epoch */ values[1] = CStringGetTextDatum(gxact->gid); values[2] = TimestampTzGetDatum(gxact->prepared_at); values[3] = ObjectIdGetDatum(gxact->owner); diff --git a/src/backend/access/transam/varsup.c b/src/backend/access/transam/varsup.c index 3e08c308d0..be57f2b9e0 100644 --- a/src/backend/access/transam/varsup.c +++ b/src/backend/access/transam/varsup.c @@ -93,8 +93,8 @@ GetNewTransactionId(bool isSubXact) if (IsBootstrapProcessingMode()) { Assert(!isSubXact); - MyProc->xid = BootstrapTransactionId; - ProcGlobal->xids[MyProc->pgxactoff] = BootstrapTransactionId; + MyProc->xid = BootstrapFullTransactionId; + ProcGlobal->xids[MyProc->pgxactoff] = BootstrapFullTransactionId; return FullTransactionIdFromEpochAndXid(0, BootstrapTransactionId); } @@ -201,7 +201,7 @@ GetNewTransactionId(bool isSubXact) * * Extend pg_subtrans and pg_commit_ts too. */ - ExtendCLOG(xid); + ExtendCLOG(full_xid); ExtendCommitTs(xid); ExtendSUBTRANS(xid); @@ -255,8 +255,8 @@ GetNewTransactionId(bool isSubXact) Assert(!MyProc->subxidStatus.overflowed); /* LWLockRelease acts as barrier */ - MyProc->xid = xid; - ProcGlobal->xids[MyProc->pgxactoff] = xid; + MyProc->xid = full_xid; + ProcGlobal->xids[MyProc->pgxactoff] = full_xid; } else { diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c index 635679cc1f..169db61aa9 100644 --- a/src/backend/commands/indexcmds.c +++ b/src/backend/commands/indexcmds.c @@ -4643,7 +4643,7 @@ set_indexsafe_procflags(void) * This should only be called before installing xid or xmin in MyProc; * otherwise, concurrent processes could see an Xmin that moves backwards. */ - Assert(MyProc->xid == InvalidTransactionId && + Assert(FullTransactionIdEquals(MyProc->xid, InvalidFullTransactionId) && MyProc->xmin == InvalidTransactionId); LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE); diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c index 03932f45c8..8a837b6cbf 100644 --- a/src/backend/commands/vacuum.c +++ b/src/backend/commands/vacuum.c @@ -1962,9 +1962,15 @@ vac_truncate_clog(TransactionId frozenXID, /* * Truncate CLOG, multixact and CommitTs to the oldest computed value. */ - TruncateCLOG(frozenXID, oldestxid_datoid); - TruncateCommitTs(frozenXID); - TruncateMultiXact(minMulti, minmulti_datoid); + { + FullTransactionId frozen_fxid = + FullTransactionIdFromAllowableAt(ReadNextFullTransactionId(), + frozenXID); + + TruncateCLOG(frozen_fxid, oldestxid_datoid); + TruncateCommitTs(frozenXID); + TruncateMultiXact(minMulti, minmulti_datoid); + } /* * Update the wrap limit for GetNewTransactionId and creation of new diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c index 40312df2ca..9281be81cd 100644 --- a/src/backend/storage/ipc/procarray.c +++ b/src/backend/storage/ipc/procarray.c @@ -588,7 +588,7 @@ ProcArrayRemove(PGPROC *proc, TransactionId latestXid) if (TransactionIdIsValid(latestXid)) { - Assert(TransactionIdIsValid(ProcGlobal->xids[myoff])); + Assert(FullTransactionIdIsValid(ProcGlobal->xids[myoff])); /* Advance global latestCompletedXid while holding the lock */ MaintainLatestCompletedXid(latestXid); @@ -596,17 +596,17 @@ ProcArrayRemove(PGPROC *proc, TransactionId latestXid) /* Same with xactCompletionCount */ TransamVariables->xactCompletionCount++; - ProcGlobal->xids[myoff] = InvalidTransactionId; + ProcGlobal->xids[myoff] = InvalidFullTransactionId; ProcGlobal->subxidStates[myoff].overflowed = false; ProcGlobal->subxidStates[myoff].count = 0; } else { /* Shouldn't be trying to remove a live transaction here */ - Assert(!TransactionIdIsValid(ProcGlobal->xids[myoff])); + Assert(!FullTransactionIdIsValid(ProcGlobal->xids[myoff])); } - Assert(!TransactionIdIsValid(ProcGlobal->xids[myoff])); + Assert(!FullTransactionIdIsValid(ProcGlobal->xids[myoff])); Assert(ProcGlobal->subxidStates[myoff].count == 0); Assert(ProcGlobal->subxidStates[myoff].overflowed == false); @@ -677,7 +677,7 @@ ProcArrayEndTransaction(PGPROC *proc, TransactionId latestXid) * else is taking a snapshot. See discussion in * src/backend/access/transam/README. */ - Assert(TransactionIdIsValid(proc->xid)); + Assert(FullTransactionIdIsValid(proc->xid)); /* * If we can immediately acquire ProcArrayLock, we clear our own XID @@ -699,7 +699,7 @@ ProcArrayEndTransaction(PGPROC *proc, TransactionId latestXid) * anyone else's calculation of a snapshot. We might change their * estimate of global xmin, but that's OK. */ - Assert(!TransactionIdIsValid(proc->xid)); + Assert(!FullTransactionIdIsValid(proc->xid)); Assert(proc->subxidStatus.count == 0); Assert(!proc->subxidStatus.overflowed); @@ -740,11 +740,11 @@ ProcArrayEndTransactionInternal(PGPROC *proc, TransactionId latestXid) * processes' PGPROC entries. */ Assert(LWLockHeldByMeInMode(ProcArrayLock, LW_EXCLUSIVE)); - Assert(TransactionIdIsValid(ProcGlobal->xids[pgxactoff])); - Assert(ProcGlobal->xids[pgxactoff] == proc->xid); + Assert(FullTransactionIdIsValid(ProcGlobal->xids[pgxactoff])); + Assert(FullTransactionIdEquals(ProcGlobal->xids[pgxactoff], proc->xid)); - ProcGlobal->xids[pgxactoff] = InvalidTransactionId; - proc->xid = InvalidTransactionId; + ProcGlobal->xids[pgxactoff] = InvalidFullTransactionId; + proc->xid = InvalidFullTransactionId; proc->vxid.lxid = InvalidLocalTransactionId; proc->xmin = InvalidTransactionId; @@ -800,7 +800,7 @@ ProcArrayGroupClearXid(PGPROC *proc, TransactionId latestXid) uint32 wakeidx; /* We should definitely have an XID to clear. */ - Assert(TransactionIdIsValid(proc->xid)); + Assert(FullTransactionIdIsValid(proc->xid)); /* Add ourselves to the list of processes needing a group XID clear. */ proc->procArrayGroupMember = true; @@ -929,8 +929,8 @@ ProcArrayClearTransaction(PGPROC *proc) pgxactoff = proc->pgxactoff; - ProcGlobal->xids[pgxactoff] = InvalidTransactionId; - proc->xid = InvalidTransactionId; + ProcGlobal->xids[pgxactoff] = InvalidFullTransactionId; + proc->xid = InvalidFullTransactionId; proc->vxid.lxid = InvalidLocalTransactionId; proc->xmin = InvalidTransactionId; @@ -1405,7 +1405,7 @@ bool TransactionIdIsInProgress(TransactionId xid) { static TransactionId *xids = NULL; - static TransactionId *other_xids; + static FullTransactionId *other_xids; XidCacheStatus *other_subxidstates; int nxids = 0; ProcArrayStruct *arrayP = procArray; @@ -1688,7 +1688,7 @@ ComputeXidHorizons(ComputeXidHorizonsResult *h) ProcArrayStruct *arrayP = procArray; TransactionId kaxmin; bool in_recovery = RecoveryInProgress(); - TransactionId *other_xids = ProcGlobal->xids; + FullTransactionId *other_xids = ProcGlobal->xids; /* inferred after ProcArrayLock is released */ h->catalog_oldest_nonremovable = InvalidTransactionId; @@ -1726,8 +1726,8 @@ ComputeXidHorizons(ComputeXidHorizonsResult *h) * definition, can't be any newer changes in the temp table than * latestCompletedXid. */ - if (TransactionIdIsValid(MyProc->xid)) - h->temp_oldest_nonremovable = MyProc->xid; + if (FullTransactionIdIsValid(MyProc->xid)) + h->temp_oldest_nonremovable = XidFromFullTransactionId(MyProc->xid); else h->temp_oldest_nonremovable = initial; } @@ -1749,7 +1749,7 @@ ComputeXidHorizons(ComputeXidHorizonsResult *h) TransactionId xmin; /* Fetch xid just once - see GetNewTransactionId */ - xid = UINT32_ACCESS_ONCE(other_xids[index]); + xid = XidFromFullTransactionId(other_xids[index]); xmin = UINT32_ACCESS_ONCE(proc->xmin); /* @@ -2126,7 +2126,7 @@ Snapshot GetSnapshotData(Snapshot snapshot) { ProcArrayStruct *arrayP = procArray; - TransactionId *other_xids = ProcGlobal->xids; + FullTransactionId *other_xids = ProcGlobal->xids; TransactionId xmin; TransactionId xmax; int count = 0; @@ -2189,8 +2189,8 @@ GetSnapshotData(Snapshot snapshot) latest_completed = TransamVariables->latestCompletedXid; mypgxactoff = MyProc->pgxactoff; - myxid = other_xids[mypgxactoff]; - Assert(myxid == MyProc->xid); + myxid = XidFromFullTransactionId(other_xids[mypgxactoff]); + Assert(myxid == XidFromFullTransactionId(MyProc->xid)); oldestxid = TransamVariables->oldestXid; curXactCompletionCount = TransamVariables->xactCompletionCount; @@ -2643,7 +2643,7 @@ GetRunningTransactionData(void) static RunningTransactionsData CurrentRunningXactsData; ProcArrayStruct *arrayP = procArray; - TransactionId *other_xids = ProcGlobal->xids; + FullTransactionId *other_xids = ProcGlobal->xids; RunningTransactions CurrentRunningXacts = &CurrentRunningXactsData; TransactionId latestCompletedXid; TransactionId oldestRunningXid; @@ -2836,7 +2836,7 @@ TransactionId GetOldestActiveTransactionId(bool inCommitOnly, bool allDbs) { ProcArrayStruct *arrayP = procArray; - TransactionId *other_xids = ProcGlobal->xids; + FullTransactionId *other_xids = ProcGlobal->xids; TransactionId oldestRunningXid; int index; @@ -2959,7 +2959,7 @@ GetOldestSafeDecodingTransactionId(bool catalogOnly) */ if (!recovery_in_progress) { - TransactionId *other_xids = ProcGlobal->xids; + FullTransactionId *other_xids = ProcGlobal->xids; /* * Spin over procArray collecting min(ProcGlobal->xids[i]) @@ -2969,7 +2969,7 @@ GetOldestSafeDecodingTransactionId(bool catalogOnly) TransactionId xid; /* Fetch xid just once - see GetNewTransactionId */ - xid = UINT32_ACCESS_ONCE(other_xids[index]); + xid = XidFromFullTransactionId(other_xids[index]); if (!TransactionIdIsNormal(xid)) continue; @@ -3140,7 +3140,7 @@ ProcNumberGetTransactionIds(ProcNumber procNumber, TransactionId *xid, if (proc->pid != 0) { - *xid = proc->xid; + *xid = XidFromFullTransactionId(proc->xid); *xmin = proc->xmin; *nsubxid = proc->subxidStatus.count; *overflowed = proc->subxidStatus.overflowed; @@ -3221,7 +3221,7 @@ BackendXidGetPid(TransactionId xid) { int result = 0; ProcArrayStruct *arrayP = procArray; - TransactionId *other_xids = ProcGlobal->xids; + FullTransactionId *other_xids = ProcGlobal->xids; int index; if (xid == InvalidTransactionId) /* never match invalid xid */ @@ -3231,7 +3231,7 @@ BackendXidGetPid(TransactionId xid) for (index = 0; index < arrayP->numProcs; index++) { - if (other_xids[index] == xid) + if (XidFromFullTransactionId(other_xids[index]) == xid) { int pgprocno = arrayP->pgprocnos[index]; PGPROC *proc = &allProcs[pgprocno]; @@ -3612,7 +3612,7 @@ MinimumActiveBackends(int min) continue; /* do not count deleted entries */ if (proc == MyProc) continue; /* do not count myself */ - if (proc->xid == InvalidTransactionId) + if (FullTransactionIdEquals(proc->xid, InvalidFullTransactionId)) continue; /* do not count if no XID assigned */ if (proc->pid == 0) continue; /* do not count prepared xacts */ diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index d930c66cdb..9f7b8526cd 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -4212,7 +4212,7 @@ GetRunningTransactionLocks(int *nlocks) { PGPROC *proc = proclock->tag.myProc; LOCK *lock = proclock->tag.myLock; - TransactionId xid = proc->xid; + TransactionId xid = XidFromFullTransactionId(proc->xid); /* * Don't record locks for transactions if we know they have @@ -4832,7 +4832,7 @@ VirtualXactLock(VirtualTransactionId vxid, bool wait) * so we won't save an XID of a different VXID. It doesn't matter whether * we save this before or after setting up the primary lock table entry. */ - xid = proc->xid; + xid = XidFromFullTransactionId(proc->xid); /* Done with proc->fpLockBits */ LWLockRelease(&proc->fpInfoLock); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index e2f34075d3..55e7130267 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -247,7 +247,7 @@ InitProcGlobal(void) * XXX: It might make sense to increase padding for these arrays, given * how hotly they are accessed. */ - ProcGlobal->xids = (TransactionId *) ptr; + ProcGlobal->xids = (FullTransactionId *) ptr; ptr = ptr + (TotalProcs * sizeof(*ProcGlobal->xids)); ProcGlobal->subxidStates = (XidCacheStatus *) ptr; @@ -461,7 +461,7 @@ InitProcess(void) MyProc->waitStatus = PROC_WAIT_STATUS_OK; MyProc->fpVXIDLock = false; MyProc->fpLocalTransactionId = InvalidLocalTransactionId; - MyProc->xid = InvalidTransactionId; + MyProc->xid = InvalidFullTransactionId; MyProc->xmin = InvalidTransactionId; MyProc->pid = MyProcPid; MyProc->vxid.procNumber = MyProcNumber; @@ -512,7 +512,7 @@ InitProcess(void) /* Initialize fields for group transaction status update. */ MyProc->clogGroupMember = false; - MyProc->clogGroupMemberXid = InvalidTransactionId; + MyProc->clogGroupMemberXid = InvalidFullTransactionId; MyProc->clogGroupMemberXidStatus = TRANSACTION_STATUS_IN_PROGRESS; MyProc->clogGroupMemberPage = -1; MyProc->clogGroupMemberLsn = InvalidXLogRecPtr; @@ -663,7 +663,7 @@ InitAuxiliaryProcess(void) MyProc->waitStatus = PROC_WAIT_STATUS_OK; MyProc->fpVXIDLock = false; MyProc->fpLocalTransactionId = InvalidLocalTransactionId; - MyProc->xid = InvalidTransactionId; + MyProc->xid = InvalidFullTransactionId; MyProc->xmin = InvalidTransactionId; MyProc->vxid.procNumber = INVALID_PROC_NUMBER; MyProc->vxid.lxid = InvalidLocalTransactionId; diff --git a/src/bin/pg_verifybackup/t/003_corruption.pl b/src/bin/pg_verifybackup/t/003_corruption.pl index b1d65b8aa0..4677e9584c 100644 --- a/src/bin/pg_verifybackup/t/003_corruption.pl +++ b/src/bin/pg_verifybackup/t/003_corruption.pl @@ -246,7 +246,7 @@ sub mutilate_extra_tablespace_file sub mutilate_missing_file { my ($backup_path) = @_; - my $pathname = "$backup_path/pg_xact/0000"; + my $pathname = "$backup_path/pg_xact/000000000000000"; unlink($pathname) || die "$pathname: $!"; return; } diff --git a/src/include/access/clog.h b/src/include/access/clog.h index a1cfed5f43..034d4e0973 100644 --- a/src/include/access/clog.h +++ b/src/include/access/clog.h @@ -11,6 +11,7 @@ #ifndef CLOG_H #define CLOG_H +#include "access/transam.h" #include "access/xlogreader.h" #include "storage/sync.h" #include "lib/stringinfo.h" @@ -32,13 +33,15 @@ typedef int XidStatus; typedef struct xl_clog_truncate { int64 pageno; - TransactionId oldestXact; + FullTransactionId oldestXact; Oid oldestXactDb; } xl_clog_truncate; -extern void TransactionIdSetTreeStatus(TransactionId xid, int nsubxids, - TransactionId *subxids, XidStatus status, XLogRecPtr lsn); -extern XidStatus TransactionIdGetStatus(TransactionId xid, XLogRecPtr *lsn); +extern void TransactionIdSetTreeStatus(FullTransactionId fxid, int nsubxids, + TransactionId *subxids, XidStatus status, + XLogRecPtr lsn); +extern XidStatus TransactionIdGetStatus(FullTransactionId fxid, + XLogRecPtr *lsn); extern Size CLOGShmemSize(void); extern void CLOGShmemInit(void); @@ -46,8 +49,8 @@ extern void BootStrapCLOG(void); extern void StartupCLOG(void); extern void TrimCLOG(void); extern void CheckPointCLOG(void); -extern void ExtendCLOG(TransactionId newestXact); -extern void TruncateCLOG(TransactionId oldestXact, Oid oldestxid_datoid); +extern void ExtendCLOG(FullTransactionId newestXact); +extern void TruncateCLOG(FullTransactionId oldestXact, Oid oldestxid_datoid); extern int clogsyncfiletag(const FileTag *ftag, char *path); diff --git a/src/include/access/transam.h b/src/include/access/transam.h index f08362898c..7559076931 100644 --- a/src/include/access/transam.h +++ b/src/include/access/transam.h @@ -54,6 +54,7 @@ #define FullTransactionIdFollowsOrEquals(a, b) ((a).value >= (b).value) #define FullTransactionIdIsValid(x) TransactionIdIsValid(XidFromFullTransactionId(x)) #define InvalidFullTransactionId FullTransactionIdFromEpochAndXid(0, InvalidTransactionId) +#define BootstrapFullTransactionId FullTransactionIdFromEpochAndXid(0, BootstrapTransactionId) #define FirstNormalFullTransactionId FullTransactionIdFromEpochAndXid(0, FirstNormalTransactionId) #define FullTransactionIdIsNormal(x) FullTransactionIdFollowsOrEquals(x, FirstNormalFullTransactionId) diff --git a/src/include/storage/proc.h b/src/include/storage/proc.h index a8d2e7db1a..f43d0a7114 100644 --- a/src/include/storage/proc.h +++ b/src/include/storage/proc.h @@ -232,7 +232,7 @@ typedef struct PGPROC * InvalidLocalTransactionId */ } vxid; - TransactionId xid; /* id of top-level transaction currently being + FullTransactionId xid; /* id of top-level transaction currently being * executed by this proc, if running and XID * is assigned; else InvalidTransactionId. * mirrored in ProcGlobal->xids[pgxactoff] */ @@ -361,7 +361,7 @@ typedef struct PGPROC bool clogGroupMember; /* true, if member of clog group */ pg_atomic_uint32 clogGroupNext; /* next clog group member */ - TransactionId clogGroupMemberXid; /* transaction id of clog group member */ + FullTransactionId clogGroupMemberXid; /* transaction id of clog group member */ XidStatus clogGroupMemberXidStatus; /* transaction status of clog * group member */ int64 clogGroupMemberPage; /* clog page corresponding to @@ -447,7 +447,7 @@ typedef struct PROC_HDR PGPROC *allProcs; /* Array mirroring PGPROC.xid for each PGPROC currently in the procarray */ - TransactionId *xids; + FullTransactionId *xids; /* * Array mirroring PGPROC.subxidStatus for each PGPROC currently in the diff --git a/src/test/recovery/t/003_recovery_targets.pl b/src/test/recovery/t/003_recovery_targets.pl index e0df1a2342..6986c93ea3 100644 --- a/src/test/recovery/t/003_recovery_targets.pl +++ b/src/test/recovery/t/003_recovery_targets.pl @@ -59,6 +59,18 @@ $node_primary->init(has_archiving => 1, allows_streaming => 1); # of recovery_target_xid parsing. system_or_bail('pg_resetwal', '--epoch' => '1', $node_primary->data_dir); +# pg_xact is not wraparound any more, create an empty pg_xact segment. +my $out = (run_command([ 'pg_resetwal', '--dry-run', + $node_primary->data_dir ]))[0]; +$out =~ /^Database block size: *(\d+)$/m or die; +my $blcksz = $1; + +open my $fh, '>', $node_primary->data_dir . "/pg_xact/000000000001000" + or die "$0: could not open file $!\n"; +print $fh "\0" x $blcksz + or die "$0: could not write file $!\n"; +close $fh; + # Start it $node_primary->start; -- 2.43.0