diff options
author | Heikki Linnakangas <heikki.linnakangas@iki.fi> | 2024-03-03 19:37:28 +0200 |
---|---|---|
committer | Heikki Linnakangas <heikki.linnakangas@iki.fi> | 2024-03-03 19:37:28 +0200 |
commit | ab355e3a88de745607f6dd4c21f0119b5c68f2ad (patch) | |
tree | 7808e71e8fbee29095708f47f80bb2bea099e52e /src/backend/access/transam/twophase.c | |
parent | 30b8d6e4ce1112168ddfe8cdbba76fbefd304b34 (diff) | |
download | postgresql-ab355e3a88de745607f6dd4c21f0119b5c68f2ad.tar.gz postgresql-ab355e3a88de745607f6dd4c21f0119b5c68f2ad.zip |
Redefine backend ID to be an index into the proc array
Previously, backend ID was an index into the ProcState array, in the
shared cache invalidation manager (sinvaladt.c). The entry in the
ProcState array was reserved at backend startup by scanning the array
for a free entry, and that was also when the backend got its backend
ID. Things become slightly simpler if we redefine backend ID to be the
index into the PGPROC array, and directly use it also as an index to
the ProcState array. This uses a little more memory, as we reserve a
few extra slots in the ProcState array for aux processes that don't
need them, but the simplicity is worth it.
Aux processes now also have a backend ID. This simplifies the
reservation of BackendStatusArray and ProcSignal slots.
You can now convert a backend ID into an index into the PGPROC array
simply by subtracting 1. We still use 0-based "pgprocnos" in various
places, for indexes into the PGPROC array, but the only difference now
is that backend IDs start at 1 while pgprocnos start at 0. (The next
commmit will get rid of the term "backend ID" altogether and make
everything 0-based.)
There is still a 'backendId' field in PGPROC, now part of 'vxid' which
encapsulates the backend ID and local transaction ID together. It's
needed for prepared xacts. For regular backends, the backendId is
always equal to pgprocno + 1, but for prepared xact PGPROC entries,
it's the ID of the original backend that processed the transaction.
Reviewed-by: Andres Freund, Reid Thompson
Discussion: https://www.postgresql.org/message-id/8171f1aa-496f-46a6-afc3-c46fe7a9b407@iki.fi
Diffstat (limited to 'src/backend/access/transam/twophase.c')
-rw-r--r-- | src/backend/access/transam/twophase.c | 37 |
1 files changed, 11 insertions, 26 deletions
diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c index 234c8d08ebc..5c282002900 100644 --- a/src/backend/access/transam/twophase.c +++ b/src/backend/access/transam/twophase.c @@ -151,7 +151,6 @@ typedef struct GlobalTransactionData { GlobalTransaction next; /* list link for free list */ int pgprocno; /* ID of associated dummy PGPROC */ - BackendId dummyBackendId; /* similar to backend id for backends */ TimestampTz prepared_at; /* time of preparation */ /* @@ -285,20 +284,6 @@ TwoPhaseShmemInit(void) /* associate it with a PGPROC assigned by InitProcGlobal */ gxacts[i].pgprocno = GetNumberFromPGProc(&PreparedXactProcs[i]); - - /* - * Assign a unique ID for each dummy proc, so that the range of - * dummy backend IDs immediately follows the range of normal - * backend IDs. We don't dare to assign a real backend ID to dummy - * procs, because prepared transactions don't take part in cache - * invalidation like a real backend ID would imply, but having a - * unique ID for them is nevertheless handy. This arrangement - * allows you to allocate an array of size (MaxBackends + - * max_prepared_xacts + 1), and have a slot for every backend and - * prepared transaction. Currently multixact.c uses that - * technique. - */ - gxacts[i].dummyBackendId = MaxBackends + 1 + i; } } else @@ -457,24 +442,24 @@ MarkAsPreparingGuts(GlobalTransaction gxact, TransactionId xid, const char *gid, Assert(LWLockHeldByMeInMode(TwoPhaseStateLock, LW_EXCLUSIVE)); Assert(gxact != NULL); - proc = &ProcGlobal->allProcs[gxact->pgprocno]; + proc = GetPGProcByNumber(gxact->pgprocno); /* Initialize the PGPROC entry */ MemSet(proc, 0, sizeof(PGPROC)); dlist_node_init(&proc->links); proc->waitStatus = PROC_WAIT_STATUS_OK; - if (LocalTransactionIdIsValid(MyProc->lxid)) + if (LocalTransactionIdIsValid(MyProc->vxid.lxid)) { /* clone VXID, for TwoPhaseGetXidByVirtualXID() to find */ - proc->lxid = MyProc->lxid; - proc->backendId = MyBackendId; + proc->vxid.lxid = MyProc->vxid.lxid; + proc->vxid.backendId = MyBackendId; } else { Assert(AmStartupProcess() || !IsPostmasterEnvironment); /* GetLockConflicts() uses this to specify a wait on the XID */ - proc->lxid = xid; - proc->backendId = InvalidBackendId; + proc->vxid.lxid = xid; + proc->vxid.backendId = InvalidBackendId; } proc->xid = xid; Assert(proc->xmin == InvalidTransactionId); @@ -522,7 +507,7 @@ static void GXactLoadSubxactData(GlobalTransaction gxact, int nsubxacts, TransactionId *children) { - PGPROC *proc = &ProcGlobal->allProcs[gxact->pgprocno]; + PGPROC *proc = GetPGProcByNumber(gxact->pgprocno); /* We need no extra lock since the GXACT isn't valid yet */ if (nsubxacts > PGPROC_MAX_CACHED_SUBXIDS) @@ -559,7 +544,7 @@ MarkAsPrepared(GlobalTransaction gxact, bool lock_held) * Put it into the global ProcArray so TransactionIdIsInProgress considers * the XID as still running. */ - ProcArrayAdd(&ProcGlobal->allProcs[gxact->pgprocno]); + ProcArrayAdd(GetPGProcByNumber(gxact->pgprocno)); } /* @@ -583,7 +568,7 @@ LockGXact(const char *gid, Oid user) for (i = 0; i < TwoPhaseState->numPrepXacts; i++) { GlobalTransaction gxact = TwoPhaseState->prepXacts[i]; - PGPROC *proc = &ProcGlobal->allProcs[gxact->pgprocno]; + PGPROC *proc = GetPGProcByNumber(gxact->pgprocno); /* Ignore not-yet-valid GIDs */ if (!gxact->valid) @@ -884,7 +869,7 @@ TwoPhaseGetXidByVirtualXID(VirtualTransactionId vxid, if (!gxact->valid) continue; - proc = &ProcGlobal->allProcs[gxact->pgprocno]; + proc = GetPGProcByNumber(gxact->pgprocno); GET_VXID_FROM_PGPROC(proc_vxid, *proc); if (VirtualTransactionIdEquals(vxid, proc_vxid)) { @@ -919,7 +904,7 @@ TwoPhaseGetDummyBackendId(TransactionId xid, bool lock_held) { GlobalTransaction gxact = TwoPhaseGetGXact(xid, lock_held); - return gxact->dummyBackendId; + return gxact->pgprocno + 1; } /* |