v3-0002-wait_event_arg-provide-quick-and-dumb-demo-of-mul.patch
text/x-patch
Filename: v3-0002-wait_event_arg-provide-quick-and-dumb-demo-of-mul.patch
Type: text/x-patch
Part: 1
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 v3-0002
Subject: wait_event_arg: provide quick and dumb demo of multixact passthrough to LWLockReportWaitStart()
| File | + | − |
|---|---|---|
| contrib/amcheck/verify_heapam.c | 1 | 1 |
| contrib/pgrowlocks/pgrowlocks.c | 1 | 1 |
| src/backend/access/heap/heapam.c | 52 | 42 |
| src/backend/access/heap/heapam_visibility.c | 11 | 11 |
| src/backend/access/transam/multixact.c | 27 | 20 |
| src/backend/storage/lmgr/lwlock.c | 13 | 6 |
| src/backend/utils/adt/multixactfuncs.c | 2 | 2 |
| src/include/access/htup_details.h | 1 | 1 |
| src/include/access/htup.h | 1 | 1 |
| src/include/access/multixact.h | 8 | 5 |
| src/include/storage/lwlock.h | 1 | 0 |
| src/test/modules/test_slru/test_multixact.c | 2 | 2 |
From 6818a30ee7849e48aae7e43ec2d8e8ddde774838 Mon Sep 17 00:00:00 2001
From: Jakub Wartak <jakub.wartak@enterprisedb.com>
Date: Mon, 1 Dec 2025 13:28:54 +0100
Subject: [PATCH v3 2/4] wait_event_arg: provide quick and dumb demo of
multixact passthrough to LWLockReportWaitStart()
XXX: This needs review if such alternation of function arguments are acceptable or not.
---
contrib/amcheck/verify_heapam.c | 2 +-
contrib/pgrowlocks/pgrowlocks.c | 2 +-
src/backend/access/heap/heapam.c | 94 ++++++++++++---------
src/backend/access/heap/heapam_visibility.c | 22 ++---
src/backend/access/transam/multixact.c | 47 ++++++-----
src/backend/storage/lmgr/lwlock.c | 19 +++--
src/backend/utils/adt/multixactfuncs.c | 4 +-
src/include/access/htup.h | 2 +-
src/include/access/htup_details.h | 2 +-
src/include/access/multixact.h | 13 +--
src/include/storage/lwlock.h | 1 +
src/test/modules/test_slru/test_multixact.c | 4 +-
12 files changed, 120 insertions(+), 92 deletions(-)
diff --git a/contrib/amcheck/verify_heapam.c b/contrib/amcheck/verify_heapam.c
index 30c2f58317..152da73221 100644
--- a/contrib/amcheck/verify_heapam.c
+++ b/contrib/amcheck/verify_heapam.c
@@ -1397,7 +1397,7 @@ check_tuple_visibility(HeapCheckContext *ctx, bool *xmin_commit_status_ok,
* We already checked above that this multixact is within limits for
* this table. Now check the update xid from this multixact.
*/
- xmax = HeapTupleGetUpdateXid(tuphdr);
+ xmax = HeapTupleGetUpdateXid(tuphdr, 0); /* DEMO: we do not care */
switch (get_xid_status(xmax, ctx, &xmax_status))
{
case XID_INVALID:
diff --git a/contrib/pgrowlocks/pgrowlocks.c b/contrib/pgrowlocks/pgrowlocks.c
index f88269332b..d4b8b15530 100644
--- a/contrib/pgrowlocks/pgrowlocks.c
+++ b/contrib/pgrowlocks/pgrowlocks.c
@@ -157,7 +157,7 @@ pgrowlocks(PG_FUNCTION_ARGS)
allow_old = HEAP_LOCKED_UPGRADED(infomask);
nmembers = GetMultiXactIdMembers(xmax, &members, allow_old,
- false);
+ false, rel->rd_locator.relNumber);
if (nmembers == -1)
{
values[Atnum_xids] = "{0}";
diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index ad9d6338ec..dd1303fc98 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -84,17 +84,18 @@ static void compute_new_xmax_infomask(TransactionId xmax, uint16 old_infomask,
uint16 old_infomask2, TransactionId add_to_xmax,
LockTupleMode mode, bool is_update,
TransactionId *result_xmax, uint16 *result_infomask,
- uint16 *result_infomask2);
+ uint16 *result_infomask2, RelFileNumber r);
static TM_Result heap_lock_updated_tuple(Relation rel,
uint16 prior_infomask,
TransactionId prior_raw_xmax,
const ItemPointerData *prior_ctid,
TransactionId xid,
- LockTupleMode mode);
+ LockTupleMode mode,
+ RelFileNumber r);
static void GetMultiXactIdHintBits(MultiXactId multi, uint16 *new_infomask,
- uint16 *new_infomask2);
+ uint16 *new_infomask2, RelFileNumber r);
static TransactionId MultiXactIdGetUpdateXid(TransactionId xmax,
- uint16 t_infomask);
+ uint16 t_infomask, RelFileNumber r);
static bool DoesMultiXactIdConflict(MultiXactId multi, uint16 infomask,
LockTupleMode lockmode, bool *current_is_member);
static void MultiXactIdWait(MultiXactId multi, MultiXactStatus status, uint16 infomask,
@@ -3068,7 +3069,8 @@ l1:
compute_new_xmax_infomask(HeapTupleHeaderGetRawXmax(tp.t_data),
tp.t_data->t_infomask, tp.t_data->t_infomask2,
xid, LockTupleExclusive, true,
- &new_xmax, &new_infomask, &new_infomask2);
+ &new_xmax, &new_infomask, &new_infomask2,
+ relation->rd_locator.relNumber);
START_CRIT_SECTION();
@@ -3618,7 +3620,7 @@ l2:
* subxact aborts.
*/
if (!HEAP_XMAX_IS_LOCKED_ONLY(oldtup.t_data->t_infomask))
- update_xact = HeapTupleGetUpdateXid(oldtup.t_data);
+ update_xact = HeapTupleGetUpdateXid(oldtup.t_data, relation->rd_locator.relNumber);
else
update_xact = InvalidTransactionId;
@@ -3761,7 +3763,8 @@ l2:
oldtup.t_data->t_infomask2,
xid, *lockmode, true,
&xmax_old_tuple, &infomask_old_tuple,
- &infomask2_old_tuple);
+ &infomask2_old_tuple,
+ relation->rd_locator.relNumber);
/*
* And also prepare an Xmax value for the new copy of the tuple. If there
@@ -3793,7 +3796,7 @@ l2:
if (oldtup.t_data->t_infomask & HEAP_XMAX_IS_MULTI)
{
GetMultiXactIdHintBits(xmax_new_tuple, &infomask_new_tuple,
- &infomask2_new_tuple);
+ &infomask2_new_tuple, relation->rd_locator.relNumber);
}
else
{
@@ -3878,7 +3881,8 @@ l2:
oldtup.t_data->t_infomask2,
xid, *lockmode, false,
&xmax_lock_old_tuple, &infomask_lock_old_tuple,
- &infomask2_lock_old_tuple);
+ &infomask2_lock_old_tuple,
+ relation->rd_locator.relNumber);
Assert(HEAP_XMAX_IS_LOCKED_ONLY(infomask_lock_old_tuple));
@@ -4709,7 +4713,8 @@ l3:
*/
nmembers =
GetMultiXactIdMembers(xwait, &members, false,
- HEAP_XMAX_IS_LOCKED_ONLY(infomask));
+ HEAP_XMAX_IS_LOCKED_ONLY(infomask),
+ relation->rd_locator.relNumber);
for (i = 0; i < nmembers; i++)
{
@@ -4827,7 +4832,7 @@ l3:
res = heap_lock_updated_tuple(relation,
infomask, xwait, &t_ctid,
GetCurrentTransactionId(),
- mode);
+ mode, relation->rd_locator.relNumber);
if (res != TM_Ok)
{
result = res;
@@ -5076,7 +5081,7 @@ l3:
res = heap_lock_updated_tuple(relation,
infomask, xwait, &t_ctid,
GetCurrentTransactionId(),
- mode);
+ mode, relation->rd_locator.relNumber);
if (res != TM_Ok)
{
result = res;
@@ -5193,7 +5198,8 @@ failed:
*/
compute_new_xmax_infomask(xmax, old_infomask, tuple->t_data->t_infomask2,
GetCurrentTransactionId(), mode, false,
- &xid, &new_infomask, &new_infomask2);
+ &xid, &new_infomask, &new_infomask2,
+ relation->rd_locator.relNumber);
START_CRIT_SECTION();
@@ -5360,7 +5366,7 @@ compute_new_xmax_infomask(TransactionId xmax, uint16 old_infomask,
uint16 old_infomask2, TransactionId add_to_xmax,
LockTupleMode mode, bool is_update,
TransactionId *result_xmax, uint16 *result_infomask,
- uint16 *result_infomask2)
+ uint16 *result_infomask2, RelFileNumber r)
{
TransactionId new_xmax;
uint16 new_infomask,
@@ -5455,7 +5461,7 @@ l5:
{
if (HEAP_XMAX_IS_LOCKED_ONLY(old_infomask) ||
!TransactionIdDidCommit(MultiXactIdGetUpdateXid(xmax,
- old_infomask)))
+ old_infomask, 11)))
{
/*
* Reset these bits and restart; otherwise fall through to
@@ -5470,8 +5476,8 @@ l5:
new_status = get_mxact_status_for_lock(mode, is_update);
new_xmax = MultiXactIdExpand((MultiXactId) xmax, add_to_xmax,
- new_status);
- GetMultiXactIdHintBits(new_xmax, &new_infomask, &new_infomask2);
+ new_status, r);
+ GetMultiXactIdHintBits(new_xmax, &new_infomask, &new_infomask2, r);
}
else if (old_infomask & HEAP_XMAX_COMMITTED)
{
@@ -5494,8 +5500,8 @@ l5:
* updater to be identical to the current one, so we need not check
* for that case as we do in the block above.
*/
- new_xmax = MultiXactIdCreate(xmax, status, add_to_xmax, new_status);
- GetMultiXactIdHintBits(new_xmax, &new_infomask, &new_infomask2);
+ new_xmax = MultiXactIdCreate(xmax, status, add_to_xmax, new_status, r);
+ GetMultiXactIdHintBits(new_xmax, &new_infomask, &new_infomask2, r);
}
else if (TransactionIdIsInProgress(xmax))
{
@@ -5576,8 +5582,8 @@ l5:
/* otherwise, just fall back to creating a new multixact */
new_status = get_mxact_status_for_lock(mode, is_update);
new_xmax = MultiXactIdCreate(xmax, old_status,
- add_to_xmax, new_status);
- GetMultiXactIdHintBits(new_xmax, &new_infomask, &new_infomask2);
+ add_to_xmax, new_status, r);
+ GetMultiXactIdHintBits(new_xmax, &new_infomask, &new_infomask2, r);
}
else if (!HEAP_XMAX_IS_LOCKED_ONLY(old_infomask) &&
TransactionIdDidCommit(xmax))
@@ -5601,8 +5607,8 @@ l5:
* updater to be identical to the current one, so we need not check
* for that case as we do in the block above.
*/
- new_xmax = MultiXactIdCreate(xmax, status, add_to_xmax, new_status);
- GetMultiXactIdHintBits(new_xmax, &new_infomask, &new_infomask2);
+ new_xmax = MultiXactIdCreate(xmax, status, add_to_xmax, new_status, r);
+ GetMultiXactIdHintBits(new_xmax, &new_infomask, &new_infomask2, r);
}
else
{
@@ -5863,7 +5869,8 @@ l4:
Assert(!HEAP_LOCKED_UPGRADED(mytup.t_data->t_infomask));
nmembers = GetMultiXactIdMembers(rawxmax, &members, false,
- HEAP_XMAX_IS_LOCKED_ONLY(old_infomask));
+ HEAP_XMAX_IS_LOCKED_ONLY(old_infomask),
+ rel->rd_locator.relNumber);
for (i = 0; i < nmembers; i++)
{
result = test_lockmode_for_conflict(members[i].status,
@@ -5978,7 +5985,8 @@ l4:
/* compute the new Xmax and infomask values for the tuple ... */
compute_new_xmax_infomask(xmax, old_infomask, mytup.t_data->t_infomask2,
xid, mode, false,
- &new_xmax, &new_infomask, &new_infomask2);
+ &new_xmax, &new_infomask, &new_infomask2,
+ rel->rd_locator.relNumber);
if (PageIsAllVisible(BufferGetPage(buf)) &&
visibilitymap_clear(rel, block, vmbuffer,
@@ -6080,7 +6088,8 @@ heap_lock_updated_tuple(Relation rel,
uint16 prior_infomask,
TransactionId prior_raw_xmax,
const ItemPointerData *prior_ctid,
- TransactionId xid, LockTupleMode mode)
+ TransactionId xid, LockTupleMode mode,
+ RelFileNumber r)
{
INJECTION_POINT("heap_lock_updated_tuple", NULL);
@@ -6104,7 +6113,7 @@ heap_lock_updated_tuple(Relation rel,
MultiXactIdSetOldestMember();
prior_xmax = (prior_infomask & HEAP_XMAX_IS_MULTI) ?
- MultiXactIdGetUpdateXid(prior_raw_xmax, prior_infomask) : prior_raw_xmax;
+ MultiXactIdGetUpdateXid(prior_raw_xmax, prior_infomask, rel->rd_locator.relNumber) : prior_raw_xmax;
return heap_lock_updated_tuple_rec(rel, prior_xmax, prior_ctid, xid, mode);
}
@@ -6748,7 +6757,7 @@ heap_inplace_unlock(Relation relation,
static TransactionId
FreezeMultiXactId(MultiXactId multi, uint16 t_infomask,
const struct VacuumCutoffs *cutoffs, uint16 *flags,
- HeapPageFreeze *pagefrz)
+ HeapPageFreeze *pagefrz, RelFileNumber r)
{
TransactionId newxmax;
MultiXactMember *members;
@@ -6803,7 +6812,7 @@ FreezeMultiXactId(MultiXactId multi, uint16 t_infomask,
}
/* replace multi with single XID for its updater? */
- update_xact = MultiXactIdGetUpdateXid(multi, t_infomask);
+ update_xact = MultiXactIdGetUpdateXid(multi, t_infomask, 0);
if (TransactionIdPrecedes(update_xact, cutoffs->relfrozenxid))
ereport(ERROR,
(errcode(ERRCODE_DATA_CORRUPTED),
@@ -6841,7 +6850,7 @@ FreezeMultiXactId(MultiXactId multi, uint16 t_infomask,
*/
nmembers =
GetMultiXactIdMembers(multi, &members, false,
- HEAP_XMAX_IS_LOCKED_ONLY(t_infomask));
+ HEAP_XMAX_IS_LOCKED_ONLY(t_infomask), r);
if (nmembers <= 0)
{
/* Nothing worth keeping */
@@ -7042,7 +7051,8 @@ FreezeMultiXactId(MultiXactId multi, uint16 t_infomask,
* Create a new multixact with the surviving members of the previous
* one, to set as new Xmax in the tuple
*/
- newxmax = MultiXactIdCreateFromMembers(nnewmembers, newmembers);
+ /* XXX/DEMO no need to extend wiat info in freeze scenario? */
+ newxmax = MultiXactIdCreateFromMembers(nnewmembers, newmembers, 0);
*flags |= FRM_RETURN_IS_MULTI;
}
@@ -7173,7 +7183,7 @@ heap_prepare_freeze_tuple(HeapTupleHeader tuple,
* FreezeLimit/MultiXactCutoff postcondition must never be violated.
*/
newxmax = FreezeMultiXactId(xid, tuple->t_infomask, cutoffs,
- &flags, pagefrz);
+ &flags, pagefrz, 0);
if (flags & FRM_NOOP)
{
@@ -7239,7 +7249,7 @@ heap_prepare_freeze_tuple(HeapTupleHeader tuple,
*/
frz->t_infomask &= ~HEAP_XMAX_BITS;
frz->t_infomask2 &= ~HEAP_KEYS_UPDATED;
- GetMultiXactIdHintBits(newxmax, &newbits, &newbits2);
+ GetMultiXactIdHintBits(newxmax, &newbits, &newbits2, 0); /* DEMO: shortcut */
frz->t_infomask |= newbits;
frz->t_infomask2 |= newbits2;
frz->xmax = newxmax;
@@ -7489,7 +7499,7 @@ heap_freeze_tuple(HeapTupleHeader tuple,
*/
static void
GetMultiXactIdHintBits(MultiXactId multi, uint16 *new_infomask,
- uint16 *new_infomask2)
+ uint16 *new_infomask2, RelFileNumber r)
{
int nmembers;
MultiXactMember *members;
@@ -7503,7 +7513,7 @@ GetMultiXactIdHintBits(MultiXactId multi, uint16 *new_infomask,
* We only use this in multis we just created, so they cannot be values
* pre-pg_upgrade.
*/
- nmembers = GetMultiXactIdMembers(multi, &members, false, false);
+ nmembers = GetMultiXactIdMembers(multi, &members, false, false, 0);
for (i = 0; i < nmembers; i++)
{
@@ -7569,7 +7579,7 @@ GetMultiXactIdHintBits(MultiXactId multi, uint16 *new_infomask,
* necessary.
*/
static TransactionId
-MultiXactIdGetUpdateXid(TransactionId xmax, uint16 t_infomask)
+MultiXactIdGetUpdateXid(TransactionId xmax, uint16 t_infomask, RelFileNumber r)
{
TransactionId update_xact = InvalidTransactionId;
MultiXactMember *members;
@@ -7582,7 +7592,7 @@ MultiXactIdGetUpdateXid(TransactionId xmax, uint16 t_infomask)
* Since we know the LOCK_ONLY bit is not set, this cannot be a multi from
* pre-pg_upgrade.
*/
- nmembers = GetMultiXactIdMembers(xmax, &members, false, false);
+ nmembers = GetMultiXactIdMembers(xmax, &members, false, false, r);
if (nmembers > 0)
{
@@ -7621,10 +7631,10 @@ MultiXactIdGetUpdateXid(TransactionId xmax, uint16 t_infomask)
* checking the hint bits.
*/
TransactionId
-HeapTupleGetUpdateXid(const HeapTupleHeaderData *tup)
+HeapTupleGetUpdateXid(const HeapTupleHeaderData *tup, uint32_t r)
{
return MultiXactIdGetUpdateXid(HeapTupleHeaderGetRawXmax(tup),
- tup->t_infomask);
+ tup->t_infomask, r);
}
/*
@@ -7649,7 +7659,7 @@ DoesMultiXactIdConflict(MultiXactId multi, uint16 infomask,
return false;
nmembers = GetMultiXactIdMembers(multi, &members, false,
- HEAP_XMAX_IS_LOCKED_ONLY(infomask));
+ HEAP_XMAX_IS_LOCKED_ONLY(infomask), 4); /* DEMO: shortcut */
if (nmembers >= 0)
{
int i;
@@ -7750,7 +7760,7 @@ Do_MultiXactIdWait(MultiXactId multi, MultiXactStatus status,
/* for pre-pg_upgrade tuples, no need to sleep at all */
nmembers = HEAP_LOCKED_UPGRADED(infomask) ? -1 :
GetMultiXactIdMembers(multi, &members, false,
- HEAP_XMAX_IS_LOCKED_ONLY(infomask));
+ HEAP_XMAX_IS_LOCKED_ONLY(infomask), 5); /* DEMO */
if (nmembers >= 0)
{
@@ -7970,7 +7980,7 @@ heap_tuple_should_freeze(HeapTupleHeader tuple,
/* need to check whether any member of the mxact is old */
nmembers = GetMultiXactIdMembers(multi, &members, false,
- HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask));
+ HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask), 3); /* DEMO: shortcut */
for (int i = 0; i < nmembers; i++)
{
diff --git a/src/backend/access/heap/heapam_visibility.c b/src/backend/access/heap/heapam_visibility.c
index 05e70b7d92..c17d95e5ae 100644
--- a/src/backend/access/heap/heapam_visibility.c
+++ b/src/backend/access/heap/heapam_visibility.c
@@ -242,7 +242,7 @@ HeapTupleSatisfiesSelf(HeapTuple htup, Snapshot snapshot, Buffer buffer)
{
TransactionId xmax;
- xmax = HeapTupleGetUpdateXid(tuple);
+ xmax = HeapTupleGetUpdateXid(tuple, htup->t_tableOid);
/* not LOCKED_ONLY, so it has to have an xmax */
Assert(TransactionIdIsValid(xmax));
@@ -297,7 +297,7 @@ HeapTupleSatisfiesSelf(HeapTuple htup, Snapshot snapshot, Buffer buffer)
if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
return true;
- xmax = HeapTupleGetUpdateXid(tuple);
+ xmax = HeapTupleGetUpdateXid(tuple, htup->t_tableOid);
/* not LOCKED_ONLY, so it has to have an xmax */
Assert(TransactionIdIsValid(xmax));
@@ -488,7 +488,7 @@ HeapTupleSatisfiesUpdate(HeapTuple htup, CommandId curcid,
{
TransactionId xmax;
- xmax = HeapTupleGetUpdateXid(tuple);
+ xmax = HeapTupleGetUpdateXid(tuple, htup->t_tableOid);
/* not LOCKED_ONLY, so it has to have an xmax */
Assert(TransactionIdIsValid(xmax));
@@ -568,7 +568,7 @@ HeapTupleSatisfiesUpdate(HeapTuple htup, CommandId curcid,
return TM_Ok;
}
- xmax = HeapTupleGetUpdateXid(tuple);
+ xmax = HeapTupleGetUpdateXid(tuple, htup->t_tableOid);
if (!TransactionIdIsValid(xmax))
{
if (MultiXactIdIsRunning(HeapTupleHeaderGetRawXmax(tuple), false))
@@ -708,7 +708,7 @@ HeapTupleSatisfiesDirty(HeapTuple htup, Snapshot snapshot,
{
TransactionId xmax;
- xmax = HeapTupleGetUpdateXid(tuple);
+ xmax = HeapTupleGetUpdateXid(tuple, htup->t_tableOid);
/* not LOCKED_ONLY, so it has to have an xmax */
Assert(TransactionIdIsValid(xmax));
@@ -781,7 +781,7 @@ HeapTupleSatisfiesDirty(HeapTuple htup, Snapshot snapshot,
if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
return true;
- xmax = HeapTupleGetUpdateXid(tuple);
+ xmax = HeapTupleGetUpdateXid(tuple, htup->t_tableOid);
/* not LOCKED_ONLY, so it has to have an xmax */
Assert(TransactionIdIsValid(xmax));
@@ -897,7 +897,7 @@ HeapTupleSatisfiesMVCC(HeapTuple htup, Snapshot snapshot,
{
TransactionId xmax;
- xmax = HeapTupleGetUpdateXid(tuple);
+ xmax = HeapTupleGetUpdateXid(tuple, htup->t_tableOid);
/* not LOCKED_ONLY, so it has to have an xmax */
Assert(TransactionIdIsValid(xmax));
@@ -960,7 +960,7 @@ HeapTupleSatisfiesMVCC(HeapTuple htup, Snapshot snapshot,
/* already checked above */
Assert(!HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask));
- xmax = HeapTupleGetUpdateXid(tuple);
+ xmax = HeapTupleGetUpdateXid(tuple, htup->t_tableOid);
/* not LOCKED_ONLY, so it has to have an xmax */
Assert(TransactionIdIsValid(xmax));
@@ -1183,7 +1183,7 @@ HeapTupleSatisfiesVacuumHorizon(HeapTuple htup, Buffer buffer, TransactionId *de
if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
{
- TransactionId xmax = HeapTupleGetUpdateXid(tuple);
+ TransactionId xmax = HeapTupleGetUpdateXid(tuple, htup->t_tableOid);
/* already checked above */
Assert(!HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask));
@@ -1378,7 +1378,7 @@ HeapTupleHeaderIsOnlyLocked(HeapTupleHeader tuple)
return false;
/* ... but if it's a multi, then perhaps the updating Xid aborted. */
- xmax = HeapTupleGetUpdateXid(tuple);
+ xmax = HeapTupleGetUpdateXid(tuple, 12); /* DEMO */
/* not LOCKED_ONLY, so it has to have an xmax */
Assert(TransactionIdIsValid(xmax));
@@ -1527,7 +1527,7 @@ HeapTupleSatisfiesHistoricMVCC(HeapTuple htup, Snapshot snapshot,
*/
else if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
{
- xmax = HeapTupleGetUpdateXid(tuple);
+ xmax = HeapTupleGetUpdateXid(tuple, htup->t_tableOid);
}
/* check if it's one of our txids, toplevel is also in there */
diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c
index 3f423636b4..b2a04e34b2 100644
--- a/src/backend/access/transam/multixact.c
+++ b/src/backend/access/transam/multixact.c
@@ -264,7 +264,9 @@ static MemoryContext MXactContext = NULL;
/* internal MultiXactId management */
static void MultiXactIdSetOldestVisible(void);
static void RecordNewMultiXact(MultiXactId multi, MultiXactOffset offset,
- int nmembers, MultiXactMember *members);
+ int nmembers, MultiXactMember *members,
+ RelFileNumber r);
+
static MultiXactId GetNewMultiXactId(int nmembers, MultiXactOffset *offset);
/* MultiXact cache management */
@@ -299,7 +301,8 @@ static void WriteMTruncateXlogRec(Oid oldestMultiDB,
*/
MultiXactId
MultiXactIdCreate(TransactionId xid1, MultiXactStatus status1,
- TransactionId xid2, MultiXactStatus status2)
+ TransactionId xid2, MultiXactStatus status2,
+ RelFileNumber r)
{
MultiXactId newMulti;
MultiXactMember members[2];
@@ -323,7 +326,7 @@ MultiXactIdCreate(TransactionId xid1, MultiXactStatus status1,
members[1].xid = xid2;
members[1].status = status2;
- newMulti = MultiXactIdCreateFromMembers(2, members);
+ newMulti = MultiXactIdCreateFromMembers(2, members, r);
debug_elog3(DEBUG2, "Create: %s",
mxid_to_string(newMulti, 2, members));
@@ -351,7 +354,8 @@ MultiXactIdCreate(TransactionId xid1, MultiXactStatus status1,
* passed in.
*/
MultiXactId
-MultiXactIdExpand(MultiXactId multi, TransactionId xid, MultiXactStatus status)
+MultiXactIdExpand(MultiXactId multi, TransactionId xid, MultiXactStatus status,
+ RelFileNumber r)
{
MultiXactId newMulti;
MultiXactMember *members;
@@ -374,7 +378,7 @@ MultiXactIdExpand(MultiXactId multi, TransactionId xid, MultiXactStatus status)
* caller of this function does a check that the multixact is no longer
* running.
*/
- nmembers = GetMultiXactIdMembers(multi, &members, false, false);
+ nmembers = GetMultiXactIdMembers(multi, &members, false, false, r);
if (nmembers < 0)
{
@@ -389,7 +393,7 @@ MultiXactIdExpand(MultiXactId multi, TransactionId xid, MultiXactStatus status)
*/
member.xid = xid;
member.status = status;
- newMulti = MultiXactIdCreateFromMembers(1, &member);
+ newMulti = MultiXactIdCreateFromMembers(1, &member, r);
debug_elog4(DEBUG2, "Expand: %u has no members, create singleton %u",
multi, newMulti);
@@ -440,7 +444,7 @@ MultiXactIdExpand(MultiXactId multi, TransactionId xid, MultiXactStatus status)
newMembers[j].xid = xid;
newMembers[j++].status = status;
- newMulti = MultiXactIdCreateFromMembers(j, newMembers);
+ newMulti = MultiXactIdCreateFromMembers(j, newMembers, r);
pfree(members);
pfree(newMembers);
@@ -474,7 +478,7 @@ MultiXactIdIsRunning(MultiXactId multi, bool isLockOnly)
* "false" here means we assume our callers have checked that the given
* multi cannot possibly come from a pg_upgraded database.
*/
- nmembers = GetMultiXactIdMembers(multi, &members, false, isLockOnly);
+ nmembers = GetMultiXactIdMembers(multi, &members, false, isLockOnly, 0);
if (nmembers <= 0)
{
@@ -655,7 +659,7 @@ ReadMultiXactIdRange(MultiXactId *oldest, MultiXactId *next)
* NB: the passed members[] array will be sorted in-place.
*/
MultiXactId
-MultiXactIdCreateFromMembers(int nmembers, MultiXactMember *members)
+MultiXactIdCreateFromMembers(int nmembers, MultiXactMember *members, RelFileNumber r)
{
MultiXactId multi;
MultiXactOffset offset;
@@ -735,7 +739,7 @@ MultiXactIdCreateFromMembers(int nmembers, MultiXactMember *members)
(void) XLogInsert(RM_MULTIXACT_ID, XLOG_MULTIXACT_CREATE_ID);
/* Now enter the information into the OFFSETs and MEMBERs logs */
- RecordNewMultiXact(multi, offset, nmembers, members);
+ RecordNewMultiXact(multi, offset, nmembers, members, r);
/* Done with critical section */
END_CRIT_SECTION();
@@ -757,7 +761,8 @@ MultiXactIdCreateFromMembers(int nmembers, MultiXactMember *members)
*/
static void
RecordNewMultiXact(MultiXactId multi, MultiXactOffset offset,
- int nmembers, MultiXactMember *members)
+ int nmembers, MultiXactMember *members,
+ RelFileNumber r)
{
int64 pageno;
int64 prev_pageno;
@@ -791,7 +796,7 @@ RecordNewMultiXact(MultiXactId multi, MultiXactOffset offset,
* multixid.
*/
lock = SimpleLruGetBankLock(MultiXactOffsetCtl, pageno);
- LWLockAcquire(lock, LW_EXCLUSIVE);
+ LWLockAcquireExt(lock, LW_EXCLUSIVE, r);
/*
* Note: we pass the MultiXactId to SimpleLruReadPage as the "transaction"
@@ -880,7 +885,7 @@ RecordNewMultiXact(MultiXactId multi, MultiXactOffset offset,
if (prevlock != NULL)
LWLockRelease(prevlock);
- LWLockAcquire(lock, LW_EXCLUSIVE);
+ LWLockAcquireExt(lock, LW_EXCLUSIVE, r);
prevlock = lock;
}
slotno = SimpleLruReadPage(MultiXactMemberCtl, pageno, true, multi);
@@ -1113,7 +1118,8 @@ GetNewMultiXactId(int nmembers, MultiXactOffset *offset)
*/
int
GetMultiXactIdMembers(MultiXactId multi, MultiXactMember **members,
- bool from_pgupgrade, bool isLockOnly)
+ bool from_pgupgrade, bool isLockOnly,
+ RelFileNumber r)
{
int64 pageno;
int64 prev_pageno;
@@ -1205,7 +1211,7 @@ GetMultiXactIdMembers(MultiXactId multi, MultiXactMember **members,
/* Acquire the bank lock for the page we need. */
lock = SimpleLruGetBankLock(MultiXactOffsetCtl, pageno);
- LWLockAcquire(lock, LW_EXCLUSIVE);
+ LWLockAcquireExt(lock, LW_EXCLUSIVE, r);
/* read this multi's offset */
slotno = SimpleLruReadPage(MultiXactOffsetCtl, pageno, true, multi);
@@ -1243,7 +1249,7 @@ GetMultiXactIdMembers(MultiXactId multi, MultiXactMember **members,
if (newlock != lock)
{
LWLockRelease(lock);
- LWLockAcquire(newlock, LW_EXCLUSIVE);
+ LWLockAcquireExt(newlock, LW_EXCLUSIVE, r);
lock = newlock;
}
slotno = SimpleLruReadPage(MultiXactOffsetCtl, pageno, true, tmpMXact);
@@ -1307,7 +1313,7 @@ GetMultiXactIdMembers(MultiXactId multi, MultiXactMember **members,
{
if (lock)
LWLockRelease(lock);
- LWLockAcquire(newlock, LW_EXCLUSIVE);
+ LWLockAcquireExt(newlock, LW_EXCLUSIVE, r);
lock = newlock;
}
@@ -2467,7 +2473,8 @@ find_multixact_start(MultiXactId multi, MultiXactOffset *result)
*/
void
GetMultiXactInfo(uint32 *multixacts, MultiXactOffset *nextOffset,
- MultiXactId *oldestMultiXactId, MultiXactOffset *oldestOffset)
+ MultiXactId *oldestMultiXactId, MultiXactOffset *oldestOffset,
+ RelFileNumber r)
{
MultiXactId nextMultiXactId;
@@ -2522,7 +2529,7 @@ MultiXactMemberFreezeThreshold(void)
uint64 members;
/* Read the current offsets and multixact usage. */
- GetMultiXactInfo(&multixacts, &nextOffset, &oldestMultiXactId, &oldestOffset);
+ GetMultiXactInfo(&multixacts, &nextOffset, &oldestMultiXactId, &oldestOffset, 0);
members = nextOffset - oldestOffset;
/* If member space utilization is low, no special action is required. */
@@ -2914,7 +2921,7 @@ multixact_redo(XLogReaderState *record)
/* Store the data back into the SLRU files */
RecordNewMultiXact(xlrec->mid, xlrec->moff, xlrec->nmembers,
- xlrec->members);
+ xlrec->members, 0);
/* Make sure nextMXact/nextOffset are beyond what this record has */
MultiXactAdvanceNextMXact(NextMultiXactId(xlrec->mid),
diff --git a/src/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c
index fb548c9a9a..653b8b89b5 100644
--- a/src/backend/storage/lmgr/lwlock.c
+++ b/src/backend/storage/lmgr/lwlock.c
@@ -204,7 +204,7 @@ static int LocalLWLockCounter;
#define MAX_NAMED_TRANCHES 256
static void InitializeLWLocks(void);
-static inline void LWLockReportWaitStart(LWLock *lock);
+static inline void LWLockReportWaitStart(LWLock *lock, uint32 additional_info);
static inline void LWLockReportWaitEnd(void);
static const char *GetLWTrancheName(uint16 trancheId);
@@ -716,9 +716,9 @@ LWLockInitialize(LWLock *lock, int tranche_id)
* event based on tranche and lock id.
*/
static inline void
-LWLockReportWaitStart(LWLock *lock)
+LWLockReportWaitStart(LWLock *lock, uint32 additional_info)
{
- pgstat_report_wait_start(PG_WAIT_LWLOCK | ((uint64_t) lock->tranche << 32));
+ pgstat_report_wait_start(PG_WAIT_LWLOCK | ((uint64_t) lock->tranche << 32) | additional_info);
}
/*
@@ -1177,6 +1177,13 @@ LWLockDequeueSelf(LWLock *lock)
*/
bool
LWLockAcquire(LWLock *lock, LWLockMode mode)
+{
+ return LWLockAcquireExt(lock, mode, 0);
+}
+
+/* XXX/DEMO just for demo purposes */
+bool
+LWLockAcquireExt(LWLock *lock, LWLockMode mode, uint32 additional_info)
{
PGPROC *proc = MyProc;
bool result = true;
@@ -1289,7 +1296,7 @@ LWLockAcquire(LWLock *lock, LWLockMode mode)
lwstats->block_count++;
#endif
- LWLockReportWaitStart(lock);
+ LWLockReportWaitStart(lock, additional_info);
if (TRACE_POSTGRESQL_LWLOCK_WAIT_START_ENABLED())
TRACE_POSTGRESQL_LWLOCK_WAIT_START(T_NAME(lock), mode);
@@ -1454,7 +1461,7 @@ LWLockAcquireOrWait(LWLock *lock, LWLockMode mode)
lwstats->block_count++;
#endif
- LWLockReportWaitStart(lock);
+ LWLockReportWaitStart(lock, 0);
if (TRACE_POSTGRESQL_LWLOCK_WAIT_START_ENABLED())
TRACE_POSTGRESQL_LWLOCK_WAIT_START(T_NAME(lock), mode);
@@ -1672,7 +1679,7 @@ LWLockWaitForVar(LWLock *lock, pg_atomic_uint64 *valptr, uint64 oldval,
lwstats->block_count++;
#endif
- LWLockReportWaitStart(lock);
+ LWLockReportWaitStart(lock, 0);
if (TRACE_POSTGRESQL_LWLOCK_WAIT_START_ENABLED())
TRACE_POSTGRESQL_LWLOCK_WAIT_START(T_NAME(lock), LW_EXCLUSIVE);
diff --git a/src/backend/utils/adt/multixactfuncs.c b/src/backend/utils/adt/multixactfuncs.c
index 9fe2ebafa7..a9573f13fc 100644
--- a/src/backend/utils/adt/multixactfuncs.c
+++ b/src/backend/utils/adt/multixactfuncs.c
@@ -58,7 +58,7 @@ pg_get_multixact_members(PG_FUNCTION_ARGS)
multi = palloc_object(mxact);
/* no need to allow for old values here */
multi->nmembers = GetMultiXactIdMembers(mxid, &multi->members, false,
- false);
+ false, 0);
multi->iter = 0;
if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
@@ -114,7 +114,7 @@ pg_get_multixact_stats(PG_FUNCTION_ARGS)
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("return type must be a row type")));
- GetMultiXactInfo(&multixacts, &nextOffset, &oldestMultiXactId, &oldestOffset);
+ GetMultiXactInfo(&multixacts, &nextOffset, &oldestMultiXactId, &oldestOffset, 0);
members = nextOffset - oldestOffset;
membersBytes = MultiXactOffsetStorageSize(nextOffset, oldestOffset);
diff --git a/src/include/access/htup.h b/src/include/access/htup.h
index cfc4e1cbc5..82150103ce 100644
--- a/src/include/access/htup.h
+++ b/src/include/access/htup.h
@@ -84,6 +84,6 @@ extern void HeapTupleHeaderAdjustCmax(const HeapTupleHeaderData *tup,
CommandId *cmax, bool *iscombo);
/* Prototype for HeapTupleHeader accessors in heapam.c */
-extern TransactionId HeapTupleGetUpdateXid(const HeapTupleHeaderData *tup);
+extern TransactionId HeapTupleGetUpdateXid(const HeapTupleHeaderData *tup, uint32_t r);
#endif /* HTUP_H */
diff --git a/src/include/access/htup_details.h b/src/include/access/htup_details.h
index d406825ff2..a4f917140a 100644
--- a/src/include/access/htup_details.h
+++ b/src/include/access/htup_details.h
@@ -404,7 +404,7 @@ HeapTupleHeaderGetUpdateXid(const HeapTupleHeaderData *tup)
if (!((tup)->t_infomask & HEAP_XMAX_INVALID) &&
((tup)->t_infomask & HEAP_XMAX_IS_MULTI) &&
!((tup)->t_infomask & HEAP_XMAX_LOCK_ONLY))
- return HeapTupleGetUpdateXid(tup);
+ return HeapTupleGetUpdateXid(tup, 13);
else
return HeapTupleHeaderGetRawXmax(tup);
}
diff --git a/src/include/access/multixact.h b/src/include/access/multixact.h
index 26f6bd2890..0df9479d6d 100644
--- a/src/include/access/multixact.h
+++ b/src/include/access/multixact.h
@@ -97,21 +97,24 @@ typedef struct xl_multixact_truncate
extern MultiXactId MultiXactIdCreate(TransactionId xid1,
MultiXactStatus status1, TransactionId xid2,
- MultiXactStatus status2);
+ MultiXactStatus status2, RelFileNumber r);
extern MultiXactId MultiXactIdExpand(MultiXactId multi, TransactionId xid,
- MultiXactStatus status);
+ MultiXactStatus status, RelFileNumber r);
extern MultiXactId MultiXactIdCreateFromMembers(int nmembers,
- MultiXactMember *members);
+ MultiXactMember *members,
+ RelFileNumber r);
extern MultiXactId ReadNextMultiXactId(void);
extern void ReadMultiXactIdRange(MultiXactId *oldest, MultiXactId *next);
extern bool MultiXactIdIsRunning(MultiXactId multi, bool isLockOnly);
extern void MultiXactIdSetOldestMember(void);
extern int GetMultiXactIdMembers(MultiXactId multi, MultiXactMember **members,
- bool from_pgupgrade, bool isLockOnly);
+ bool from_pgupgrade, bool isLockOnly,
+ RelFileNumber r);
extern void GetMultiXactInfo(uint32 *multixacts, MultiXactOffset *nextOffset,
MultiXactId *oldestMultiXactId,
- MultiXactOffset *oldestOffset);
+ MultiXactOffset *oldestOffset,
+ RelFileNumber r);
extern bool MultiXactIdPrecedes(MultiXactId multi1, MultiXactId multi2);
extern bool MultiXactIdPrecedesOrEquals(MultiXactId multi1,
MultiXactId multi2);
diff --git a/src/include/storage/lwlock.h b/src/include/storage/lwlock.h
index 600512be70..9944fbc117 100644
--- a/src/include/storage/lwlock.h
+++ b/src/include/storage/lwlock.h
@@ -122,6 +122,7 @@ extern PGDLLIMPORT bool Trace_lwlocks;
#endif
extern bool LWLockAcquire(LWLock *lock, LWLockMode mode);
+extern bool LWLockAcquireExt(LWLock *lock, LWLockMode mode, uint32 additional_info);
extern bool LWLockConditionalAcquire(LWLock *lock, LWLockMode mode);
extern bool LWLockAcquireOrWait(LWLock *lock, LWLockMode mode);
extern void LWLockRelease(LWLock *lock);
diff --git a/src/test/modules/test_slru/test_multixact.c b/src/test/modules/test_slru/test_multixact.c
index e6de33c424..bc499047eb 100644
--- a/src/test/modules/test_slru/test_multixact.c
+++ b/src/test/modules/test_slru/test_multixact.c
@@ -31,7 +31,7 @@ test_create_multixact(PG_FUNCTION_ARGS)
MultiXactIdSetOldestMember();
id = MultiXactIdCreate(GetCurrentTransactionId(), MultiXactStatusUpdate,
- GetCurrentTransactionId(), MultiXactStatusForShare);
+ GetCurrentTransactionId(), MultiXactStatusForShare, 0);
PG_RETURN_TRANSACTIONID(id);
}
@@ -47,7 +47,7 @@ test_read_multixact(PG_FUNCTION_ARGS)
/* discard caches */
AtEOXact_MultiXact();
- if (GetMultiXactIdMembers(id, &members, false, false) == -1)
+ if (GetMultiXactIdMembers(id, &members, false, false, 0) == -1)
elog(ERROR, "MultiXactId not found");
PG_RETURN_VOID();
--
2.43.0