0003-WIP-make-clog-64-bit.patch
application/octet-stream
Filename: 0003-WIP-make-clog-64-bit.patch
Type: application/octet-stream
Part: 2
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: format-patch
Series: patch 0003
Subject: WIP - make clog 64 bit
| File | + | − |
|---|---|---|
| src/backend/access/rmgrdesc/clogdesc.c | 4 | 2 |
| src/backend/access/transam/clog.c | 105 | 99 |
| src/backend/access/transam/transam.c | 21 | 5 |
| src/backend/access/transam/twophase.c | 4 | 4 |
| src/backend/access/transam/varsup.c | 5 | 5 |
| src/backend/commands/indexcmds.c | 1 | 1 |
| src/backend/commands/vacuum.c | 9 | 3 |
| src/backend/storage/ipc/procarray.c | 29 | 29 |
| src/backend/storage/lmgr/lock.c | 2 | 2 |
| src/backend/storage/lmgr/proc.c | 4 | 4 |
| src/bin/pg_verifybackup/t/003_corruption.pl | 1 | 1 |
| src/include/access/clog.h | 9 | 6 |
| src/include/access/transam.h | 1 | 0 |
| src/include/storage/proc.h | 3 | 3 |
| src/test/recovery/t/003_recovery_targets.pl | 12 | 0 |
From 8af31945cdc9031a3212d87659b201b5c62ed61a Mon Sep 17 00:00:00 2001
From: Maxim Orlov <orlovmg@gmail.com>
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