PostgreSQL Source Code git master
procarray.h File Reference
#include "storage/lock.h"
#include "storage/standby.h"
#include "utils/relcache.h"
#include "utils/snapshot.h"
Include dependency graph for procarray.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

Size ProcArrayShmemSize (void)
 
void ProcArrayShmemInit (void)
 
void ProcArrayAdd (PGPROC *proc)
 
void ProcArrayRemove (PGPROC *proc, TransactionId latestXid)
 
void ProcArrayEndTransaction (PGPROC *proc, TransactionId latestXid)
 
void ProcArrayClearTransaction (PGPROC *proc)
 
void ProcArrayInitRecovery (TransactionId initializedUptoXID)
 
void ProcArrayApplyRecoveryInfo (RunningTransactions running)
 
void ProcArrayApplyXidAssignment (TransactionId topxid, int nsubxids, TransactionId *subxids)
 
void RecordKnownAssignedTransactionIds (TransactionId xid)
 
void ExpireTreeKnownAssignedTransactionIds (TransactionId xid, int nsubxids, TransactionId *subxids, TransactionId max_xid)
 
void ExpireAllKnownAssignedTransactionIds (void)
 
void ExpireOldKnownAssignedTransactionIds (TransactionId xid)
 
void KnownAssignedTransactionIdsIdleMaintenance (void)
 
int GetMaxSnapshotXidCount (void)
 
int GetMaxSnapshotSubxidCount (void)
 
Snapshot GetSnapshotData (Snapshot snapshot)
 
bool ProcArrayInstallImportedXmin (TransactionId xmin, VirtualTransactionId *sourcevxid)
 
bool ProcArrayInstallRestoredXmin (TransactionId xmin, PGPROC *proc)
 
RunningTransactions GetRunningTransactionData (void)
 
bool TransactionIdIsInProgress (TransactionId xid)
 
TransactionId GetOldestNonRemovableTransactionId (Relation rel)
 
TransactionId GetOldestTransactionIdConsideredRunning (void)
 
TransactionId GetOldestActiveTransactionId (bool inCommitOnly, bool allDbs)
 
TransactionId GetOldestSafeDecodingTransactionId (bool catalogOnly)
 
void GetReplicationHorizons (TransactionId *xmin, TransactionId *catalog_xmin)
 
VirtualTransactionIdGetVirtualXIDsDelayingChkpt (int *nvxids, int type)
 
bool HaveVirtualXIDsDelayingChkpt (VirtualTransactionId *vxids, int nvxids, int type)
 
PGPROCProcNumberGetProc (int procNumber)
 
void ProcNumberGetTransactionIds (int procNumber, TransactionId *xid, TransactionId *xmin, int *nsubxid, bool *overflowed)
 
PGPROCBackendPidGetProc (int pid)
 
PGPROCBackendPidGetProcWithLock (int pid)
 
int BackendXidGetPid (TransactionId xid)
 
bool IsBackendPid (int pid)
 
VirtualTransactionIdGetCurrentVirtualXIDs (TransactionId limitXmin, bool excludeXmin0, bool allDbs, int excludeVacuum, int *nvxids)
 
VirtualTransactionIdGetConflictingVirtualXIDs (TransactionId limitXmin, Oid dbOid)
 
pid_t CancelVirtualTransaction (VirtualTransactionId vxid, ProcSignalReason sigmode)
 
pid_t SignalVirtualTransaction (VirtualTransactionId vxid, ProcSignalReason sigmode, bool conflictPending)
 
bool MinimumActiveBackends (int min)
 
int CountDBBackends (Oid databaseid)
 
int CountDBConnections (Oid databaseid)
 
void CancelDBBackends (Oid databaseid, ProcSignalReason sigmode, bool conflictPending)
 
int CountUserBackends (Oid roleid)
 
bool CountOtherDBBackends (Oid databaseId, int *nbackends, int *nprepared)
 
void TerminateOtherDBBackends (Oid databaseId)
 
void XidCacheRemoveRunningXids (TransactionId xid, int nxids, const TransactionId *xids, TransactionId latestXid)
 
void ProcArraySetReplicationSlotXmin (TransactionId xmin, TransactionId catalog_xmin, bool already_locked)
 
void ProcArrayGetReplicationSlotXmin (TransactionId *xmin, TransactionId *catalog_xmin)
 

Function Documentation

◆ BackendPidGetProc()

PGPROC * BackendPidGetProc ( int  pid)

Definition at line 3158 of file procarray.c.

3159{
3160 PGPROC *result;
3161
3162 if (pid == 0) /* never match dummy PGPROCs */
3163 return NULL;
3164
3165 LWLockAcquire(ProcArrayLock, LW_SHARED);
3166
3167 result = BackendPidGetProcWithLock(pid);
3168
3169 LWLockRelease(ProcArrayLock);
3170
3171 return result;
3172}
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1174
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1894
@ LW_SHARED
Definition: lwlock.h:113
PGPROC * BackendPidGetProcWithLock(int pid)
Definition: procarray.c:3181
Definition: proc.h:179

References BackendPidGetProcWithLock(), LW_SHARED, LWLockAcquire(), and LWLockRelease().

Referenced by IsBackendPid(), pg_isolation_test_session_is_blocked(), pg_log_backend_memory_contexts(), pg_signal_backend(), pg_stat_get_activity(), pg_stat_get_backend_wait_event(), pg_stat_get_backend_wait_event_type(), pg_stat_reset_backend_stats(), pgstat_fetch_stat_backend_by_pid(), TerminateOtherDBBackends(), and test_shm_mq_main().

◆ BackendPidGetProcWithLock()

PGPROC * BackendPidGetProcWithLock ( int  pid)

Definition at line 3181 of file procarray.c.

3182{
3183 PGPROC *result = NULL;
3184 ProcArrayStruct *arrayP = procArray;
3185 int index;
3186
3187 if (pid == 0) /* never match dummy PGPROCs */
3188 return NULL;
3189
3190 for (index = 0; index < arrayP->numProcs; index++)
3191 {
3192 PGPROC *proc = &allProcs[arrayP->pgprocnos[index]];
3193
3194 if (proc->pid == pid)
3195 {
3196 result = proc;
3197 break;
3198 }
3199 }
3200
3201 return result;
3202}
static PGPROC * allProcs
Definition: procarray.c:271
static ProcArrayStruct * procArray
Definition: procarray.c:269
int pid
Definition: proc.h:199
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:99
Definition: type.h:96

References allProcs, ProcArrayStruct::numProcs, ProcArrayStruct::pgprocnos, PGPROC::pid, and procArray.

Referenced by BackendPidGetProc(), and GetBlockerStatusData().

◆ BackendXidGetPid()

int BackendXidGetPid ( TransactionId  xid)

Definition at line 3218 of file procarray.c.

3219{
3220 int result = 0;
3221 ProcArrayStruct *arrayP = procArray;
3222 TransactionId *other_xids = ProcGlobal->xids;
3223 int index;
3224
3225 if (xid == InvalidTransactionId) /* never match invalid xid */
3226 return 0;
3227
3228 LWLockAcquire(ProcArrayLock, LW_SHARED);
3229
3230 for (index = 0; index < arrayP->numProcs; index++)
3231 {
3232 if (other_xids[index] == xid)
3233 {
3234 int pgprocno = arrayP->pgprocnos[index];
3235 PGPROC *proc = &allProcs[pgprocno];
3236
3237 result = proc->pid;
3238 break;
3239 }
3240 }
3241
3242 LWLockRelease(ProcArrayLock);
3243
3244 return result;
3245}
uint32 TransactionId
Definition: c.h:660
PROC_HDR * ProcGlobal
Definition: proc.c:79
TransactionId * xids
Definition: proc.h:391
#define InvalidTransactionId
Definition: transam.h:31

References allProcs, InvalidTransactionId, LW_SHARED, LWLockAcquire(), LWLockRelease(), ProcArrayStruct::numProcs, ProcArrayStruct::pgprocnos, PGPROC::pid, procArray, ProcGlobal, and PROC_HDR::xids.

Referenced by pgrowlocks().

◆ CancelDBBackends()

void CancelDBBackends ( Oid  databaseid,
ProcSignalReason  sigmode,
bool  conflictPending 
)

Definition at line 3621 of file procarray.c.

3622{
3623 ProcArrayStruct *arrayP = procArray;
3624 int index;
3625
3626 /* tell all backends to die */
3627 LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3628
3629 for (index = 0; index < arrayP->numProcs; index++)
3630 {
3631 int pgprocno = arrayP->pgprocnos[index];
3632 PGPROC *proc = &allProcs[pgprocno];
3633
3634 if (databaseid == InvalidOid || proc->databaseId == databaseid)
3635 {
3636 VirtualTransactionId procvxid;
3637 pid_t pid;
3638
3639 GET_VXID_FROM_PGPROC(procvxid, *proc);
3640
3641 proc->recoveryConflictPending = conflictPending;
3642 pid = proc->pid;
3643 if (pid != 0)
3644 {
3645 /*
3646 * Kill the pid if it's still here. If not, that's what we
3647 * wanted so ignore any errors.
3648 */
3649 (void) SendProcSignal(pid, sigmode, procvxid.procNumber);
3650 }
3651 }
3652 }
3653
3654 LWLockRelease(ProcArrayLock);
3655}
#define GET_VXID_FROM_PGPROC(vxid_dst, proc)
Definition: lock.h:79
@ LW_EXCLUSIVE
Definition: lwlock.h:112
#define InvalidOid
Definition: postgres_ext.h:37
int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber)
Definition: procsignal.c:284
bool recoveryConflictPending
Definition: proc.h:237
Oid databaseId
Definition: proc.h:224
ProcNumber procNumber
Definition: lock.h:63

References allProcs, PGPROC::databaseId, GET_VXID_FROM_PGPROC, InvalidOid, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), ProcArrayStruct::numProcs, ProcArrayStruct::pgprocnos, PGPROC::pid, procArray, VirtualTransactionId::procNumber, PGPROC::recoveryConflictPending, and SendProcSignal().

Referenced by ResolveRecoveryConflictWithDatabase(), and SendRecoveryConflictWithBufferPin().

◆ CancelVirtualTransaction()

pid_t CancelVirtualTransaction ( VirtualTransactionId  vxid,
ProcSignalReason  sigmode 
)

Definition at line 3453 of file procarray.c.

3454{
3455 return SignalVirtualTransaction(vxid, sigmode, true);
3456}
pid_t SignalVirtualTransaction(VirtualTransactionId vxid, ProcSignalReason sigmode, bool conflictPending)
Definition: procarray.c:3459

References SignalVirtualTransaction().

Referenced by ResolveRecoveryConflictWithVirtualXIDs().

◆ CountDBBackends()

int CountDBBackends ( Oid  databaseid)

Definition at line 3561 of file procarray.c.

3562{
3563 ProcArrayStruct *arrayP = procArray;
3564 int count = 0;
3565 int index;
3566
3567 LWLockAcquire(ProcArrayLock, LW_SHARED);
3568
3569 for (index = 0; index < arrayP->numProcs; index++)
3570 {
3571 int pgprocno = arrayP->pgprocnos[index];
3572 PGPROC *proc = &allProcs[pgprocno];
3573
3574 if (proc->pid == 0)
3575 continue; /* do not count prepared xacts */
3576 if (!OidIsValid(databaseid) ||
3577 proc->databaseId == databaseid)
3578 count++;
3579 }
3580
3581 LWLockRelease(ProcArrayLock);
3582
3583 return count;
3584}
#define OidIsValid(objectId)
Definition: c.h:777

References allProcs, PGPROC::databaseId, LW_SHARED, LWLockAcquire(), LWLockRelease(), ProcArrayStruct::numProcs, OidIsValid, ProcArrayStruct::pgprocnos, PGPROC::pid, and procArray.

Referenced by ResolveRecoveryConflictWithDatabase().

◆ CountDBConnections()

int CountDBConnections ( Oid  databaseid)

Definition at line 3590 of file procarray.c.

3591{
3592 ProcArrayStruct *arrayP = procArray;
3593 int count = 0;
3594 int index;
3595
3596 LWLockAcquire(ProcArrayLock, LW_SHARED);
3597
3598 for (index = 0; index < arrayP->numProcs; index++)
3599 {
3600 int pgprocno = arrayP->pgprocnos[index];
3601 PGPROC *proc = &allProcs[pgprocno];
3602
3603 if (proc->pid == 0)
3604 continue; /* do not count prepared xacts */
3605 if (!proc->isRegularBackend)
3606 continue; /* count only regular backend processes */
3607 if (!OidIsValid(databaseid) ||
3608 proc->databaseId == databaseid)
3609 count++;
3610 }
3611
3612 LWLockRelease(ProcArrayLock);
3613
3614 return count;
3615}
bool isRegularBackend
Definition: proc.h:230

References allProcs, PGPROC::databaseId, PGPROC::isRegularBackend, LW_SHARED, LWLockAcquire(), LWLockRelease(), ProcArrayStruct::numProcs, OidIsValid, ProcArrayStruct::pgprocnos, PGPROC::pid, and procArray.

Referenced by CheckMyDatabase().

◆ CountOtherDBBackends()

bool CountOtherDBBackends ( Oid  databaseId,
int *  nbackends,
int *  nprepared 
)

Definition at line 3712 of file procarray.c.

3713{
3714 ProcArrayStruct *arrayP = procArray;
3715
3716#define MAXAUTOVACPIDS 10 /* max autovacs to SIGTERM per iteration */
3717 int autovac_pids[MAXAUTOVACPIDS];
3718 int tries;
3719
3720 /* 50 tries with 100ms sleep between tries makes 5 sec total wait */
3721 for (tries = 0; tries < 50; tries++)
3722 {
3723 int nautovacs = 0;
3724 bool found = false;
3725 int index;
3726
3728
3729 *nbackends = *nprepared = 0;
3730
3731 LWLockAcquire(ProcArrayLock, LW_SHARED);
3732
3733 for (index = 0; index < arrayP->numProcs; index++)
3734 {
3735 int pgprocno = arrayP->pgprocnos[index];
3736 PGPROC *proc = &allProcs[pgprocno];
3737 uint8 statusFlags = ProcGlobal->statusFlags[index];
3738
3739 if (proc->databaseId != databaseId)
3740 continue;
3741 if (proc == MyProc)
3742 continue;
3743
3744 found = true;
3745
3746 if (proc->pid == 0)
3747 (*nprepared)++;
3748 else
3749 {
3750 (*nbackends)++;
3751 if ((statusFlags & PROC_IS_AUTOVACUUM) &&
3752 nautovacs < MAXAUTOVACPIDS)
3753 autovac_pids[nautovacs++] = proc->pid;
3754 }
3755 }
3756
3757 LWLockRelease(ProcArrayLock);
3758
3759 if (!found)
3760 return false; /* no conflicting backends, so done */
3761
3762 /*
3763 * Send SIGTERM to any conflicting autovacuums before sleeping. We
3764 * postpone this step until after the loop because we don't want to
3765 * hold ProcArrayLock while issuing kill(). We have no idea what might
3766 * block kill() inside the kernel...
3767 */
3768 for (index = 0; index < nautovacs; index++)
3769 (void) kill(autovac_pids[index], SIGTERM); /* ignore any error */
3770
3771 /* sleep, then try again */
3772 pg_usleep(100 * 1000L); /* 100ms */
3773 }
3774
3775 return true; /* timed out, still conflicts */
3776}
uint8_t uint8
Definition: c.h:539
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:123
#define PROC_IS_AUTOVACUUM
Definition: proc.h:57
#define MAXAUTOVACPIDS
void pg_usleep(long microsec)
Definition: signal.c:53
PGPROC * MyProc
Definition: proc.c:67
uint8 * statusFlags
Definition: proc.h:403
#define kill(pid, sig)
Definition: win32_port.h:493

References allProcs, CHECK_FOR_INTERRUPTS, PGPROC::databaseId, kill, LW_SHARED, LWLockAcquire(), LWLockRelease(), MAXAUTOVACPIDS, MyProc, ProcArrayStruct::numProcs, pg_usleep(), ProcArrayStruct::pgprocnos, PGPROC::pid, PROC_IS_AUTOVACUUM, procArray, ProcGlobal, and PROC_HDR::statusFlags.

Referenced by createdb(), dropdb(), movedb(), and RenameDatabase().

◆ CountUserBackends()

int CountUserBackends ( Oid  roleid)

Definition at line 3662 of file procarray.c.

3663{
3664 ProcArrayStruct *arrayP = procArray;
3665 int count = 0;
3666 int index;
3667
3668 LWLockAcquire(ProcArrayLock, LW_SHARED);
3669
3670 for (index = 0; index < arrayP->numProcs; index++)
3671 {
3672 int pgprocno = arrayP->pgprocnos[index];
3673 PGPROC *proc = &allProcs[pgprocno];
3674
3675 if (proc->pid == 0)
3676 continue; /* do not count prepared xacts */
3677 if (!proc->isRegularBackend)
3678 continue; /* count only regular backend processes */
3679 if (proc->roleId == roleid)
3680 count++;
3681 }
3682
3683 LWLockRelease(ProcArrayLock);
3684
3685 return count;
3686}
Oid roleId
Definition: proc.h:225

References allProcs, PGPROC::isRegularBackend, LW_SHARED, LWLockAcquire(), LWLockRelease(), ProcArrayStruct::numProcs, ProcArrayStruct::pgprocnos, PGPROC::pid, procArray, and PGPROC::roleId.

Referenced by InitializeSessionUserId().

◆ ExpireAllKnownAssignedTransactionIds()

void ExpireAllKnownAssignedTransactionIds ( void  )

Definition at line 4460 of file procarray.c.

4461{
4462 FullTransactionId latestXid;
4463
4464 LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
4466
4467 /* Reset latestCompletedXid to nextXid - 1 */
4469 latestXid = TransamVariables->nextXid;
4470 FullTransactionIdRetreat(&latestXid);
4472
4473 /*
4474 * Any transactions that were in-progress were effectively aborted, so
4475 * advance xactCompletionCount.
4476 */
4478
4479 /*
4480 * Reset lastOverflowedXid. Currently, lastOverflowedXid has no use after
4481 * the call of this function. But do this for unification with what
4482 * ExpireOldKnownAssignedTransactionIds() do.
4483 */
4485 LWLockRelease(ProcArrayLock);
4486}
Assert(PointerIsAligned(start, uint64))
static void KnownAssignedXidsRemovePreceding(TransactionId removeXid)
Definition: procarray.c:4997
TransactionId lastOverflowedXid
Definition: procarray.c:91
FullTransactionId latestCompletedXid
Definition: transam.h:238
FullTransactionId nextXid
Definition: transam.h:220
uint64 xactCompletionCount
Definition: transam.h:248
static void FullTransactionIdRetreat(FullTransactionId *dest)
Definition: transam.h:103
#define FullTransactionIdIsValid(x)
Definition: transam.h:55
TransamVariablesData * TransamVariables
Definition: varsup.c:34

References Assert(), FullTransactionIdIsValid, FullTransactionIdRetreat(), InvalidTransactionId, KnownAssignedXidsRemovePreceding(), ProcArrayStruct::lastOverflowedXid, TransamVariablesData::latestCompletedXid, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), TransamVariablesData::nextXid, procArray, TransamVariables, and TransamVariablesData::xactCompletionCount.

Referenced by ShutdownRecoveryTransactionEnvironment().

◆ ExpireOldKnownAssignedTransactionIds()

void ExpireOldKnownAssignedTransactionIds ( TransactionId  xid)

Definition at line 4494 of file procarray.c.

4495{
4496 TransactionId latestXid;
4497
4498 LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
4499
4500 /* As in ProcArrayEndTransaction, advance latestCompletedXid */
4501 latestXid = xid;
4502 TransactionIdRetreat(latestXid);
4504
4505 /* ... and xactCompletionCount */
4507
4508 /*
4509 * Reset lastOverflowedXid if we know all transactions that have been
4510 * possibly running are being gone. Not doing so could cause an incorrect
4511 * lastOverflowedXid value, which makes extra snapshots be marked as
4512 * suboverflowed.
4513 */
4517 LWLockRelease(ProcArrayLock);
4518}
static void MaintainLatestCompletedXidRecovery(TransactionId latestXid)
Definition: procarray.c:989
#define TransactionIdRetreat(dest)
Definition: transam.h:141
static bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.h:263

References InvalidTransactionId, KnownAssignedXidsRemovePreceding(), ProcArrayStruct::lastOverflowedXid, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MaintainLatestCompletedXidRecovery(), procArray, TransactionIdPrecedes(), TransactionIdRetreat, TransamVariables, and TransamVariablesData::xactCompletionCount.

Referenced by ProcArrayApplyRecoveryInfo().

◆ ExpireTreeKnownAssignedTransactionIds()

void ExpireTreeKnownAssignedTransactionIds ( TransactionId  xid,
int  nsubxids,
TransactionId subxids,
TransactionId  max_xid 
)

Definition at line 4434 of file procarray.c.

4436{
4438
4439 /*
4440 * Uses same locking as transaction commit
4441 */
4442 LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
4443
4444 KnownAssignedXidsRemoveTree(xid, nsubxids, subxids);
4445
4446 /* As in ProcArrayEndTransaction, advance latestCompletedXid */
4448
4449 /* ... and xactCompletionCount */
4451
4452 LWLockRelease(ProcArrayLock);
4453}
static void KnownAssignedXidsRemoveTree(TransactionId xid, int nsubxids, TransactionId *subxids)
Definition: procarray.c:4975
HotStandbyState standbyState
Definition: xlogutils.c:53
@ STANDBY_INITIALIZED
Definition: xlogutils.h:53

References Assert(), KnownAssignedXidsRemoveTree(), LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MaintainLatestCompletedXidRecovery(), STANDBY_INITIALIZED, standbyState, TransamVariables, and TransamVariablesData::xactCompletionCount.

Referenced by xact_redo_abort(), and xact_redo_commit().

◆ GetConflictingVirtualXIDs()

VirtualTransactionId * GetConflictingVirtualXIDs ( TransactionId  limitXmin,
Oid  dbOid 
)

Definition at line 3379 of file procarray.c.

3380{
3381 static VirtualTransactionId *vxids;
3382 ProcArrayStruct *arrayP = procArray;
3383 int count = 0;
3384 int index;
3385
3386 /*
3387 * If first time through, get workspace to remember main XIDs in. We
3388 * malloc it permanently to avoid repeated palloc/pfree overhead. Allow
3389 * result space, remembering room for a terminator.
3390 */
3391 if (vxids == NULL)
3392 {
3393 vxids = (VirtualTransactionId *)
3394 malloc(sizeof(VirtualTransactionId) * (arrayP->maxProcs + 1));
3395 if (vxids == NULL)
3396 ereport(ERROR,
3397 (errcode(ERRCODE_OUT_OF_MEMORY),
3398 errmsg("out of memory")));
3399 }
3400
3401 LWLockAcquire(ProcArrayLock, LW_SHARED);
3402
3403 for (index = 0; index < arrayP->numProcs; index++)
3404 {
3405 int pgprocno = arrayP->pgprocnos[index];
3406 PGPROC *proc = &allProcs[pgprocno];
3407
3408 /* Exclude prepared transactions */
3409 if (proc->pid == 0)
3410 continue;
3411
3412 if (!OidIsValid(dbOid) ||
3413 proc->databaseId == dbOid)
3414 {
3415 /* Fetch xmin just once - can't change on us, but good coding */
3416 TransactionId pxmin = UINT32_ACCESS_ONCE(proc->xmin);
3417
3418 /*
3419 * We ignore an invalid pxmin because this means that backend has
3420 * no snapshot currently. We hold a Share lock to avoid contention
3421 * with users taking snapshots. That is not a problem because the
3422 * current xmin is always at least one higher than the latest
3423 * removed xid, so any new snapshot would never conflict with the
3424 * test here.
3425 */
3426 if (!TransactionIdIsValid(limitXmin) ||
3427 (TransactionIdIsValid(pxmin) && !TransactionIdFollows(pxmin, limitXmin)))
3428 {
3430
3431 GET_VXID_FROM_PGPROC(vxid, *proc);
3433 vxids[count++] = vxid;
3434 }
3435 }
3436 }
3437
3438 LWLockRelease(ProcArrayLock);
3439
3440 /* add the terminator */
3441 vxids[count].procNumber = INVALID_PROC_NUMBER;
3443
3444 return vxids;
3445}
int errcode(int sqlerrcode)
Definition: elog.c:863
int errmsg(const char *fmt,...)
Definition: elog.c:1080
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:150
#define malloc(a)
Definition: header.h:50
#define VirtualTransactionIdIsValid(vxid)
Definition: lock.h:69
#define InvalidLocalTransactionId
Definition: lock.h:67
#define UINT32_ACCESS_ONCE(var)
Definition: procarray.c:68
#define INVALID_PROC_NUMBER
Definition: procnumber.h:26
TransactionId xmin
Definition: proc.h:194
LocalTransactionId localTransactionId
Definition: lock.h:64
static bool TransactionIdFollows(TransactionId id1, TransactionId id2)
Definition: transam.h:297
#define TransactionIdIsValid(xid)
Definition: transam.h:41

References allProcs, PGPROC::databaseId, ereport, errcode(), errmsg(), ERROR, GET_VXID_FROM_PGPROC, INVALID_PROC_NUMBER, InvalidLocalTransactionId, VirtualTransactionId::localTransactionId, LW_SHARED, LWLockAcquire(), LWLockRelease(), malloc, ProcArrayStruct::maxProcs, ProcArrayStruct::numProcs, OidIsValid, ProcArrayStruct::pgprocnos, PGPROC::pid, procArray, VirtualTransactionId::procNumber, TransactionIdFollows(), TransactionIdIsValid, UINT32_ACCESS_ONCE, VirtualTransactionIdIsValid, and PGPROC::xmin.

Referenced by ResolveRecoveryConflictWithSnapshot(), and ResolveRecoveryConflictWithTablespace().

◆ GetCurrentVirtualXIDs()

VirtualTransactionId * GetCurrentVirtualXIDs ( TransactionId  limitXmin,
bool  excludeXmin0,
bool  allDbs,
int  excludeVacuum,
int *  nvxids 
)

Definition at line 3286 of file procarray.c.

3289{
3290 VirtualTransactionId *vxids;
3291 ProcArrayStruct *arrayP = procArray;
3292 int count = 0;
3293 int index;
3294
3295 /* allocate what's certainly enough result space */
3296 vxids = (VirtualTransactionId *)
3297 palloc(sizeof(VirtualTransactionId) * arrayP->maxProcs);
3298
3299 LWLockAcquire(ProcArrayLock, LW_SHARED);
3300
3301 for (index = 0; index < arrayP->numProcs; index++)
3302 {
3303 int pgprocno = arrayP->pgprocnos[index];
3304 PGPROC *proc = &allProcs[pgprocno];
3305 uint8 statusFlags = ProcGlobal->statusFlags[index];
3306
3307 if (proc == MyProc)
3308 continue;
3309
3310 if (excludeVacuum & statusFlags)
3311 continue;
3312
3313 if (allDbs || proc->databaseId == MyDatabaseId)
3314 {
3315 /* Fetch xmin just once - might change on us */
3316 TransactionId pxmin = UINT32_ACCESS_ONCE(proc->xmin);
3317
3318 if (excludeXmin0 && !TransactionIdIsValid(pxmin))
3319 continue;
3320
3321 /*
3322 * InvalidTransactionId precedes all other XIDs, so a proc that
3323 * hasn't set xmin yet will not be rejected by this test.
3324 */
3325 if (!TransactionIdIsValid(limitXmin) ||
3326 TransactionIdPrecedesOrEquals(pxmin, limitXmin))
3327 {
3329
3330 GET_VXID_FROM_PGPROC(vxid, *proc);
3332 vxids[count++] = vxid;
3333 }
3334 }
3335 }
3336
3337 LWLockRelease(ProcArrayLock);
3338
3339 *nvxids = count;
3340 return vxids;
3341}
Oid MyDatabaseId
Definition: globals.c:94
void * palloc(Size size)
Definition: mcxt.c:1365
static bool TransactionIdPrecedesOrEquals(TransactionId id1, TransactionId id2)
Definition: transam.h:282

References allProcs, PGPROC::databaseId, GET_VXID_FROM_PGPROC, LW_SHARED, LWLockAcquire(), LWLockRelease(), ProcArrayStruct::maxProcs, MyDatabaseId, MyProc, ProcArrayStruct::numProcs, palloc(), ProcArrayStruct::pgprocnos, procArray, ProcGlobal, PROC_HDR::statusFlags, TransactionIdIsValid, TransactionIdPrecedesOrEquals(), UINT32_ACCESS_ONCE, VirtualTransactionIdIsValid, and PGPROC::xmin.

Referenced by WaitForOlderSnapshots().

◆ GetMaxSnapshotSubxidCount()

int GetMaxSnapshotSubxidCount ( void  )

Definition at line 2028 of file procarray.c.

2029{
2031}
#define TOTAL_MAX_CACHED_SUBXIDS

References TOTAL_MAX_CACHED_SUBXIDS.

Referenced by ExportSnapshot(), GetSnapshotData(), ImportSnapshot(), and SetTransactionSnapshot().

◆ GetMaxSnapshotXidCount()

int GetMaxSnapshotXidCount ( void  )

Definition at line 2017 of file procarray.c.

2018{
2019 return procArray->maxProcs;
2020}

References ProcArrayStruct::maxProcs, and procArray.

Referenced by GetSnapshotData(), ImportSnapshot(), SetTransactionSnapshot(), and SnapBuildInitialSnapshot().

◆ GetOldestActiveTransactionId()

TransactionId GetOldestActiveTransactionId ( bool  inCommitOnly,
bool  allDbs 
)

Definition at line 2833 of file procarray.c.

2834{
2835 ProcArrayStruct *arrayP = procArray;
2836 TransactionId *other_xids = ProcGlobal->xids;
2837 TransactionId oldestRunningXid;
2838 int index;
2839
2841
2842 /*
2843 * Read nextXid, as the upper bound of what's still active.
2844 *
2845 * Reading a TransactionId is atomic, but we must grab the lock to make
2846 * sure that all XIDs < nextXid are already present in the proc array (or
2847 * have already completed), when we spin over it.
2848 */
2849 LWLockAcquire(XidGenLock, LW_SHARED);
2851 LWLockRelease(XidGenLock);
2852
2853 /*
2854 * Spin over procArray collecting all xids and subxids.
2855 */
2856 LWLockAcquire(ProcArrayLock, LW_SHARED);
2857 for (index = 0; index < arrayP->numProcs; index++)
2858 {
2859 TransactionId xid;
2860 int pgprocno = arrayP->pgprocnos[index];
2861 PGPROC *proc = &allProcs[pgprocno];
2862
2863 /* Fetch xid just once - see GetNewTransactionId */
2864 xid = UINT32_ACCESS_ONCE(other_xids[index]);
2865
2866 if (!TransactionIdIsNormal(xid))
2867 continue;
2868
2869 if (inCommitOnly &&
2871 continue;
2872
2873 if (!allDbs && proc->databaseId != MyDatabaseId)
2874 continue;
2875
2876 if (TransactionIdPrecedes(xid, oldestRunningXid))
2877 oldestRunningXid = xid;
2878
2879 /*
2880 * Top-level XID of a transaction is always less than any of its
2881 * subxids, so we don't need to check if any of the subxids are
2882 * smaller than oldestRunningXid
2883 */
2884 }
2885 LWLockRelease(ProcArrayLock);
2886
2887 return oldestRunningXid;
2888}
#define DELAY_CHKPT_IN_COMMIT
Definition: proc.h:137
int delayChkptFlags
Definition: proc.h:257
#define XidFromFullTransactionId(x)
Definition: transam.h:48
#define TransactionIdIsNormal(xid)
Definition: transam.h:42
bool RecoveryInProgress(void)
Definition: xlog.c:6406

References allProcs, Assert(), PGPROC::databaseId, DELAY_CHKPT_IN_COMMIT, PGPROC::delayChkptFlags, LW_SHARED, LWLockAcquire(), LWLockRelease(), MyDatabaseId, TransamVariablesData::nextXid, ProcArrayStruct::numProcs, ProcArrayStruct::pgprocnos, procArray, ProcGlobal, RecoveryInProgress(), TransactionIdIsNormal, TransactionIdPrecedes(), TransamVariables, UINT32_ACCESS_ONCE, XidFromFullTransactionId, and PROC_HDR::xids.

Referenced by CreateCheckPoint(), get_candidate_xid(), and ProcessStandbyPSRequestMessage().

◆ GetOldestNonRemovableTransactionId()

TransactionId GetOldestNonRemovableTransactionId ( Relation  rel)

Definition at line 1953 of file procarray.c.

1954{
1955 ComputeXidHorizonsResult horizons;
1956
1957 ComputeXidHorizons(&horizons);
1958
1959 switch (GlobalVisHorizonKindForRel(rel))
1960 {
1961 case VISHORIZON_SHARED:
1962 return horizons.shared_oldest_nonremovable;
1963 case VISHORIZON_CATALOG:
1964 return horizons.catalog_oldest_nonremovable;
1965 case VISHORIZON_DATA:
1966 return horizons.data_oldest_nonremovable;
1967 case VISHORIZON_TEMP:
1968 return horizons.temp_oldest_nonremovable;
1969 }
1970
1971 /* just to prevent compiler warnings */
1972 return InvalidTransactionId;
1973}
static void ComputeXidHorizons(ComputeXidHorizonsResult *h)
Definition: procarray.c:1683
@ VISHORIZON_SHARED
Definition: procarray.c:251
@ VISHORIZON_DATA
Definition: procarray.c:253
@ VISHORIZON_CATALOG
Definition: procarray.c:252
@ VISHORIZON_TEMP
Definition: procarray.c:254
static GlobalVisHorizonKind GlobalVisHorizonKindForRel(Relation rel)
Definition: procarray.c:1919
TransactionId data_oldest_nonremovable
Definition: procarray.c:237
TransactionId temp_oldest_nonremovable
Definition: procarray.c:243
TransactionId shared_oldest_nonremovable
Definition: procarray.c:214
TransactionId catalog_oldest_nonremovable
Definition: procarray.c:231

References ComputeXidHorizonsResult::catalog_oldest_nonremovable, ComputeXidHorizons(), ComputeXidHorizonsResult::data_oldest_nonremovable, GlobalVisHorizonKindForRel(), InvalidTransactionId, ComputeXidHorizonsResult::shared_oldest_nonremovable, ComputeXidHorizonsResult::temp_oldest_nonremovable, VISHORIZON_CATALOG, VISHORIZON_DATA, VISHORIZON_SHARED, and VISHORIZON_TEMP.

Referenced by _bt_pendingfsm_finalize(), acquire_sample_rows(), GetStrictOldestNonRemovableTransactionId(), heapam_index_build_range_scan(), removable_cutoff(), statapprox_heap(), vac_update_datfrozenxid(), and vacuum_get_cutoffs().

◆ GetOldestSafeDecodingTransactionId()

TransactionId GetOldestSafeDecodingTransactionId ( bool  catalogOnly)

Definition at line 2907 of file procarray.c.

2908{
2909 ProcArrayStruct *arrayP = procArray;
2910 TransactionId oldestSafeXid;
2911 int index;
2912 bool recovery_in_progress = RecoveryInProgress();
2913
2914 Assert(LWLockHeldByMe(ProcArrayLock));
2915
2916 /*
2917 * Acquire XidGenLock, so no transactions can acquire an xid while we're
2918 * running. If no transaction with xid were running concurrently a new xid
2919 * could influence the RecentXmin et al.
2920 *
2921 * We initialize the computation to nextXid since that's guaranteed to be
2922 * a safe, albeit pessimal, value.
2923 */
2924 LWLockAcquire(XidGenLock, LW_SHARED);
2926
2927 /*
2928 * If there's already a slot pegging the xmin horizon, we can start with
2929 * that value, it's guaranteed to be safe since it's computed by this
2930 * routine initially and has been enforced since. We can always use the
2931 * slot's general xmin horizon, but the catalog horizon is only usable
2932 * when only catalog data is going to be looked at.
2933 */
2936 oldestSafeXid))
2937 oldestSafeXid = procArray->replication_slot_xmin;
2938
2939 if (catalogOnly &&
2942 oldestSafeXid))
2944
2945 /*
2946 * If we're not in recovery, we walk over the procarray and collect the
2947 * lowest xid. Since we're called with ProcArrayLock held and have
2948 * acquired XidGenLock, no entries can vanish concurrently, since
2949 * ProcGlobal->xids[i] is only set with XidGenLock held and only cleared
2950 * with ProcArrayLock held.
2951 *
2952 * In recovery we can't lower the safe value besides what we've computed
2953 * above, so we'll have to wait a bit longer there. We unfortunately can
2954 * *not* use KnownAssignedXidsGetOldestXmin() since the KnownAssignedXids
2955 * machinery can miss values and return an older value than is safe.
2956 */
2957 if (!recovery_in_progress)
2958 {
2959 TransactionId *other_xids = ProcGlobal->xids;
2960
2961 /*
2962 * Spin over procArray collecting min(ProcGlobal->xids[i])
2963 */
2964 for (index = 0; index < arrayP->numProcs; index++)
2965 {
2966 TransactionId xid;
2967
2968 /* Fetch xid just once - see GetNewTransactionId */
2969 xid = UINT32_ACCESS_ONCE(other_xids[index]);
2970
2971 if (!TransactionIdIsNormal(xid))
2972 continue;
2973
2974 if (TransactionIdPrecedes(xid, oldestSafeXid))
2975 oldestSafeXid = xid;
2976 }
2977 }
2978
2979 LWLockRelease(XidGenLock);
2980
2981 return oldestSafeXid;
2982}
bool LWLockHeldByMe(LWLock *lock)
Definition: lwlock.c:1977
TransactionId replication_slot_xmin
Definition: procarray.c:94
TransactionId replication_slot_catalog_xmin
Definition: procarray.c:96

References Assert(), LW_SHARED, LWLockAcquire(), LWLockHeldByMe(), LWLockRelease(), TransamVariablesData::nextXid, ProcArrayStruct::numProcs, procArray, ProcGlobal, RecoveryInProgress(), ProcArrayStruct::replication_slot_catalog_xmin, ProcArrayStruct::replication_slot_xmin, TransactionIdIsNormal, TransactionIdIsValid, TransactionIdPrecedes(), TransamVariables, UINT32_ACCESS_ONCE, XidFromFullTransactionId, and PROC_HDR::xids.

Referenced by CreateInitDecodingContext(), init_conflict_slot_xmin(), SnapBuildInitialSnapshot(), and synchronize_one_slot().

◆ GetOldestTransactionIdConsideredRunning()

TransactionId GetOldestTransactionIdConsideredRunning ( void  )

Definition at line 1982 of file procarray.c.

1983{
1984 ComputeXidHorizonsResult horizons;
1985
1986 ComputeXidHorizons(&horizons);
1987
1988 return horizons.oldest_considered_running;
1989}
TransactionId oldest_considered_running
Definition: procarray.c:205

References ComputeXidHorizons(), and ComputeXidHorizonsResult::oldest_considered_running.

Referenced by CreateCheckPoint(), and CreateRestartPoint().

◆ GetReplicationHorizons()

void GetReplicationHorizons ( TransactionId xmin,
TransactionId catalog_xmin 
)

Definition at line 1995 of file procarray.c.

1996{
1997 ComputeXidHorizonsResult horizons;
1998
1999 ComputeXidHorizons(&horizons);
2000
2001 /*
2002 * Don't want to use shared_oldest_nonremovable here, as that contains the
2003 * effect of replication slot's catalog_xmin. We want to send a separate
2004 * feedback for the catalog horizon, so the primary can remove data table
2005 * contents more aggressively.
2006 */
2007 *xmin = horizons.shared_oldest_nonremovable_raw;
2008 *catalog_xmin = horizons.slot_catalog_xmin;
2009}
TransactionId slot_catalog_xmin
Definition: procarray.c:192
TransactionId shared_oldest_nonremovable_raw
Definition: procarray.c:225

References ComputeXidHorizons(), ComputeXidHorizonsResult::shared_oldest_nonremovable_raw, and ComputeXidHorizonsResult::slot_catalog_xmin.

Referenced by XLogWalRcvSendHSFeedback().

◆ GetRunningTransactionData()

RunningTransactions GetRunningTransactionData ( void  )

Definition at line 2637 of file procarray.c.

2638{
2639 /* result workspace */
2640 static RunningTransactionsData CurrentRunningXactsData;
2641
2642 ProcArrayStruct *arrayP = procArray;
2643 TransactionId *other_xids = ProcGlobal->xids;
2644 RunningTransactions CurrentRunningXacts = &CurrentRunningXactsData;
2645 TransactionId latestCompletedXid;
2646 TransactionId oldestRunningXid;
2647 TransactionId oldestDatabaseRunningXid;
2648 TransactionId *xids;
2649 int index;
2650 int count;
2651 int subcount;
2652 bool suboverflowed;
2653
2655
2656 /*
2657 * Allocating space for maxProcs xids is usually overkill; numProcs would
2658 * be sufficient. But it seems better to do the malloc while not holding
2659 * the lock, so we can't look at numProcs. Likewise, we allocate much
2660 * more subxip storage than is probably needed.
2661 *
2662 * Should only be allocated in bgwriter, since only ever executed during
2663 * checkpoints.
2664 */
2665 if (CurrentRunningXacts->xids == NULL)
2666 {
2667 /*
2668 * First call
2669 */
2670 CurrentRunningXacts->xids = (TransactionId *)
2672 if (CurrentRunningXacts->xids == NULL)
2673 ereport(ERROR,
2674 (errcode(ERRCODE_OUT_OF_MEMORY),
2675 errmsg("out of memory")));
2676 }
2677
2678 xids = CurrentRunningXacts->xids;
2679
2680 count = subcount = 0;
2681 suboverflowed = false;
2682
2683 /*
2684 * Ensure that no xids enter or leave the procarray while we obtain
2685 * snapshot.
2686 */
2687 LWLockAcquire(ProcArrayLock, LW_SHARED);
2688 LWLockAcquire(XidGenLock, LW_SHARED);
2689
2690 latestCompletedXid =
2692 oldestDatabaseRunningXid = oldestRunningXid =
2694
2695 /*
2696 * Spin over procArray collecting all xids
2697 */
2698 for (index = 0; index < arrayP->numProcs; index++)
2699 {
2700 TransactionId xid;
2701
2702 /* Fetch xid just once - see GetNewTransactionId */
2703 xid = UINT32_ACCESS_ONCE(other_xids[index]);
2704
2705 /*
2706 * We don't need to store transactions that don't have a TransactionId
2707 * yet because they will not show as running on a standby server.
2708 */
2709 if (!TransactionIdIsValid(xid))
2710 continue;
2711
2712 /*
2713 * Be careful not to exclude any xids before calculating the values of
2714 * oldestRunningXid and suboverflowed, since these are used to clean
2715 * up transaction information held on standbys.
2716 */
2717 if (TransactionIdPrecedes(xid, oldestRunningXid))
2718 oldestRunningXid = xid;
2719
2720 /*
2721 * Also, update the oldest running xid within the current database. As
2722 * fetching pgprocno and PGPROC could cause cache misses, we do cheap
2723 * TransactionId comparison first.
2724 */
2725 if (TransactionIdPrecedes(xid, oldestDatabaseRunningXid))
2726 {
2727 int pgprocno = arrayP->pgprocnos[index];
2728 PGPROC *proc = &allProcs[pgprocno];
2729
2730 if (proc->databaseId == MyDatabaseId)
2731 oldestDatabaseRunningXid = xid;
2732 }
2733
2735 suboverflowed = true;
2736
2737 /*
2738 * If we wished to exclude xids this would be the right place for it.
2739 * Procs with the PROC_IN_VACUUM flag set don't usually assign xids,
2740 * but they do during truncation at the end when they get the lock and
2741 * truncate, so it is not much of a problem to include them if they
2742 * are seen and it is cleaner to include them.
2743 */
2744
2745 xids[count++] = xid;
2746 }
2747
2748 /*
2749 * Spin over procArray collecting all subxids, but only if there hasn't
2750 * been a suboverflow.
2751 */
2752 if (!suboverflowed)
2753 {
2754 XidCacheStatus *other_subxidstates = ProcGlobal->subxidStates;
2755
2756 for (index = 0; index < arrayP->numProcs; index++)
2757 {
2758 int pgprocno = arrayP->pgprocnos[index];
2759 PGPROC *proc = &allProcs[pgprocno];
2760 int nsubxids;
2761
2762 /*
2763 * Save subtransaction XIDs. Other backends can't add or remove
2764 * entries while we're holding XidGenLock.
2765 */
2766 nsubxids = other_subxidstates[index].count;
2767 if (nsubxids > 0)
2768 {
2769 /* barrier not really required, as XidGenLock is held, but ... */
2770 pg_read_barrier(); /* pairs with GetNewTransactionId */
2771
2772 memcpy(&xids[count], proc->subxids.xids,
2773 nsubxids * sizeof(TransactionId));
2774 count += nsubxids;
2775 subcount += nsubxids;
2776
2777 /*
2778 * Top-level XID of a transaction is always less than any of
2779 * its subxids, so we don't need to check if any of the
2780 * subxids are smaller than oldestRunningXid
2781 */
2782 }
2783 }
2784 }
2785
2786 /*
2787 * It's important *not* to include the limits set by slots here because
2788 * snapbuild.c uses oldestRunningXid to manage its xmin horizon. If those
2789 * were to be included here the initial value could never increase because
2790 * of a circular dependency where slots only increase their limits when
2791 * running xacts increases oldestRunningXid and running xacts only
2792 * increases if slots do.
2793 */
2794
2795 CurrentRunningXacts->xcnt = count - subcount;
2796 CurrentRunningXacts->subxcnt = subcount;
2797 CurrentRunningXacts->subxid_status = suboverflowed ? SUBXIDS_IN_SUBTRANS : SUBXIDS_IN_ARRAY;
2799 CurrentRunningXacts->oldestRunningXid = oldestRunningXid;
2800 CurrentRunningXacts->oldestDatabaseRunningXid = oldestDatabaseRunningXid;
2801 CurrentRunningXacts->latestCompletedXid = latestCompletedXid;
2802
2803 Assert(TransactionIdIsValid(CurrentRunningXacts->nextXid));
2804 Assert(TransactionIdIsValid(CurrentRunningXacts->oldestRunningXid));
2805 Assert(TransactionIdIsNormal(CurrentRunningXacts->latestCompletedXid));
2806
2807 /* We don't release the locks here, the caller is responsible for that */
2808
2809 return CurrentRunningXacts;
2810}
#define pg_read_barrier()
Definition: atomics.h:154
@ SUBXIDS_IN_SUBTRANS
Definition: standby.h:82
@ SUBXIDS_IN_ARRAY
Definition: standby.h:80
struct XidCache subxids
Definition: proc.h:282
XidCacheStatus * subxidStates
Definition: proc.h:397
TransactionId oldestRunningXid
Definition: standby.h:92
TransactionId nextXid
Definition: standby.h:91
TransactionId oldestDatabaseRunningXid
Definition: standby.h:93
TransactionId latestCompletedXid
Definition: standby.h:95
subxids_array_status subxid_status
Definition: standby.h:90
TransactionId * xids
Definition: standby.h:97
bool overflowed
Definition: proc.h:46
uint8 count
Definition: proc.h:44
TransactionId xids[PGPROC_MAX_CACHED_SUBXIDS]
Definition: proc.h:51

References allProcs, Assert(), XidCacheStatus::count, PGPROC::databaseId, ereport, errcode(), errmsg(), ERROR, TransamVariablesData::latestCompletedXid, RunningTransactionsData::latestCompletedXid, LW_SHARED, LWLockAcquire(), malloc, MyDatabaseId, TransamVariablesData::nextXid, RunningTransactionsData::nextXid, ProcArrayStruct::numProcs, RunningTransactionsData::oldestDatabaseRunningXid, RunningTransactionsData::oldestRunningXid, XidCacheStatus::overflowed, pg_read_barrier, ProcArrayStruct::pgprocnos, procArray, ProcGlobal, RecoveryInProgress(), RunningTransactionsData::subxcnt, RunningTransactionsData::subxid_status, PGPROC::subxids, SUBXIDS_IN_ARRAY, SUBXIDS_IN_SUBTRANS, PROC_HDR::subxidStates, TOTAL_MAX_CACHED_SUBXIDS, TransactionIdIsNormal, TransactionIdIsValid, TransactionIdPrecedes(), TransamVariables, UINT32_ACCESS_ONCE, RunningTransactionsData::xcnt, XidFromFullTransactionId, XidCache::xids, PROC_HDR::xids, and RunningTransactionsData::xids.

Referenced by GetStrictOldestNonRemovableTransactionId(), and LogStandbySnapshot().

◆ GetSnapshotData()

Snapshot GetSnapshotData ( Snapshot  snapshot)

Definition at line 2123 of file procarray.c.

2124{
2125 ProcArrayStruct *arrayP = procArray;
2126 TransactionId *other_xids = ProcGlobal->xids;
2127 TransactionId xmin;
2128 TransactionId xmax;
2129 int count = 0;
2130 int subcount = 0;
2131 bool suboverflowed = false;
2132 FullTransactionId latest_completed;
2133 TransactionId oldestxid;
2134 int mypgxactoff;
2135 TransactionId myxid;
2136 uint64 curXactCompletionCount;
2137
2138 TransactionId replication_slot_xmin = InvalidTransactionId;
2139 TransactionId replication_slot_catalog_xmin = InvalidTransactionId;
2140
2141 Assert(snapshot != NULL);
2142
2143 /*
2144 * Allocating space for maxProcs xids is usually overkill; numProcs would
2145 * be sufficient. But it seems better to do the malloc while not holding
2146 * the lock, so we can't look at numProcs. Likewise, we allocate much
2147 * more subxip storage than is probably needed.
2148 *
2149 * This does open a possibility for avoiding repeated malloc/free: since
2150 * maxProcs does not change at runtime, we can simply reuse the previous
2151 * xip arrays if any. (This relies on the fact that all callers pass
2152 * static SnapshotData structs.)
2153 */
2154 if (snapshot->xip == NULL)
2155 {
2156 /*
2157 * First call for this snapshot. Snapshot is same size whether or not
2158 * we are in recovery, see later comments.
2159 */
2160 snapshot->xip = (TransactionId *)
2162 if (snapshot->xip == NULL)
2163 ereport(ERROR,
2164 (errcode(ERRCODE_OUT_OF_MEMORY),
2165 errmsg("out of memory")));
2166 Assert(snapshot->subxip == NULL);
2167 snapshot->subxip = (TransactionId *)
2169 if (snapshot->subxip == NULL)
2170 ereport(ERROR,
2171 (errcode(ERRCODE_OUT_OF_MEMORY),
2172 errmsg("out of memory")));
2173 }
2174
2175 /*
2176 * It is sufficient to get shared lock on ProcArrayLock, even if we are
2177 * going to set MyProc->xmin.
2178 */
2179 LWLockAcquire(ProcArrayLock, LW_SHARED);
2180
2181 if (GetSnapshotDataReuse(snapshot))
2182 {
2183 LWLockRelease(ProcArrayLock);
2184 return snapshot;
2185 }
2186
2187 latest_completed = TransamVariables->latestCompletedXid;
2188 mypgxactoff = MyProc->pgxactoff;
2189 myxid = other_xids[mypgxactoff];
2190 Assert(myxid == MyProc->xid);
2191
2192 oldestxid = TransamVariables->oldestXid;
2193 curXactCompletionCount = TransamVariables->xactCompletionCount;
2194
2195 /* xmax is always latestCompletedXid + 1 */
2196 xmax = XidFromFullTransactionId(latest_completed);
2199
2200 /* initialize xmin calculation with xmax */
2201 xmin = xmax;
2202
2203 /* take own xid into account, saves a check inside the loop */
2204 if (TransactionIdIsNormal(myxid) && NormalTransactionIdPrecedes(myxid, xmin))
2205 xmin = myxid;
2206
2208
2209 if (!snapshot->takenDuringRecovery)
2210 {
2211 int numProcs = arrayP->numProcs;
2212 TransactionId *xip = snapshot->xip;
2213 int *pgprocnos = arrayP->pgprocnos;
2214 XidCacheStatus *subxidStates = ProcGlobal->subxidStates;
2215 uint8 *allStatusFlags = ProcGlobal->statusFlags;
2216
2217 /*
2218 * First collect set of pgxactoff/xids that need to be included in the
2219 * snapshot.
2220 */
2221 for (int pgxactoff = 0; pgxactoff < numProcs; pgxactoff++)
2222 {
2223 /* Fetch xid just once - see GetNewTransactionId */
2224 TransactionId xid = UINT32_ACCESS_ONCE(other_xids[pgxactoff]);
2225 uint8 statusFlags;
2226
2227 Assert(allProcs[arrayP->pgprocnos[pgxactoff]].pgxactoff == pgxactoff);
2228
2229 /*
2230 * If the transaction has no XID assigned, we can skip it; it
2231 * won't have sub-XIDs either.
2232 */
2233 if (likely(xid == InvalidTransactionId))
2234 continue;
2235
2236 /*
2237 * We don't include our own XIDs (if any) in the snapshot. It
2238 * needs to be included in the xmin computation, but we did so
2239 * outside the loop.
2240 */
2241 if (pgxactoff == mypgxactoff)
2242 continue;
2243
2244 /*
2245 * The only way we are able to get here with a non-normal xid is
2246 * during bootstrap - with this backend using
2247 * BootstrapTransactionId. But the above test should filter that
2248 * out.
2249 */
2251
2252 /*
2253 * If the XID is >= xmax, we can skip it; such transactions will
2254 * be treated as running anyway (and any sub-XIDs will also be >=
2255 * xmax).
2256 */
2257 if (!NormalTransactionIdPrecedes(xid, xmax))
2258 continue;
2259
2260 /*
2261 * Skip over backends doing logical decoding which manages xmin
2262 * separately (check below) and ones running LAZY VACUUM.
2263 */
2264 statusFlags = allStatusFlags[pgxactoff];
2265 if (statusFlags & (PROC_IN_LOGICAL_DECODING | PROC_IN_VACUUM))
2266 continue;
2267
2268 if (NormalTransactionIdPrecedes(xid, xmin))
2269 xmin = xid;
2270
2271 /* Add XID to snapshot. */
2272 xip[count++] = xid;
2273
2274 /*
2275 * Save subtransaction XIDs if possible (if we've already
2276 * overflowed, there's no point). Note that the subxact XIDs must
2277 * be later than their parent, so no need to check them against
2278 * xmin. We could filter against xmax, but it seems better not to
2279 * do that much work while holding the ProcArrayLock.
2280 *
2281 * The other backend can add more subxids concurrently, but cannot
2282 * remove any. Hence it's important to fetch nxids just once.
2283 * Should be safe to use memcpy, though. (We needn't worry about
2284 * missing any xids added concurrently, because they must postdate
2285 * xmax.)
2286 *
2287 * Again, our own XIDs are not included in the snapshot.
2288 */
2289 if (!suboverflowed)
2290 {
2291
2292 if (subxidStates[pgxactoff].overflowed)
2293 suboverflowed = true;
2294 else
2295 {
2296 int nsubxids = subxidStates[pgxactoff].count;
2297
2298 if (nsubxids > 0)
2299 {
2300 int pgprocno = pgprocnos[pgxactoff];
2301 PGPROC *proc = &allProcs[pgprocno];
2302
2303 pg_read_barrier(); /* pairs with GetNewTransactionId */
2304
2305 memcpy(snapshot->subxip + subcount,
2306 proc->subxids.xids,
2307 nsubxids * sizeof(TransactionId));
2308 subcount += nsubxids;
2309 }
2310 }
2311 }
2312 }
2313 }
2314 else
2315 {
2316 /*
2317 * We're in hot standby, so get XIDs from KnownAssignedXids.
2318 *
2319 * We store all xids directly into subxip[]. Here's why:
2320 *
2321 * In recovery we don't know which xids are top-level and which are
2322 * subxacts, a design choice that greatly simplifies xid processing.
2323 *
2324 * It seems like we would want to try to put xids into xip[] only, but
2325 * that is fairly small. We would either need to make that bigger or
2326 * to increase the rate at which we WAL-log xid assignment; neither is
2327 * an appealing choice.
2328 *
2329 * We could try to store xids into xip[] first and then into subxip[]
2330 * if there are too many xids. That only works if the snapshot doesn't
2331 * overflow because we do not search subxip[] in that case. A simpler
2332 * way is to just store all xids in the subxip array because this is
2333 * by far the bigger array. We just leave the xip array empty.
2334 *
2335 * Either way we need to change the way XidInMVCCSnapshot() works
2336 * depending upon when the snapshot was taken, or change normal
2337 * snapshot processing so it matches.
2338 *
2339 * Note: It is possible for recovery to end before we finish taking
2340 * the snapshot, and for newly assigned transaction ids to be added to
2341 * the ProcArray. xmax cannot change while we hold ProcArrayLock, so
2342 * those newly added transaction ids would be filtered away, so we
2343 * need not be concerned about them.
2344 */
2345 subcount = KnownAssignedXidsGetAndSetXmin(snapshot->subxip, &xmin,
2346 xmax);
2347
2349 suboverflowed = true;
2350 }
2351
2352
2353 /*
2354 * Fetch into local variable while ProcArrayLock is held - the
2355 * LWLockRelease below is a barrier, ensuring this happens inside the
2356 * lock.
2357 */
2358 replication_slot_xmin = procArray->replication_slot_xmin;
2359 replication_slot_catalog_xmin = procArray->replication_slot_catalog_xmin;
2360
2362 MyProc->xmin = TransactionXmin = xmin;
2363
2364 LWLockRelease(ProcArrayLock);
2365
2366 /* maintain state for GlobalVis* */
2367 {
2368 TransactionId def_vis_xid;
2369 TransactionId def_vis_xid_data;
2370 FullTransactionId def_vis_fxid;
2371 FullTransactionId def_vis_fxid_data;
2372 FullTransactionId oldestfxid;
2373
2374 /*
2375 * Converting oldestXid is only safe when xid horizon cannot advance,
2376 * i.e. holding locks. While we don't hold the lock anymore, all the
2377 * necessary data has been gathered with lock held.
2378 */
2379 oldestfxid = FullXidRelativeTo(latest_completed, oldestxid);
2380
2381 /* Check whether there's a replication slot requiring an older xmin. */
2382 def_vis_xid_data =
2383 TransactionIdOlder(xmin, replication_slot_xmin);
2384
2385 /*
2386 * Rows in non-shared, non-catalog tables possibly could be vacuumed
2387 * if older than this xid.
2388 */
2389 def_vis_xid = def_vis_xid_data;
2390
2391 /*
2392 * Check whether there's a replication slot requiring an older catalog
2393 * xmin.
2394 */
2395 def_vis_xid =
2396 TransactionIdOlder(replication_slot_catalog_xmin, def_vis_xid);
2397
2398 def_vis_fxid = FullXidRelativeTo(latest_completed, def_vis_xid);
2399 def_vis_fxid_data = FullXidRelativeTo(latest_completed, def_vis_xid_data);
2400
2401 /*
2402 * Check if we can increase upper bound. As a previous
2403 * GlobalVisUpdate() might have computed more aggressive values, don't
2404 * overwrite them if so.
2405 */
2407 FullTransactionIdNewer(def_vis_fxid,
2410 FullTransactionIdNewer(def_vis_fxid,
2413 FullTransactionIdNewer(def_vis_fxid_data,
2415 /* See temp_oldest_nonremovable computation in ComputeXidHorizons() */
2416 if (TransactionIdIsNormal(myxid))
2418 FullXidRelativeTo(latest_completed, myxid);
2419 else
2420 {
2421 GlobalVisTempRels.definitely_needed = latest_completed;
2423 }
2424
2425 /*
2426 * Check if we know that we can initialize or increase the lower
2427 * bound. Currently the only cheap way to do so is to use
2428 * TransamVariables->oldestXid as input.
2429 *
2430 * We should definitely be able to do better. We could e.g. put a
2431 * global lower bound value into TransamVariables.
2432 */
2435 oldestfxid);
2438 oldestfxid);
2441 oldestfxid);
2442 /* accurate value known */
2444 }
2445
2446 RecentXmin = xmin;
2448
2449 snapshot->xmin = xmin;
2450 snapshot->xmax = xmax;
2451 snapshot->xcnt = count;
2452 snapshot->subxcnt = subcount;
2453 snapshot->suboverflowed = suboverflowed;
2454 snapshot->snapXactCompletionCount = curXactCompletionCount;
2455
2456 snapshot->curcid = GetCurrentCommandId(false);
2457
2458 /*
2459 * This is a new snapshot, so set both refcounts are zero, and mark it as
2460 * not copied in persistent memory.
2461 */
2462 snapshot->active_count = 0;
2463 snapshot->regd_count = 0;
2464 snapshot->copied = false;
2465
2466 return snapshot;
2467}
#define likely(x)
Definition: c.h:406
uint64_t uint64
Definition: c.h:542
#define PROC_IN_LOGICAL_DECODING
Definition: proc.h:61
#define PROC_IN_VACUUM
Definition: proc.h:58
static GlobalVisState GlobalVisDataRels
Definition: procarray.c:299
static GlobalVisState GlobalVisSharedRels
Definition: procarray.c:297
static GlobalVisState GlobalVisCatalogRels
Definition: procarray.c:298
static FullTransactionId FullXidRelativeTo(FullTransactionId rel, TransactionId xid)
Definition: procarray.c:4283
static int KnownAssignedXidsGetAndSetXmin(TransactionId *xarray, TransactionId *xmin, TransactionId xmax)
Definition: procarray.c:5089
int GetMaxSnapshotSubxidCount(void)
Definition: procarray.c:2028
static GlobalVisState GlobalVisTempRels
Definition: procarray.c:300
int GetMaxSnapshotXidCount(void)
Definition: procarray.c:2017
static bool GetSnapshotDataReuse(Snapshot snapshot)
Definition: procarray.c:2043
TransactionId RecentXmin
Definition: snapmgr.c:160
TransactionId TransactionXmin
Definition: snapmgr.c:159
FullTransactionId definitely_needed
Definition: procarray.c:170
FullTransactionId maybe_needed
Definition: procarray.c:173
int pgxactoff
Definition: proc.h:201
TransactionId xid
Definition: proc.h:189
TransactionId xmin
Definition: snapshot.h:153
int32 subxcnt
Definition: snapshot.h:177
bool copied
Definition: snapshot.h:181
uint32 regd_count
Definition: snapshot.h:201
uint32 active_count
Definition: snapshot.h:200
CommandId curcid
Definition: snapshot.h:183
uint32 xcnt
Definition: snapshot.h:165
TransactionId * subxip
Definition: snapshot.h:176
uint64 snapXactCompletionCount
Definition: snapshot.h:209
TransactionId xmax
Definition: snapshot.h:154
TransactionId * xip
Definition: snapshot.h:164
bool suboverflowed
Definition: snapshot.h:178
bool takenDuringRecovery
Definition: snapshot.h:180
TransactionId oldestXid
Definition: transam.h:222
static FullTransactionId FullTransactionIdNewer(FullTransactionId a, FullTransactionId b)
Definition: transam.h:422
#define NormalTransactionIdPrecedes(id1, id2)
Definition: transam.h:147
static void FullTransactionIdAdvance(FullTransactionId *dest)
Definition: transam.h:128
#define TransactionIdAdvance(dest)
Definition: transam.h:91
static TransactionId TransactionIdOlder(TransactionId a, TransactionId b)
Definition: transam.h:396
CommandId GetCurrentCommandId(bool used)
Definition: xact.c:830

References SnapshotData::active_count, allProcs, Assert(), SnapshotData::copied, XidCacheStatus::count, SnapshotData::curcid, GlobalVisState::definitely_needed, ereport, errcode(), errmsg(), ERROR, FullTransactionIdAdvance(), FullTransactionIdNewer(), FullXidRelativeTo(), GetCurrentCommandId(), GetMaxSnapshotSubxidCount(), GetMaxSnapshotXidCount(), GetSnapshotDataReuse(), GlobalVisCatalogRels, GlobalVisDataRels, GlobalVisSharedRels, GlobalVisTempRels, InvalidTransactionId, KnownAssignedXidsGetAndSetXmin(), ProcArrayStruct::lastOverflowedXid, TransamVariablesData::latestCompletedXid, likely, LW_SHARED, LWLockAcquire(), LWLockRelease(), malloc, GlobalVisState::maybe_needed, MyProc, NormalTransactionIdPrecedes, ProcArrayStruct::numProcs, TransamVariablesData::oldestXid, pg_read_barrier, ProcArrayStruct::pgprocnos, PGPROC::pgxactoff, PROC_IN_LOGICAL_DECODING, PROC_IN_VACUUM, procArray, ProcGlobal, RecentXmin, RecoveryInProgress(), SnapshotData::regd_count, ProcArrayStruct::replication_slot_catalog_xmin, ProcArrayStruct::replication_slot_xmin, SnapshotData::snapXactCompletionCount, PROC_HDR::statusFlags, SnapshotData::suboverflowed, SnapshotData::subxcnt, PGPROC::subxids, PROC_HDR::subxidStates, SnapshotData::subxip, SnapshotData::takenDuringRecovery, TransactionIdAdvance, TransactionIdIsNormal, TransactionIdIsValid, TransactionIdOlder(), TransactionIdPrecedesOrEquals(), TransactionXmin, TransamVariables, UINT32_ACCESS_ONCE, TransamVariablesData::xactCompletionCount, SnapshotData::xcnt, PGPROC::xid, XidFromFullTransactionId, XidCache::xids, PROC_HDR::xids, SnapshotData::xip, SnapshotData::xmax, PGPROC::xmin, and SnapshotData::xmin.

Referenced by GetLatestSnapshot(), GetNonHistoricCatalogSnapshot(), GetSerializableTransactionSnapshotInt(), GetTransactionSnapshot(), and SetTransactionSnapshot().

◆ GetVirtualXIDsDelayingChkpt()

VirtualTransactionId * GetVirtualXIDsDelayingChkpt ( int *  nvxids,
int  type 
)

Definition at line 3005 of file procarray.c.

3006{
3007 VirtualTransactionId *vxids;
3008 ProcArrayStruct *arrayP = procArray;
3009 int count = 0;
3010 int index;
3011
3012 Assert(type != 0);
3013
3014 /* allocate what's certainly enough result space */
3015 vxids = (VirtualTransactionId *)
3016 palloc(sizeof(VirtualTransactionId) * arrayP->maxProcs);
3017
3018 LWLockAcquire(ProcArrayLock, LW_SHARED);
3019
3020 for (index = 0; index < arrayP->numProcs; index++)
3021 {
3022 int pgprocno = arrayP->pgprocnos[index];
3023 PGPROC *proc = &allProcs[pgprocno];
3024
3025 if ((proc->delayChkptFlags & type) != 0)
3026 {
3028
3029 GET_VXID_FROM_PGPROC(vxid, *proc);
3031 vxids[count++] = vxid;
3032 }
3033 }
3034
3035 LWLockRelease(ProcArrayLock);
3036
3037 *nvxids = count;
3038 return vxids;
3039}
const char * type

References allProcs, Assert(), PGPROC::delayChkptFlags, GET_VXID_FROM_PGPROC, LW_SHARED, LWLockAcquire(), LWLockRelease(), ProcArrayStruct::maxProcs, ProcArrayStruct::numProcs, palloc(), ProcArrayStruct::pgprocnos, procArray, type, and VirtualTransactionIdIsValid.

Referenced by CreateCheckPoint().

◆ HaveVirtualXIDsDelayingChkpt()

bool HaveVirtualXIDsDelayingChkpt ( VirtualTransactionId vxids,
int  nvxids,
int  type 
)

Definition at line 3051 of file procarray.c.

3052{
3053 bool result = false;
3054 ProcArrayStruct *arrayP = procArray;
3055 int index;
3056
3057 Assert(type != 0);
3058
3059 LWLockAcquire(ProcArrayLock, LW_SHARED);
3060
3061 for (index = 0; index < arrayP->numProcs; index++)
3062 {
3063 int pgprocno = arrayP->pgprocnos[index];
3064 PGPROC *proc = &allProcs[pgprocno];
3066
3067 GET_VXID_FROM_PGPROC(vxid, *proc);
3068
3069 if ((proc->delayChkptFlags & type) != 0 &&
3071 {
3072 int i;
3073
3074 for (i = 0; i < nvxids; i++)
3075 {
3076 if (VirtualTransactionIdEquals(vxid, vxids[i]))
3077 {
3078 result = true;
3079 break;
3080 }
3081 }
3082 if (result)
3083 break;
3084 }
3085 }
3086
3087 LWLockRelease(ProcArrayLock);
3088
3089 return result;
3090}
int i
Definition: isn.c:77
#define VirtualTransactionIdEquals(vxid1, vxid2)
Definition: lock.h:73

References allProcs, Assert(), PGPROC::delayChkptFlags, GET_VXID_FROM_PGPROC, i, LW_SHARED, LWLockAcquire(), LWLockRelease(), ProcArrayStruct::numProcs, ProcArrayStruct::pgprocnos, procArray, type, VirtualTransactionIdEquals, and VirtualTransactionIdIsValid.

Referenced by CreateCheckPoint().

◆ IsBackendPid()

bool IsBackendPid ( int  pid)

Definition at line 3253 of file procarray.c.

3254{
3255 return (BackendPidGetProc(pid) != NULL);
3256}
PGPROC * BackendPidGetProc(int pid)
Definition: procarray.c:3158

References BackendPidGetProc().

Referenced by pg_stat_get_subscription().

◆ KnownAssignedTransactionIdsIdleMaintenance()

void KnownAssignedTransactionIdsIdleMaintenance ( void  )

Definition at line 4526 of file procarray.c.

4527{
4529}
@ KAX_STARTUP_PROCESS_IDLE
Definition: procarray.c:265
static void KnownAssignedXidsCompress(KAXCompressReason reason, bool haveLock)
Definition: procarray.c:4627

References KAX_STARTUP_PROCESS_IDLE, and KnownAssignedXidsCompress().

Referenced by WaitForWALToBecomeAvailable().

◆ MinimumActiveBackends()

bool MinimumActiveBackends ( int  min)

Definition at line 3508 of file procarray.c.

3509{
3510 ProcArrayStruct *arrayP = procArray;
3511 int count = 0;
3512 int index;
3513
3514 /* Quick short-circuit if no minimum is specified */
3515 if (min == 0)
3516 return true;
3517
3518 /*
3519 * Note: for speed, we don't acquire ProcArrayLock. This is a little bit
3520 * bogus, but since we are only testing fields for zero or nonzero, it
3521 * should be OK. The result is only used for heuristic purposes anyway...
3522 */
3523 for (index = 0; index < arrayP->numProcs; index++)
3524 {
3525 int pgprocno = arrayP->pgprocnos[index];
3526 PGPROC *proc = &allProcs[pgprocno];
3527
3528 /*
3529 * Since we're not holding a lock, need to be prepared to deal with
3530 * garbage, as someone could have incremented numProcs but not yet
3531 * filled the structure.
3532 *
3533 * If someone just decremented numProcs, 'proc' could also point to a
3534 * PGPROC entry that's no longer in the array. It still points to a
3535 * PGPROC struct, though, because freed PGPROC entries just go to the
3536 * free list and are recycled. Its contents are nonsense in that case,
3537 * but that's acceptable for this function.
3538 */
3539 if (pgprocno == -1)
3540 continue; /* do not count deleted entries */
3541 if (proc == MyProc)
3542 continue; /* do not count myself */
3543 if (proc->xid == InvalidTransactionId)
3544 continue; /* do not count if no XID assigned */
3545 if (proc->pid == 0)
3546 continue; /* do not count prepared xacts */
3547 if (proc->waitLock != NULL)
3548 continue; /* do not count if blocked on a lock */
3549 count++;
3550 if (count >= min)
3551 break;
3552 }
3553
3554 return count >= min;
3555}
LOCK * waitLock
Definition: proc.h:249

References allProcs, InvalidTransactionId, MyProc, ProcArrayStruct::numProcs, ProcArrayStruct::pgprocnos, PGPROC::pid, procArray, PGPROC::waitLock, and PGPROC::xid.

Referenced by XLogFlush().

◆ ProcArrayAdd()

void ProcArrayAdd ( PGPROC proc)

Definition at line 468 of file procarray.c.

469{
470 int pgprocno = GetNumberFromPGProc(proc);
471 ProcArrayStruct *arrayP = procArray;
472 int index;
473 int movecount;
474
475 /* See ProcGlobal comment explaining why both locks are held */
476 LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
477 LWLockAcquire(XidGenLock, LW_EXCLUSIVE);
478
479 if (arrayP->numProcs >= arrayP->maxProcs)
480 {
481 /*
482 * Oops, no room. (This really shouldn't happen, since there is a
483 * fixed supply of PGPROC structs too, and so we should have failed
484 * earlier.)
485 */
487 (errcode(ERRCODE_TOO_MANY_CONNECTIONS),
488 errmsg("sorry, too many clients already")));
489 }
490
491 /*
492 * Keep the procs array sorted by (PGPROC *) so that we can utilize
493 * locality of references much better. This is useful while traversing the
494 * ProcArray because there is an increased likelihood of finding the next
495 * PGPROC structure in the cache.
496 *
497 * Since the occurrence of adding/removing a proc is much lower than the
498 * access to the ProcArray itself, the overhead should be marginal
499 */
500 for (index = 0; index < arrayP->numProcs; index++)
501 {
502 int this_procno = arrayP->pgprocnos[index];
503
504 Assert(this_procno >= 0 && this_procno < (arrayP->maxProcs + NUM_AUXILIARY_PROCS));
505 Assert(allProcs[this_procno].pgxactoff == index);
506
507 /* If we have found our right position in the array, break */
508 if (this_procno > pgprocno)
509 break;
510 }
511
512 movecount = arrayP->numProcs - index;
513 memmove(&arrayP->pgprocnos[index + 1],
514 &arrayP->pgprocnos[index],
515 movecount * sizeof(*arrayP->pgprocnos));
516 memmove(&ProcGlobal->xids[index + 1],
518 movecount * sizeof(*ProcGlobal->xids));
519 memmove(&ProcGlobal->subxidStates[index + 1],
521 movecount * sizeof(*ProcGlobal->subxidStates));
522 memmove(&ProcGlobal->statusFlags[index + 1],
524 movecount * sizeof(*ProcGlobal->statusFlags));
525
526 arrayP->pgprocnos[index] = GetNumberFromPGProc(proc);
527 proc->pgxactoff = index;
528 ProcGlobal->xids[index] = proc->xid;
531
532 arrayP->numProcs++;
533
534 /* adjust pgxactoff for all following PGPROCs */
535 index++;
536 for (; index < arrayP->numProcs; index++)
537 {
538 int procno = arrayP->pgprocnos[index];
539
540 Assert(procno >= 0 && procno < (arrayP->maxProcs + NUM_AUXILIARY_PROCS));
541 Assert(allProcs[procno].pgxactoff == index - 1);
542
543 allProcs[procno].pgxactoff = index;
544 }
545
546 /*
547 * Release in reversed acquisition order, to reduce frequency of having to
548 * wait for XidGenLock while holding ProcArrayLock.
549 */
550 LWLockRelease(XidGenLock);
551 LWLockRelease(ProcArrayLock);
552}
#define FATAL
Definition: elog.h:41
#define NUM_AUXILIARY_PROCS
Definition: proc.h:463
#define GetNumberFromPGProc(proc)
Definition: proc.h:441
uint8 statusFlags
Definition: proc.h:259
XidCacheStatus subxidStatus
Definition: proc.h:280

References allProcs, Assert(), ereport, errcode(), errmsg(), FATAL, GetNumberFromPGProc, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), ProcArrayStruct::maxProcs, NUM_AUXILIARY_PROCS, ProcArrayStruct::numProcs, ProcArrayStruct::pgprocnos, PGPROC::pgxactoff, procArray, ProcGlobal, PGPROC::statusFlags, PROC_HDR::statusFlags, PROC_HDR::subxidStates, PGPROC::subxidStatus, PGPROC::xid, and PROC_HDR::xids.

Referenced by InitProcessPhase2(), and MarkAsPrepared().

◆ ProcArrayApplyRecoveryInfo()

void ProcArrayApplyRecoveryInfo ( RunningTransactions  running)

Definition at line 1054 of file procarray.c.

1055{
1056 TransactionId *xids;
1057 TransactionId advanceNextXid;
1058 int nxids;
1059 int i;
1060
1065
1066 /*
1067 * Remove stale transactions, if any.
1068 */
1070
1071 /*
1072 * Adjust TransamVariables->nextXid before StandbyReleaseOldLocks(),
1073 * because we will need it up to date for accessing two-phase transactions
1074 * in StandbyReleaseOldLocks().
1075 */
1076 advanceNextXid = running->nextXid;
1077 TransactionIdRetreat(advanceNextXid);
1080
1081 /*
1082 * Remove stale locks, if any.
1083 */
1085
1086 /*
1087 * If our snapshot is already valid, nothing else to do...
1088 */
1090 return;
1091
1092 /*
1093 * If our initial RunningTransactionsData had an overflowed snapshot then
1094 * we knew we were missing some subxids from our snapshot. If we continue
1095 * to see overflowed snapshots then we might never be able to start up, so
1096 * we make another test to see if our snapshot is now valid. We know that
1097 * the missing subxids are equal to or earlier than nextXid. After we
1098 * initialise we continue to apply changes during recovery, so once the
1099 * oldestRunningXid is later than the nextXid from the initial snapshot we
1100 * know that we no longer have missing information and can mark the
1101 * snapshot as valid.
1102 */
1104 {
1105 /*
1106 * If the snapshot isn't overflowed or if its empty we can reset our
1107 * pending state and use this snapshot instead.
1108 */
1109 if (running->subxid_status != SUBXIDS_MISSING || running->xcnt == 0)
1110 {
1111 /*
1112 * If we have already collected known assigned xids, we need to
1113 * throw them away before we apply the recovery snapshot.
1114 */
1117 }
1118 else
1119 {
1121 running->oldestRunningXid))
1122 {
1124 elog(DEBUG1,
1125 "recovery snapshots are now enabled");
1126 }
1127 else
1128 elog(DEBUG1,
1129 "recovery snapshot waiting for non-overflowed snapshot or "
1130 "until oldest active xid on standby is at least %u (now %u)",
1132 running->oldestRunningXid);
1133 return;
1134 }
1135 }
1136
1138
1139 /*
1140 * NB: this can be reached at least twice, so make sure new code can deal
1141 * with that.
1142 */
1143
1144 /*
1145 * Nobody else is running yet, but take locks anyhow
1146 */
1147 LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
1148
1149 /*
1150 * KnownAssignedXids is sorted so we cannot just add the xids, we have to
1151 * sort them first.
1152 *
1153 * Some of the new xids are top-level xids and some are subtransactions.
1154 * We don't call SubTransSetParent because it doesn't matter yet. If we
1155 * aren't overflowed then all xids will fit in snapshot and so we don't
1156 * need subtrans. If we later overflow, an xid assignment record will add
1157 * xids to subtrans. If RunningTransactionsData is overflowed then we
1158 * don't have enough information to correctly update subtrans anyway.
1159 */
1160
1161 /*
1162 * Allocate a temporary array to avoid modifying the array passed as
1163 * argument.
1164 */
1165 xids = palloc(sizeof(TransactionId) * (running->xcnt + running->subxcnt));
1166
1167 /*
1168 * Add to the temp array any xids which have not already completed.
1169 */
1170 nxids = 0;
1171 for (i = 0; i < running->xcnt + running->subxcnt; i++)
1172 {
1173 TransactionId xid = running->xids[i];
1174
1175 /*
1176 * The running-xacts snapshot can contain xids that were still visible
1177 * in the procarray when the snapshot was taken, but were already
1178 * WAL-logged as completed. They're not running anymore, so ignore
1179 * them.
1180 */
1182 continue;
1183
1184 xids[nxids++] = xid;
1185 }
1186
1187 if (nxids > 0)
1188 {
1190 {
1191 LWLockRelease(ProcArrayLock);
1192 elog(ERROR, "KnownAssignedXids is not empty");
1193 }
1194
1195 /*
1196 * Sort the array so that we can add them safely into
1197 * KnownAssignedXids.
1198 *
1199 * We have to sort them logically, because in KnownAssignedXidsAdd we
1200 * call TransactionIdFollowsOrEquals and so on. But we know these XIDs
1201 * come from RUNNING_XACTS, which means there are only normal XIDs
1202 * from the same epoch, so this is safe.
1203 */
1204 qsort(xids, nxids, sizeof(TransactionId), xidLogicalComparator);
1205
1206 /*
1207 * Add the sorted snapshot into KnownAssignedXids. The running-xacts
1208 * snapshot may include duplicated xids because of prepared
1209 * transactions, so ignore them.
1210 */
1211 for (i = 0; i < nxids; i++)
1212 {
1213 if (i > 0 && TransactionIdEquals(xids[i - 1], xids[i]))
1214 {
1215 elog(DEBUG1,
1216 "found duplicated transaction %u for KnownAssignedXids insertion",
1217 xids[i]);
1218 continue;
1219 }
1220 KnownAssignedXidsAdd(xids[i], xids[i], true);
1221 }
1222
1224 }
1225
1226 pfree(xids);
1227
1228 /*
1229 * latestObservedXid is at least set to the point where SUBTRANS was
1230 * started up to (cf. ProcArrayInitRecovery()) or to the biggest xid
1231 * RecordKnownAssignedTransactionIds() was called for. Initialize
1232 * subtrans from thereon, up to nextXid - 1.
1233 *
1234 * We need to duplicate parts of RecordKnownAssignedTransactionId() here,
1235 * because we've just added xids to the known assigned xids machinery that
1236 * haven't gone through RecordKnownAssignedTransactionId().
1237 */
1241 {
1244 }
1245 TransactionIdRetreat(latestObservedXid); /* = running->nextXid - 1 */
1246
1247 /* ----------
1248 * Now we've got the running xids we need to set the global values that
1249 * are used to track snapshots as they evolve further.
1250 *
1251 * - latestCompletedXid which will be the xmax for snapshots
1252 * - lastOverflowedXid which shows whether snapshots overflow
1253 * - nextXid
1254 *
1255 * If the snapshot overflowed, then we still initialise with what we know,
1256 * but the recovery snapshot isn't fully valid yet because we know there
1257 * are some subxids missing. We don't know the specific subxids that are
1258 * missing, so conservatively assume the last one is latestObservedXid.
1259 * ----------
1260 */
1261 if (running->subxid_status == SUBXIDS_MISSING)
1262 {
1264
1267 }
1268 else
1269 {
1271
1273
1274 /*
1275 * If the 'xids' array didn't include all subtransactions, we have to
1276 * mark any snapshots taken as overflowed.
1277 */
1278 if (running->subxid_status == SUBXIDS_IN_SUBTRANS)
1280 else
1281 {
1284 }
1285 }
1286
1287 /*
1288 * If a transaction wrote a commit record in the gap between taking and
1289 * logging the snapshot then latestCompletedXid may already be higher than
1290 * the value from the snapshot, so check before we use the incoming value.
1291 * It also might not yet be set at all.
1292 */
1294
1295 /*
1296 * NB: No need to increment TransamVariables->xactCompletionCount here,
1297 * nobody can see it yet.
1298 */
1299
1300 LWLockRelease(ProcArrayLock);
1301
1304 elog(DEBUG1, "recovery snapshots are now enabled");
1305 else
1306 elog(DEBUG1,
1307 "recovery snapshot waiting for non-overflowed snapshot or "
1308 "until oldest active xid on standby is at least %u (now %u)",
1310 running->oldestRunningXid);
1311}
#define DEBUG3
Definition: elog.h:28
#define DEBUG1
Definition: elog.h:30
#define elog(elevel,...)
Definition: elog.h:226
void pfree(void *pointer)
Definition: mcxt.c:1594
#define qsort(a, b, c, d)
Definition: port.h:500
static TransactionId standbySnapshotPendingXmin
Definition: procarray.c:290
static TransactionId latestObservedXid
Definition: procarray.c:283
static void KnownAssignedXidsDisplay(int trace_level)
Definition: procarray.c:5180
static void KnownAssignedXidsReset(void)
Definition: procarray.c:5218
static void KnownAssignedXidsAdd(TransactionId from_xid, TransactionId to_xid, bool exclusive_lock)
Definition: procarray.c:4744
void ExpireOldKnownAssignedTransactionIds(TransactionId xid)
Definition: procarray.c:4494
void StandbyReleaseOldLocks(TransactionId oldxid)
Definition: standby.c:1130
@ SUBXIDS_MISSING
Definition: standby.h:81
int numKnownAssignedXids
Definition: procarray.c:80
void ExtendSUBTRANS(TransactionId newestXact)
Definition: subtrans.c:353
bool TransactionIdDidCommit(TransactionId transactionId)
Definition: transam.c:126
bool TransactionIdDidAbort(TransactionId transactionId)
Definition: transam.c:188
#define TransactionIdEquals(id1, id2)
Definition: transam.h:43
void AdvanceNextFullTransactionIdPastXid(TransactionId xid)
Definition: varsup.c:304
int xidLogicalComparator(const void *arg1, const void *arg2)
Definition: xid.c:169
@ STANDBY_SNAPSHOT_READY
Definition: xlogutils.h:55
@ STANDBY_SNAPSHOT_PENDING
Definition: xlogutils.h:54

References AdvanceNextFullTransactionIdPastXid(), Assert(), DEBUG1, DEBUG3, elog, ERROR, ExpireOldKnownAssignedTransactionIds(), ExtendSUBTRANS(), FullTransactionIdIsValid, i, InvalidTransactionId, KnownAssignedXidsAdd(), KnownAssignedXidsDisplay(), KnownAssignedXidsReset(), ProcArrayStruct::lastOverflowedXid, RunningTransactionsData::latestCompletedXid, latestObservedXid, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MaintainLatestCompletedXidRecovery(), TransamVariablesData::nextXid, RunningTransactionsData::nextXid, ProcArrayStruct::numKnownAssignedXids, RunningTransactionsData::oldestRunningXid, palloc(), pfree(), procArray, qsort, STANDBY_INITIALIZED, STANDBY_SNAPSHOT_PENDING, STANDBY_SNAPSHOT_READY, StandbyReleaseOldLocks(), standbySnapshotPendingXmin, standbyState, RunningTransactionsData::subxcnt, RunningTransactionsData::subxid_status, SUBXIDS_IN_ARRAY, SUBXIDS_IN_SUBTRANS, SUBXIDS_MISSING, TransactionIdAdvance, TransactionIdDidAbort(), TransactionIdDidCommit(), TransactionIdEquals, TransactionIdIsNormal, TransactionIdIsValid, TransactionIdPrecedes(), TransactionIdRetreat, TransamVariables, RunningTransactionsData::xcnt, xidLogicalComparator(), and RunningTransactionsData::xids.

Referenced by standby_redo(), StartupXLOG(), and xlog_redo().

◆ ProcArrayApplyXidAssignment()

void ProcArrayApplyXidAssignment ( TransactionId  topxid,
int  nsubxids,
TransactionId subxids 
)

Definition at line 1318 of file procarray.c.

1320{
1321 TransactionId max_xid;
1322 int i;
1323
1325
1326 max_xid = TransactionIdLatest(topxid, nsubxids, subxids);
1327
1328 /*
1329 * Mark all the subtransactions as observed.
1330 *
1331 * NOTE: This will fail if the subxid contains too many previously
1332 * unobserved xids to fit into known-assigned-xids. That shouldn't happen
1333 * as the code stands, because xid-assignment records should never contain
1334 * more than PGPROC_MAX_CACHED_SUBXIDS entries.
1335 */
1337
1338 /*
1339 * Notice that we update pg_subtrans with the top-level xid, rather than
1340 * the parent xid. This is a difference between normal processing and
1341 * recovery, yet is still correct in all cases. The reason is that
1342 * subtransaction commit is not marked in clog until commit processing, so
1343 * all aborted subtransactions have already been clearly marked in clog.
1344 * As a result we are able to refer directly to the top-level
1345 * transaction's state rather than skipping through all the intermediate
1346 * states in the subtransaction tree. This should be the first time we
1347 * have attempted to SubTransSetParent().
1348 */
1349 for (i = 0; i < nsubxids; i++)
1350 SubTransSetParent(subxids[i], topxid);
1351
1352 /* KnownAssignedXids isn't maintained yet, so we're done for now */
1354 return;
1355
1356 /*
1357 * Uses same locking as transaction commit
1358 */
1359 LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
1360
1361 /*
1362 * Remove subxids from known-assigned-xacts.
1363 */
1365
1366 /*
1367 * Advance lastOverflowedXid to be at least the last of these subxids.
1368 */
1370 procArray->lastOverflowedXid = max_xid;
1371
1372 LWLockRelease(ProcArrayLock);
1373}
void RecordKnownAssignedTransactionIds(TransactionId xid)
Definition: procarray.c:4365
void SubTransSetParent(TransactionId xid, TransactionId parent)
Definition: subtrans.c:84
TransactionId TransactionIdLatest(TransactionId mainxid, int nxids, const TransactionId *xids)
Definition: transam.c:281

References Assert(), i, InvalidTransactionId, KnownAssignedXidsRemoveTree(), ProcArrayStruct::lastOverflowedXid, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), procArray, RecordKnownAssignedTransactionIds(), STANDBY_INITIALIZED, standbyState, SubTransSetParent(), TransactionIdLatest(), and TransactionIdPrecedes().

Referenced by xact_redo().

◆ ProcArrayClearTransaction()

void ProcArrayClearTransaction ( PGPROC proc)

Definition at line 907 of file procarray.c.

908{
909 int pgxactoff;
910
911 /*
912 * Currently we need to lock ProcArrayLock exclusively here, as we
913 * increment xactCompletionCount below. We also need it at least in shared
914 * mode for pgproc->pgxactoff to stay the same below.
915 *
916 * We could however, as this action does not actually change anyone's view
917 * of the set of running XIDs (our entry is duplicate with the gxact that
918 * has already been inserted into the ProcArray), lower the lock level to
919 * shared if we were to make xactCompletionCount an atomic variable. But
920 * that doesn't seem worth it currently, as a 2PC commit is heavyweight
921 * enough for this not to be the bottleneck. If it ever becomes a
922 * bottleneck it may also be worth considering to combine this with the
923 * subsequent ProcArrayRemove()
924 */
925 LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
926
927 pgxactoff = proc->pgxactoff;
928
931
934 proc->recoveryConflictPending = false;
935
937 Assert(!proc->delayChkptFlags);
938
939 /*
940 * Need to increment completion count even though transaction hasn't
941 * really committed yet. The reason for that is that GetSnapshotData()
942 * omits the xid of the current transaction, thus without the increment we
943 * otherwise could end up reusing the snapshot later. Which would be bad,
944 * because it might not count the prepared transaction as running.
945 */
947
948 /* Clear the subtransaction-XID cache too */
949 Assert(ProcGlobal->subxidStates[pgxactoff].count == proc->subxidStatus.count &&
951 if (proc->subxidStatus.count > 0 || proc->subxidStatus.overflowed)
952 {
953 ProcGlobal->subxidStates[pgxactoff].count = 0;
954 ProcGlobal->subxidStates[pgxactoff].overflowed = false;
955 proc->subxidStatus.count = 0;
956 proc->subxidStatus.overflowed = false;
957 }
958
959 LWLockRelease(ProcArrayLock);
960}
#define PROC_VACUUM_STATE_MASK
Definition: proc.h:65
LocalTransactionId lxid
Definition: proc.h:217
struct PGPROC::@130 vxid

References Assert(), XidCacheStatus::count, PGPROC::delayChkptFlags, InvalidLocalTransactionId, InvalidTransactionId, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), PGPROC::lxid, XidCacheStatus::overflowed, PGPROC::pgxactoff, PROC_VACUUM_STATE_MASK, ProcGlobal, PGPROC::recoveryConflictPending, PGPROC::statusFlags, PROC_HDR::subxidStates, PGPROC::subxidStatus, TransamVariables, PGPROC::vxid, TransamVariablesData::xactCompletionCount, PGPROC::xid, PROC_HDR::xids, and PGPROC::xmin.

Referenced by PrepareTransaction().

◆ ProcArrayEndTransaction()

void ProcArrayEndTransaction ( PGPROC proc,
TransactionId  latestXid 
)

Definition at line 667 of file procarray.c.

668{
669 if (TransactionIdIsValid(latestXid))
670 {
671 /*
672 * We must lock ProcArrayLock while clearing our advertised XID, so
673 * that we do not exit the set of "running" transactions while someone
674 * else is taking a snapshot. See discussion in
675 * src/backend/access/transam/README.
676 */
678
679 /*
680 * If we can immediately acquire ProcArrayLock, we clear our own XID
681 * and release the lock. If not, use group XID clearing to improve
682 * efficiency.
683 */
684 if (LWLockConditionalAcquire(ProcArrayLock, LW_EXCLUSIVE))
685 {
686 ProcArrayEndTransactionInternal(proc, latestXid);
687 LWLockRelease(ProcArrayLock);
688 }
689 else
690 ProcArrayGroupClearXid(proc, latestXid);
691 }
692 else
693 {
694 /*
695 * If we have no XID, we don't need to lock, since we won't affect
696 * anyone else's calculation of a snapshot. We might change their
697 * estimate of global xmin, but that's OK.
698 */
700 Assert(proc->subxidStatus.count == 0);
702
705
706 /* be sure this is cleared in abort */
707 proc->delayChkptFlags = 0;
708
709 proc->recoveryConflictPending = false;
710
711 /* must be cleared with xid/xmin: */
712 /* avoid unnecessarily dirtying shared cachelines */
714 {
715 Assert(!LWLockHeldByMe(ProcArrayLock));
716 LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
718 proc->statusFlags &= ~PROC_VACUUM_STATE_MASK;
720 LWLockRelease(ProcArrayLock);
721 }
722 }
723}
bool LWLockConditionalAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1345
static void ProcArrayEndTransactionInternal(PGPROC *proc, TransactionId latestXid)
Definition: procarray.c:731
static void ProcArrayGroupClearXid(PGPROC *proc, TransactionId latestXid)
Definition: procarray.c:792

References Assert(), XidCacheStatus::count, PGPROC::delayChkptFlags, InvalidLocalTransactionId, InvalidTransactionId, LW_EXCLUSIVE, LWLockAcquire(), LWLockConditionalAcquire(), LWLockHeldByMe(), LWLockRelease(), PGPROC::lxid, XidCacheStatus::overflowed, PGPROC::pgxactoff, PROC_VACUUM_STATE_MASK, ProcArrayEndTransactionInternal(), ProcArrayGroupClearXid(), ProcGlobal, PGPROC::recoveryConflictPending, PGPROC::statusFlags, PROC_HDR::statusFlags, PGPROC::subxidStatus, TransactionIdIsValid, PGPROC::vxid, PGPROC::xid, and PGPROC::xmin.

Referenced by AbortTransaction(), and CommitTransaction().

◆ ProcArrayGetReplicationSlotXmin()

void ProcArrayGetReplicationSlotXmin ( TransactionId xmin,
TransactionId catalog_xmin 
)

Definition at line 3930 of file procarray.c.

3932{
3933 LWLockAcquire(ProcArrayLock, LW_SHARED);
3934
3935 if (xmin != NULL)
3937
3938 if (catalog_xmin != NULL)
3940
3941 LWLockRelease(ProcArrayLock);
3942}

References LW_SHARED, LWLockAcquire(), LWLockRelease(), procArray, ProcArrayStruct::replication_slot_catalog_xmin, and ProcArrayStruct::replication_slot_xmin.

Referenced by logical_begin_heap_rewrite().

◆ ProcArrayInitRecovery()

void ProcArrayInitRecovery ( TransactionId  initializedUptoXID)

Definition at line 1023 of file procarray.c.

1024{
1026 Assert(TransactionIdIsNormal(initializedUptoXID));
1027
1028 /*
1029 * we set latestObservedXid to the xid SUBTRANS has been initialized up
1030 * to, so we can extend it from that point onwards in
1031 * RecordKnownAssignedTransactionIds, and when we get consistent in
1032 * ProcArrayApplyRecoveryInfo().
1033 */
1034 latestObservedXid = initializedUptoXID;
1036}

References Assert(), latestObservedXid, STANDBY_INITIALIZED, standbyState, TransactionIdIsNormal, and TransactionIdRetreat.

Referenced by StartupXLOG().

◆ ProcArrayInstallImportedXmin()

bool ProcArrayInstallImportedXmin ( TransactionId  xmin,
VirtualTransactionId sourcevxid 
)

Definition at line 2480 of file procarray.c.

2482{
2483 bool result = false;
2484 ProcArrayStruct *arrayP = procArray;
2485 int index;
2486
2488 if (!sourcevxid)
2489 return false;
2490
2491 /* Get lock so source xact can't end while we're doing this */
2492 LWLockAcquire(ProcArrayLock, LW_SHARED);
2493
2494 /*
2495 * Find the PGPROC entry of the source transaction. (This could use
2496 * GetPGProcByNumber(), unless it's a prepared xact. But this isn't
2497 * performance critical.)
2498 */
2499 for (index = 0; index < arrayP->numProcs; index++)
2500 {
2501 int pgprocno = arrayP->pgprocnos[index];
2502 PGPROC *proc = &allProcs[pgprocno];
2503 int statusFlags = ProcGlobal->statusFlags[index];
2504 TransactionId xid;
2505
2506 /* Ignore procs running LAZY VACUUM */
2507 if (statusFlags & PROC_IN_VACUUM)
2508 continue;
2509
2510 /* We are only interested in the specific virtual transaction. */
2511 if (proc->vxid.procNumber != sourcevxid->procNumber)
2512 continue;
2513 if (proc->vxid.lxid != sourcevxid->localTransactionId)
2514 continue;
2515
2516 /*
2517 * We check the transaction's database ID for paranoia's sake: if it's
2518 * in another DB then its xmin does not cover us. Caller should have
2519 * detected this already, so we just treat any funny cases as
2520 * "transaction not found".
2521 */
2522 if (proc->databaseId != MyDatabaseId)
2523 continue;
2524
2525 /*
2526 * Likewise, let's just make real sure its xmin does cover us.
2527 */
2528 xid = UINT32_ACCESS_ONCE(proc->xmin);
2529 if (!TransactionIdIsNormal(xid) ||
2531 continue;
2532
2533 /*
2534 * We're good. Install the new xmin. As in GetSnapshotData, set
2535 * TransactionXmin too. (Note that because snapmgr.c called
2536 * GetSnapshotData first, we'll be overwriting a valid xmin here, so
2537 * we don't check that.)
2538 */
2539 MyProc->xmin = TransactionXmin = xmin;
2540
2541 result = true;
2542 break;
2543 }
2544
2545 LWLockRelease(ProcArrayLock);
2546
2547 return result;
2548}
ProcNumber procNumber
Definition: proc.h:212

References allProcs, Assert(), PGPROC::databaseId, VirtualTransactionId::localTransactionId, LW_SHARED, LWLockAcquire(), LWLockRelease(), PGPROC::lxid, MyDatabaseId, MyProc, ProcArrayStruct::numProcs, ProcArrayStruct::pgprocnos, PROC_IN_VACUUM, procArray, ProcGlobal, VirtualTransactionId::procNumber, PGPROC::procNumber, PROC_HDR::statusFlags, TransactionIdIsNormal, TransactionIdPrecedesOrEquals(), TransactionXmin, UINT32_ACCESS_ONCE, PGPROC::vxid, and PGPROC::xmin.

Referenced by GetSerializableTransactionSnapshotInt(), and SetTransactionSnapshot().

◆ ProcArrayInstallRestoredXmin()

bool ProcArrayInstallRestoredXmin ( TransactionId  xmin,
PGPROC proc 
)

Definition at line 2564 of file procarray.c.

2565{
2566 bool result = false;
2567 TransactionId xid;
2568
2570 Assert(proc != NULL);
2571
2572 /*
2573 * Get an exclusive lock so that we can copy statusFlags from source proc.
2574 */
2575 LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
2576
2577 /*
2578 * Be certain that the referenced PGPROC has an advertised xmin which is
2579 * no later than the one we're installing, so that the system-wide xmin
2580 * can't go backwards. Also, make sure it's running in the same database,
2581 * so that the per-database xmin cannot go backwards.
2582 */
2583 xid = UINT32_ACCESS_ONCE(proc->xmin);
2584 if (proc->databaseId == MyDatabaseId &&
2585 TransactionIdIsNormal(xid) &&
2587 {
2588 /*
2589 * Install xmin and propagate the statusFlags that affect how the
2590 * value is interpreted by vacuum.
2591 */
2592 MyProc->xmin = TransactionXmin = xmin;
2593 MyProc->statusFlags = (MyProc->statusFlags & ~PROC_XMIN_FLAGS) |
2594 (proc->statusFlags & PROC_XMIN_FLAGS);
2596
2597 result = true;
2598 }
2599
2600 LWLockRelease(ProcArrayLock);
2601
2602 return result;
2603}
#define PROC_XMIN_FLAGS
Definition: proc.h:72

References Assert(), PGPROC::databaseId, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MyDatabaseId, MyProc, PGPROC::pgxactoff, PROC_XMIN_FLAGS, ProcGlobal, PGPROC::statusFlags, PROC_HDR::statusFlags, TransactionIdIsNormal, TransactionIdPrecedesOrEquals(), TransactionXmin, UINT32_ACCESS_ONCE, and PGPROC::xmin.

Referenced by SetTransactionSnapshot().

◆ ProcArrayRemove()

void ProcArrayRemove ( PGPROC proc,
TransactionId  latestXid 
)

Definition at line 565 of file procarray.c.

566{
567 ProcArrayStruct *arrayP = procArray;
568 int myoff;
569 int movecount;
570
571#ifdef XIDCACHE_DEBUG
572 /* dump stats at backend shutdown, but not prepared-xact end */
573 if (proc->pid != 0)
574 DisplayXidCache();
575#endif
576
577 /* See ProcGlobal comment explaining why both locks are held */
578 LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
579 LWLockAcquire(XidGenLock, LW_EXCLUSIVE);
580
581 myoff = proc->pgxactoff;
582
583 Assert(myoff >= 0 && myoff < arrayP->numProcs);
584 Assert(ProcGlobal->allProcs[arrayP->pgprocnos[myoff]].pgxactoff == myoff);
585
586 if (TransactionIdIsValid(latestXid))
587 {
589
590 /* Advance global latestCompletedXid while holding the lock */
592
593 /* Same with xactCompletionCount */
595
597 ProcGlobal->subxidStates[myoff].overflowed = false;
598 ProcGlobal->subxidStates[myoff].count = 0;
599 }
600 else
601 {
602 /* Shouldn't be trying to remove a live transaction here */
604 }
605
607 Assert(ProcGlobal->subxidStates[myoff].count == 0);
608 Assert(ProcGlobal->subxidStates[myoff].overflowed == false);
609
610 ProcGlobal->statusFlags[myoff] = 0;
611
612 /* Keep the PGPROC array sorted. See notes above */
613 movecount = arrayP->numProcs - myoff - 1;
614 memmove(&arrayP->pgprocnos[myoff],
615 &arrayP->pgprocnos[myoff + 1],
616 movecount * sizeof(*arrayP->pgprocnos));
617 memmove(&ProcGlobal->xids[myoff],
618 &ProcGlobal->xids[myoff + 1],
619 movecount * sizeof(*ProcGlobal->xids));
620 memmove(&ProcGlobal->subxidStates[myoff],
621 &ProcGlobal->subxidStates[myoff + 1],
622 movecount * sizeof(*ProcGlobal->subxidStates));
623 memmove(&ProcGlobal->statusFlags[myoff],
624 &ProcGlobal->statusFlags[myoff + 1],
625 movecount * sizeof(*ProcGlobal->statusFlags));
626
627 arrayP->pgprocnos[arrayP->numProcs - 1] = -1; /* for debugging */
628 arrayP->numProcs--;
629
630 /*
631 * Adjust pgxactoff of following procs for removed PGPROC (note that
632 * numProcs already has been decremented).
633 */
634 for (int index = myoff; index < arrayP->numProcs; index++)
635 {
636 int procno = arrayP->pgprocnos[index];
637
638 Assert(procno >= 0 && procno < (arrayP->maxProcs + NUM_AUXILIARY_PROCS));
639 Assert(allProcs[procno].pgxactoff - 1 == index);
640
641 allProcs[procno].pgxactoff = index;
642 }
643
644 /*
645 * Release in reversed acquisition order, to reduce frequency of having to
646 * wait for XidGenLock while holding ProcArrayLock.
647 */
648 LWLockRelease(XidGenLock);
649 LWLockRelease(ProcArrayLock);
650}
static void MaintainLatestCompletedXid(TransactionId latestXid)
Definition: procarray.c:967
PGPROC * allProcs
Definition: proc.h:388

References allProcs, PROC_HDR::allProcs, Assert(), XidCacheStatus::count, InvalidTransactionId, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MaintainLatestCompletedXid(), ProcArrayStruct::maxProcs, NUM_AUXILIARY_PROCS, ProcArrayStruct::numProcs, XidCacheStatus::overflowed, ProcArrayStruct::pgprocnos, PGPROC::pgxactoff, PGPROC::pid, procArray, ProcGlobal, PROC_HDR::statusFlags, PROC_HDR::subxidStates, TransactionIdIsValid, TransamVariables, TransamVariablesData::xactCompletionCount, and PROC_HDR::xids.

Referenced by FinishPreparedTransaction(), and RemoveProcFromArray().

◆ ProcArraySetReplicationSlotXmin()

void ProcArraySetReplicationSlotXmin ( TransactionId  xmin,
TransactionId  catalog_xmin,
bool  already_locked 
)

Definition at line 3905 of file procarray.c.

3907{
3908 Assert(!already_locked || LWLockHeldByMe(ProcArrayLock));
3909
3910 if (!already_locked)
3911 LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3912
3915
3916 if (!already_locked)
3917 LWLockRelease(ProcArrayLock);
3918
3919 elog(DEBUG1, "xmin required by slots: data %u, catalog %u",
3920 xmin, catalog_xmin);
3921}

References Assert(), DEBUG1, elog, LW_EXCLUSIVE, LWLockAcquire(), LWLockHeldByMe(), LWLockRelease(), procArray, ProcArrayStruct::replication_slot_catalog_xmin, and ProcArrayStruct::replication_slot_xmin.

Referenced by ReplicationSlotsComputeRequiredXmin().

◆ ProcArrayShmemInit()

void ProcArrayShmemInit ( void  )

Definition at line 418 of file procarray.c.

419{
420 bool found;
421
422 /* Create or attach to the ProcArray shared structure */
424 ShmemInitStruct("Proc Array",
425 add_size(offsetof(ProcArrayStruct, pgprocnos),
426 mul_size(sizeof(int),
428 &found);
429
430 if (!found)
431 {
432 /*
433 * We're the first - initialize.
434 */
435 procArray->numProcs = 0;
445 }
446
448
449 /* Create or attach to the KnownAssignedXids arrays too, if needed */
451 {
453 ShmemInitStruct("KnownAssignedXids",
454 mul_size(sizeof(TransactionId),
456 &found);
457 KnownAssignedXidsValid = (bool *)
458 ShmemInitStruct("KnownAssignedXidsValid",
459 mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS),
460 &found);
461 }
462}
#define PROCARRAY_MAXPROCS
static TransactionId * KnownAssignedXids
Definition: procarray.c:281
static bool * KnownAssignedXidsValid
Definition: procarray.c:282
Size add_size(Size s1, Size s2)
Definition: shmem.c:495
Size mul_size(Size s1, Size s2)
Definition: shmem.c:510
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition: shmem.c:389
int maxKnownAssignedXids
Definition: procarray.c:79
int tailKnownAssignedXids
Definition: procarray.c:81
int headKnownAssignedXids
Definition: procarray.c:82
bool EnableHotStandby
Definition: xlog.c:123

References add_size(), allProcs, PROC_HDR::allProcs, EnableHotStandby, ProcArrayStruct::headKnownAssignedXids, InvalidTransactionId, KnownAssignedXids, KnownAssignedXidsValid, ProcArrayStruct::lastOverflowedXid, ProcArrayStruct::maxKnownAssignedXids, ProcArrayStruct::maxProcs, mul_size(), ProcArrayStruct::numKnownAssignedXids, ProcArrayStruct::numProcs, procArray, PROCARRAY_MAXPROCS, ProcGlobal, ProcArrayStruct::replication_slot_catalog_xmin, ProcArrayStruct::replication_slot_xmin, ShmemInitStruct(), ProcArrayStruct::tailKnownAssignedXids, TOTAL_MAX_CACHED_SUBXIDS, TransamVariables, and TransamVariablesData::xactCompletionCount.

Referenced by CreateOrAttachShmemStructs().

◆ ProcArrayShmemSize()

Size ProcArrayShmemSize ( void  )

Definition at line 376 of file procarray.c.

377{
378 Size size;
379
380 /* Size of the ProcArray structure itself */
381#define PROCARRAY_MAXPROCS (MaxBackends + max_prepared_xacts)
382
383 size = offsetof(ProcArrayStruct, pgprocnos);
384 size = add_size(size, mul_size(sizeof(int), PROCARRAY_MAXPROCS));
385
386 /*
387 * During Hot Standby processing we have a data structure called
388 * KnownAssignedXids, created in shared memory. Local data structures are
389 * also created in various backends during GetSnapshotData(),
390 * TransactionIdIsInProgress() and GetRunningTransactionData(). All of the
391 * main structures created in those functions must be identically sized,
392 * since we may at times copy the whole of the data structures around. We
393 * refer to this size as TOTAL_MAX_CACHED_SUBXIDS.
394 *
395 * Ideally we'd only create this structure if we were actually doing hot
396 * standby in the current run, but we don't know that yet at the time
397 * shared memory is being set up.
398 */
399#define TOTAL_MAX_CACHED_SUBXIDS \
400 ((PGPROC_MAX_CACHED_SUBXIDS + 1) * PROCARRAY_MAXPROCS)
401
403 {
404 size = add_size(size,
405 mul_size(sizeof(TransactionId),
407 size = add_size(size,
408 mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS));
409 }
410
411 return size;
412}
size_t Size
Definition: c.h:613

References add_size(), EnableHotStandby, mul_size(), PROCARRAY_MAXPROCS, and TOTAL_MAX_CACHED_SUBXIDS.

Referenced by CalculateShmemSize().

◆ ProcNumberGetProc()

PGPROC * ProcNumberGetProc ( int  procNumber)

Definition at line 3100 of file procarray.c.

3101{
3102 PGPROC *result;
3103
3104 if (procNumber < 0 || procNumber >= ProcGlobal->allProcCount)
3105 return NULL;
3106 result = GetPGProcByNumber(procNumber);
3107
3108 if (result->pid == 0)
3109 return NULL;
3110
3111 return result;
3112}
#define GetPGProcByNumber(n)
Definition: proc.h:440
uint32 allProcCount
Definition: proc.h:406

References PROC_HDR::allProcCount, GetPGProcByNumber, PGPROC::pid, and ProcGlobal.

Referenced by checkTempNamespaceStatus(), LogRecoveryConflict(), VirtualXactLock(), WaitForLockersMultiple(), and WaitForOlderSnapshots().

◆ ProcNumberGetTransactionIds()

void ProcNumberGetTransactionIds ( int  procNumber,
TransactionId xid,
TransactionId xmin,
int *  nsubxid,
bool *  overflowed 
)

Definition at line 3122 of file procarray.c.

3124{
3125 PGPROC *proc;
3126
3127 *xid = InvalidTransactionId;
3128 *xmin = InvalidTransactionId;
3129 *nsubxid = 0;
3130 *overflowed = false;
3131
3132 if (procNumber < 0 || procNumber >= ProcGlobal->allProcCount)
3133 return;
3134 proc = GetPGProcByNumber(procNumber);
3135
3136 /* Need to lock out additions/removals of backends */
3137 LWLockAcquire(ProcArrayLock, LW_SHARED);
3138
3139 if (proc->pid != 0)
3140 {
3141 *xid = proc->xid;
3142 *xmin = proc->xmin;
3143 *nsubxid = proc->subxidStatus.count;
3144 *overflowed = proc->subxidStatus.overflowed;
3145 }
3146
3147 LWLockRelease(ProcArrayLock);
3148}

References PROC_HDR::allProcCount, XidCacheStatus::count, GetPGProcByNumber, InvalidTransactionId, LW_SHARED, LWLockAcquire(), LWLockRelease(), XidCacheStatus::overflowed, PGPROC::pid, ProcGlobal, PGPROC::subxidStatus, PGPROC::xid, and PGPROC::xmin.

Referenced by pgstat_read_current_status().

◆ RecordKnownAssignedTransactionIds()

void RecordKnownAssignedTransactionIds ( TransactionId  xid)

Definition at line 4365 of file procarray.c.

4366{
4370
4371 elog(DEBUG4, "record known xact %u latestObservedXid %u",
4372 xid, latestObservedXid);
4373
4374 /*
4375 * When a newly observed xid arrives, it is frequently the case that it is
4376 * *not* the next xid in sequence. When this occurs, we must treat the
4377 * intervening xids as running also.
4378 */
4380 {
4381 TransactionId next_expected_xid;
4382
4383 /*
4384 * Extend subtrans like we do in GetNewTransactionId() during normal
4385 * operation using individual extend steps. Note that we do not need
4386 * to extend clog since its extensions are WAL logged.
4387 *
4388 * This part has to be done regardless of standbyState since we
4389 * immediately start assigning subtransactions to their toplevel
4390 * transactions.
4391 */
4392 next_expected_xid = latestObservedXid;
4393 while (TransactionIdPrecedes(next_expected_xid, xid))
4394 {
4395 TransactionIdAdvance(next_expected_xid);
4396 ExtendSUBTRANS(next_expected_xid);
4397 }
4398 Assert(next_expected_xid == xid);
4399
4400 /*
4401 * If the KnownAssignedXids machinery isn't up yet, there's nothing
4402 * more to do since we don't track assigned xids yet.
4403 */
4405 {
4406 latestObservedXid = xid;
4407 return;
4408 }
4409
4410 /*
4411 * Add (latestObservedXid, xid] onto the KnownAssignedXids array.
4412 */
4413 next_expected_xid = latestObservedXid;
4414 TransactionIdAdvance(next_expected_xid);
4415 KnownAssignedXidsAdd(next_expected_xid, xid, false);
4416
4417 /*
4418 * Now we can advance latestObservedXid
4419 */
4420 latestObservedXid = xid;
4421
4422 /* TransamVariables->nextXid must be beyond any observed xid */
4424 }
4425}
#define DEBUG4
Definition: elog.h:27

References AdvanceNextFullTransactionIdPastXid(), Assert(), DEBUG4, elog, ExtendSUBTRANS(), KnownAssignedXidsAdd(), latestObservedXid, STANDBY_INITIALIZED, standbyState, TransactionIdAdvance, TransactionIdFollows(), TransactionIdIsValid, and TransactionIdPrecedes().

Referenced by ApplyWalRecord(), ProcArrayApplyXidAssignment(), xact_redo_abort(), and xact_redo_commit().

◆ SignalVirtualTransaction()

pid_t SignalVirtualTransaction ( VirtualTransactionId  vxid,
ProcSignalReason  sigmode,
bool  conflictPending 
)

Definition at line 3459 of file procarray.c.

3461{
3462 ProcArrayStruct *arrayP = procArray;
3463 int index;
3464 pid_t pid = 0;
3465
3466 LWLockAcquire(ProcArrayLock, LW_SHARED);
3467
3468 for (index = 0; index < arrayP->numProcs; index++)
3469 {
3470 int pgprocno = arrayP->pgprocnos[index];
3471 PGPROC *proc = &allProcs[pgprocno];
3472 VirtualTransactionId procvxid;
3473
3474 GET_VXID_FROM_PGPROC(procvxid, *proc);
3475
3476 if (procvxid.procNumber == vxid.procNumber &&
3477 procvxid.localTransactionId == vxid.localTransactionId)
3478 {
3479 proc->recoveryConflictPending = conflictPending;
3480 pid = proc->pid;
3481 if (pid != 0)
3482 {
3483 /*
3484 * Kill the pid if it's still here. If not, that's what we
3485 * wanted so ignore any errors.
3486 */
3487 (void) SendProcSignal(pid, sigmode, vxid.procNumber);
3488 }
3489 break;
3490 }
3491 }
3492
3493 LWLockRelease(ProcArrayLock);
3494
3495 return pid;
3496}

References allProcs, GET_VXID_FROM_PGPROC, VirtualTransactionId::localTransactionId, LW_SHARED, LWLockAcquire(), LWLockRelease(), ProcArrayStruct::numProcs, ProcArrayStruct::pgprocnos, PGPROC::pid, procArray, VirtualTransactionId::procNumber, PGPROC::recoveryConflictPending, and SendProcSignal().

Referenced by CancelVirtualTransaction(), and ResolveRecoveryConflictWithLock().

◆ TerminateOtherDBBackends()

void TerminateOtherDBBackends ( Oid  databaseId)

Definition at line 3790 of file procarray.c.

3791{
3792 ProcArrayStruct *arrayP = procArray;
3793 List *pids = NIL;
3794 int nprepared = 0;
3795 int i;
3796
3797 LWLockAcquire(ProcArrayLock, LW_SHARED);
3798
3799 for (i = 0; i < procArray->numProcs; i++)
3800 {
3801 int pgprocno = arrayP->pgprocnos[i];
3802 PGPROC *proc = &allProcs[pgprocno];
3803
3804 if (proc->databaseId != databaseId)
3805 continue;
3806 if (proc == MyProc)
3807 continue;
3808
3809 if (proc->pid != 0)
3810 pids = lappend_int(pids, proc->pid);
3811 else
3812 nprepared++;
3813 }
3814
3815 LWLockRelease(ProcArrayLock);
3816
3817 if (nprepared > 0)
3818 ereport(ERROR,
3819 (errcode(ERRCODE_OBJECT_IN_USE),
3820 errmsg("database \"%s\" is being used by prepared transactions",
3821 get_database_name(databaseId)),
3822 errdetail_plural("There is %d prepared transaction using the database.",
3823 "There are %d prepared transactions using the database.",
3824 nprepared,
3825 nprepared)));
3826
3827 if (pids)
3828 {
3829 ListCell *lc;
3830
3831 /*
3832 * Permissions checks relax the pg_terminate_backend checks in two
3833 * ways, both by omitting the !OidIsValid(proc->roleId) check:
3834 *
3835 * - Accept terminating autovacuum workers, since DROP DATABASE
3836 * without FORCE terminates them.
3837 *
3838 * - Accept terminating bgworkers. For bgworker authors, it's
3839 * convenient to be able to recommend FORCE if a worker is blocking
3840 * DROP DATABASE unexpectedly.
3841 *
3842 * Unlike pg_terminate_backend, we don't raise some warnings - like
3843 * "PID %d is not a PostgreSQL server process", because for us already
3844 * finished session is not a problem.
3845 */
3846 foreach(lc, pids)
3847 {
3848 int pid = lfirst_int(lc);
3849 PGPROC *proc = BackendPidGetProc(pid);
3850
3851 if (proc != NULL)
3852 {
3853 if (superuser_arg(proc->roleId) && !superuser())
3854 ereport(ERROR,
3855 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
3856 errmsg("permission denied to terminate process"),
3857 errdetail("Only roles with the %s attribute may terminate processes of roles with the %s attribute.",
3858 "SUPERUSER", "SUPERUSER")));
3859
3860 if (!has_privs_of_role(GetUserId(), proc->roleId) &&
3861 !has_privs_of_role(GetUserId(), ROLE_PG_SIGNAL_BACKEND))
3862 ereport(ERROR,
3863 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
3864 errmsg("permission denied to terminate process"),
3865 errdetail("Only roles with privileges of the role whose process is being terminated or with privileges of the \"%s\" role may terminate this process.",
3866 "pg_signal_backend")));
3867 }
3868 }
3869
3870 /*
3871 * There's a race condition here: once we release the ProcArrayLock,
3872 * it's possible for the session to exit before we issue kill. That
3873 * race condition possibility seems too unlikely to worry about. See
3874 * pg_signal_backend.
3875 */
3876 foreach(lc, pids)
3877 {
3878 int pid = lfirst_int(lc);
3879 PGPROC *proc = BackendPidGetProc(pid);
3880
3881 if (proc != NULL)
3882 {
3883 /*
3884 * If we have setsid(), signal the backend's whole process
3885 * group
3886 */
3887#ifdef HAVE_SETSID
3888 (void) kill(-pid, SIGTERM);
3889#else
3890 (void) kill(pid, SIGTERM);
3891#endif
3892 }
3893 }
3894 }
3895}
bool has_privs_of_role(Oid member, Oid role)
Definition: acl.c:5284
int errdetail(const char *fmt,...)
Definition: elog.c:1216
int errdetail_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n,...)
Definition: elog.c:1308
List * lappend_int(List *list, int datum)
Definition: list.c:357
char * get_database_name(Oid dbid)
Definition: lsyscache.c:1259
Oid GetUserId(void)
Definition: miscinit.c:469
#define NIL
Definition: pg_list.h:68
#define lfirst_int(lc)
Definition: pg_list.h:173
Definition: pg_list.h:54
bool superuser_arg(Oid roleid)
Definition: superuser.c:56
bool superuser(void)
Definition: superuser.c:46

References allProcs, BackendPidGetProc(), PGPROC::databaseId, ereport, errcode(), errdetail(), errdetail_plural(), errmsg(), ERROR, get_database_name(), GetUserId(), has_privs_of_role(), i, kill, lappend_int(), lfirst_int, LW_SHARED, LWLockAcquire(), LWLockRelease(), MyProc, NIL, ProcArrayStruct::numProcs, ProcArrayStruct::pgprocnos, PGPROC::pid, procArray, PGPROC::roleId, superuser(), and superuser_arg().

Referenced by dropdb().

◆ TransactionIdIsInProgress()

bool TransactionIdIsInProgress ( TransactionId  xid)

Definition at line 1402 of file procarray.c.

1403{
1404 static TransactionId *xids = NULL;
1405 static TransactionId *other_xids;
1406 XidCacheStatus *other_subxidstates;
1407 int nxids = 0;
1408 ProcArrayStruct *arrayP = procArray;
1409 TransactionId topxid;
1410 TransactionId latestCompletedXid;
1411 int mypgxactoff;
1412 int numProcs;
1413 int j;
1414
1415 /*
1416 * Don't bother checking a transaction older than RecentXmin; it could not
1417 * possibly still be running. (Note: in particular, this guarantees that
1418 * we reject InvalidTransactionId, FrozenTransactionId, etc as not
1419 * running.)
1420 */
1422 {
1424 return false;
1425 }
1426
1427 /*
1428 * We may have just checked the status of this transaction, so if it is
1429 * already known to be completed, we can fall out without any access to
1430 * shared memory.
1431 */
1433 {
1435 return false;
1436 }
1437
1438 /*
1439 * Also, we can handle our own transaction (and subtransactions) without
1440 * any access to shared memory.
1441 */
1443 {
1445 return true;
1446 }
1447
1448 /*
1449 * If first time through, get workspace to remember main XIDs in. We
1450 * malloc it permanently to avoid repeated palloc/pfree overhead.
1451 */
1452 if (xids == NULL)
1453 {
1454 /*
1455 * In hot standby mode, reserve enough space to hold all xids in the
1456 * known-assigned list. If we later finish recovery, we no longer need
1457 * the bigger array, but we don't bother to shrink it.
1458 */
1459 int maxxids = RecoveryInProgress() ? TOTAL_MAX_CACHED_SUBXIDS : arrayP->maxProcs;
1460
1461 xids = (TransactionId *) malloc(maxxids * sizeof(TransactionId));
1462 if (xids == NULL)
1463 ereport(ERROR,
1464 (errcode(ERRCODE_OUT_OF_MEMORY),
1465 errmsg("out of memory")));
1466 }
1467
1468 other_xids = ProcGlobal->xids;
1469 other_subxidstates = ProcGlobal->subxidStates;
1470
1471 LWLockAcquire(ProcArrayLock, LW_SHARED);
1472
1473 /*
1474 * Now that we have the lock, we can check latestCompletedXid; if the
1475 * target Xid is after that, it's surely still running.
1476 */
1477 latestCompletedXid =
1479 if (TransactionIdPrecedes(latestCompletedXid, xid))
1480 {
1481 LWLockRelease(ProcArrayLock);
1483 return true;
1484 }
1485
1486 /* No shortcuts, gotta grovel through the array */
1487 mypgxactoff = MyProc->pgxactoff;
1488 numProcs = arrayP->numProcs;
1489 for (int pgxactoff = 0; pgxactoff < numProcs; pgxactoff++)
1490 {
1491 int pgprocno;
1492 PGPROC *proc;
1493 TransactionId pxid;
1494 int pxids;
1495
1496 /* Ignore ourselves --- dealt with it above */
1497 if (pgxactoff == mypgxactoff)
1498 continue;
1499
1500 /* Fetch xid just once - see GetNewTransactionId */
1501 pxid = UINT32_ACCESS_ONCE(other_xids[pgxactoff]);
1502
1503 if (!TransactionIdIsValid(pxid))
1504 continue;
1505
1506 /*
1507 * Step 1: check the main Xid
1508 */
1509 if (TransactionIdEquals(pxid, xid))
1510 {
1511 LWLockRelease(ProcArrayLock);
1513 return true;
1514 }
1515
1516 /*
1517 * We can ignore main Xids that are younger than the target Xid, since
1518 * the target could not possibly be their child.
1519 */
1520 if (TransactionIdPrecedes(xid, pxid))
1521 continue;
1522
1523 /*
1524 * Step 2: check the cached child-Xids arrays
1525 */
1526 pxids = other_subxidstates[pgxactoff].count;
1527 pg_read_barrier(); /* pairs with barrier in GetNewTransactionId() */
1528 pgprocno = arrayP->pgprocnos[pgxactoff];
1529 proc = &allProcs[pgprocno];
1530 for (j = pxids - 1; j >= 0; j--)
1531 {
1532 /* Fetch xid just once - see GetNewTransactionId */
1534
1535 if (TransactionIdEquals(cxid, xid))
1536 {
1537 LWLockRelease(ProcArrayLock);
1539 return true;
1540 }
1541 }
1542
1543 /*
1544 * Save the main Xid for step 4. We only need to remember main Xids
1545 * that have uncached children. (Note: there is no race condition
1546 * here because the overflowed flag cannot be cleared, only set, while
1547 * we hold ProcArrayLock. So we can't miss an Xid that we need to
1548 * worry about.)
1549 */
1550 if (other_subxidstates[pgxactoff].overflowed)
1551 xids[nxids++] = pxid;
1552 }
1553
1554 /*
1555 * Step 3: in hot standby mode, check the known-assigned-xids list. XIDs
1556 * in the list must be treated as running.
1557 */
1558 if (RecoveryInProgress())
1559 {
1560 /* none of the PGPROC entries should have XIDs in hot standby mode */
1561 Assert(nxids == 0);
1562
1563 if (KnownAssignedXidExists(xid))
1564 {
1565 LWLockRelease(ProcArrayLock);
1567 return true;
1568 }
1569
1570 /*
1571 * If the KnownAssignedXids overflowed, we have to check pg_subtrans
1572 * too. Fetch all xids from KnownAssignedXids that are lower than
1573 * xid, since if xid is a subtransaction its parent will always have a
1574 * lower value. Note we will collect both main and subXIDs here, but
1575 * there's no help for it.
1576 */
1578 nxids = KnownAssignedXidsGet(xids, xid);
1579 }
1580
1581 LWLockRelease(ProcArrayLock);
1582
1583 /*
1584 * If none of the relevant caches overflowed, we know the Xid is not
1585 * running without even looking at pg_subtrans.
1586 */
1587 if (nxids == 0)
1588 {
1591 return false;
1592 }
1593
1594 /*
1595 * Step 4: have to check pg_subtrans.
1596 *
1597 * At this point, we know it's either a subtransaction of one of the Xids
1598 * in xids[], or it's not running. If it's an already-failed
1599 * subtransaction, we want to say "not running" even though its parent may
1600 * still be running. So first, check pg_xact to see if it's been aborted.
1601 */
1603
1604 if (TransactionIdDidAbort(xid))
1605 {
1607 return false;
1608 }
1609
1610 /*
1611 * It isn't aborted, so check whether the transaction tree it belongs to
1612 * is still running (or, more precisely, whether it was running when we
1613 * held ProcArrayLock).
1614 */
1615 topxid = SubTransGetTopmostTransaction(xid);
1617 if (!TransactionIdEquals(topxid, xid) &&
1618 pg_lfind32(topxid, xids, nxids))
1619 return true;
1620
1622 return false;
1623}
int j
Definition: isn.c:78
static bool pg_lfind32(uint32 key, const uint32 *base, uint32 nelem)
Definition: pg_lfind.h:153
#define xc_no_overflow_inc()
Definition: procarray.c:342
#define xc_by_recent_xmin_inc()
Definition: procarray.c:335
static int KnownAssignedXidsGet(TransactionId *xarray, TransactionId xmax)
Definition: procarray.c:5075
#define xc_by_my_xact_inc()
Definition: procarray.c:337
#define xc_by_known_assigned_inc()
Definition: procarray.c:341
#define xc_by_child_xid_inc()
Definition: procarray.c:340
#define xc_slow_answer_inc()
Definition: procarray.c:343
#define xc_by_main_xid_inc()
Definition: procarray.c:339
static bool KnownAssignedXidExists(TransactionId xid)
Definition: procarray.c:4936
#define xc_by_latest_xid_inc()
Definition: procarray.c:338
#define xc_by_known_xact_inc()
Definition: procarray.c:336
static TransactionId cachedXidIsNotInProgress
Definition: procarray.c:276
TransactionId SubTransGetTopmostTransaction(TransactionId xid)
Definition: subtrans.c:162
bool TransactionIdIsCurrentTransactionId(TransactionId xid)
Definition: xact.c:942

References allProcs, Assert(), cachedXidIsNotInProgress, XidCacheStatus::count, ereport, errcode(), errmsg(), ERROR, j, KnownAssignedXidExists(), KnownAssignedXidsGet(), ProcArrayStruct::lastOverflowedXid, TransamVariablesData::latestCompletedXid, LW_SHARED, LWLockAcquire(), LWLockRelease(), malloc, ProcArrayStruct::maxProcs, MyProc, ProcArrayStruct::numProcs, pg_lfind32(), pg_read_barrier, ProcArrayStruct::pgprocnos, PGPROC::pgxactoff, procArray, ProcGlobal, RecentXmin, RecoveryInProgress(), SubTransGetTopmostTransaction(), PGPROC::subxids, PROC_HDR::subxidStates, TOTAL_MAX_CACHED_SUBXIDS, TransactionIdDidAbort(), TransactionIdEquals, TransactionIdIsCurrentTransactionId(), TransactionIdIsValid, TransactionIdPrecedes(), TransactionIdPrecedesOrEquals(), TransamVariables, UINT32_ACCESS_ONCE, xc_by_child_xid_inc, xc_by_known_assigned_inc, xc_by_known_xact_inc, xc_by_latest_xid_inc, xc_by_main_xid_inc, xc_by_my_xact_inc, xc_by_recent_xmin_inc, xc_no_overflow_inc, xc_slow_answer_inc, XidFromFullTransactionId, XidCache::xids, and PROC_HDR::xids.

Referenced by check_safe_enum_use(), compute_new_xmax_infomask(), ConditionalXactLockTableWait(), Do_MultiXactIdWait(), DoesMultiXactIdConflict(), FreezeMultiXactId(), get_xid_status(), HandleConcurrentAbort(), HeapTupleHeaderIsOnlyLocked(), HeapTupleSatisfiesDirty(), HeapTupleSatisfiesSelf(), HeapTupleSatisfiesToast(), HeapTupleSatisfiesUpdate(), HeapTupleSatisfiesVacuumHorizon(), MultiXactIdExpand(), MultiXactIdIsRunning(), pg_xact_status(), ReorderBufferCheckAndTruncateAbortedTXN(), test_lockmode_for_conflict(), verify_heapam(), and XactLockTableWait().

◆ XidCacheRemoveRunningXids()

void XidCacheRemoveRunningXids ( TransactionId  xid,
int  nxids,
const TransactionId xids,
TransactionId  latestXid 
)

Definition at line 3953 of file procarray.c.

3956{
3957 int i,
3958 j;
3959 XidCacheStatus *mysubxidstat;
3960
3962
3963 /*
3964 * We must hold ProcArrayLock exclusively in order to remove transactions
3965 * from the PGPROC array. (See src/backend/access/transam/README.) It's
3966 * possible this could be relaxed since we know this routine is only used
3967 * to abort subtransactions, but pending closer analysis we'd best be
3968 * conservative.
3969 *
3970 * Note that we do not have to be careful about memory ordering of our own
3971 * reads wrt. GetNewTransactionId() here - only this process can modify
3972 * relevant fields of MyProc/ProcGlobal->xids[]. But we do have to be
3973 * careful about our own writes being well ordered.
3974 */
3975 LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3976
3977 mysubxidstat = &ProcGlobal->subxidStates[MyProc->pgxactoff];
3978
3979 /*
3980 * Under normal circumstances xid and xids[] will be in increasing order,
3981 * as will be the entries in subxids. Scan backwards to avoid O(N^2)
3982 * behavior when removing a lot of xids.
3983 */
3984 for (i = nxids - 1; i >= 0; i--)
3985 {
3986 TransactionId anxid = xids[i];
3987
3988 for (j = MyProc->subxidStatus.count - 1; j >= 0; j--)
3989 {
3990 if (TransactionIdEquals(MyProc->subxids.xids[j], anxid))
3991 {
3994 mysubxidstat->count--;
3996 break;
3997 }
3998 }
3999
4000 /*
4001 * Ordinarily we should have found it, unless the cache has
4002 * overflowed. However it's also possible for this routine to be
4003 * invoked multiple times for the same subtransaction, in case of an
4004 * error during AbortSubTransaction. So instead of Assert, emit a
4005 * debug warning.
4006 */
4007 if (j < 0 && !MyProc->subxidStatus.overflowed)
4008 elog(WARNING, "did not find subXID %u in MyProc", anxid);
4009 }
4010
4011 for (j = MyProc->subxidStatus.count - 1; j >= 0; j--)
4012 {
4014 {
4017 mysubxidstat->count--;
4019 break;
4020 }
4021 }
4022 /* Ordinarily we should have found it, unless the cache has overflowed */
4023 if (j < 0 && !MyProc->subxidStatus.overflowed)
4024 elog(WARNING, "did not find subXID %u in MyProc", xid);
4025
4026 /* Also advance global latestCompletedXid while holding the lock */
4027 MaintainLatestCompletedXid(latestXid);
4028
4029 /* ... and xactCompletionCount */
4031
4032 LWLockRelease(ProcArrayLock);
4033}
#define pg_write_barrier()
Definition: atomics.h:155
#define WARNING
Definition: elog.h:36

References Assert(), XidCacheStatus::count, elog, i, j, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MaintainLatestCompletedXid(), MyProc, pg_write_barrier, PGPROC::pgxactoff, ProcGlobal, PGPROC::subxids, PROC_HDR::subxidStates, PGPROC::subxidStatus, TransactionIdEquals, TransactionIdIsValid, TransamVariables, WARNING, TransamVariablesData::xactCompletionCount, and XidCache::xids.

Referenced by RecordTransactionAbort().