mirror of
https://github.com/postgres/postgres.git
synced 2025-12-19 17:02:53 +03:00
Replace BackendIds with 0-based ProcNumbers
Now that BackendId was just another index into the proc array, it was redundant with the 0-based proc numbers used in other places. Replace all usage of backend IDs with proc numbers. The only place where the term "backend id" remains is in a few pgstat functions that expose backend IDs at the SQL level. Those IDs are now in fact 0-based ProcNumbers too, but the documentation still calls them "backend ids". That term still seems appropriate to describe what the numbers are, so I let it be. One user-visible effect is that pg_temp_0 is now a valid temp schema name, for backend with ProcNumber 0. Reviewed-by: Andres Freund Discussion: https://www.postgresql.org/message-id/8171f1aa-496f-46a6-afc3-c46fe7a9b407@iki.fi
This commit is contained in:
@@ -203,12 +203,12 @@ pg_subtrans and PGPROC are done at the time it is assigned.
|
||||
A transaction that has no XID still needs to be identified for various
|
||||
purposes, notably holding locks. For this purpose we assign a "virtual
|
||||
transaction ID" or VXID to each top-level transaction. VXIDs are formed from
|
||||
two fields, the backendID and a backend-local counter; this arrangement allows
|
||||
assignment of a new VXID at transaction start without any contention for
|
||||
shared memory. To ensure that a VXID isn't re-used too soon after backend
|
||||
two fields, the procNumber and a backend-local counter; this arrangement
|
||||
allows assignment of a new VXID at transaction start without any contention
|
||||
for shared memory. To ensure that a VXID isn't re-used too soon after backend
|
||||
exit, we store the last local counter value into shared memory at backend
|
||||
exit, and initialize it from the previous value for the same backendID slot
|
||||
at backend start. All these counters go back to zero at shared memory
|
||||
exit, and initialize it from the previous value for the same PGPROC slot at
|
||||
backend start. All these counters go back to zero at shared memory
|
||||
re-initialization, but that's OK because VXIDs never appear anywhere on-disk.
|
||||
|
||||
Internally, a backend needs a way to identify subtransactions whether or not
|
||||
|
||||
@@ -501,7 +501,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status,
|
||||
* still work, just less efficiently -- we handle this case by
|
||||
* switching to a different bank lock in the loop below.
|
||||
*/
|
||||
if (nextidx != INVALID_PGPROCNO &&
|
||||
if (nextidx != INVALID_PROC_NUMBER &&
|
||||
GetPGProcByNumber(nextidx)->clogGroupMemberPage != proc->clogGroupMemberPage)
|
||||
{
|
||||
/*
|
||||
@@ -509,7 +509,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status,
|
||||
* needs an XID status update.
|
||||
*/
|
||||
proc->clogGroupMember = false;
|
||||
pg_atomic_write_u32(&proc->clogGroupNext, INVALID_PGPROCNO);
|
||||
pg_atomic_write_u32(&proc->clogGroupNext, INVALID_PROC_NUMBER);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -525,9 +525,9 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status,
|
||||
* If the list was not empty, the leader will update the status of our
|
||||
* XID. It is impossible to have followers without a leader because the
|
||||
* first process that has added itself to the list will always have
|
||||
* nextidx as INVALID_PGPROCNO.
|
||||
* nextidx as INVALID_PROC_NUMBER.
|
||||
*/
|
||||
if (nextidx != INVALID_PGPROCNO)
|
||||
if (nextidx != INVALID_PROC_NUMBER)
|
||||
{
|
||||
int extraWaits = 0;
|
||||
|
||||
@@ -543,7 +543,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status,
|
||||
}
|
||||
pgstat_report_wait_end();
|
||||
|
||||
Assert(pg_atomic_read_u32(&proc->clogGroupNext) == INVALID_PGPROCNO);
|
||||
Assert(pg_atomic_read_u32(&proc->clogGroupNext) == INVALID_PROC_NUMBER);
|
||||
|
||||
/* Fix semaphore count for any absorbed wakeups */
|
||||
while (extraWaits-- > 0)
|
||||
@@ -568,13 +568,13 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status,
|
||||
* group.
|
||||
*/
|
||||
nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst,
|
||||
INVALID_PGPROCNO);
|
||||
INVALID_PROC_NUMBER);
|
||||
|
||||
/* Remember head of list so we can perform wakeups after dropping lock. */
|
||||
wakeidx = nextidx;
|
||||
|
||||
/* Walk the list and update the status of all XIDs. */
|
||||
while (nextidx != INVALID_PGPROCNO)
|
||||
while (nextidx != INVALID_PROC_NUMBER)
|
||||
{
|
||||
PGPROC *nextproc = &ProcGlobal->allProcs[nextidx];
|
||||
int thispageno = nextproc->clogGroupMemberPage;
|
||||
@@ -633,12 +633,12 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status,
|
||||
* clogGroupNext to invalid while saving the semaphores to an array, then
|
||||
* a single write barrier, then another pass unlocking the semaphores.)
|
||||
*/
|
||||
while (wakeidx != INVALID_PGPROCNO)
|
||||
while (wakeidx != INVALID_PROC_NUMBER)
|
||||
{
|
||||
PGPROC *wakeproc = &ProcGlobal->allProcs[wakeidx];
|
||||
|
||||
wakeidx = pg_atomic_read_u32(&wakeproc->clogGroupNext);
|
||||
pg_atomic_write_u32(&wakeproc->clogGroupNext, INVALID_PGPROCNO);
|
||||
pg_atomic_write_u32(&wakeproc->clogGroupNext, INVALID_PROC_NUMBER);
|
||||
|
||||
/* ensure all previous writes are visible before follower continues. */
|
||||
pg_write_barrier();
|
||||
|
||||
@@ -237,11 +237,11 @@ typedef struct MultiXactStateData
|
||||
/*
|
||||
* Per-backend data starts here. We have two arrays stored in the area
|
||||
* immediately following the MultiXactStateData struct. Each is indexed by
|
||||
* BackendId.
|
||||
* ProcNumber.
|
||||
*
|
||||
* In both arrays, there's a slot for all normal backends (1..MaxBackends)
|
||||
* followed by a slot for max_prepared_xacts prepared transactions. Valid
|
||||
* BackendIds start from 1; element zero of each array is never used.
|
||||
* In both arrays, there's a slot for all normal backends
|
||||
* (0..MaxBackends-1) followed by a slot for max_prepared_xacts prepared
|
||||
* transactions.
|
||||
*
|
||||
* OldestMemberMXactId[k] is the oldest MultiXactId each backend's current
|
||||
* transaction(s) could possibly be a member of, or InvalidMultiXactId
|
||||
@@ -285,8 +285,7 @@ typedef struct MultiXactStateData
|
||||
} MultiXactStateData;
|
||||
|
||||
/*
|
||||
* Last element of OldestMemberMXactId and OldestVisibleMXactId arrays.
|
||||
* Valid elements are (1..MaxOldestSlot); element 0 is never used.
|
||||
* Size of OldestMemberMXactId and OldestVisibleMXactId arrays.
|
||||
*/
|
||||
#define MaxOldestSlot (MaxBackends + max_prepared_xacts)
|
||||
|
||||
@@ -397,7 +396,7 @@ MultiXactIdCreate(TransactionId xid1, MultiXactStatus status1,
|
||||
Assert(!TransactionIdEquals(xid1, xid2) || (status1 != status2));
|
||||
|
||||
/* MultiXactIdSetOldestMember() must have been called already. */
|
||||
Assert(MultiXactIdIsValid(OldestMemberMXactId[MyBackendId]));
|
||||
Assert(MultiXactIdIsValid(OldestMemberMXactId[MyProcNumber]));
|
||||
|
||||
/*
|
||||
* Note: unlike MultiXactIdExpand, we don't bother to check that both XIDs
|
||||
@@ -451,7 +450,7 @@ MultiXactIdExpand(MultiXactId multi, TransactionId xid, MultiXactStatus status)
|
||||
Assert(TransactionIdIsValid(xid));
|
||||
|
||||
/* MultiXactIdSetOldestMember() must have been called already. */
|
||||
Assert(MultiXactIdIsValid(OldestMemberMXactId[MyBackendId]));
|
||||
Assert(MultiXactIdIsValid(OldestMemberMXactId[MyProcNumber]));
|
||||
|
||||
debug_elog5(DEBUG2, "Expand: received multi %u, xid %u status %s",
|
||||
multi, xid, mxstatus_to_string(status));
|
||||
@@ -626,7 +625,7 @@ MultiXactIdIsRunning(MultiXactId multi, bool isLockOnly)
|
||||
void
|
||||
MultiXactIdSetOldestMember(void)
|
||||
{
|
||||
if (!MultiXactIdIsValid(OldestMemberMXactId[MyBackendId]))
|
||||
if (!MultiXactIdIsValid(OldestMemberMXactId[MyProcNumber]))
|
||||
{
|
||||
MultiXactId nextMXact;
|
||||
|
||||
@@ -655,12 +654,12 @@ MultiXactIdSetOldestMember(void)
|
||||
if (nextMXact < FirstMultiXactId)
|
||||
nextMXact = FirstMultiXactId;
|
||||
|
||||
OldestMemberMXactId[MyBackendId] = nextMXact;
|
||||
OldestMemberMXactId[MyProcNumber] = nextMXact;
|
||||
|
||||
LWLockRelease(MultiXactGenLock);
|
||||
|
||||
debug_elog4(DEBUG2, "MultiXact: setting OldestMember[%d] = %u",
|
||||
MyBackendId, nextMXact);
|
||||
MyProcNumber, nextMXact);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -683,7 +682,7 @@ MultiXactIdSetOldestMember(void)
|
||||
static void
|
||||
MultiXactIdSetOldestVisible(void)
|
||||
{
|
||||
if (!MultiXactIdIsValid(OldestVisibleMXactId[MyBackendId]))
|
||||
if (!MultiXactIdIsValid(OldestVisibleMXactId[MyProcNumber]))
|
||||
{
|
||||
MultiXactId oldestMXact;
|
||||
int i;
|
||||
@@ -699,7 +698,7 @@ MultiXactIdSetOldestVisible(void)
|
||||
if (oldestMXact < FirstMultiXactId)
|
||||
oldestMXact = FirstMultiXactId;
|
||||
|
||||
for (i = 1; i <= MaxOldestSlot; i++)
|
||||
for (i = 0; i < MaxOldestSlot; i++)
|
||||
{
|
||||
MultiXactId thisoldest = OldestMemberMXactId[i];
|
||||
|
||||
@@ -708,12 +707,12 @@ MultiXactIdSetOldestVisible(void)
|
||||
oldestMXact = thisoldest;
|
||||
}
|
||||
|
||||
OldestVisibleMXactId[MyBackendId] = oldestMXact;
|
||||
OldestVisibleMXactId[MyProcNumber] = oldestMXact;
|
||||
|
||||
LWLockRelease(MultiXactGenLock);
|
||||
|
||||
debug_elog4(DEBUG2, "MultiXact: setting OldestVisible[%d] = %u",
|
||||
MyBackendId, oldestMXact);
|
||||
MyProcNumber, oldestMXact);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1285,7 +1284,7 @@ GetMultiXactIdMembers(MultiXactId multi, MultiXactMember **members,
|
||||
* multi. It cannot possibly still be running.
|
||||
*/
|
||||
if (isLockOnly &&
|
||||
MultiXactIdPrecedes(multi, OldestVisibleMXactId[MyBackendId]))
|
||||
MultiXactIdPrecedes(multi, OldestVisibleMXactId[MyProcNumber]))
|
||||
{
|
||||
debug_elog2(DEBUG2, "GetMembers: a locker-only multi is too old");
|
||||
*members = NULL;
|
||||
@@ -1752,8 +1751,8 @@ AtEOXact_MultiXact(void)
|
||||
* We assume that storing a MultiXactId is atomic and so we need not take
|
||||
* MultiXactGenLock to do this.
|
||||
*/
|
||||
OldestMemberMXactId[MyBackendId] = InvalidMultiXactId;
|
||||
OldestVisibleMXactId[MyBackendId] = InvalidMultiXactId;
|
||||
OldestMemberMXactId[MyProcNumber] = InvalidMultiXactId;
|
||||
OldestVisibleMXactId[MyProcNumber] = InvalidMultiXactId;
|
||||
|
||||
/*
|
||||
* Discard the local MultiXactId cache. Since MXactContext was created as
|
||||
@@ -1773,7 +1772,7 @@ AtEOXact_MultiXact(void)
|
||||
void
|
||||
AtPrepare_MultiXact(void)
|
||||
{
|
||||
MultiXactId myOldestMember = OldestMemberMXactId[MyBackendId];
|
||||
MultiXactId myOldestMember = OldestMemberMXactId[MyProcNumber];
|
||||
|
||||
if (MultiXactIdIsValid(myOldestMember))
|
||||
RegisterTwoPhaseRecord(TWOPHASE_RM_MULTIXACT_ID, 0,
|
||||
@@ -1793,10 +1792,10 @@ PostPrepare_MultiXact(TransactionId xid)
|
||||
* Transfer our OldestMemberMXactId value to the slot reserved for the
|
||||
* prepared transaction.
|
||||
*/
|
||||
myOldestMember = OldestMemberMXactId[MyBackendId];
|
||||
myOldestMember = OldestMemberMXactId[MyProcNumber];
|
||||
if (MultiXactIdIsValid(myOldestMember))
|
||||
{
|
||||
BackendId dummyBackendId = TwoPhaseGetDummyBackendId(xid, false);
|
||||
ProcNumber dummyProcNumber = TwoPhaseGetDummyProcNumber(xid, false);
|
||||
|
||||
/*
|
||||
* Even though storing MultiXactId is atomic, acquire lock to make
|
||||
@@ -1806,8 +1805,8 @@ PostPrepare_MultiXact(TransactionId xid)
|
||||
*/
|
||||
LWLockAcquire(MultiXactGenLock, LW_EXCLUSIVE);
|
||||
|
||||
OldestMemberMXactId[dummyBackendId] = myOldestMember;
|
||||
OldestMemberMXactId[MyBackendId] = InvalidMultiXactId;
|
||||
OldestMemberMXactId[dummyProcNumber] = myOldestMember;
|
||||
OldestMemberMXactId[MyProcNumber] = InvalidMultiXactId;
|
||||
|
||||
LWLockRelease(MultiXactGenLock);
|
||||
}
|
||||
@@ -1820,7 +1819,7 @@ PostPrepare_MultiXact(TransactionId xid)
|
||||
* We assume that storing a MultiXactId is atomic and so we need not take
|
||||
* MultiXactGenLock to do this.
|
||||
*/
|
||||
OldestVisibleMXactId[MyBackendId] = InvalidMultiXactId;
|
||||
OldestVisibleMXactId[MyProcNumber] = InvalidMultiXactId;
|
||||
|
||||
/*
|
||||
* Discard the local MultiXactId cache like in AtEOXact_MultiXact.
|
||||
@@ -1837,7 +1836,7 @@ void
|
||||
multixact_twophase_recover(TransactionId xid, uint16 info,
|
||||
void *recdata, uint32 len)
|
||||
{
|
||||
BackendId dummyBackendId = TwoPhaseGetDummyBackendId(xid, false);
|
||||
ProcNumber dummyProcNumber = TwoPhaseGetDummyProcNumber(xid, false);
|
||||
MultiXactId oldestMember;
|
||||
|
||||
/*
|
||||
@@ -1847,7 +1846,7 @@ multixact_twophase_recover(TransactionId xid, uint16 info,
|
||||
Assert(len == sizeof(MultiXactId));
|
||||
oldestMember = *((MultiXactId *) recdata);
|
||||
|
||||
OldestMemberMXactId[dummyBackendId] = oldestMember;
|
||||
OldestMemberMXactId[dummyProcNumber] = oldestMember;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1858,11 +1857,11 @@ void
|
||||
multixact_twophase_postcommit(TransactionId xid, uint16 info,
|
||||
void *recdata, uint32 len)
|
||||
{
|
||||
BackendId dummyBackendId = TwoPhaseGetDummyBackendId(xid, true);
|
||||
ProcNumber dummyProcNumber = TwoPhaseGetDummyProcNumber(xid, true);
|
||||
|
||||
Assert(len == sizeof(MultiXactId));
|
||||
|
||||
OldestMemberMXactId[dummyBackendId] = InvalidMultiXactId;
|
||||
OldestMemberMXactId[dummyProcNumber] = InvalidMultiXactId;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1886,9 +1885,9 @@ MultiXactShmemSize(void)
|
||||
{
|
||||
Size size;
|
||||
|
||||
/* We need 2*MaxOldestSlot + 1 perBackendXactIds[] entries */
|
||||
/* We need 2*MaxOldestSlot perBackendXactIds[] entries */
|
||||
#define SHARED_MULTIXACT_STATE_SIZE \
|
||||
add_size(offsetof(MultiXactStateData, perBackendXactIds) + sizeof(MultiXactId), \
|
||||
add_size(offsetof(MultiXactStateData, perBackendXactIds), \
|
||||
mul_size(sizeof(MultiXactId) * 2, MaxOldestSlot))
|
||||
|
||||
size = SHARED_MULTIXACT_STATE_SIZE;
|
||||
@@ -1938,8 +1937,7 @@ MultiXactShmemInit(void)
|
||||
Assert(found);
|
||||
|
||||
/*
|
||||
* Set up array pointers. Note that perBackendXactIds[0] is wasted space
|
||||
* since we only use indexes 1..MaxOldestSlot in each array.
|
||||
* Set up array pointers.
|
||||
*/
|
||||
OldestMemberMXactId = MultiXactState->perBackendXactIds;
|
||||
OldestVisibleMXactId = OldestMemberMXactId + MaxOldestSlot;
|
||||
@@ -2617,7 +2615,7 @@ GetOldestMultiXactId(void)
|
||||
nextMXact = FirstMultiXactId;
|
||||
|
||||
oldestMXact = nextMXact;
|
||||
for (i = 1; i <= MaxOldestSlot; i++)
|
||||
for (i = 0; i < MaxOldestSlot; i++)
|
||||
{
|
||||
MultiXactId thisoldest;
|
||||
|
||||
|
||||
@@ -94,7 +94,7 @@ typedef struct FixedParallelState
|
||||
bool is_superuser;
|
||||
PGPROC *parallel_leader_pgproc;
|
||||
pid_t parallel_leader_pid;
|
||||
BackendId parallel_leader_backend_id;
|
||||
ProcNumber parallel_leader_proc_number;
|
||||
TimestampTz xact_ts;
|
||||
TimestampTz stmt_ts;
|
||||
SerializableXactHandle serializable_xact_handle;
|
||||
@@ -337,7 +337,7 @@ InitializeParallelDSM(ParallelContext *pcxt)
|
||||
&fps->temp_toast_namespace_id);
|
||||
fps->parallel_leader_pgproc = MyProc;
|
||||
fps->parallel_leader_pid = MyProcPid;
|
||||
fps->parallel_leader_backend_id = MyBackendId;
|
||||
fps->parallel_leader_proc_number = MyProcNumber;
|
||||
fps->xact_ts = GetCurrentTransactionStartTimestamp();
|
||||
fps->stmt_ts = GetCurrentStatementStartTimestamp();
|
||||
fps->serializable_xact_handle = ShareSerializableXact();
|
||||
@@ -1351,7 +1351,7 @@ ParallelWorkerMain(Datum main_arg)
|
||||
|
||||
/* Arrange to signal the leader if we exit. */
|
||||
ParallelLeaderPid = fps->parallel_leader_pid;
|
||||
ParallelLeaderBackendId = fps->parallel_leader_backend_id;
|
||||
ParallelLeaderProcNumber = fps->parallel_leader_proc_number;
|
||||
before_shmem_exit(ParallelWorkerShutdown, PointerGetDatum(seg));
|
||||
|
||||
/*
|
||||
@@ -1367,7 +1367,7 @@ ParallelWorkerMain(Datum main_arg)
|
||||
mqh = shm_mq_attach(mq, seg, NULL);
|
||||
pq_redirect_to_shm_mq(seg, mqh);
|
||||
pq_set_parallel_leader(fps->parallel_leader_pid,
|
||||
fps->parallel_leader_backend_id);
|
||||
fps->parallel_leader_proc_number);
|
||||
|
||||
/*
|
||||
* Send a BackendKeyData message to the process that initiated parallelism
|
||||
@@ -1594,7 +1594,7 @@ ParallelWorkerShutdown(int code, Datum arg)
|
||||
{
|
||||
SendProcSignal(ParallelLeaderPid,
|
||||
PROCSIG_PARALLEL_MESSAGE,
|
||||
ParallelLeaderBackendId);
|
||||
ParallelLeaderProcNumber);
|
||||
|
||||
dsm_detach((dsm_segment *) DatumGetPointer(arg));
|
||||
}
|
||||
|
||||
@@ -132,7 +132,7 @@ int max_prepared_xacts = 0;
|
||||
*
|
||||
* 3. To begin COMMIT PREPARED or ROLLBACK PREPARED, check that the entry is
|
||||
* valid and not locked, then mark the entry as locked by storing my current
|
||||
* backend ID into locking_backend. This prevents concurrent attempts to
|
||||
* proc number into locking_backend. This prevents concurrent attempts to
|
||||
* commit or rollback the same prepared xact.
|
||||
*
|
||||
* 4. On completion of COMMIT PREPARED or ROLLBACK PREPARED, remove the entry
|
||||
@@ -165,7 +165,7 @@ typedef struct GlobalTransactionData
|
||||
TransactionId xid; /* The GXACT id */
|
||||
|
||||
Oid owner; /* ID of user that executed the xact */
|
||||
BackendId locking_backend; /* backend currently working on the xact */
|
||||
ProcNumber locking_backend; /* backend currently working on the xact */
|
||||
bool valid; /* true if PGPROC entry is in proc array */
|
||||
bool ondisk; /* true if prepare state file is on disk */
|
||||
bool inredo; /* true if entry was added via xlog_redo */
|
||||
@@ -333,7 +333,7 @@ AtAbort_Twophase(void)
|
||||
if (!MyLockedGxact->valid)
|
||||
RemoveGXact(MyLockedGxact);
|
||||
else
|
||||
MyLockedGxact->locking_backend = InvalidBackendId;
|
||||
MyLockedGxact->locking_backend = INVALID_PROC_NUMBER;
|
||||
LWLockRelease(TwoPhaseStateLock);
|
||||
|
||||
MyLockedGxact = NULL;
|
||||
@@ -347,7 +347,7 @@ void
|
||||
PostPrepare_Twophase(void)
|
||||
{
|
||||
LWLockAcquire(TwoPhaseStateLock, LW_EXCLUSIVE);
|
||||
MyLockedGxact->locking_backend = InvalidBackendId;
|
||||
MyLockedGxact->locking_backend = INVALID_PROC_NUMBER;
|
||||
LWLockRelease(TwoPhaseStateLock);
|
||||
|
||||
MyLockedGxact = NULL;
|
||||
@@ -452,14 +452,14 @@ MarkAsPreparingGuts(GlobalTransaction gxact, TransactionId xid, const char *gid,
|
||||
{
|
||||
/* clone VXID, for TwoPhaseGetXidByVirtualXID() to find */
|
||||
proc->vxid.lxid = MyProc->vxid.lxid;
|
||||
proc->vxid.backendId = MyBackendId;
|
||||
proc->vxid.procNumber = MyProcNumber;
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert(AmStartupProcess() || !IsPostmasterEnvironment);
|
||||
/* GetLockConflicts() uses this to specify a wait on the XID */
|
||||
proc->vxid.lxid = xid;
|
||||
proc->vxid.backendId = InvalidBackendId;
|
||||
proc->vxid.procNumber = INVALID_PROC_NUMBER;
|
||||
}
|
||||
proc->xid = xid;
|
||||
Assert(proc->xmin == InvalidTransactionId);
|
||||
@@ -484,7 +484,7 @@ MarkAsPreparingGuts(GlobalTransaction gxact, TransactionId xid, const char *gid,
|
||||
gxact->prepared_at = prepared_at;
|
||||
gxact->xid = xid;
|
||||
gxact->owner = owner;
|
||||
gxact->locking_backend = MyBackendId;
|
||||
gxact->locking_backend = MyProcNumber;
|
||||
gxact->valid = false;
|
||||
gxact->inredo = false;
|
||||
strcpy(gxact->gid, gid);
|
||||
@@ -577,7 +577,7 @@ LockGXact(const char *gid, Oid user)
|
||||
continue;
|
||||
|
||||
/* Found it, but has someone else got it locked? */
|
||||
if (gxact->locking_backend != InvalidBackendId)
|
||||
if (gxact->locking_backend != INVALID_PROC_NUMBER)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
|
||||
errmsg("prepared transaction with identifier \"%s\" is busy",
|
||||
@@ -602,7 +602,7 @@ LockGXact(const char *gid, Oid user)
|
||||
errhint("Connect to the database where the transaction was prepared to finish it.")));
|
||||
|
||||
/* OK for me to lock it */
|
||||
gxact->locking_backend = MyBackendId;
|
||||
gxact->locking_backend = MyProcNumber;
|
||||
MyLockedGxact = gxact;
|
||||
|
||||
LWLockRelease(TwoPhaseStateLock);
|
||||
@@ -849,7 +849,7 @@ TwoPhaseGetGXact(TransactionId xid, bool lock_held)
|
||||
*
|
||||
* (This won't find recovered xacts.) If more than one matches, return any
|
||||
* and set "have_more" to true. To witness multiple matches, a single
|
||||
* BackendId must consume 2^32 LXIDs, with no intervening database restart.
|
||||
* proc number must consume 2^32 LXIDs, with no intervening database restart.
|
||||
*/
|
||||
TransactionId
|
||||
TwoPhaseGetXidByVirtualXID(VirtualTransactionId vxid,
|
||||
@@ -873,7 +873,10 @@ TwoPhaseGetXidByVirtualXID(VirtualTransactionId vxid,
|
||||
GET_VXID_FROM_PGPROC(proc_vxid, *proc);
|
||||
if (VirtualTransactionIdEquals(vxid, proc_vxid))
|
||||
{
|
||||
/* Startup process sets proc->backendId to InvalidBackendId. */
|
||||
/*
|
||||
* Startup process sets proc->vxid.procNumber to
|
||||
* INVALID_PROC_NUMBER.
|
||||
*/
|
||||
Assert(!gxact->inredo);
|
||||
|
||||
if (result != InvalidTransactionId)
|
||||
@@ -891,20 +894,20 @@ TwoPhaseGetXidByVirtualXID(VirtualTransactionId vxid,
|
||||
}
|
||||
|
||||
/*
|
||||
* TwoPhaseGetDummyBackendId
|
||||
* Get the dummy backend ID for prepared transaction specified by XID
|
||||
* TwoPhaseGetDummyProcNumber
|
||||
* Get the dummy proc number for prepared transaction specified by XID
|
||||
*
|
||||
* Dummy backend IDs are similar to real backend IDs of real backends.
|
||||
* They start at MaxBackends + 1, and are unique across all currently active
|
||||
* real backends and prepared transactions. If lock_held is set to true,
|
||||
* Dummy proc numbers are similar to proc numbers of real backends. They
|
||||
* start at MaxBackends, and are unique across all currently active real
|
||||
* backends and prepared transactions. If lock_held is set to true,
|
||||
* TwoPhaseStateLock will not be taken, so the caller had better hold it.
|
||||
*/
|
||||
BackendId
|
||||
TwoPhaseGetDummyBackendId(TransactionId xid, bool lock_held)
|
||||
ProcNumber
|
||||
TwoPhaseGetDummyProcNumber(TransactionId xid, bool lock_held)
|
||||
{
|
||||
GlobalTransaction gxact = TwoPhaseGetGXact(xid, lock_held);
|
||||
|
||||
return gxact->pgprocno + 1;
|
||||
return gxact->pgprocno;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2549,7 +2552,7 @@ PrepareRedoAdd(char *buf, XLogRecPtr start_lsn,
|
||||
gxact->prepare_end_lsn = end_lsn;
|
||||
gxact->xid = hdr->xid;
|
||||
gxact->owner = hdr->owner;
|
||||
gxact->locking_backend = InvalidBackendId;
|
||||
gxact->locking_backend = INVALID_PROC_NUMBER;
|
||||
gxact->valid = false;
|
||||
gxact->ondisk = XLogRecPtrIsInvalid(start_lsn);
|
||||
gxact->inredo = true; /* yes, added in redo */
|
||||
|
||||
@@ -2084,10 +2084,10 @@ StartTransaction(void)
|
||||
AtStart_ResourceOwner();
|
||||
|
||||
/*
|
||||
* Assign a new LocalTransactionId, and combine it with the backendId to
|
||||
* Assign a new LocalTransactionId, and combine it with the proc number to
|
||||
* form a virtual transaction id.
|
||||
*/
|
||||
vxid.backendId = MyBackendId;
|
||||
vxid.procNumber = MyProcNumber;
|
||||
vxid.localTransactionId = GetNextLocalTransactionId();
|
||||
|
||||
/*
|
||||
@@ -2097,9 +2097,10 @@ StartTransaction(void)
|
||||
|
||||
/*
|
||||
* Advertise it in the proc array. We assume assignment of
|
||||
* localTransactionId is atomic, and the backendId should be set already.
|
||||
* localTransactionId is atomic, and the proc number should be set
|
||||
* already.
|
||||
*/
|
||||
Assert(MyProc->vxid.backendId == vxid.backendId);
|
||||
Assert(MyProc->vxid.procNumber == vxid.procNumber);
|
||||
MyProc->vxid.lxid = vxid.localTransactionId;
|
||||
|
||||
TRACE_POSTGRESQL_TRANSACTION_START(vxid.localTransactionId);
|
||||
|
||||
@@ -722,7 +722,7 @@ XLogPrefetcherNextBlock(uintptr_t pgsr_private, XLogRecPtr *lsn)
|
||||
* same relation (with some scheme to handle invalidations
|
||||
* safely), but for now we'll call smgropen() every time.
|
||||
*/
|
||||
reln = smgropen(block->rlocator, InvalidBackendId);
|
||||
reln = smgropen(block->rlocator, INVALID_PROC_NUMBER);
|
||||
|
||||
/*
|
||||
* If the relation file doesn't exist on disk, for example because
|
||||
|
||||
@@ -491,7 +491,7 @@ XLogReadBufferExtended(RelFileLocator rlocator, ForkNumber forknum,
|
||||
}
|
||||
|
||||
/* Open the relation at smgr level */
|
||||
smgr = smgropen(rlocator, InvalidBackendId);
|
||||
smgr = smgropen(rlocator, INVALID_PROC_NUMBER);
|
||||
|
||||
/*
|
||||
* Create the target file if it doesn't already exist. This lets us cope
|
||||
@@ -598,7 +598,7 @@ CreateFakeRelcacheEntry(RelFileLocator rlocator)
|
||||
* We will never be working with temp rels during recovery or while
|
||||
* syncing WAL-skipped files.
|
||||
*/
|
||||
rel->rd_backend = InvalidBackendId;
|
||||
rel->rd_backend = INVALID_PROC_NUMBER;
|
||||
|
||||
/* It must be a permanent table here */
|
||||
rel->rd_rel->relpersistence = RELPERSISTENCE_PERMANENT;
|
||||
@@ -620,7 +620,7 @@ CreateFakeRelcacheEntry(RelFileLocator rlocator)
|
||||
* Set up a non-pinned SMgrRelation reference, so that we don't need to
|
||||
* worry about unpinning it on error.
|
||||
*/
|
||||
rel->rd_smgr = smgropen(rlocator, InvalidBackendId);
|
||||
rel->rd_smgr = smgropen(rlocator, INVALID_PROC_NUMBER);
|
||||
|
||||
return rel;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user