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

Go to the source code of this file.

Functions

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

Function Documentation

◆ BackendPidGetProc()

PGPROC * BackendPidGetProc ( int  pid)

Definition at line 3159 of file procarray.c.

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

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

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

◆ BackendPidGetProcWithLock()

PGPROC * BackendPidGetProcWithLock ( int  pid)

Definition at line 3182 of file procarray.c.

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

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

Referenced by BackendPidGetProc(), and GetBlockerStatusData().

◆ BackendXidGetPid()

int BackendXidGetPid ( TransactionId  xid)

Definition at line 3219 of file procarray.c.

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

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

Referenced by pgrowlocks().

◆ CancelDBBackends()

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

Definition at line 3621 of file procarray.c.

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

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

Referenced by ResolveRecoveryConflictWithDatabase(), and SendRecoveryConflictWithBufferPin().

◆ CancelVirtualTransaction()

pid_t CancelVirtualTransaction ( VirtualTransactionId  vxid,
ProcSignalReason  sigmode 
)

Definition at line 3453 of file procarray.c.

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

References SignalVirtualTransaction().

Referenced by ResolveRecoveryConflictWithVirtualXIDs().

◆ CountDBBackends()

int CountDBBackends ( Oid  databaseid)

Definition at line 3561 of file procarray.c.

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

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

Referenced by ResolveRecoveryConflictWithDatabase().

◆ CountDBConnections()

int CountDBConnections ( Oid  databaseid)

Definition at line 3590 of file procarray.c.

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

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

Referenced by CheckMyDatabase().

◆ CountOtherDBBackends()

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

Definition at line 3714 of file procarray.c.

3715{
3716 ProcArrayStruct *arrayP = procArray;
3717
3718#define MAXAUTOVACPIDS 10 /* max autovacs to SIGTERM per iteration */
3719 int autovac_pids[MAXAUTOVACPIDS];
3720
3721 /*
3722 * Retry up to 50 times with 100ms between attempts (max 5s total). Can be
3723 * reduced to 3 attempts (max 0.3s total) to speed up tests.
3724 */
3725 int ntries = 50;
3726
3727#ifdef USE_INJECTION_POINTS
3728 if (IS_INJECTION_POINT_ATTACHED("procarray-reduce-count"))
3729 ntries = 3;
3730#endif
3731
3732 for (int tries = 0; tries < ntries; tries++)
3733 {
3734 int nautovacs = 0;
3735 bool found = false;
3736 int index;
3737
3739
3740 *nbackends = *nprepared = 0;
3741
3742 LWLockAcquire(ProcArrayLock, LW_SHARED);
3743
3744 for (index = 0; index < arrayP->numProcs; index++)
3745 {
3746 int pgprocno = arrayP->pgprocnos[index];
3747 PGPROC *proc = &allProcs[pgprocno];
3748 uint8 statusFlags = ProcGlobal->statusFlags[index];
3749
3750 if (proc->databaseId != databaseId)
3751 continue;
3752 if (proc == MyProc)
3753 continue;
3754
3755 found = true;
3756
3757 if (proc->pid == 0)
3758 (*nprepared)++;
3759 else
3760 {
3761 (*nbackends)++;
3762 if ((statusFlags & PROC_IS_AUTOVACUUM) &&
3763 nautovacs < MAXAUTOVACPIDS)
3764 autovac_pids[nautovacs++] = proc->pid;
3765 }
3766 }
3767
3768 LWLockRelease(ProcArrayLock);
3769
3770 if (!found)
3771 return false; /* no conflicting backends, so done */
3772
3773 /*
3774 * Send SIGTERM to any conflicting autovacuums before sleeping. We
3775 * postpone this step until after the loop because we don't want to
3776 * hold ProcArrayLock while issuing kill(). We have no idea what might
3777 * block kill() inside the kernel...
3778 */
3779 for (index = 0; index < nautovacs; index++)
3780 (void) kill(autovac_pids[index], SIGTERM); /* ignore any error */
3781
3782 /*
3783 * Terminate all background workers for this database, if they have
3784 * requested it (BGWORKER_INTERRUPTIBLE).
3785 */
3787
3788 /* sleep, then try again */
3789 pg_usleep(100 * 1000L); /* 100ms */
3790 }
3791
3792 return true; /* timed out, still conflicts */
3793}
void TerminateBackgroundWorkersForDatabase(Oid databaseId)
Definition: bgworker.c:1420
uint8_t uint8
Definition: c.h:550
#define IS_INJECTION_POINT_ATTACHED(name)
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:123
#define PROC_IS_AUTOVACUUM
Definition: proc.h:57
#define MAXAUTOVACPIDS
void pg_usleep(long microsec)
Definition: signal.c:53
PGPROC * MyProc
Definition: proc.c:67
uint8 * statusFlags
Definition: proc.h:403
#define kill(pid, sig)
Definition: win32_port.h: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)

Definition at line 3662 of file procarray.c.

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

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

Referenced by InitializeSessionUserId().

◆ ExpireAllKnownAssignedTransactionIds()

void ExpireAllKnownAssignedTransactionIds ( void  )

Definition at line 4477 of file procarray.c.

4478{
4479 FullTransactionId latestXid;
4480
4481 LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
4483
4484 /* Reset latestCompletedXid to nextXid - 1 */
4486 latestXid = TransamVariables->nextXid;
4487 FullTransactionIdRetreat(&latestXid);
4489
4490 /*
4491 * Any transactions that were in-progress were effectively aborted, so
4492 * advance xactCompletionCount.
4493 */
4495
4496 /*
4497 * Reset lastOverflowedXid. Currently, lastOverflowedXid has no use after
4498 * the call of this function. But do this for unification with what
4499 * ExpireOldKnownAssignedTransactionIds() do.
4500 */
4502 LWLockRelease(ProcArrayLock);
4503}
Assert(PointerIsAligned(start, uint64))
static void KnownAssignedXidsRemovePreceding(TransactionId removeXid)
Definition: procarray.c:5014
TransactionId lastOverflowedXid
Definition: procarray.c:93
FullTransactionId latestCompletedXid
Definition: transam.h:238
FullTransactionId nextXid
Definition: transam.h:220
uint64 xactCompletionCount
Definition: transam.h:248
static void FullTransactionIdRetreat(FullTransactionId *dest)
Definition: transam.h:103
#define FullTransactionIdIsValid(x)
Definition: transam.h:55
TransamVariablesData * TransamVariables
Definition: varsup.c:34

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

Referenced by ShutdownRecoveryTransactionEnvironment().

◆ ExpireOldKnownAssignedTransactionIds()

void ExpireOldKnownAssignedTransactionIds ( TransactionId  xid)

Definition at line 4511 of file procarray.c.

4512{
4513 TransactionId latestXid;
4514
4515 LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
4516
4517 /* As in ProcArrayEndTransaction, advance latestCompletedXid */
4518 latestXid = xid;
4519 TransactionIdRetreat(latestXid);
4521
4522 /* ... and xactCompletionCount */
4524
4525 /*
4526 * Reset lastOverflowedXid if we know all transactions that have been
4527 * possibly running are being gone. Not doing so could cause an incorrect
4528 * lastOverflowedXid value, which makes extra snapshots be marked as
4529 * suboverflowed.
4530 */
4534 LWLockRelease(ProcArrayLock);
4535}
static void MaintainLatestCompletedXidRecovery(TransactionId latestXid)
Definition: procarray.c:991
#define TransactionIdRetreat(dest)
Definition: transam.h:141
static bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.h:263

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

Referenced by ProcArrayApplyRecoveryInfo().

◆ ExpireTreeKnownAssignedTransactionIds()

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

Definition at line 4451 of file procarray.c.

4453{
4455
4456 /*
4457 * Uses same locking as transaction commit
4458 */
4459 LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
4460
4461 KnownAssignedXidsRemoveTree(xid, nsubxids, subxids);
4462
4463 /* As in ProcArrayEndTransaction, advance latestCompletedXid */
4465
4466 /* ... and xactCompletionCount */
4468
4469 LWLockRelease(ProcArrayLock);
4470}
static void KnownAssignedXidsRemoveTree(TransactionId xid, int nsubxids, TransactionId *subxids)
Definition: procarray.c:4992
HotStandbyState standbyState
Definition: xlogutils.c:53
@ STANDBY_INITIALIZED
Definition: xlogutils.h:53

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

Referenced by xact_redo_abort(), and xact_redo_commit().

◆ GetConflictingVirtualXIDs()

VirtualTransactionId * GetConflictingVirtualXIDs ( TransactionId  limitXmin,
Oid  dbOid 
)

Definition at line 3379 of file procarray.c.

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

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

Referenced by ResolveRecoveryConflictWithSnapshot(), and ResolveRecoveryConflictWithTablespace().

◆ GetCurrentVirtualXIDs()

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

Definition at line 3287 of file procarray.c.

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

Definition at line 2030 of file procarray.c.

2031{
2033}
#define TOTAL_MAX_CACHED_SUBXIDS

References TOTAL_MAX_CACHED_SUBXIDS.

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

◆ GetMaxSnapshotXidCount()

int GetMaxSnapshotXidCount ( void  )

Definition at line 2019 of file procarray.c.

2020{
2021 return procArray->maxProcs;
2022}

References ProcArrayStruct::maxProcs, and procArray.

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

◆ GetOldestActiveTransactionId()

TransactionId GetOldestActiveTransactionId ( bool  inCommitOnly,
bool  allDbs 
)

Definition at line 2835 of file procarray.c.

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

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

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

◆ GetOldestNonRemovableTransactionId()

TransactionId GetOldestNonRemovableTransactionId ( Relation  rel)

Definition at line 1955 of file procarray.c.

1956{
1957 ComputeXidHorizonsResult horizons;
1958
1959 ComputeXidHorizons(&horizons);
1960
1961 switch (GlobalVisHorizonKindForRel(rel))
1962 {
1963 case VISHORIZON_SHARED:
1964 return horizons.shared_oldest_nonremovable;
1965 case VISHORIZON_CATALOG:
1966 return horizons.catalog_oldest_nonremovable;
1967 case VISHORIZON_DATA:
1968 return horizons.data_oldest_nonremovable;
1969 case VISHORIZON_TEMP:
1970 return horizons.temp_oldest_nonremovable;
1971 }
1972
1973 /* just to prevent compiler warnings */
1974 return InvalidTransactionId;
1975}
static void ComputeXidHorizons(ComputeXidHorizonsResult *h)
Definition: procarray.c:1685
@ VISHORIZON_SHARED
Definition: procarray.c:253
@ VISHORIZON_DATA
Definition: procarray.c:255
@ VISHORIZON_CATALOG
Definition: procarray.c:254
@ VISHORIZON_TEMP
Definition: procarray.c:256
static GlobalVisHorizonKind GlobalVisHorizonKindForRel(Relation rel)
Definition: procarray.c:1921
TransactionId data_oldest_nonremovable
Definition: procarray.c:239
TransactionId temp_oldest_nonremovable
Definition: procarray.c:245
TransactionId shared_oldest_nonremovable
Definition: procarray.c:216
TransactionId catalog_oldest_nonremovable
Definition: procarray.c:233

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

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

◆ GetOldestSafeDecodingTransactionId()

TransactionId GetOldestSafeDecodingTransactionId ( bool  catalogOnly)

Definition at line 2909 of file procarray.c.

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

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

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

◆ GetOldestTransactionIdConsideredRunning()

TransactionId GetOldestTransactionIdConsideredRunning ( void  )

Definition at line 1984 of file procarray.c.

1985{
1986 ComputeXidHorizonsResult horizons;
1987
1988 ComputeXidHorizons(&horizons);
1989
1990 return horizons.oldest_considered_running;
1991}
TransactionId oldest_considered_running
Definition: procarray.c:207

References ComputeXidHorizons(), and ComputeXidHorizonsResult::oldest_considered_running.

Referenced by CreateCheckPoint(), and CreateRestartPoint().

◆ GetReplicationHorizons()

void GetReplicationHorizons ( TransactionId xmin,
TransactionId catalog_xmin 
)

Definition at line 1997 of file procarray.c.

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

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

Referenced by XLogWalRcvSendHSFeedback().

◆ GetRunningTransactionData()

RunningTransactions GetRunningTransactionData ( void  )

Definition at line 2639 of file procarray.c.

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

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

Referenced by GetStrictOldestNonRemovableTransactionId(), and LogStandbySnapshot().

◆ GetSnapshotData()

Snapshot GetSnapshotData ( Snapshot  snapshot)

Definition at line 2125 of file procarray.c.

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

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

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

◆ GetVirtualXIDsDelayingChkpt()

VirtualTransactionId * GetVirtualXIDsDelayingChkpt ( int *  nvxids,
int  type 
)

Definition at line 3007 of file procarray.c.

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

Definition at line 3052 of file procarray.c.

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

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

Referenced by CreateCheckPoint().

◆ IsBackendPid()

bool IsBackendPid ( int  pid)

Definition at line 3254 of file procarray.c.

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

References BackendPidGetProc().

Referenced by pg_stat_get_subscription().

◆ KnownAssignedTransactionIdsIdleMaintenance()

void KnownAssignedTransactionIdsIdleMaintenance ( void  )

Definition at line 4543 of file procarray.c.

4544{
4546}
@ KAX_STARTUP_PROCESS_IDLE
Definition: procarray.c:267
static void KnownAssignedXidsCompress(KAXCompressReason reason, bool haveLock)
Definition: procarray.c:4644

References KAX_STARTUP_PROCESS_IDLE, and KnownAssignedXidsCompress().

Referenced by WaitForWALToBecomeAvailable().

◆ MinimumActiveBackends()

bool MinimumActiveBackends ( int  min)

Definition at line 3508 of file procarray.c.

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

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

Referenced by XLogFlush().

◆ ProcArrayAdd()

void ProcArrayAdd ( PGPROC proc)

Definition at line 470 of file procarray.c.

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

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

Referenced by InitProcessPhase2(), and MarkAsPrepared().

◆ ProcArrayApplyRecoveryInfo()

void ProcArrayApplyRecoveryInfo ( RunningTransactions  running)

Definition at line 1056 of file procarray.c.

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

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

Definition at line 1320 of file procarray.c.

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

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

Referenced by xact_redo().

◆ ProcArrayClearTransaction()

void ProcArrayClearTransaction ( PGPROC proc)

Definition at line 909 of file procarray.c.

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

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

Referenced by PrepareTransaction().

◆ ProcArrayEndTransaction()

void ProcArrayEndTransaction ( PGPROC proc,
TransactionId  latestXid 
)

Definition at line 669 of file procarray.c.

670{
671 if (TransactionIdIsValid(latestXid))
672 {
673 /*
674 * We must lock ProcArrayLock while clearing our advertised XID, so
675 * that we do not exit the set of "running" transactions while someone
676 * else is taking a snapshot. See discussion in
677 * src/backend/access/transam/README.
678 */
680
681 /*
682 * If we can immediately acquire ProcArrayLock, we clear our own XID
683 * and release the lock. If not, use group XID clearing to improve
684 * efficiency.
685 */
686 if (LWLockConditionalAcquire(ProcArrayLock, LW_EXCLUSIVE))
687 {
688 ProcArrayEndTransactionInternal(proc, latestXid);
689 LWLockRelease(ProcArrayLock);
690 }
691 else
692 ProcArrayGroupClearXid(proc, latestXid);
693 }
694 else
695 {
696 /*
697 * If we have no XID, we don't need to lock, since we won't affect
698 * anyone else's calculation of a snapshot. We might change their
699 * estimate of global xmin, but that's OK.
700 */
702 Assert(proc->subxidStatus.count == 0);
704
707
708 /* be sure this is cleared in abort */
709 proc->delayChkptFlags = 0;
710
711 proc->recoveryConflictPending = false;
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:1349
static void ProcArrayEndTransactionInternal(PGPROC *proc, TransactionId latestXid)
Definition: procarray.c:733
static void ProcArrayGroupClearXid(PGPROC *proc, TransactionId latestXid)
Definition: procarray.c:794

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

Referenced by AbortTransaction(), and CommitTransaction().

◆ ProcArrayGetReplicationSlotXmin()

void ProcArrayGetReplicationSlotXmin ( TransactionId xmin,
TransactionId catalog_xmin 
)

Definition at line 3947 of file procarray.c.

3949{
3950 LWLockAcquire(ProcArrayLock, LW_SHARED);
3951
3952 if (xmin != NULL)
3954
3955 if (catalog_xmin != NULL)
3957
3958 LWLockRelease(ProcArrayLock);
3959}

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

Referenced by logical_begin_heap_rewrite().

◆ ProcArrayInitRecovery()

void ProcArrayInitRecovery ( TransactionId  initializedUptoXID)

Definition at line 1025 of file procarray.c.

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

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

Referenced by StartupXLOG().

◆ ProcArrayInstallImportedXmin()

bool ProcArrayInstallImportedXmin ( TransactionId  xmin,
VirtualTransactionId sourcevxid 
)

Definition at line 2482 of file procarray.c.

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

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

Referenced by GetSerializableTransactionSnapshotInt(), and SetTransactionSnapshot().

◆ ProcArrayInstallRestoredXmin()

bool ProcArrayInstallRestoredXmin ( TransactionId  xmin,
PGPROC proc 
)

Definition at line 2566 of file procarray.c.

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

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

Referenced by SetTransactionSnapshot().

◆ ProcArrayRemove()

void ProcArrayRemove ( PGPROC proc,
TransactionId  latestXid 
)

Definition at line 567 of file procarray.c.

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

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

Referenced by FinishPreparedTransaction(), and RemoveProcFromArray().

◆ ProcArraySetReplicationSlotXmin()

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

Definition at line 3922 of file procarray.c.

3924{
3925 Assert(!already_locked || LWLockHeldByMe(ProcArrayLock));
3926
3927 if (!already_locked)
3928 LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3929
3932
3933 if (!already_locked)
3934 LWLockRelease(ProcArrayLock);
3935
3936 elog(DEBUG1, "xmin required by slots: data %u, catalog %u",
3937 xmin, catalog_xmin);
3938}

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

Referenced by ReplicationSlotsComputeRequiredXmin().

◆ ProcArrayShmemInit()

void ProcArrayShmemInit ( void  )

Definition at line 420 of file procarray.c.

421{
422 bool found;
423
424 /* Create or attach to the ProcArray shared structure */
426 ShmemInitStruct("Proc Array",
427 add_size(offsetof(ProcArrayStruct, pgprocnos),
428 mul_size(sizeof(int),
430 &found);
431
432 if (!found)
433 {
434 /*
435 * We're the first - initialize.
436 */
437 procArray->numProcs = 0;
447 }
448
450
451 /* Create or attach to the KnownAssignedXids arrays too, if needed */
453 {
455 ShmemInitStruct("KnownAssignedXids",
456 mul_size(sizeof(TransactionId),
458 &found);
459 KnownAssignedXidsValid = (bool *)
460 ShmemInitStruct("KnownAssignedXidsValid",
461 mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS),
462 &found);
463 }
464}
#define PROCARRAY_MAXPROCS
static TransactionId * KnownAssignedXids
Definition: procarray.c:283
static bool * KnownAssignedXidsValid
Definition: procarray.c:284
Size add_size(Size s1, Size s2)
Definition: shmem.c:495
Size mul_size(Size s1, Size s2)
Definition: shmem.c:510
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition: shmem.c:389
int maxKnownAssignedXids
Definition: procarray.c:81
int tailKnownAssignedXids
Definition: procarray.c:83
int headKnownAssignedXids
Definition: procarray.c:84
bool EnableHotStandby
Definition: xlog.c:124

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

Referenced by CreateOrAttachShmemStructs().

◆ ProcArrayShmemSize()

Size ProcArrayShmemSize ( void  )

Definition at line 378 of file procarray.c.

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

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

Referenced by CalculateShmemSize().

◆ ProcNumberGetProc()

PGPROC * ProcNumberGetProc ( int  procNumber)

Definition at line 3101 of file procarray.c.

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

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

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

◆ ProcNumberGetTransactionIds()

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

Definition at line 3123 of file procarray.c.

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

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

Referenced by pgstat_read_current_status().

◆ RecordKnownAssignedTransactionIds()

void RecordKnownAssignedTransactionIds ( TransactionId  xid)

Definition at line 4382 of file procarray.c.

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

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

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

◆ SignalVirtualTransaction()

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

Definition at line 3459 of file procarray.c.

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

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

Referenced by CancelVirtualTransaction(), and ResolveRecoveryConflictWithLock().

◆ TerminateOtherDBBackends()

void TerminateOtherDBBackends ( Oid  databaseId)

Definition at line 3807 of file procarray.c.

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

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

Referenced by dropdb().

◆ TransactionIdIsInProgress()

bool TransactionIdIsInProgress ( TransactionId  xid)

Definition at line 1404 of file procarray.c.

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

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

Referenced by check_safe_enum_use(), compute_new_xmax_infomask(), ConditionalXactLockTableWait(), Do_MultiXactIdWait(), DoesMultiXactIdConflict(), FreezeMultiXactId(), get_xid_status(), HandleConcurrentAbort(), 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 
)

Definition at line 3970 of file procarray.c.

3973{
3974 int i,
3975 j;
3976 XidCacheStatus *mysubxidstat;
3977
3979
3980 /*
3981 * We must hold ProcArrayLock exclusively in order to remove transactions
3982 * from the PGPROC array. (See src/backend/access/transam/README.) It's
3983 * possible this could be relaxed since we know this routine is only used
3984 * to abort subtransactions, but pending closer analysis we'd best be
3985 * conservative.
3986 *
3987 * Note that we do not have to be careful about memory ordering of our own
3988 * reads wrt. GetNewTransactionId() here - only this process can modify
3989 * relevant fields of MyProc/ProcGlobal->xids[]. But we do have to be
3990 * careful about our own writes being well ordered.
3991 */
3992 LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3993
3994 mysubxidstat = &ProcGlobal->subxidStates[MyProc->pgxactoff];
3995
3996 /*
3997 * Under normal circumstances xid and xids[] will be in increasing order,
3998 * as will be the entries in subxids. Scan backwards to avoid O(N^2)
3999 * behavior when removing a lot of xids.
4000 */
4001 for (i = nxids - 1; i >= 0; i--)
4002 {
4003 TransactionId anxid = xids[i];
4004
4005 for (j = MyProc->subxidStatus.count - 1; j >= 0; j--)
4006 {
4007 if (TransactionIdEquals(MyProc->subxids.xids[j], anxid))
4008 {
4011 mysubxidstat->count--;
4013 break;
4014 }
4015 }
4016
4017 /*
4018 * Ordinarily we should have found it, unless the cache has
4019 * overflowed. However it's also possible for this routine to be
4020 * invoked multiple times for the same subtransaction, in case of an
4021 * error during AbortSubTransaction. So instead of Assert, emit a
4022 * debug warning.
4023 */
4024 if (j < 0 && !MyProc->subxidStatus.overflowed)
4025 elog(WARNING, "did not find subXID %u in MyProc", anxid);
4026 }
4027
4028 for (j = MyProc->subxidStatus.count - 1; j >= 0; j--)
4029 {
4031 {
4034 mysubxidstat->count--;
4036 break;
4037 }
4038 }
4039 /* Ordinarily we should have found it, unless the cache has overflowed */
4040 if (j < 0 && !MyProc->subxidStatus.overflowed)
4041 elog(WARNING, "did not find subXID %u in MyProc", xid);
4042
4043 /* Also advance global latestCompletedXid while holding the lock */
4044 MaintainLatestCompletedXid(latestXid);
4045
4046 /* ... and xactCompletionCount */
4048
4049 LWLockRelease(ProcArrayLock);
4050}
#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().