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

Go to the source code of this file.

Functions

Size ProcArrayShmemSize (void)
 
void ProcArrayShmemInit (void)
 
void ProcArrayAdd (PGPROC *proc)
 
void ProcArrayRemove (PGPROC *proc, TransactionId latestXid)
 
void ProcArrayEndTransaction (PGPROC *proc, TransactionId latestXid)
 
void ProcArrayClearTransaction (PGPROC *proc)
 
void ProcArrayInitRecovery (TransactionId initializedUptoXID)
 
void ProcArrayApplyRecoveryInfo (RunningTransactions running)
 
void ProcArrayApplyXidAssignment (TransactionId topxid, int nsubxids, TransactionId *subxids)
 
void RecordKnownAssignedTransactionIds (TransactionId xid)
 
void ExpireTreeKnownAssignedTransactionIds (TransactionId xid, int nsubxids, TransactionId *subxids, TransactionId max_xid)
 
void ExpireAllKnownAssignedTransactionIds (void)
 
void ExpireOldKnownAssignedTransactionIds (TransactionId xid)
 
void KnownAssignedTransactionIdsIdleMaintenance (void)
 
int GetMaxSnapshotXidCount (void)
 
int GetMaxSnapshotSubxidCount (void)
 
Snapshot GetSnapshotData (Snapshot snapshot)
 
bool ProcArrayInstallImportedXmin (TransactionId xmin, VirtualTransactionId *sourcevxid)
 
bool ProcArrayInstallRestoredXmin (TransactionId xmin, PGPROC *proc)
 
RunningTransactions GetRunningTransactionData (void)
 
bool TransactionIdIsInProgress (TransactionId xid)
 
TransactionId GetOldestNonRemovableTransactionId (Relation rel)
 
TransactionId GetOldestTransactionIdConsideredRunning (void)
 
TransactionId GetOldestActiveTransactionId (bool inCommitOnly, bool allDbs)
 
TransactionId GetOldestSafeDecodingTransactionId (bool catalogOnly)
 
void GetReplicationHorizons (TransactionId *xmin, TransactionId *catalog_xmin)
 
VirtualTransactionIdGetVirtualXIDsDelayingChkpt (int *nvxids, int type)
 
bool HaveVirtualXIDsDelayingChkpt (VirtualTransactionId *vxids, int nvxids, int type)
 
PGPROCProcNumberGetProc (int procNumber)
 
void ProcNumberGetTransactionIds (int procNumber, TransactionId *xid, TransactionId *xmin, int *nsubxid, bool *overflowed)
 
PGPROCBackendPidGetProc (int pid)
 
PGPROCBackendPidGetProcWithLock (int pid)
 
int BackendXidGetPid (TransactionId xid)
 
bool IsBackendPid (int pid)
 
VirtualTransactionIdGetCurrentVirtualXIDs (TransactionId limitXmin, bool excludeXmin0, bool allDbs, int excludeVacuum, int *nvxids)
 
VirtualTransactionIdGetConflictingVirtualXIDs (TransactionId limitXmin, Oid dbOid)
 
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 3156 of file procarray.c.

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

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

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

◆ BackendPidGetProcWithLock()

PGPROC * BackendPidGetProcWithLock ( int  pid)
extern

Definition at line 3179 of file procarray.c.

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

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

Referenced by BackendPidGetProc(), and GetBlockerStatusData().

◆ BackendXidGetPid()

int BackendXidGetPid ( TransactionId  xid)
extern

Definition at line 3216 of file procarray.c.

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

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

Referenced by pgrowlocks().

◆ CountDBBackends()

int CountDBBackends ( Oid  databaseid)
extern

Definition at line 3629 of file procarray.c.

3630{
3631 ProcArrayStruct *arrayP = procArray;
3632 int count = 0;
3633 int index;
3634
3635 LWLockAcquire(ProcArrayLock, LW_SHARED);
3636
3637 for (index = 0; index < arrayP->numProcs; index++)
3638 {
3639 int pgprocno = arrayP->pgprocnos[index];
3640 PGPROC *proc = &allProcs[pgprocno];
3641
3642 if (proc->pid == 0)
3643 continue; /* do not count prepared xacts */
3644 if (!OidIsValid(databaseid) ||
3645 proc->databaseId == databaseid)
3646 count++;
3647 }
3648
3649 LWLockRelease(ProcArrayLock);
3650
3651 return count;
3652}
#define OidIsValid(objectId)
Definition c.h:860
Oid databaseId
Definition proc.h:198

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

Referenced by ResolveRecoveryConflictWithDatabase().

◆ CountDBConnections()

int CountDBConnections ( Oid  databaseid)
extern

Definition at line 3658 of file procarray.c.

3659{
3660 ProcArrayStruct *arrayP = procArray;
3661 int count = 0;
3662 int index;
3663
3664 LWLockAcquire(ProcArrayLock, LW_SHARED);
3665
3666 for (index = 0; index < arrayP->numProcs; index++)
3667 {
3668 int pgprocno = arrayP->pgprocnos[index];
3669 PGPROC *proc = &allProcs[pgprocno];
3670
3671 if (proc->pid == 0)
3672 continue; /* do not count prepared xacts */
3673 if (proc->backendType != B_BACKEND)
3674 continue; /* count only regular backend processes */
3675 if (!OidIsValid(databaseid) ||
3676 proc->databaseId == databaseid)
3677 count++;
3678 }
3679
3680 LWLockRelease(ProcArrayLock);
3681
3682 return count;
3683}
@ B_BACKEND
Definition miscadmin.h:342
BackendType backendType
Definition proc.h:195

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

Referenced by CheckMyDatabase().

◆ CountOtherDBBackends()

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

Definition at line 3742 of file procarray.c.

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

References allProcs, CHECK_FOR_INTERRUPTS, PGPROC::databaseId, IS_INJECTION_POINT_ATTACHED, kill, LW_SHARED, LWLockAcquire(), LWLockRelease(), MAXAUTOVACPIDS, MyProc, ProcArrayStruct::numProcs, pg_usleep(), ProcArrayStruct::pgprocnos, 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 3690 of file procarray.c.

3691{
3692 ProcArrayStruct *arrayP = procArray;
3693 int count = 0;
3694 int index;
3695
3696 LWLockAcquire(ProcArrayLock, LW_SHARED);
3697
3698 for (index = 0; index < arrayP->numProcs; index++)
3699 {
3700 int pgprocno = arrayP->pgprocnos[index];
3701 PGPROC *proc = &allProcs[pgprocno];
3702
3703 if (proc->pid == 0)
3704 continue; /* do not count prepared xacts */
3705 if (proc->backendType != B_BACKEND)
3706 continue; /* count only regular backend processes */
3707 if (proc->roleId == roleid)
3708 count++;
3709 }
3710
3711 LWLockRelease(ProcArrayLock);
3712
3713 return count;
3714}
Oid roleId
Definition proc.h:199

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

Referenced by InitializeSessionUserId().

◆ ExpireAllKnownAssignedTransactionIds()

void ExpireAllKnownAssignedTransactionIds ( void  )
extern

Definition at line 4505 of file procarray.c.

4506{
4507 FullTransactionId latestXid;
4508
4509 LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
4511
4512 /* Reset latestCompletedXid to nextXid - 1 */
4514 latestXid = TransamVariables->nextXid;
4515 FullTransactionIdRetreat(&latestXid);
4517
4518 /*
4519 * Any transactions that were in-progress were effectively aborted, so
4520 * advance xactCompletionCount.
4521 */
4523
4524 /*
4525 * Reset lastOverflowedXid. Currently, lastOverflowedXid has no use after
4526 * the call of this function. But do this for unification with what
4527 * ExpireOldKnownAssignedTransactionIds() do.
4528 */
4530 LWLockRelease(ProcArrayLock);
4531}
#define Assert(condition)
Definition c.h:945
@ LW_EXCLUSIVE
Definition lwlock.h:112
static void KnownAssignedXidsRemovePreceding(TransactionId removeXid)
Definition procarray.c:5042
TransactionId lastOverflowedXid
Definition procarray.c:95
FullTransactionId latestCompletedXid
Definition transam.h:238
FullTransactionId nextXid
Definition transam.h:220
uint64 xactCompletionCount
Definition transam.h:248
static void FullTransactionIdRetreat(FullTransactionId *dest)
Definition transam.h:103
#define FullTransactionIdIsValid(x)
Definition transam.h:55
TransamVariablesData * TransamVariables
Definition varsup.c:34

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

Referenced by ShutdownRecoveryTransactionEnvironment().

◆ ExpireOldKnownAssignedTransactionIds()

void ExpireOldKnownAssignedTransactionIds ( TransactionId  xid)
extern

Definition at line 4539 of file procarray.c.

4540{
4541 TransactionId latestXid;
4542
4543 LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
4544
4545 /* As in ProcArrayEndTransaction, advance latestCompletedXid */
4546 latestXid = xid;
4547 TransactionIdRetreat(latestXid);
4549
4550 /* ... and xactCompletionCount */
4552
4553 /*
4554 * Reset lastOverflowedXid if we know all transactions that have been
4555 * possibly running are being gone. Not doing so could cause an incorrect
4556 * lastOverflowedXid value, which makes extra snapshots be marked as
4557 * suboverflowed.
4558 */
4562 LWLockRelease(ProcArrayLock);
4563}
static void MaintainLatestCompletedXidRecovery(TransactionId latestXid)
Definition procarray.c:988
#define TransactionIdRetreat(dest)
Definition transam.h:141
static bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition transam.h:263

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

Referenced by ProcArrayApplyRecoveryInfo().

◆ ExpireTreeKnownAssignedTransactionIds()

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

Definition at line 4479 of file procarray.c.

4481{
4483
4484 /*
4485 * Uses same locking as transaction commit
4486 */
4487 LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
4488
4489 KnownAssignedXidsRemoveTree(xid, nsubxids, subxids);
4490
4491 /* As in ProcArrayEndTransaction, advance latestCompletedXid */
4493
4494 /* ... and xactCompletionCount */
4496
4497 LWLockRelease(ProcArrayLock);
4498}
static void KnownAssignedXidsRemoveTree(TransactionId xid, int nsubxids, TransactionId *subxids)
Definition procarray.c:5020
HotStandbyState standbyState
Definition xlogutils.c:53
@ STANDBY_INITIALIZED
Definition xlogutils.h:53

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

Referenced by xact_redo_abort(), and xact_redo_commit().

◆ GetConflictingVirtualXIDs()

VirtualTransactionId * GetConflictingVirtualXIDs ( TransactionId  limitXmin,
Oid  dbOid 
)
extern

Definition at line 3376 of file procarray.c.

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

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

Referenced by ResolveRecoveryConflictWithSnapshot(), and ResolveRecoveryConflictWithTablespace().

◆ GetCurrentVirtualXIDs()

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

Definition at line 3284 of file procarray.c.

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

References allProcs, PGPROC::databaseId, GET_VXID_FROM_PGPROC, LW_SHARED, LWLockAcquire(), LWLockRelease(), ProcArrayStruct::maxProcs, MyDatabaseId, MyProc, ProcArrayStruct::numProcs, palloc_array, ProcArrayStruct::pgprocnos, 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 2027 of file procarray.c.

2028{
2030}
#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 2016 of file procarray.c.

2017{
2018 return procArray->maxProcs;
2019}

References ProcArrayStruct::maxProcs, and procArray.

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

◆ GetOldestActiveTransactionId()

TransactionId GetOldestActiveTransactionId ( bool  inCommitOnly,
bool  allDbs 
)
extern

Definition at line 2832 of file procarray.c.

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

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

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

◆ GetOldestNonRemovableTransactionId()

TransactionId GetOldestNonRemovableTransactionId ( Relation  rel)
extern

Definition at line 1952 of file procarray.c.

1953{
1954 ComputeXidHorizonsResult horizons;
1955
1956 ComputeXidHorizons(&horizons);
1957
1958 switch (GlobalVisHorizonKindForRel(rel))
1959 {
1960 case VISHORIZON_SHARED:
1961 return horizons.shared_oldest_nonremovable;
1962 case VISHORIZON_CATALOG:
1963 return horizons.catalog_oldest_nonremovable;
1964 case VISHORIZON_DATA:
1965 return horizons.data_oldest_nonremovable;
1966 case VISHORIZON_TEMP:
1967 return horizons.temp_oldest_nonremovable;
1968 }
1969
1970 /* just to prevent compiler warnings */
1971 return InvalidTransactionId;
1972}
static void ComputeXidHorizons(ComputeXidHorizonsResult *h)
Definition procarray.c:1682
@ VISHORIZON_SHARED
Definition procarray.c:255
@ VISHORIZON_DATA
Definition procarray.c:257
@ VISHORIZON_CATALOG
Definition procarray.c:256
@ VISHORIZON_TEMP
Definition procarray.c:258
static GlobalVisHorizonKind GlobalVisHorizonKindForRel(Relation rel)
Definition procarray.c:1918
TransactionId data_oldest_nonremovable
Definition procarray.c:241
TransactionId temp_oldest_nonremovable
Definition procarray.c:247
TransactionId shared_oldest_nonremovable
Definition procarray.c:218
TransactionId catalog_oldest_nonremovable
Definition procarray.c:235

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

Referenced by _bt_pendingfsm_finalize(), 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 2906 of file procarray.c.

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

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

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

◆ GetOldestTransactionIdConsideredRunning()

TransactionId GetOldestTransactionIdConsideredRunning ( void  )
extern

Definition at line 1981 of file procarray.c.

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

References ComputeXidHorizons(), and ComputeXidHorizonsResult::oldest_considered_running.

Referenced by CreateCheckPoint(), and CreateRestartPoint().

◆ GetReplicationHorizons()

void GetReplicationHorizons ( TransactionId xmin,
TransactionId catalog_xmin 
)
extern

Definition at line 1994 of file procarray.c.

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

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

Referenced by XLogWalRcvSendHSFeedback().

◆ GetRunningTransactionData()

RunningTransactions GetRunningTransactionData ( void  )
extern

Definition at line 2636 of file procarray.c.

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

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

Referenced by GetStrictOldestNonRemovableTransactionId(), and LogStandbySnapshot().

◆ GetSnapshotData()

Snapshot GetSnapshotData ( Snapshot  snapshot)
extern

Definition at line 2122 of file procarray.c.

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

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

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

◆ GetVirtualXIDsDelayingChkpt()

VirtualTransactionId * GetVirtualXIDsDelayingChkpt ( int *  nvxids,
int  type 
)
extern

Definition at line 3004 of file procarray.c.

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

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

Referenced by CreateCheckPoint().

◆ HaveVirtualXIDsDelayingChkpt()

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

Definition at line 3049 of file procarray.c.

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

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

Referenced by CreateCheckPoint().

◆ IsBackendPid()

bool IsBackendPid ( int  pid)
extern

Definition at line 3251 of file procarray.c.

3252{
3253 return (BackendPidGetProc(pid) != NULL);
3254}
PGPROC * BackendPidGetProc(int pid)
Definition procarray.c:3156

References BackendPidGetProc().

Referenced by pg_stat_get_subscription().

◆ KnownAssignedTransactionIdsIdleMaintenance()

void KnownAssignedTransactionIdsIdleMaintenance ( void  )
extern

Definition at line 4571 of file procarray.c.

4572{
4574}
@ KAX_STARTUP_PROCESS_IDLE
Definition procarray.c:269
static void KnownAssignedXidsCompress(KAXCompressReason reason, bool haveLock)
Definition procarray.c:4672

References KAX_STARTUP_PROCESS_IDLE, and KnownAssignedXidsCompress().

Referenced by WaitForWALToBecomeAvailable().

◆ MinimumActiveBackends()

bool MinimumActiveBackends ( int  min)
extern

Definition at line 3576 of file procarray.c.

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

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

Referenced by XLogFlush().

◆ ProcArrayAdd()

void ProcArrayAdd ( PGPROC proc)
extern

Definition at line 472 of file procarray.c.

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

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

Referenced by InitProcessPhase2(), and MarkAsPrepared().

◆ ProcArrayApplyRecoveryInfo()

void ProcArrayApplyRecoveryInfo ( RunningTransactions  running)
extern

Definition at line 1053 of file procarray.c.

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

References AdvanceNextFullTransactionIdPastXid(), Assert, DEBUG1, DEBUG3, elog, ERROR, ExpireOldKnownAssignedTransactionIds(), ExtendSUBTRANS(), FullTransactionIdIsValid, i, InvalidTransactionId, KnownAssignedXidsAdd(), KnownAssignedXidsDisplay(), KnownAssignedXidsReset(), ProcArrayStruct::lastOverflowedXid, RunningTransactionsData::latestCompletedXid, latestObservedXid, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MaintainLatestCompletedXidRecovery(), TransamVariablesData::nextXid, RunningTransactionsData::nextXid, ProcArrayStruct::numKnownAssignedXids, RunningTransactionsData::oldestRunningXid, palloc_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 1317 of file procarray.c.

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

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

Referenced by xact_redo().

◆ ProcArrayClearTransaction()

void ProcArrayClearTransaction ( PGPROC proc)
extern

Definition at line 907 of file procarray.c.

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

References Assert, XidCacheStatus::count, PGPROC::delayChkptFlags, InvalidLocalTransactionId, InvalidTransactionId, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), PGPROC::lxid, XidCacheStatus::overflowed, PGPROC::pgxactoff, PROC_VACUUM_STATE_MASK, ProcGlobal, PGPROC::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 671 of file procarray.c.

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

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

3977{
3978 LWLockAcquire(ProcArrayLock, LW_SHARED);
3979
3980 if (xmin != NULL)
3982
3983 if (catalog_xmin != NULL)
3985
3986 LWLockRelease(ProcArrayLock);
3987}

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

Referenced by logical_begin_heap_rewrite().

◆ ProcArrayInitRecovery()

void ProcArrayInitRecovery ( TransactionId  initializedUptoXID)
extern

Definition at line 1022 of file procarray.c.

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

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

Referenced by StartupXLOG().

◆ ProcArrayInstallImportedXmin()

bool ProcArrayInstallImportedXmin ( TransactionId  xmin,
VirtualTransactionId sourcevxid 
)
extern

Definition at line 2479 of file procarray.c.

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

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

Referenced by GetSerializableTransactionSnapshotInt(), and SetTransactionSnapshot().

◆ ProcArrayInstallRestoredXmin()

bool ProcArrayInstallRestoredXmin ( TransactionId  xmin,
PGPROC proc 
)
extern

Definition at line 2563 of file procarray.c.

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

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

Referenced by SetTransactionSnapshot().

◆ ProcArrayRemove()

void ProcArrayRemove ( PGPROC proc,
TransactionId  latestXid 
)
extern

Definition at line 569 of file procarray.c.

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

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

Referenced by FinishPreparedTransaction(), and RemoveProcFromArray().

◆ ProcArraySetReplicationSlotXmin()

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

Definition at line 3950 of file procarray.c.

3952{
3953 Assert(!already_locked || LWLockHeldByMe(ProcArrayLock));
3954
3955 if (!already_locked)
3956 LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3957
3960
3961 if (!already_locked)
3962 LWLockRelease(ProcArrayLock);
3963
3964 elog(DEBUG1, "xmin required by slots: data %u, catalog %u",
3965 xmin, catalog_xmin);
3966}

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

Referenced by ReplicationSlotsComputeRequiredXmin().

◆ ProcArrayShmemInit()

void ProcArrayShmemInit ( void  )
extern

Definition at line 422 of file procarray.c.

423{
424 bool found;
425
426 /* Create or attach to the ProcArray shared structure */
428 ShmemInitStruct("Proc Array",
429 add_size(offsetof(ProcArrayStruct, pgprocnos),
430 mul_size(sizeof(int),
432 &found);
433
434 if (!found)
435 {
436 /*
437 * We're the first - initialize.
438 */
439 procArray->numProcs = 0;
449 }
450
452
453 /* Create or attach to the KnownAssignedXids arrays too, if needed */
455 {
457 ShmemInitStruct("KnownAssignedXids",
458 mul_size(sizeof(TransactionId),
460 &found);
461 KnownAssignedXidsValid = (bool *)
462 ShmemInitStruct("KnownAssignedXidsValid",
463 mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS),
464 &found);
465 }
466}
#define PROCARRAY_MAXPROCS
static TransactionId * KnownAssignedXids
Definition procarray.c:285
static bool * KnownAssignedXidsValid
Definition procarray.c:286
Size add_size(Size s1, Size s2)
Definition shmem.c:485
Size mul_size(Size s1, Size s2)
Definition shmem.c:500
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition shmem.c:381
int maxKnownAssignedXids
Definition procarray.c:83
int tailKnownAssignedXids
Definition procarray.c:85
int headKnownAssignedXids
Definition procarray.c:86
bool EnableHotStandby
Definition xlog.c:125

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

Referenced by CreateOrAttachShmemStructs().

◆ ProcArrayShmemSize()

Size ProcArrayShmemSize ( void  )
extern

Definition at line 380 of file procarray.c.

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

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

Referenced by CalculateShmemSize().

◆ ProcNumberGetProc()

PGPROC * ProcNumberGetProc ( int  procNumber)
extern

Definition at line 3098 of file procarray.c.

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

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

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

◆ ProcNumberGetTransactionIds()

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

Definition at line 3120 of file procarray.c.

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

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

Referenced by pgstat_read_current_status().

◆ RecordKnownAssignedTransactionIds()

void RecordKnownAssignedTransactionIds ( TransactionId  xid)
extern

Definition at line 4410 of file procarray.c.

4411{
4415
4416 elog(DEBUG4, "record known xact %u latestObservedXid %u",
4417 xid, latestObservedXid);
4418
4419 /*
4420 * When a newly observed xid arrives, it is frequently the case that it is
4421 * *not* the next xid in sequence. When this occurs, we must treat the
4422 * intervening xids as running also.
4423 */
4425 {
4426 TransactionId next_expected_xid;
4427
4428 /*
4429 * Extend subtrans like we do in GetNewTransactionId() during normal
4430 * operation using individual extend steps. Note that we do not need
4431 * to extend clog since its extensions are WAL logged.
4432 *
4433 * This part has to be done regardless of standbyState since we
4434 * immediately start assigning subtransactions to their toplevel
4435 * transactions.
4436 */
4437 next_expected_xid = latestObservedXid;
4438 while (TransactionIdPrecedes(next_expected_xid, xid))
4439 {
4440 TransactionIdAdvance(next_expected_xid);
4441 ExtendSUBTRANS(next_expected_xid);
4442 }
4443 Assert(next_expected_xid == xid);
4444
4445 /*
4446 * If the KnownAssignedXids machinery isn't up yet, there's nothing
4447 * more to do since we don't track assigned xids yet.
4448 */
4450 {
4451 latestObservedXid = xid;
4452 return;
4453 }
4454
4455 /*
4456 * Add (latestObservedXid, xid] onto the KnownAssignedXids array.
4457 */
4458 next_expected_xid = latestObservedXid;
4459 TransactionIdAdvance(next_expected_xid);
4460 KnownAssignedXidsAdd(next_expected_xid, xid, false);
4461
4462 /*
4463 * Now we can advance latestObservedXid
4464 */
4465 latestObservedXid = xid;
4466
4467 /* TransamVariables->nextXid must be beyond any observed xid */
4469 }
4470}
#define DEBUG4
Definition elog.h:27

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

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

◆ SignalRecoveryConflict()

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

Definition at line 3454 of file procarray.c.

3455{
3456 bool found = false;
3457
3458 LWLockAcquire(ProcArrayLock, LW_SHARED);
3459
3460 /*
3461 * Kill the pid if it's still here. If not, that's what we wanted so
3462 * ignore any errors.
3463 */
3464 if (proc->pid == pid)
3465 {
3466 (void) pg_atomic_fetch_or_u32(&proc->pendingRecoveryConflicts, (1 << reason));
3467
3468 /* wake up the process */
3470 found = true;
3471 }
3472
3473 LWLockRelease(ProcArrayLock);
3474
3475 return found;
3476}
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:287
@ PROCSIG_RECOVERY_CONFLICT
Definition procsignal.h:39
pg_atomic_uint32 pendingRecoveryConflicts
Definition proc.h:267

References 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 3529 of file procarray.c.

3530{
3531 ProcArrayStruct *arrayP = procArray;
3532 int index;
3533
3534 /* tell all backends to die */
3535 LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3536
3537 for (index = 0; index < arrayP->numProcs; index++)
3538 {
3539 int pgprocno = arrayP->pgprocnos[index];
3540 PGPROC *proc = &allProcs[pgprocno];
3541
3542 if (databaseid == InvalidOid || proc->databaseId == databaseid)
3543 {
3544 VirtualTransactionId procvxid;
3545 pid_t pid;
3546
3547 GET_VXID_FROM_PGPROC(procvxid, *proc);
3548
3549 pid = proc->pid;
3550 if (pid != 0)
3551 {
3552 (void) pg_atomic_fetch_or_u32(&proc->pendingRecoveryConflicts, (1 << reason));
3553
3554 /*
3555 * Kill the pid if it's still here. If not, that's what we
3556 * wanted so ignore any errors.
3557 */
3559 }
3560 }
3561 }
3562
3563 LWLockRelease(ProcArrayLock);
3564}
#define InvalidOid

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

Referenced by ResolveRecoveryConflictWithDatabase(), and SendRecoveryConflictWithBufferPin().

◆ SignalRecoveryConflictWithVirtualXID()

bool SignalRecoveryConflictWithVirtualXID ( VirtualTransactionId  vxid,
RecoveryConflictReason  reason 
)
extern

Definition at line 3484 of file procarray.c.

3485{
3486 ProcArrayStruct *arrayP = procArray;
3487 int index;
3488 pid_t pid = 0;
3489
3490 LWLockAcquire(ProcArrayLock, LW_SHARED);
3491
3492 for (index = 0; index < arrayP->numProcs; index++)
3493 {
3494 int pgprocno = arrayP->pgprocnos[index];
3495 PGPROC *proc = &allProcs[pgprocno];
3496 VirtualTransactionId procvxid;
3497
3498 GET_VXID_FROM_PGPROC(procvxid, *proc);
3499
3500 if (procvxid.procNumber == vxid.procNumber &&
3501 procvxid.localTransactionId == vxid.localTransactionId)
3502 {
3503 pid = proc->pid;
3504 if (pid != 0)
3505 {
3506 (void) pg_atomic_fetch_or_u32(&proc->pendingRecoveryConflicts, (1 << reason));
3507
3508 /*
3509 * Kill the pid if it's still here. If not, that's what we
3510 * wanted so ignore any errors.
3511 */
3513 }
3514 break;
3515 }
3516 }
3517
3518 LWLockRelease(ProcArrayLock);
3519
3520 return pid != 0;
3521}

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

Referenced by ResolveRecoveryConflictWithLock(), and ResolveRecoveryConflictWithVirtualXIDs().

◆ TerminateOtherDBBackends()

void TerminateOtherDBBackends ( Oid  databaseId)
extern

Definition at line 3835 of file procarray.c.

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

Referenced by dropdb().

◆ TransactionIdIsInProgress()

bool TransactionIdIsInProgress ( TransactionId  xid)
extern

Definition at line 1401 of file procarray.c.

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

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

Referenced by check_safe_enum_use(), compute_new_xmax_infomask(), ConditionalXactLockTableWait(), Do_MultiXactIdWait(), DoesMultiXactIdConflict(), FreezeMultiXactId(), get_xid_status(), HandleConcurrentAbort(), 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 3998 of file procarray.c.

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

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

Referenced by RecordTransactionAbort().