PostgreSQL Source Code git master
Loading...
Searching...
No Matches
procarray.h File Reference
#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

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)
 
bool SignalRecoveryConflict (PGPROC *proc, pid_t pid, RecoveryConflictReason reason)
 
bool SignalRecoveryConflictWithVirtualXID (VirtualTransactionId vxid, RecoveryConflictReason reason)
 
void SignalRecoveryConflictWithDatabase (Oid databaseid, RecoveryConflictReason reason)
 
bool MinimumActiveBackends (int min)
 
int CountDBBackends (Oid databaseid)
 
int CountDBConnections (Oid databaseid)
 
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)
extern

Definition at line 3148 of file procarray.c.

3149{
3150 PGPROC *result;
3151
3152 if (pid == 0) /* never match dummy PGPROCs */
3153 return NULL;
3154
3156
3158
3160
3161 return result;
3162}
uint32 result
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition lwlock.c:1150
void LWLockRelease(LWLock *lock)
Definition lwlock.c:1767
@ LW_SHARED
Definition lwlock.h:105
static int fb(int x)
PGPROC * BackendPidGetProcWithLock(int pid)
Definition procarray.c:3171
Definition proc.h:179

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

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(), TerminateBackgroundWorkersForDatabase(), TerminateOtherDBBackends(), and test_shm_mq_main().

◆ BackendPidGetProcWithLock()

PGPROC * BackendPidGetProcWithLock ( int  pid)
extern

Definition at line 3171 of file procarray.c.

3172{
3173 PGPROC *result = NULL;
3175 int index;
3176
3177 if (pid == 0) /* never match dummy PGPROCs */
3178 return NULL;
3179
3180 for (index = 0; index < arrayP->numProcs; index++)
3181 {
3182 PGPROC *proc = &allProcs[arrayP->pgprocnos[index]];
3183
3184 if (proc->pid == pid)
3185 {
3186 result = proc;
3187 break;
3188 }
3189 }
3190
3191 return result;
3192}
static PGPROC * allProcs
Definition procarray.c:285
static ProcArrayStruct * procArray
Definition procarray.c:111
int pid
Definition proc.h:197
Definition type.h:97

References allProcs, fb(), PGPROC::pid, procArray, and result.

Referenced by BackendPidGetProc(), and GetBlockerStatusData().

◆ BackendXidGetPid()

int BackendXidGetPid ( TransactionId  xid)
extern

Definition at line 3208 of file procarray.c.

3209{
3210 int result = 0;
3213 int index;
3214
3215 if (xid == InvalidTransactionId) /* never match invalid xid */
3216 return 0;
3217
3219
3220 for (index = 0; index < arrayP->numProcs; index++)
3221 {
3222 if (other_xids[index] == xid)
3223 {
3224 int pgprocno = arrayP->pgprocnos[index];
3225 PGPROC *proc = &allProcs[pgprocno];
3226
3227 result = proc->pid;
3228 break;
3229 }
3230 }
3231
3233
3234 return result;
3235}
uint32 TransactionId
Definition c.h:736
PROC_HDR * ProcGlobal
Definition proc.c:74
TransactionId * xids
Definition proc.h:444
#define InvalidTransactionId
Definition transam.h:31

References allProcs, fb(), InvalidTransactionId, LW_SHARED, LWLockAcquire(), LWLockRelease(), PGPROC::pid, procArray, ProcGlobal, result, and PROC_HDR::xids.

Referenced by pgrowlocks().

◆ CountDBBackends()

int CountDBBackends ( Oid  databaseid)
extern

Definition at line 3621 of file procarray.c.

3622{
3624 int count = 0;
3625 int index;
3626
3628
3629 for (index = 0; index < arrayP->numProcs; index++)
3630 {
3631 int pgprocno = arrayP->pgprocnos[index];
3632 PGPROC *proc = &allProcs[pgprocno];
3633
3634 if (proc->pid == 0)
3635 continue; /* do not count prepared xacts */
3636 if (!OidIsValid(databaseid) ||
3637 proc->databaseId == databaseid)
3638 count++;
3639 }
3640
3642
3643 return count;
3644}
#define OidIsValid(objectId)
Definition c.h:858
Oid databaseId
Definition proc.h:201

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

Referenced by ResolveRecoveryConflictWithDatabase().

◆ CountDBConnections()

int CountDBConnections ( Oid  databaseid)
extern

Definition at line 3650 of file procarray.c.

3651{
3653 int count = 0;
3654 int index;
3655
3657
3658 for (index = 0; index < arrayP->numProcs; index++)
3659 {
3660 int pgprocno = arrayP->pgprocnos[index];
3661 PGPROC *proc = &allProcs[pgprocno];
3662
3663 if (proc->pid == 0)
3664 continue; /* do not count prepared xacts */
3665 if (proc->backendType != B_BACKEND)
3666 continue; /* count only regular backend processes */
3667 if (!OidIsValid(databaseid) ||
3668 proc->databaseId == databaseid)
3669 count++;
3670 }
3671
3673
3674 return count;
3675}
@ B_BACKEND
Definition miscadmin.h:345
BackendType backendType
Definition proc.h:198

References allProcs, B_BACKEND, PGPROC::backendType, PGPROC::databaseId, fb(), LW_SHARED, LWLockAcquire(), LWLockRelease(), OidIsValid, PGPROC::pid, and procArray.

Referenced by CheckMyDatabase().

◆ CountOtherDBBackends()

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

Definition at line 3734 of file procarray.c.

3735{
3737
3738#define MAXAUTOVACPIDS 10 /* max autovacs to SIGTERM per iteration */
3740
3741 /*
3742 * Retry up to 50 times with 100ms between attempts (max 5s total). Can be
3743 * reduced to 3 attempts (max 0.3s total) to speed up tests.
3744 */
3745 int ntries = 50;
3746
3747#ifdef USE_INJECTION_POINTS
3748 if (IS_INJECTION_POINT_ATTACHED("procarray-reduce-count"))
3749 ntries = 3;
3750#endif
3751
3752 for (int tries = 0; tries < ntries; tries++)
3753 {
3754 int nautovacs = 0;
3755 bool found = false;
3756 int index;
3757
3759
3760 *nbackends = *nprepared = 0;
3761
3763
3764 for (index = 0; index < arrayP->numProcs; index++)
3765 {
3766 int pgprocno = arrayP->pgprocnos[index];
3767 PGPROC *proc = &allProcs[pgprocno];
3768 uint8 statusFlags = ProcGlobal->statusFlags[index];
3769
3770 if (proc->databaseId != databaseId)
3771 continue;
3772 if (proc == MyProc)
3773 continue;
3774
3775 found = true;
3776
3777 if (proc->pid == 0)
3778 (*nprepared)++;
3779 else
3780 {
3781 (*nbackends)++;
3782 if ((statusFlags & PROC_IS_AUTOVACUUM) &&
3784 autovac_pids[nautovacs++] = proc->pid;
3785 }
3786 }
3787
3789
3790 if (!found)
3791 return false; /* no conflicting backends, so done */
3792
3793 /*
3794 * Send SIGTERM to any conflicting autovacuums before sleeping. We
3795 * postpone this step until after the loop because we don't want to
3796 * hold ProcArrayLock while issuing kill(). We have no idea what might
3797 * block kill() inside the kernel...
3798 */
3799 for (index = 0; index < nautovacs; index++)
3800 (void) kill(autovac_pids[index], SIGTERM); /* ignore any error */
3801
3802 /*
3803 * Terminate all background workers for this database, if they have
3804 * requested it (BGWORKER_INTERRUPTIBLE).
3805 */
3807
3808 /* sleep, then try again */
3809 pg_usleep(100 * 1000L); /* 100ms */
3810 }
3811
3812 return true; /* timed out, still conflicts */
3813}
void TerminateBackgroundWorkersForDatabase(Oid databaseId)
Definition bgworker.c:1427
uint8_t uint8
Definition c.h:622
#define IS_INJECTION_POINT_ATTACHED(name)
#define CHECK_FOR_INTERRUPTS()
Definition miscadmin.h:125
#define PROC_IS_AUTOVACUUM
Definition proc.h:61
#define MAXAUTOVACPIDS
void pg_usleep(long microsec)
Definition signal.c:53
PGPROC * MyProc
Definition proc.c:71
uint8 * statusFlags
Definition proc.h:456
#define kill(pid, sig)
Definition win32_port.h:490

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

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

◆ CountUserBackends()

int CountUserBackends ( Oid  roleid)
extern

Definition at line 3682 of file procarray.c.

3683{
3685 int count = 0;
3686 int index;
3687
3689
3690 for (index = 0; index < arrayP->numProcs; index++)
3691 {
3692 int pgprocno = arrayP->pgprocnos[index];
3693 PGPROC *proc = &allProcs[pgprocno];
3694
3695 if (proc->pid == 0)
3696 continue; /* do not count prepared xacts */
3697 if (proc->backendType != B_BACKEND)
3698 continue; /* count only regular backend processes */
3699 if (proc->roleId == roleid)
3700 count++;
3701 }
3702
3704
3705 return count;
3706}
Oid roleId
Definition proc.h:202

References allProcs, B_BACKEND, PGPROC::backendType, fb(), LW_SHARED, LWLockAcquire(), LWLockRelease(), PGPROC::pid, procArray, and PGPROC::roleId.

Referenced by InitializeSessionUserId().

◆ ExpireAllKnownAssignedTransactionIds()

void ExpireAllKnownAssignedTransactionIds ( void  )
extern

Definition at line 4530 of file procarray.c.

4531{
4533
4536
4537 /* Reset latestCompletedXid to nextXid - 1 */
4542
4543 /*
4544 * Any transactions that were in-progress were effectively aborted, so
4545 * advance xactCompletionCount.
4546 */
4548
4549 /*
4550 * Reset lastOverflowedXid. Currently, lastOverflowedXid has no use after
4551 * the call of this function. But do this for unification with what
4552 * ExpireOldKnownAssignedTransactionIds() do.
4553 */
4556}
#define Assert(condition)
Definition c.h:943
@ LW_EXCLUSIVE
Definition lwlock.h:104
static void KnownAssignedXidsRemovePreceding(TransactionId removeXid)
Definition procarray.c:5067
TransactionId lastOverflowedXid
Definition procarray.c:96
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:37

References Assert, fb(), 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)
extern

Definition at line 4564 of file procarray.c.

4565{
4567
4569
4570 /* As in ProcArrayEndTransaction, advance latestCompletedXid */
4571 latestXid = xid;
4574
4575 /* ... and xactCompletionCount */
4577
4578 /*
4579 * Reset lastOverflowedXid if we know all transactions that have been
4580 * possibly running are being gone. Not doing so could cause an incorrect
4581 * lastOverflowedXid value, which makes extra snapshots be marked as
4582 * suboverflowed.
4583 */
4588}
static void MaintainLatestCompletedXidRecovery(TransactionId latestXid)
Definition procarray.c:980
#define TransactionIdRetreat(dest)
Definition transam.h:141
static bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition transam.h:263

References fb(), 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 
)
extern

Definition at line 4504 of file procarray.c.

4506{
4508
4509 /*
4510 * Uses same locking as transaction commit
4511 */
4513
4515
4516 /* As in ProcArrayEndTransaction, advance latestCompletedXid */
4518
4519 /* ... and xactCompletionCount */
4521
4523}
static void KnownAssignedXidsRemoveTree(TransactionId xid, int nsubxids, TransactionId *subxids)
Definition procarray.c:5045
HotStandbyState standbyState
Definition xlogutils.c:53
@ STANDBY_INITIALIZED
Definition xlogutils.h:53

References Assert, fb(), 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 
)
extern

Definition at line 3368 of file procarray.c.

3369{
3372 int count = 0;
3373 int index;
3374
3375 /*
3376 * If first time through, get workspace to remember main XIDs in. We
3377 * malloc it permanently to avoid repeated palloc/pfree overhead. Allow
3378 * result space, remembering room for a terminator.
3379 */
3380 if (vxids == NULL)
3381 {
3383 malloc(sizeof(VirtualTransactionId) * (arrayP->maxProcs + 1));
3384 if (vxids == NULL)
3385 ereport(ERROR,
3387 errmsg("out of memory")));
3388 }
3389
3391
3392 for (index = 0; index < arrayP->numProcs; index++)
3393 {
3394 int pgprocno = arrayP->pgprocnos[index];
3395 PGPROC *proc = &allProcs[pgprocno];
3396
3397 /* Exclude prepared transactions */
3398 if (proc->pid == 0)
3399 continue;
3400
3401 if (!OidIsValid(dbOid) ||
3402 proc->databaseId == dbOid)
3403 {
3404 /* Fetch xmin just once - can't change on us, but good coding */
3406
3407 /*
3408 * We ignore an invalid pxmin because this means that backend has
3409 * no snapshot currently. We hold a Share lock to avoid contention
3410 * with users taking snapshots. That is not a problem because the
3411 * current xmin is always at least one higher than the latest
3412 * removed xid, so any new snapshot would never conflict with the
3413 * test here.
3414 */
3417 {
3419
3420 GET_VXID_FROM_PGPROC(vxid, *proc);
3422 vxids[count++] = vxid;
3423 }
3424 }
3425 }
3426
3428
3429 /* add the terminator */
3430 vxids[count].procNumber = INVALID_PROC_NUMBER;
3431 vxids[count].localTransactionId = InvalidLocalTransactionId;
3432
3433 return vxids;
3434}
int errcode(int sqlerrcode)
Definition elog.c:875
#define ERROR
Definition elog.h:40
#define ereport(elevel,...)
Definition elog.h:152
#define VirtualTransactionIdIsValid(vxid)
Definition lock.h:70
#define GET_VXID_FROM_PGPROC(vxid_dst, proc)
Definition lock.h:80
#define InvalidLocalTransactionId
Definition lock.h:68
static char * errmsg
#define UINT32_ACCESS_ONCE(var)
Definition procarray.c:73
#define INVALID_PROC_NUMBER
Definition procnumber.h:26
#define malloc(a)
TransactionId xmin
Definition proc.h:242
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, fb(), GET_VXID_FROM_PGPROC, INVALID_PROC_NUMBER, InvalidLocalTransactionId, LW_SHARED, LWLockAcquire(), LWLockRelease(), malloc, OidIsValid, PGPROC::pid, procArray, 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 
)
extern

Definition at line 3276 of file procarray.c.

3279{
3282 int count = 0;
3283 int index;
3284
3285 /* allocate what's certainly enough result space */
3287
3289
3290 for (index = 0; index < arrayP->numProcs; index++)
3291 {
3292 int pgprocno = arrayP->pgprocnos[index];
3293 PGPROC *proc = &allProcs[pgprocno];
3294 uint8 statusFlags = ProcGlobal->statusFlags[index];
3295
3296 if (proc == MyProc)
3297 continue;
3298
3299 if (excludeVacuum & statusFlags)
3300 continue;
3301
3302 if (allDbs || proc->databaseId == MyDatabaseId)
3303 {
3304 /* Fetch xmin just once - might change on us */
3306
3308 continue;
3309
3310 /*
3311 * InvalidTransactionId precedes all other XIDs, so a proc that
3312 * hasn't set xmin yet will not be rejected by this test.
3313 */
3316 {
3318
3319 GET_VXID_FROM_PGPROC(vxid, *proc);
3321 vxids[count++] = vxid;
3322 }
3323 }
3324 }
3325
3327
3328 *nvxids = count;
3329 return vxids;
3330}
#define palloc_array(type, count)
Definition fe_memutils.h:91
Oid MyDatabaseId
Definition globals.c:96
static bool TransactionIdPrecedesOrEquals(TransactionId id1, TransactionId id2)
Definition transam.h:282

References allProcs, PGPROC::databaseId, fb(), GET_VXID_FROM_PGPROC, LW_SHARED, LWLockAcquire(), LWLockRelease(), MyDatabaseId, MyProc, palloc_array, procArray, ProcGlobal, PROC_HDR::statusFlags, TransactionIdIsValid, TransactionIdPrecedesOrEquals(), UINT32_ACCESS_ONCE, VirtualTransactionIdIsValid, and PGPROC::xmin.

Referenced by WaitForOlderSnapshots().

◆ GetMaxSnapshotSubxidCount()

int GetMaxSnapshotSubxidCount ( void  )
extern

Definition at line 2019 of file procarray.c.

2020{
2022}
#define TOTAL_MAX_CACHED_SUBXIDS

References TOTAL_MAX_CACHED_SUBXIDS.

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

◆ GetMaxSnapshotXidCount()

int GetMaxSnapshotXidCount ( void  )
extern

Definition at line 2008 of file procarray.c.

2009{
2010 return procArray->maxProcs;
2011}

References ProcArrayStruct::maxProcs, and procArray.

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

◆ GetOldestActiveTransactionId()

TransactionId GetOldestActiveTransactionId ( bool  inCommitOnly,
bool  allDbs 
)
extern

Definition at line 2824 of file procarray.c.

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

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

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

◆ GetOldestNonRemovableTransactionId()

TransactionId GetOldestNonRemovableTransactionId ( Relation  rel)
extern

Definition at line 1944 of file procarray.c.

1945{
1947
1949
1950 switch (GlobalVisHorizonKindForRel(rel))
1951 {
1952 case VISHORIZON_SHARED:
1953 return horizons.shared_oldest_nonremovable;
1954 case VISHORIZON_CATALOG:
1955 return horizons.catalog_oldest_nonremovable;
1956 case VISHORIZON_DATA:
1957 return horizons.data_oldest_nonremovable;
1958 case VISHORIZON_TEMP:
1959 return horizons.temp_oldest_nonremovable;
1960 }
1961
1962 /* just to prevent compiler warnings */
1963 return InvalidTransactionId;
1964}
static void ComputeXidHorizons(ComputeXidHorizonsResult *h)
Definition procarray.c:1674
@ VISHORIZON_SHARED
Definition procarray.c:268
@ VISHORIZON_DATA
Definition procarray.c:270
@ VISHORIZON_CATALOG
Definition procarray.c:269
@ VISHORIZON_TEMP
Definition procarray.c:271
static GlobalVisHorizonKind GlobalVisHorizonKindForRel(Relation rel)
Definition procarray.c:1910

References ComputeXidHorizons(), fb(), GlobalVisHorizonKindForRel(), InvalidTransactionId, VISHORIZON_CATALOG, VISHORIZON_DATA, VISHORIZON_SHARED, and VISHORIZON_TEMP.

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

◆ GetOldestSafeDecodingTransactionId()

TransactionId GetOldestSafeDecodingTransactionId ( bool  catalogOnly)
extern

Definition at line 2898 of file procarray.c.

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

References Assert, fb(), LW_SHARED, LWLockAcquire(), LWLockHeldByMe(), LWLockRelease(), TransamVariablesData::nextXid, 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  )
extern

Definition at line 1973 of file procarray.c.

1974{
1976
1978
1979 return horizons.oldest_considered_running;
1980}

References ComputeXidHorizons(), and fb().

Referenced by CreateCheckPoint(), and CreateRestartPoint().

◆ GetReplicationHorizons()

void GetReplicationHorizons ( TransactionId xmin,
TransactionId catalog_xmin 
)
extern

Definition at line 1986 of file procarray.c.

1987{
1989
1991
1992 /*
1993 * Don't want to use shared_oldest_nonremovable here, as that contains the
1994 * effect of replication slot's catalog_xmin. We want to send a separate
1995 * feedback for the catalog horizon, so the primary can remove data table
1996 * contents more aggressively.
1997 */
1998 *xmin = horizons.shared_oldest_nonremovable_raw;
1999 *catalog_xmin = horizons.slot_catalog_xmin;
2000}

References ComputeXidHorizons(), and fb().

Referenced by XLogWalRcvSendHSFeedback().

◆ GetRunningTransactionData()

RunningTransactions GetRunningTransactionData ( void  )
extern

Definition at line 2628 of file procarray.c.

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

References allProcs, Assert, PGPROC::databaseId, ereport, errcode(), errmsg, ERROR, fb(), TransamVariablesData::latestCompletedXid, LW_SHARED, LWLockAcquire(), malloc, memcpy(), MyDatabaseId, TransamVariablesData::nextXid, XidCacheStatus::overflowed, pg_read_barrier, procArray, ProcGlobal, RecoveryInProgress(), PGPROC::subxids, SUBXIDS_IN_ARRAY, SUBXIDS_IN_SUBTRANS, PROC_HDR::subxidStates, TOTAL_MAX_CACHED_SUBXIDS, TransactionIdIsNormal, TransactionIdIsValid, TransactionIdPrecedes(), TransamVariables, UINT32_ACCESS_ONCE, XidFromFullTransactionId, XidCache::xids, and PROC_HDR::xids.

Referenced by GetStrictOldestNonRemovableTransactionId(), and LogStandbySnapshot().

◆ GetSnapshotData()

Snapshot GetSnapshotData ( Snapshot  snapshot)
extern

Definition at line 2114 of file procarray.c.

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

References SnapshotData::active_count, allProcs, Assert, SnapshotData::copied, XidCacheStatus::count, SnapshotData::curcid, GlobalVisState::definitely_needed, ereport, errcode(), errmsg, ERROR, fb(), 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, memcpy(), MyProc, NormalTransactionIdPrecedes, TransamVariablesData::oldestXid, pg_read_barrier, 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 
)
extern

Definition at line 2996 of file procarray.c.

2997{
3000 int count = 0;
3001 int index;
3002
3003 Assert(type != 0);
3004
3005 /* allocate what's certainly enough result space */
3007
3009
3010 for (index = 0; index < arrayP->numProcs; index++)
3011 {
3012 int pgprocno = arrayP->pgprocnos[index];
3013 PGPROC *proc = &allProcs[pgprocno];
3014
3015 if ((proc->delayChkptFlags & type) != 0)
3016 {
3018
3019 GET_VXID_FROM_PGPROC(vxid, *proc);
3021 vxids[count++] = vxid;
3022 }
3023 }
3024
3026
3027 *nvxids = count;
3028 return vxids;
3029}
const char * type

References allProcs, Assert, PGPROC::delayChkptFlags, fb(), GET_VXID_FROM_PGPROC, LW_SHARED, LWLockAcquire(), LWLockRelease(), palloc_array, procArray, type, and VirtualTransactionIdIsValid.

Referenced by CreateCheckPoint().

◆ HaveVirtualXIDsDelayingChkpt()

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

Definition at line 3041 of file procarray.c.

3042{
3043 bool result = false;
3045 int index;
3046
3047 Assert(type != 0);
3048
3050
3051 for (index = 0; index < arrayP->numProcs; index++)
3052 {
3053 int pgprocno = arrayP->pgprocnos[index];
3054 PGPROC *proc = &allProcs[pgprocno];
3056
3057 GET_VXID_FROM_PGPROC(vxid, *proc);
3058
3059 if ((proc->delayChkptFlags & type) != 0 &&
3061 {
3062 int i;
3063
3064 for (i = 0; i < nvxids; i++)
3065 {
3067 {
3068 result = true;
3069 break;
3070 }
3071 }
3072 if (result)
3073 break;
3074 }
3075 }
3076
3078
3079 return result;
3080}
int i
Definition isn.c:77
#define VirtualTransactionIdEquals(vxid1, vxid2)
Definition lock.h:74

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

Referenced by CreateCheckPoint().

◆ IsBackendPid()

bool IsBackendPid ( int  pid)
extern

Definition at line 3243 of file procarray.c.

3244{
3245 return (BackendPidGetProc(pid) != NULL);
3246}
PGPROC * BackendPidGetProc(int pid)
Definition procarray.c:3148

References BackendPidGetProc(), and fb().

Referenced by pg_stat_get_subscription().

◆ KnownAssignedTransactionIdsIdleMaintenance()

void KnownAssignedTransactionIdsIdleMaintenance ( void  )
extern

Definition at line 4596 of file procarray.c.

4597{
4599}
@ KAX_STARTUP_PROCESS_IDLE
Definition procarray.c:282
static void KnownAssignedXidsCompress(KAXCompressReason reason, bool haveLock)
Definition procarray.c:4697

References KAX_STARTUP_PROCESS_IDLE, and KnownAssignedXidsCompress().

Referenced by WaitForWALToBecomeAvailable().

◆ MinimumActiveBackends()

bool MinimumActiveBackends ( int  min)
extern

Definition at line 3568 of file procarray.c.

3569{
3571 int count = 0;
3572 int index;
3573
3574 /* Quick short-circuit if no minimum is specified */
3575 if (min == 0)
3576 return true;
3577
3578 /*
3579 * Note: for speed, we don't acquire ProcArrayLock. This is a little bit
3580 * bogus, but since we are only testing fields for zero or nonzero, it
3581 * should be OK. The result is only used for heuristic purposes anyway...
3582 */
3583 for (index = 0; index < arrayP->numProcs; index++)
3584 {
3585 int pgprocno = arrayP->pgprocnos[index];
3586 PGPROC *proc = &allProcs[pgprocno];
3587
3588 /*
3589 * Since we're not holding a lock, need to be prepared to deal with
3590 * garbage, as someone could have incremented numProcs but not yet
3591 * filled the structure.
3592 *
3593 * If someone just decremented numProcs, 'proc' could also point to a
3594 * PGPROC entry that's no longer in the array. It still points to a
3595 * PGPROC struct, though, because freed PGPROC entries just go to the
3596 * free list and are recycled. Its contents are nonsense in that case,
3597 * but that's acceptable for this function.
3598 */
3599 if (pgprocno == -1)
3600 continue; /* do not count deleted entries */
3601 if (proc == MyProc)
3602 continue; /* do not count myself */
3603 if (proc->xid == InvalidTransactionId)
3604 continue; /* do not count if no XID assigned */
3605 if (proc->pid == 0)
3606 continue; /* do not count prepared xacts */
3607 if (proc->waitLock != NULL)
3608 continue; /* do not count if blocked on a lock */
3609 count++;
3610 if (count >= min)
3611 break;
3612 }
3613
3614 return count >= min;
3615}
LOCK * waitLock
Definition proc.h:304

References allProcs, fb(), InvalidTransactionId, MyProc, PGPROC::pid, procArray, PGPROC::waitLock, and PGPROC::xid.

Referenced by XLogFlush().

◆ ProcArrayAdd()

void ProcArrayAdd ( PGPROC proc)
extern

Definition at line 464 of file procarray.c.

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

References allProcs, Assert, ereport, errcode(), errmsg, FATAL, fb(), GetNumberFromPGProc, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), NUM_AUXILIARY_PROCS, 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)
extern

Definition at line 1045 of file procarray.c.

1046{
1047 TransactionId *xids;
1049 int nxids;
1050 int i;
1051
1056
1057 /*
1058 * Remove stale transactions, if any.
1059 */
1061
1062 /*
1063 * Adjust TransamVariables->nextXid before StandbyReleaseOldLocks(),
1064 * because we will need it up to date for accessing two-phase transactions
1065 * in StandbyReleaseOldLocks().
1066 */
1067 advanceNextXid = running->nextXid;
1071
1072 /*
1073 * Remove stale locks, if any.
1074 */
1076
1077 /*
1078 * If our snapshot is already valid, nothing else to do...
1079 */
1081 return;
1082
1083 /*
1084 * If our initial RunningTransactionsData had an overflowed snapshot then
1085 * we knew we were missing some subxids from our snapshot. If we continue
1086 * to see overflowed snapshots then we might never be able to start up, so
1087 * we make another test to see if our snapshot is now valid. We know that
1088 * the missing subxids are equal to or earlier than nextXid. After we
1089 * initialise we continue to apply changes during recovery, so once the
1090 * oldestRunningXid is later than the nextXid from the initial snapshot we
1091 * know that we no longer have missing information and can mark the
1092 * snapshot as valid.
1093 */
1095 {
1096 /*
1097 * If the snapshot isn't overflowed or if its empty we can reset our
1098 * pending state and use this snapshot instead.
1099 */
1100 if (running->subxid_status != SUBXIDS_MISSING || running->xcnt == 0)
1101 {
1102 /*
1103 * If we have already collected known assigned xids, we need to
1104 * throw them away before we apply the recovery snapshot.
1105 */
1108 }
1109 else
1110 {
1112 running->oldestRunningXid))
1113 {
1115 elog(DEBUG1,
1116 "recovery snapshots are now enabled");
1117 }
1118 else
1119 elog(DEBUG1,
1120 "recovery snapshot waiting for non-overflowed snapshot or "
1121 "until oldest active xid on standby is at least %u (now %u)",
1123 running->oldestRunningXid);
1124 return;
1125 }
1126 }
1127
1129
1130 /*
1131 * NB: this can be reached at least twice, so make sure new code can deal
1132 * with that.
1133 */
1134
1135 /*
1136 * Nobody else is running yet, but take locks anyhow
1137 */
1139
1140 /*
1141 * KnownAssignedXids is sorted so we cannot just add the xids, we have to
1142 * sort them first.
1143 *
1144 * Some of the new xids are top-level xids and some are subtransactions.
1145 * We don't call SubTransSetParent because it doesn't matter yet. If we
1146 * aren't overflowed then all xids will fit in snapshot and so we don't
1147 * need subtrans. If we later overflow, an xid assignment record will add
1148 * xids to subtrans. If RunningTransactionsData is overflowed then we
1149 * don't have enough information to correctly update subtrans anyway.
1150 */
1151
1152 /*
1153 * Allocate a temporary array to avoid modifying the array passed as
1154 * argument.
1155 */
1156 xids = palloc_array(TransactionId, running->xcnt + running->subxcnt);
1157
1158 /*
1159 * Add to the temp array any xids which have not already completed.
1160 */
1161 nxids = 0;
1162 for (i = 0; i < running->xcnt + running->subxcnt; i++)
1163 {
1164 TransactionId xid = running->xids[i];
1165
1166 /*
1167 * The running-xacts snapshot can contain xids that were still visible
1168 * in the procarray when the snapshot was taken, but were already
1169 * WAL-logged as completed. They're not running anymore, so ignore
1170 * them.
1171 */
1173 continue;
1174
1175 xids[nxids++] = xid;
1176 }
1177
1178 if (nxids > 0)
1179 {
1181 {
1183 elog(ERROR, "KnownAssignedXids is not empty");
1184 }
1185
1186 /*
1187 * Sort the array so that we can add them safely into
1188 * KnownAssignedXids.
1189 *
1190 * We have to sort them logically, because in KnownAssignedXidsAdd we
1191 * call TransactionIdFollowsOrEquals and so on. But we know these XIDs
1192 * come from RUNNING_XACTS, which means there are only normal XIDs
1193 * from the same epoch, so this is safe.
1194 */
1196
1197 /*
1198 * Add the sorted snapshot into KnownAssignedXids. The running-xacts
1199 * snapshot may include duplicated xids because of prepared
1200 * transactions, so ignore them.
1201 */
1202 for (i = 0; i < nxids; i++)
1203 {
1204 if (i > 0 && TransactionIdEquals(xids[i - 1], xids[i]))
1205 {
1206 elog(DEBUG1,
1207 "found duplicated transaction %u for KnownAssignedXids insertion",
1208 xids[i]);
1209 continue;
1210 }
1211 KnownAssignedXidsAdd(xids[i], xids[i], true);
1212 }
1213
1215 }
1216
1217 pfree(xids);
1218
1219 /*
1220 * latestObservedXid is at least set to the point where SUBTRANS was
1221 * started up to (cf. ProcArrayInitRecovery()) or to the biggest xid
1222 * RecordKnownAssignedTransactionIds() was called for. Initialize
1223 * subtrans from thereon, up to nextXid - 1.
1224 *
1225 * We need to duplicate parts of RecordKnownAssignedTransactionId() here,
1226 * because we've just added xids to the known assigned xids machinery that
1227 * haven't gone through RecordKnownAssignedTransactionId().
1228 */
1232 {
1235 }
1236 TransactionIdRetreat(latestObservedXid); /* = running->nextXid - 1 */
1237
1238 /* ----------
1239 * Now we've got the running xids we need to set the global values that
1240 * are used to track snapshots as they evolve further.
1241 *
1242 * - latestCompletedXid which will be the xmax for snapshots
1243 * - lastOverflowedXid which shows whether snapshots overflow
1244 * - nextXid
1245 *
1246 * If the snapshot overflowed, then we still initialise with what we know,
1247 * but the recovery snapshot isn't fully valid yet because we know there
1248 * are some subxids missing. We don't know the specific subxids that are
1249 * missing, so conservatively assume the last one is latestObservedXid.
1250 * ----------
1251 */
1252 if (running->subxid_status == SUBXIDS_MISSING)
1253 {
1255
1258 }
1259 else
1260 {
1262
1264
1265 /*
1266 * If the 'xids' array didn't include all subtransactions, we have to
1267 * mark any snapshots taken as overflowed.
1268 */
1269 if (running->subxid_status == SUBXIDS_IN_SUBTRANS)
1271 else
1272 {
1275 }
1276 }
1277
1278 /*
1279 * If a transaction wrote a commit record in the gap between taking and
1280 * logging the snapshot then latestCompletedXid may already be higher than
1281 * the value from the snapshot, so check before we use the incoming value.
1282 * It also might not yet be set at all.
1283 */
1285
1286 /*
1287 * NB: No need to increment TransamVariables->xactCompletionCount here,
1288 * nobody can see it yet.
1289 */
1290
1292
1295 elog(DEBUG1, "recovery snapshots are now enabled");
1296 else
1297 elog(DEBUG1,
1298 "recovery snapshot waiting for non-overflowed snapshot or "
1299 "until oldest active xid on standby is at least %u (now %u)",
1301 running->oldestRunningXid);
1302}
#define DEBUG3
Definition elog.h:29
#define DEBUG1
Definition elog.h:31
#define elog(elevel,...)
Definition elog.h:228
void pfree(void *pointer)
Definition mcxt.c:1619
#define qsort(a, b, c, d)
Definition port.h:496
static TransactionId standbySnapshotPendingXmin
Definition procarray.c:307
static TransactionId latestObservedXid
Definition procarray.c:300
static void KnownAssignedXidsDisplay(int trace_level)
Definition procarray.c:5250
static void KnownAssignedXidsReset(void)
Definition procarray.c:5288
static void KnownAssignedXidsAdd(TransactionId from_xid, TransactionId to_xid, bool exclusive_lock)
Definition procarray.c:4814
void ExpireOldKnownAssignedTransactionIds(TransactionId xid)
Definition procarray.c:4564
void StandbyReleaseOldLocks(TransactionId oldxid)
Definition standby.c:1132
@ SUBXIDS_MISSING
Definition standby.h:122
int numKnownAssignedXids
Definition procarray.c:85
TransactionId oldestRunningXid
Definition standby.h:133
TransactionId nextXid
Definition standby.h:132
TransactionId latestCompletedXid
Definition standby.h:136
subxids_array_status subxid_status
Definition standby.h:131
TransactionId * xids
Definition standby.h:138
void ExtendSUBTRANS(TransactionId newestXact)
Definition subtrans.c:372
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:299
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(), fb(), 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_array, 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 
)
extern

Definition at line 1309 of file procarray.c.

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

References Assert, fb(), 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)
extern

Definition at line 899 of file procarray.c.

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

References Assert, XidCacheStatus::count, PGPROC::delayChkptFlags, fb(), InvalidLocalTransactionId, InvalidTransactionId, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), PGPROC::lxid, XidCacheStatus::overflowed, PGPROC::pgxactoff, PROC_VACUUM_STATE_MASK, ProcGlobal, 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 
)
extern

Definition at line 663 of file procarray.c.

664{
666 {
667 /*
668 * We must lock ProcArrayLock while clearing our advertised XID, so
669 * that we do not exit the set of "running" transactions while someone
670 * else is taking a snapshot. See discussion in
671 * src/backend/access/transam/README.
672 */
674
675 /*
676 * If we can immediately acquire ProcArrayLock, we clear our own XID
677 * and release the lock. If not, use group XID clearing to improve
678 * efficiency.
679 */
681 {
684 }
685 else
687 }
688 else
689 {
690 /*
691 * If we have no XID, we don't need to lock, since we won't affect
692 * anyone else's calculation of a snapshot. We might change their
693 * estimate of global xmin, but that's OK.
694 */
696 Assert(proc->subxidStatus.count == 0);
698
701
702 /* be sure this is cleared in abort */
703 proc->delayChkptFlags = 0;
704
705 /* must be cleared with xid/xmin: */
706 /* avoid unnecessarily dirtying shared cachelines */
708 {
715 }
716 }
717}
bool LWLockConditionalAcquire(LWLock *lock, LWLockMode mode)
Definition lwlock.c:1321
static void ProcArrayEndTransactionInternal(PGPROC *proc, TransactionId latestXid)
Definition procarray.c:725
static void ProcArrayGroupClearXid(PGPROC *proc, TransactionId latestXid)
Definition procarray.c:784

References Assert, XidCacheStatus::count, PGPROC::delayChkptFlags, fb(), InvalidLocalTransactionId, InvalidTransactionId, LW_EXCLUSIVE, LWLockAcquire(), LWLockConditionalAcquire(), LWLockHeldByMe(), LWLockRelease(), PGPROC::lxid, XidCacheStatus::overflowed, PGPROC::pgxactoff, PROC_VACUUM_STATE_MASK, ProcArrayEndTransactionInternal(), ProcArrayGroupClearXid(), ProcGlobal, 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 
)
extern

Definition at line 3967 of file procarray.c.

3969{
3971
3972 if (xmin != NULL)
3974
3975 if (catalog_xmin != NULL)
3977
3979}

References fb(), 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)
extern

Definition at line 1014 of file procarray.c.

1015{
1018
1019 /*
1020 * we set latestObservedXid to the xid SUBTRANS has been initialized up
1021 * to, so we can extend it from that point onwards in
1022 * RecordKnownAssignedTransactionIds, and when we get consistent in
1023 * ProcArrayApplyRecoveryInfo().
1024 */
1027}

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

Referenced by StartupXLOG().

◆ ProcArrayInstallImportedXmin()

bool ProcArrayInstallImportedXmin ( TransactionId  xmin,
VirtualTransactionId sourcevxid 
)
extern

Definition at line 2471 of file procarray.c.

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

References allProcs, Assert, PGPROC::databaseId, fb(), LW_SHARED, LWLockAcquire(), LWLockRelease(), PGPROC::lxid, MyDatabaseId, MyProc, PROC_IN_VACUUM, procArray, ProcGlobal, PGPROC::procNumber, result, 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 
)
extern

Definition at line 2555 of file procarray.c.

2556{
2557 bool result = false;
2558 TransactionId xid;
2559
2561 Assert(proc != NULL);
2562
2563 /*
2564 * Get an exclusive lock so that we can copy statusFlags from source proc.
2565 */
2567
2568 /*
2569 * Be certain that the referenced PGPROC has an advertised xmin which is
2570 * no later than the one we're installing, so that the system-wide xmin
2571 * can't go backwards. Also, make sure it's running in the same database,
2572 * so that the per-database xmin cannot go backwards.
2573 */
2574 xid = UINT32_ACCESS_ONCE(proc->xmin);
2575 if (proc->databaseId == MyDatabaseId &&
2576 TransactionIdIsNormal(xid) &&
2578 {
2579 /*
2580 * Install xmin and propagate the statusFlags that affect how the
2581 * value is interpreted by vacuum.
2582 */
2583 MyProc->xmin = TransactionXmin = xmin;
2585 (proc->statusFlags & PROC_XMIN_FLAGS);
2587
2588 result = true;
2589 }
2590
2592
2593 return result;
2594}
#define PROC_XMIN_FLAGS
Definition proc.h:76

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

Referenced by SetTransactionSnapshot().

◆ ProcArrayRemove()

void ProcArrayRemove ( PGPROC proc,
TransactionId  latestXid 
)
extern

Definition at line 561 of file procarray.c.

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

References allProcs, PROC_HDR::allProcs, Assert, XidCacheStatus::count, fb(), InvalidTransactionId, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MaintainLatestCompletedXid(), NUM_AUXILIARY_PROCS, XidCacheStatus::overflowed, 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 
)
extern

Definition at line 3942 of file procarray.c.

3944{
3946
3947 if (!already_locked)
3949
3952
3953 if (!already_locked)
3955
3956 elog(DEBUG1, "xmin required by slots: data %u, catalog %u",
3957 xmin, catalog_xmin);
3958}

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

Referenced by ReplicationSlotsComputeRequiredXmin().

◆ ProcNumberGetProc()

PGPROC * ProcNumberGetProc ( int  procNumber)
extern

Definition at line 3090 of file procarray.c.

3091{
3092 PGPROC *result;
3093
3095 return NULL;
3096 result = GetPGProcByNumber(procNumber);
3097
3098 if (result->pid == 0)
3099 return NULL;
3100
3101 return result;
3102}
#define GetPGProcByNumber(n)
Definition proc.h:504
uint32 allProcCount
Definition proc.h:459

References PROC_HDR::allProcCount, fb(), GetPGProcByNumber, ProcGlobal, and result.

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

◆ ProcNumberGetTransactionIds()

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

Definition at line 3112 of file procarray.c.

3114{
3115 PGPROC *proc;
3116
3117 *xid = InvalidTransactionId;
3118 *xmin = InvalidTransactionId;
3119 *nsubxid = 0;
3120 *overflowed = false;
3121
3123 return;
3124 proc = GetPGProcByNumber(procNumber);
3125
3126 /* Need to lock out additions/removals of backends */
3128
3129 if (proc->pid != 0)
3130 {
3131 *xid = proc->xid;
3132 *xmin = proc->xmin;
3133 *nsubxid = proc->subxidStatus.count;
3134 *overflowed = proc->subxidStatus.overflowed;
3135 }
3136
3138}

References PROC_HDR::allProcCount, XidCacheStatus::count, fb(), 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)
extern

Definition at line 4435 of file procarray.c.

4436{
4440
4441 elog(DEBUG4, "record known xact %u latestObservedXid %u",
4442 xid, latestObservedXid);
4443
4444 /*
4445 * When a newly observed xid arrives, it is frequently the case that it is
4446 * *not* the next xid in sequence. When this occurs, we must treat the
4447 * intervening xids as running also.
4448 */
4450 {
4452
4453 /*
4454 * Extend subtrans like we do in GetNewTransactionId() during normal
4455 * operation using individual extend steps. Note that we do not need
4456 * to extend clog since its extensions are WAL logged.
4457 *
4458 * This part has to be done regardless of standbyState since we
4459 * immediately start assigning subtransactions to their toplevel
4460 * transactions.
4461 */
4464 {
4467 }
4468 Assert(next_expected_xid == xid);
4469
4470 /*
4471 * If the KnownAssignedXids machinery isn't up yet, there's nothing
4472 * more to do since we don't track assigned xids yet.
4473 */
4475 {
4476 latestObservedXid = xid;
4477 return;
4478 }
4479
4480 /*
4481 * Add (latestObservedXid, xid] onto the KnownAssignedXids array.
4482 */
4486
4487 /*
4488 * Now we can advance latestObservedXid
4489 */
4490 latestObservedXid = xid;
4491
4492 /* TransamVariables->nextXid must be beyond any observed xid */
4494 }
4495}
#define DEBUG4
Definition elog.h:28

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

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

◆ SignalRecoveryConflict()

bool SignalRecoveryConflict ( PGPROC proc,
pid_t  pid,
RecoveryConflictReason  reason 
)
extern

Definition at line 3446 of file procarray.c.

3447{
3448 bool found = false;
3449
3451
3452 /*
3453 * Kill the pid if it's still here. If not, that's what we wanted so
3454 * ignore any errors.
3455 */
3456 if (proc->pid == pid)
3457 {
3458 (void) pg_atomic_fetch_or_u32(&proc->pendingRecoveryConflicts, (1 << reason));
3459
3460 /* wake up the process */
3462 found = true;
3463 }
3464
3466
3467 return found;
3468}
static uint32 pg_atomic_fetch_or_u32(volatile pg_atomic_uint32 *ptr, uint32 or_)
Definition atomics.h:410
int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber)
Definition procsignal.c:296
@ PROCSIG_RECOVERY_CONFLICT
Definition procsignal.h:41
pg_atomic_uint32 pendingRecoveryConflicts
Definition proc.h:270

References fb(), GetNumberFromPGProc, LW_SHARED, LWLockAcquire(), LWLockRelease(), PGPROC::pendingRecoveryConflicts, pg_atomic_fetch_or_u32(), PGPROC::pid, PROCSIG_RECOVERY_CONFLICT, and SendProcSignal().

Referenced by InvalidatePossiblyObsoleteSlot().

◆ SignalRecoveryConflictWithDatabase()

void SignalRecoveryConflictWithDatabase ( Oid  databaseid,
RecoveryConflictReason  reason 
)
extern

Definition at line 3521 of file procarray.c.

3522{
3524 int index;
3525
3526 /* tell all backends to die */
3528
3529 for (index = 0; index < arrayP->numProcs; index++)
3530 {
3531 int pgprocno = arrayP->pgprocnos[index];
3532 PGPROC *proc = &allProcs[pgprocno];
3533
3534 if (databaseid == InvalidOid || proc->databaseId == databaseid)
3535 {
3537 pid_t pid;
3538
3540
3541 pid = proc->pid;
3542 if (pid != 0)
3543 {
3544 (void) pg_atomic_fetch_or_u32(&proc->pendingRecoveryConflicts, (1 << reason));
3545
3546 /*
3547 * Kill the pid if it's still here. If not, that's what we
3548 * wanted so ignore any errors.
3549 */
3551 }
3552 }
3553 }
3554
3556}
#define InvalidOid

References allProcs, PGPROC::databaseId, fb(), GET_VXID_FROM_PGPROC, InvalidOid, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), PGPROC::pendingRecoveryConflicts, pg_atomic_fetch_or_u32(), PGPROC::pid, procArray, PROCSIG_RECOVERY_CONFLICT, and SendProcSignal().

Referenced by ResolveRecoveryConflictWithDatabase(), and SendRecoveryConflictWithBufferPin().

◆ SignalRecoveryConflictWithVirtualXID()

bool SignalRecoveryConflictWithVirtualXID ( VirtualTransactionId  vxid,
RecoveryConflictReason  reason 
)
extern

Definition at line 3476 of file procarray.c.

3477{
3479 int index;
3480 pid_t pid = 0;
3481
3483
3484 for (index = 0; index < arrayP->numProcs; index++)
3485 {
3486 int pgprocno = arrayP->pgprocnos[index];
3487 PGPROC *proc = &allProcs[pgprocno];
3489
3491
3492 if (procvxid.procNumber == vxid.procNumber &&
3493 procvxid.localTransactionId == vxid.localTransactionId)
3494 {
3495 pid = proc->pid;
3496 if (pid != 0)
3497 {
3498 (void) pg_atomic_fetch_or_u32(&proc->pendingRecoveryConflicts, (1 << reason));
3499
3500 /*
3501 * Kill the pid if it's still here. If not, that's what we
3502 * wanted so ignore any errors.
3503 */
3505 }
3506 break;
3507 }
3508 }
3509
3511
3512 return pid != 0;
3513}
LocalTransactionId localTransactionId
Definition lock.h:65
ProcNumber procNumber
Definition lock.h:64

References allProcs, fb(), GET_VXID_FROM_PGPROC, VirtualTransactionId::localTransactionId, LW_SHARED, LWLockAcquire(), LWLockRelease(), PGPROC::pendingRecoveryConflicts, pg_atomic_fetch_or_u32(), PGPROC::pid, procArray, VirtualTransactionId::procNumber, PROCSIG_RECOVERY_CONFLICT, and SendProcSignal().

Referenced by ResolveRecoveryConflictWithLock(), and ResolveRecoveryConflictWithVirtualXIDs().

◆ TerminateOtherDBBackends()

void TerminateOtherDBBackends ( Oid  databaseId)
extern

Definition at line 3827 of file procarray.c.

3828{
3830 List *pids = NIL;
3831 int nprepared = 0;
3832 int i;
3833
3835
3836 for (i = 0; i < procArray->numProcs; i++)
3837 {
3838 int pgprocno = arrayP->pgprocnos[i];
3839 PGPROC *proc = &allProcs[pgprocno];
3840
3841 if (proc->databaseId != databaseId)
3842 continue;
3843 if (proc == MyProc)
3844 continue;
3845
3846 if (proc->pid != 0)
3847 pids = lappend_int(pids, proc->pid);
3848 else
3849 nprepared++;
3850 }
3851
3853
3854 if (nprepared > 0)
3855 ereport(ERROR,
3857 errmsg("database \"%s\" is being used by prepared transactions",
3858 get_database_name(databaseId)),
3859 errdetail_plural("There is %d prepared transaction using the database.",
3860 "There are %d prepared transactions using the database.",
3861 nprepared,
3862 nprepared)));
3863
3864 if (pids)
3865 {
3866 ListCell *lc;
3867
3868 /*
3869 * Permissions checks relax the pg_terminate_backend checks in two
3870 * ways, both by omitting the !OidIsValid(proc->roleId) check:
3871 *
3872 * - Accept terminating autovacuum workers, since DROP DATABASE
3873 * without FORCE terminates them.
3874 *
3875 * - Accept terminating bgworkers. For bgworker authors, it's
3876 * convenient to be able to recommend FORCE if a worker is blocking
3877 * DROP DATABASE unexpectedly.
3878 *
3879 * Unlike pg_terminate_backend, we don't raise some warnings - like
3880 * "PID %d is not a PostgreSQL server process", because for us already
3881 * finished session is not a problem.
3882 */
3883 foreach(lc, pids)
3884 {
3885 int pid = lfirst_int(lc);
3886 PGPROC *proc = BackendPidGetProc(pid);
3887
3888 if (proc != NULL)
3889 {
3890 if (superuser_arg(proc->roleId) && !superuser())
3891 ereport(ERROR,
3893 errmsg("permission denied to terminate process"),
3894 errdetail("Only roles with the %s attribute may terminate processes of roles with the %s attribute.",
3895 "SUPERUSER", "SUPERUSER")));
3896
3897 if (!has_privs_of_role(GetUserId(), proc->roleId) &&
3899 ereport(ERROR,
3901 errmsg("permission denied to terminate process"),
3902 errdetail("Only roles with privileges of the role whose process is being terminated or with privileges of the \"%s\" role may terminate this process.",
3903 "pg_signal_backend")));
3904 }
3905 }
3906
3907 /*
3908 * There's a race condition here: once we release the ProcArrayLock,
3909 * it's possible for the session to exit before we issue kill. That
3910 * race condition possibility seems too unlikely to worry about. See
3911 * pg_signal_backend.
3912 */
3913 foreach(lc, pids)
3914 {
3915 int pid = lfirst_int(lc);
3916 PGPROC *proc = BackendPidGetProc(pid);
3917
3918 if (proc != NULL)
3919 {
3920 /*
3921 * If we have setsid(), signal the backend's whole process
3922 * group
3923 */
3924#ifdef HAVE_SETSID
3925 (void) kill(-pid, SIGTERM);
3926#else
3927 (void) kill(pid, SIGTERM);
3928#endif
3929 }
3930 }
3931 }
3932}
bool has_privs_of_role(Oid member, Oid role)
Definition acl.c:5314
int errdetail(const char *fmt,...) pg_attribute_printf(1
int errdetail_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n,...) pg_attribute_printf(1
List * lappend_int(List *list, int datum)
Definition list.c:357
char * get_database_name(Oid dbid)
Definition lsyscache.c:1384
Oid GetUserId(void)
Definition miscinit.c:470
#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:57
bool superuser(void)
Definition superuser.c:47

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

Referenced by dropdb().

◆ TransactionIdIsInProgress()

bool TransactionIdIsInProgress ( TransactionId  xid)
extern

Definition at line 1393 of file procarray.c.

1394{
1395 static TransactionId *xids = NULL;
1396 static TransactionId *other_xids;
1398 int nxids = 0;
1401 TransactionId latestCompletedXid;
1402 int mypgxactoff;
1403 int numProcs;
1404 int j;
1405
1406 /*
1407 * Don't bother checking a transaction older than RecentXmin; it could not
1408 * possibly still be running. (Note: in particular, this guarantees that
1409 * we reject InvalidTransactionId, FrozenTransactionId, etc as not
1410 * running.)
1411 */
1413 {
1415 return false;
1416 }
1417
1418 /*
1419 * We may have just checked the status of this transaction, so if it is
1420 * already known to be completed, we can fall out without any access to
1421 * shared memory.
1422 */
1424 {
1426 return false;
1427 }
1428
1429 /*
1430 * Also, we can handle our own transaction (and subtransactions) without
1431 * any access to shared memory.
1432 */
1434 {
1436 return true;
1437 }
1438
1439 /*
1440 * If first time through, get workspace to remember main XIDs in. We
1441 * malloc it permanently to avoid repeated palloc/pfree overhead.
1442 */
1443 if (xids == NULL)
1444 {
1445 /*
1446 * In hot standby mode, reserve enough space to hold all xids in the
1447 * known-assigned list. If we later finish recovery, we no longer need
1448 * the bigger array, but we don't bother to shrink it.
1449 */
1451
1452 xids = (TransactionId *) malloc(maxxids * sizeof(TransactionId));
1453 if (xids == NULL)
1454 ereport(ERROR,
1456 errmsg("out of memory")));
1457 }
1458
1461
1463
1464 /*
1465 * Now that we have the lock, we can check latestCompletedXid; if the
1466 * target Xid is after that, it's surely still running.
1467 */
1468 latestCompletedXid =
1470 if (TransactionIdPrecedes(latestCompletedXid, xid))
1471 {
1474 return true;
1475 }
1476
1477 /* No shortcuts, gotta grovel through the array */
1479 numProcs = arrayP->numProcs;
1480 for (int pgxactoff = 0; pgxactoff < numProcs; pgxactoff++)
1481 {
1482 int pgprocno;
1483 PGPROC *proc;
1485 int pxids;
1486
1487 /* Ignore ourselves --- dealt with it above */
1488 if (pgxactoff == mypgxactoff)
1489 continue;
1490
1491 /* Fetch xid just once - see GetNewTransactionId */
1492 pxid = UINT32_ACCESS_ONCE(other_xids[pgxactoff]);
1493
1495 continue;
1496
1497 /*
1498 * Step 1: check the main Xid
1499 */
1500 if (TransactionIdEquals(pxid, xid))
1501 {
1504 return true;
1505 }
1506
1507 /*
1508 * We can ignore main Xids that are younger than the target Xid, since
1509 * the target could not possibly be their child.
1510 */
1511 if (TransactionIdPrecedes(xid, pxid))
1512 continue;
1513
1514 /*
1515 * Step 2: check the cached child-Xids arrays
1516 */
1517 pxids = other_subxidstates[pgxactoff].count;
1518 pg_read_barrier(); /* pairs with barrier in GetNewTransactionId() */
1519 pgprocno = arrayP->pgprocnos[pgxactoff];
1520 proc = &allProcs[pgprocno];
1521 for (j = pxids - 1; j >= 0; j--)
1522 {
1523 /* Fetch xid just once - see GetNewTransactionId */
1525
1526 if (TransactionIdEquals(cxid, xid))
1527 {
1530 return true;
1531 }
1532 }
1533
1534 /*
1535 * Save the main Xid for step 4. We only need to remember main Xids
1536 * that have uncached children. (Note: there is no race condition
1537 * here because the overflowed flag cannot be cleared, only set, while
1538 * we hold ProcArrayLock. So we can't miss an Xid that we need to
1539 * worry about.)
1540 */
1541 if (other_subxidstates[pgxactoff].overflowed)
1542 xids[nxids++] = pxid;
1543 }
1544
1545 /*
1546 * Step 3: in hot standby mode, check the known-assigned-xids list. XIDs
1547 * in the list must be treated as running.
1548 */
1549 if (RecoveryInProgress())
1550 {
1551 /* none of the PGPROC entries should have XIDs in hot standby mode */
1552 Assert(nxids == 0);
1553
1554 if (KnownAssignedXidExists(xid))
1555 {
1558 return true;
1559 }
1560
1561 /*
1562 * If the KnownAssignedXids overflowed, we have to check pg_subtrans
1563 * too. Fetch all xids from KnownAssignedXids that are lower than
1564 * xid, since if xid is a subtransaction its parent will always have a
1565 * lower value. Note we will collect both main and subXIDs here, but
1566 * there's no help for it.
1567 */
1569 nxids = KnownAssignedXidsGet(xids, xid);
1570 }
1571
1573
1574 /*
1575 * If none of the relevant caches overflowed, we know the Xid is not
1576 * running without even looking at pg_subtrans.
1577 */
1578 if (nxids == 0)
1579 {
1582 return false;
1583 }
1584
1585 /*
1586 * Step 4: have to check pg_subtrans.
1587 *
1588 * At this point, we know it's either a subtransaction of one of the Xids
1589 * in xids[], or it's not running. If it's an already-failed
1590 * subtransaction, we want to say "not running" even though its parent may
1591 * still be running. So first, check pg_xact to see if it's been aborted.
1592 */
1594
1595 if (TransactionIdDidAbort(xid))
1596 {
1598 return false;
1599 }
1600
1601 /*
1602 * It isn't aborted, so check whether the transaction tree it belongs to
1603 * is still running (or, more precisely, whether it was running when we
1604 * held ProcArrayLock).
1605 */
1608 if (!TransactionIdEquals(topxid, xid) &&
1609 pg_lfind32(topxid, xids, nxids))
1610 return true;
1611
1613 return false;
1614}
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:359
#define xc_by_recent_xmin_inc()
Definition procarray.c:352
static int KnownAssignedXidsGet(TransactionId *xarray, TransactionId xmax)
Definition procarray.c:5145
#define xc_by_my_xact_inc()
Definition procarray.c:354
#define xc_by_known_assigned_inc()
Definition procarray.c:358
#define xc_by_child_xid_inc()
Definition procarray.c:357
#define xc_slow_answer_inc()
Definition procarray.c:360
#define xc_by_main_xid_inc()
Definition procarray.c:356
static bool KnownAssignedXidExists(TransactionId xid)
Definition procarray.c:5006
#define xc_by_latest_xid_inc()
Definition procarray.c:355
#define xc_by_known_xact_inc()
Definition procarray.c:353
static TransactionId cachedXidIsNotInProgress
Definition procarray.c:290
TransactionId SubTransGetTopmostTransaction(TransactionId xid)
Definition subtrans.c:170
bool TransactionIdIsCurrentTransactionId(TransactionId xid)
Definition xact.c:943

References allProcs, Assert, cachedXidIsNotInProgress, ereport, errcode(), errmsg, ERROR, fb(), j, KnownAssignedXidExists(), KnownAssignedXidsGet(), ProcArrayStruct::lastOverflowedXid, TransamVariablesData::latestCompletedXid, LW_SHARED, LWLockAcquire(), LWLockRelease(), malloc, MyProc, pg_lfind32(), pg_read_barrier, 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(), HeapTupleCleanMoved(), HeapTupleHeaderIsOnlyLocked(), HeapTupleSatisfiesDirty(), HeapTupleSatisfiesSelf(), 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 
)
extern

Definition at line 3990 of file procarray.c.

3993{
3994 int i,
3995 j;
3997
3999
4000 /*
4001 * We must hold ProcArrayLock exclusively in order to remove transactions
4002 * from the PGPROC array. (See src/backend/access/transam/README.) It's
4003 * possible this could be relaxed since we know this routine is only used
4004 * to abort subtransactions, but pending closer analysis we'd best be
4005 * conservative.
4006 *
4007 * Note that we do not have to be careful about memory ordering of our own
4008 * reads wrt. GetNewTransactionId() here - only this process can modify
4009 * relevant fields of MyProc/ProcGlobal->xids[]. But we do have to be
4010 * careful about our own writes being well ordered.
4011 */
4013
4015
4016 /*
4017 * Under normal circumstances xid and xids[] will be in increasing order,
4018 * as will be the entries in subxids. Scan backwards to avoid O(N^2)
4019 * behavior when removing a lot of xids.
4020 */
4021 for (i = nxids - 1; i >= 0; i--)
4022 {
4023 TransactionId anxid = xids[i];
4024
4025 for (j = MyProc->subxidStatus.count - 1; j >= 0; j--)
4026 {
4028 {
4031 mysubxidstat->count--;
4033 break;
4034 }
4035 }
4036
4037 /*
4038 * Ordinarily we should have found it, unless the cache has
4039 * overflowed. However it's also possible for this routine to be
4040 * invoked multiple times for the same subtransaction, in case of an
4041 * error during AbortSubTransaction. So instead of Assert, emit a
4042 * debug warning.
4043 */
4044 if (j < 0 && !MyProc->subxidStatus.overflowed)
4045 elog(WARNING, "did not find subXID %u in MyProc", anxid);
4046 }
4047
4048 for (j = MyProc->subxidStatus.count - 1; j >= 0; j--)
4049 {
4051 {
4054 mysubxidstat->count--;
4056 break;
4057 }
4058 }
4059 /* Ordinarily we should have found it, unless the cache has overflowed */
4060 if (j < 0 && !MyProc->subxidStatus.overflowed)
4061 elog(WARNING, "did not find subXID %u in MyProc", xid);
4062
4063 /* Also advance global latestCompletedXid while holding the lock */
4065
4066 /* ... and xactCompletionCount */
4068
4070}
#define pg_write_barrier()
Definition atomics.h:155
#define WARNING
Definition elog.h:37

References Assert, XidCacheStatus::count, elog, fb(), 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().