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

Go to the source code of this file.

Functions

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

Function Documentation

◆ BackendPidGetProc()

PGPROC * BackendPidGetProc ( int  pid)
extern

Definition at line 3154 of file procarray.c.

3155{
3156 PGPROC *result;
3157
3158 if (pid == 0) /* never match dummy PGPROCs */
3159 return NULL;
3160
3162
3163 result = BackendPidGetProcWithLock(pid);
3164
3166
3167 return result;
3168}
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition lwlock.c:1176
void LWLockRelease(LWLock *lock)
Definition lwlock.c:1793
@ LW_SHARED
Definition lwlock.h:113
static int fb(int x)
PGPROC * BackendPidGetProcWithLock(int pid)
Definition procarray.c:3177
Definition proc.h:180

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

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

◆ BackendPidGetProcWithLock()

PGPROC * BackendPidGetProcWithLock ( int  pid)
extern

Definition at line 3177 of file procarray.c.

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

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

Referenced by BackendPidGetProc(), and GetBlockerStatusData().

◆ BackendXidGetPid()

int BackendXidGetPid ( TransactionId  xid)
extern

Definition at line 3214 of file procarray.c.

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

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

Referenced by pgrowlocks().

◆ CancelDBBackends()

void CancelDBBackends ( Oid  databaseid,
ProcSignalReason  sigmode 
)
extern

Definition at line 3608 of file procarray.c.

3609{
3611 int index;
3612
3613 /* tell all backends to die */
3615
3616 for (index = 0; index < arrayP->numProcs; index++)
3617 {
3618 int pgprocno = arrayP->pgprocnos[index];
3619 PGPROC *proc = &allProcs[pgprocno];
3620
3621 if (databaseid == InvalidOid || proc->databaseId == databaseid)
3622 {
3624 pid_t pid;
3625
3627
3628 pid = proc->pid;
3629 if (pid != 0)
3630 {
3631 /*
3632 * Kill the pid if it's still here. If not, that's what we
3633 * wanted so ignore any errors.
3634 */
3635 (void) SendProcSignal(pid, sigmode, procvxid.procNumber);
3636 }
3637 }
3638 }
3639
3641}
#define GET_VXID_FROM_PGPROC(vxid_dst, proc)
Definition lock.h:79
@ LW_EXCLUSIVE
Definition lwlock.h:112
#define InvalidOid
int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber)
Definition procsignal.c:284
Oid databaseId
Definition proc.h:225

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

Referenced by ResolveRecoveryConflictWithDatabase(), and SendRecoveryConflictWithBufferPin().

◆ CountDBBackends()

int CountDBBackends ( Oid  databaseid)
extern

Definition at line 3548 of file procarray.c.

3549{
3551 int count = 0;
3552 int index;
3553
3555
3556 for (index = 0; index < arrayP->numProcs; index++)
3557 {
3558 int pgprocno = arrayP->pgprocnos[index];
3559 PGPROC *proc = &allProcs[pgprocno];
3560
3561 if (proc->pid == 0)
3562 continue; /* do not count prepared xacts */
3563 if (!OidIsValid(databaseid) ||
3564 proc->databaseId == databaseid)
3565 count++;
3566 }
3567
3569
3570 return count;
3571}
#define OidIsValid(objectId)
Definition c.h:788

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

Referenced by ResolveRecoveryConflictWithDatabase().

◆ CountDBConnections()

int CountDBConnections ( Oid  databaseid)
extern

Definition at line 3577 of file procarray.c.

3578{
3580 int count = 0;
3581 int index;
3582
3584
3585 for (index = 0; index < arrayP->numProcs; index++)
3586 {
3587 int pgprocno = arrayP->pgprocnos[index];
3588 PGPROC *proc = &allProcs[pgprocno];
3589
3590 if (proc->pid == 0)
3591 continue; /* do not count prepared xacts */
3592 if (proc->backendType != B_BACKEND)
3593 continue; /* count only regular backend processes */
3594 if (!OidIsValid(databaseid) ||
3595 proc->databaseId == databaseid)
3596 count++;
3597 }
3598
3600
3601 return count;
3602}
@ B_BACKEND
Definition miscadmin.h:342
BackendType backendType
Definition proc.h:231

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

Referenced by CheckMyDatabase().

◆ CountOtherDBBackends()

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

Definition at line 3700 of file procarray.c.

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

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

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

◆ CountUserBackends()

int CountUserBackends ( Oid  roleid)
extern

Definition at line 3648 of file procarray.c.

3649{
3651 int count = 0;
3652 int index;
3653
3655
3656 for (index = 0; index < arrayP->numProcs; index++)
3657 {
3658 int pgprocno = arrayP->pgprocnos[index];
3659 PGPROC *proc = &allProcs[pgprocno];
3660
3661 if (proc->pid == 0)
3662 continue; /* do not count prepared xacts */
3663 if (proc->backendType != B_BACKEND)
3664 continue; /* count only regular backend processes */
3665 if (proc->roleId == roleid)
3666 count++;
3667 }
3668
3670
3671 return count;
3672}
Oid roleId
Definition proc.h:226

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

Referenced by InitializeSessionUserId().

◆ ExpireAllKnownAssignedTransactionIds()

void ExpireAllKnownAssignedTransactionIds ( void  )
extern

Definition at line 4463 of file procarray.c.

4464{
4466
4469
4470 /* Reset latestCompletedXid to nextXid - 1 */
4475
4476 /*
4477 * Any transactions that were in-progress were effectively aborted, so
4478 * advance xactCompletionCount.
4479 */
4481
4482 /*
4483 * Reset lastOverflowedXid. Currently, lastOverflowedXid has no use after
4484 * the call of this function. But do this for unification with what
4485 * ExpireOldKnownAssignedTransactionIds() do.
4486 */
4489}
#define Assert(condition)
Definition c.h:873
static void KnownAssignedXidsRemovePreceding(TransactionId removeXid)
Definition procarray.c:5000
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, fb(), FullTransactionIdIsValid, FullTransactionIdRetreat(), InvalidTransactionId, KnownAssignedXidsRemovePreceding(), ProcArrayStruct::lastOverflowedXid, TransamVariablesData::latestCompletedXid, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), TransamVariablesData::nextXid, procArray, TransamVariables, and TransamVariablesData::xactCompletionCount.

Referenced by ShutdownRecoveryTransactionEnvironment().

◆ ExpireOldKnownAssignedTransactionIds()

void ExpireOldKnownAssignedTransactionIds ( TransactionId  xid)
extern

Definition at line 4497 of file procarray.c.

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

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

Referenced by ProcArrayApplyRecoveryInfo().

◆ ExpireTreeKnownAssignedTransactionIds()

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

Definition at line 4437 of file procarray.c.

4439{
4441
4442 /*
4443 * Uses same locking as transaction commit
4444 */
4446
4448
4449 /* As in ProcArrayEndTransaction, advance latestCompletedXid */
4451
4452 /* ... and xactCompletionCount */
4454
4456}
static void KnownAssignedXidsRemoveTree(TransactionId xid, int nsubxids, TransactionId *subxids)
Definition procarray.c:4978
HotStandbyState standbyState
Definition xlogutils.c:53
@ STANDBY_INITIALIZED
Definition xlogutils.h:53

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

Referenced by xact_redo_abort(), and xact_redo_commit().

◆ GetConflictingVirtualXIDs()

VirtualTransactionId * GetConflictingVirtualXIDs ( TransactionId  limitXmin,
Oid  dbOid 
)
extern

Definition at line 3374 of file procarray.c.

3375{
3378 int count = 0;
3379 int index;
3380
3381 /*
3382 * If first time through, get workspace to remember main XIDs in. We
3383 * malloc it permanently to avoid repeated palloc/pfree overhead. Allow
3384 * result space, remembering room for a terminator.
3385 */
3386 if (vxids == NULL)
3387 {
3389 malloc(sizeof(VirtualTransactionId) * (arrayP->maxProcs + 1));
3390 if (vxids == NULL)
3391 ereport(ERROR,
3393 errmsg("out of memory")));
3394 }
3395
3397
3398 for (index = 0; index < arrayP->numProcs; index++)
3399 {
3400 int pgprocno = arrayP->pgprocnos[index];
3401 PGPROC *proc = &allProcs[pgprocno];
3402
3403 /* Exclude prepared transactions */
3404 if (proc->pid == 0)
3405 continue;
3406
3407 if (!OidIsValid(dbOid) ||
3408 proc->databaseId == dbOid)
3409 {
3410 /* Fetch xmin just once - can't change on us, but good coding */
3412
3413 /*
3414 * We ignore an invalid pxmin because this means that backend has
3415 * no snapshot currently. We hold a Share lock to avoid contention
3416 * with users taking snapshots. That is not a problem because the
3417 * current xmin is always at least one higher than the latest
3418 * removed xid, so any new snapshot would never conflict with the
3419 * test here.
3420 */
3423 {
3425
3426 GET_VXID_FROM_PGPROC(vxid, *proc);
3428 vxids[count++] = vxid;
3429 }
3430 }
3431 }
3432
3434
3435 /* add the terminator */
3436 vxids[count].procNumber = INVALID_PROC_NUMBER;
3437 vxids[count].localTransactionId = InvalidLocalTransactionId;
3438
3439 return vxids;
3440}
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:195
static bool TransactionIdFollows(TransactionId id1, TransactionId id2)
Definition transam.h:297
#define TransactionIdIsValid(xid)
Definition transam.h:41

References allProcs, PGPROC::databaseId, ereport, errcode(), errmsg(), ERROR, fb(), GET_VXID_FROM_PGPROC, INVALID_PROC_NUMBER, InvalidLocalTransactionId, LW_SHARED, LWLockAcquire(), LWLockRelease(), malloc, OidIsValid, PGPROC::pid, procArray, TransactionIdFollows(), TransactionIdIsValid, UINT32_ACCESS_ONCE, VirtualTransactionIdIsValid, and PGPROC::xmin.

Referenced by ResolveRecoveryConflictWithSnapshot(), and ResolveRecoveryConflictWithTablespace().

◆ GetCurrentVirtualXIDs()

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

Definition at line 3282 of file procarray.c.

3285{
3288 int count = 0;
3289 int index;
3290
3291 /* allocate what's certainly enough result space */
3293
3295
3296 for (index = 0; index < arrayP->numProcs; index++)
3297 {
3298 int pgprocno = arrayP->pgprocnos[index];
3299 PGPROC *proc = &allProcs[pgprocno];
3300 uint8 statusFlags = ProcGlobal->statusFlags[index];
3301
3302 if (proc == MyProc)
3303 continue;
3304
3305 if (excludeVacuum & statusFlags)
3306 continue;
3307
3308 if (allDbs || proc->databaseId == MyDatabaseId)
3309 {
3310 /* Fetch xmin just once - might change on us */
3312
3314 continue;
3315
3316 /*
3317 * InvalidTransactionId precedes all other XIDs, so a proc that
3318 * hasn't set xmin yet will not be rejected by this test.
3319 */
3322 {
3324
3325 GET_VXID_FROM_PGPROC(vxid, *proc);
3327 vxids[count++] = vxid;
3328 }
3329 }
3330 }
3331
3333
3334 *nvxids = count;
3335 return vxids;
3336}
#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, fb(), GET_VXID_FROM_PGPROC, LW_SHARED, LWLockAcquire(), LWLockRelease(), MyDatabaseId, MyProc, palloc_array, procArray, ProcGlobal, PROC_HDR::statusFlags, TransactionIdIsValid, TransactionIdPrecedesOrEquals(), UINT32_ACCESS_ONCE, VirtualTransactionIdIsValid, and PGPROC::xmin.

Referenced by WaitForOlderSnapshots().

◆ GetMaxSnapshotSubxidCount()

int GetMaxSnapshotSubxidCount ( void  )
extern

Definition at line 2025 of file procarray.c.

2026{
2028}
#define TOTAL_MAX_CACHED_SUBXIDS

References TOTAL_MAX_CACHED_SUBXIDS.

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

◆ GetMaxSnapshotXidCount()

int GetMaxSnapshotXidCount ( void  )
extern

Definition at line 2014 of file procarray.c.

2015{
2016 return procArray->maxProcs;
2017}

References ProcArrayStruct::maxProcs, and procArray.

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

◆ GetOldestActiveTransactionId()

TransactionId GetOldestActiveTransactionId ( bool  inCommitOnly,
bool  allDbs 
)
extern

Definition at line 2830 of file procarray.c.

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

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

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

◆ GetOldestNonRemovableTransactionId()

TransactionId GetOldestNonRemovableTransactionId ( Relation  rel)
extern

Definition at line 1950 of file procarray.c.

1951{
1953
1955
1956 switch (GlobalVisHorizonKindForRel(rel))
1957 {
1958 case VISHORIZON_SHARED:
1959 return horizons.shared_oldest_nonremovable;
1960 case VISHORIZON_CATALOG:
1961 return horizons.catalog_oldest_nonremovable;
1962 case VISHORIZON_DATA:
1963 return horizons.data_oldest_nonremovable;
1964 case VISHORIZON_TEMP:
1965 return horizons.temp_oldest_nonremovable;
1966 }
1967
1968 /* just to prevent compiler warnings */
1969 return InvalidTransactionId;
1970}
static void ComputeXidHorizons(ComputeXidHorizonsResult *h)
Definition procarray.c:1680
@ 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:1916

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

Definition at line 2904 of file procarray.c.

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

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

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

◆ GetOldestTransactionIdConsideredRunning()

TransactionId GetOldestTransactionIdConsideredRunning ( void  )
extern

Definition at line 1979 of file procarray.c.

1980{
1982
1984
1985 return horizons.oldest_considered_running;
1986}

References ComputeXidHorizons(), and fb().

Referenced by CreateCheckPoint(), and CreateRestartPoint().

◆ GetReplicationHorizons()

void GetReplicationHorizons ( TransactionId xmin,
TransactionId catalog_xmin 
)
extern

Definition at line 1992 of file procarray.c.

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

References ComputeXidHorizons(), and fb().

Referenced by XLogWalRcvSendHSFeedback().

◆ GetRunningTransactionData()

RunningTransactions GetRunningTransactionData ( void  )
extern

Definition at line 2634 of file procarray.c.

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

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

Referenced by GetStrictOldestNonRemovableTransactionId(), and LogStandbySnapshot().

◆ GetSnapshotData()

Snapshot GetSnapshotData ( Snapshot  snapshot)
extern

Definition at line 2120 of file procarray.c.

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

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

◆ GetVirtualXIDsDelayingChkpt()

VirtualTransactionId * GetVirtualXIDsDelayingChkpt ( int nvxids,
int  type 
)
extern

Definition at line 3002 of file procarray.c.

3003{
3006 int count = 0;
3007 int index;
3008
3009 Assert(type != 0);
3010
3011 /* allocate what's certainly enough result space */
3013
3015
3016 for (index = 0; index < arrayP->numProcs; index++)
3017 {
3018 int pgprocno = arrayP->pgprocnos[index];
3019 PGPROC *proc = &allProcs[pgprocno];
3020
3021 if ((proc->delayChkptFlags & type) != 0)
3022 {
3024
3025 GET_VXID_FROM_PGPROC(vxid, *proc);
3027 vxids[count++] = vxid;
3028 }
3029 }
3030
3032
3033 *nvxids = count;
3034 return vxids;
3035}
const char * type

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

Referenced by CreateCheckPoint().

◆ HaveVirtualXIDsDelayingChkpt()

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

Definition at line 3047 of file procarray.c.

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

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

Referenced by CreateCheckPoint().

◆ IsBackendPid()

bool IsBackendPid ( int  pid)
extern

Definition at line 3249 of file procarray.c.

3250{
3251 return (BackendPidGetProc(pid) != NULL);
3252}
PGPROC * BackendPidGetProc(int pid)
Definition procarray.c:3154

References BackendPidGetProc(), and fb().

Referenced by pg_stat_get_subscription().

◆ KnownAssignedTransactionIdsIdleMaintenance()

void KnownAssignedTransactionIdsIdleMaintenance ( void  )
extern

Definition at line 4529 of file procarray.c.

4530{
4532}
@ KAX_STARTUP_PROCESS_IDLE
Definition procarray.c:267
static void KnownAssignedXidsCompress(KAXCompressReason reason, bool haveLock)
Definition procarray.c:4630

References KAX_STARTUP_PROCESS_IDLE, and KnownAssignedXidsCompress().

Referenced by WaitForWALToBecomeAvailable().

◆ MinimumActiveBackends()

bool MinimumActiveBackends ( int  min)
extern

Definition at line 3495 of file procarray.c.

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

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

Referenced by XLogFlush().

◆ ProcArrayAdd()

void ProcArrayAdd ( PGPROC proc)
extern

Definition at line 470 of file procarray.c.

471{
472 int pgprocno = GetNumberFromPGProc(proc);
474 int index;
475 int movecount;
476
477 /* See ProcGlobal comment explaining why both locks are held */
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 */
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
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));
520 movecount * sizeof(*ProcGlobal->xids));
523 movecount * sizeof(*ProcGlobal->subxidStates));
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 */
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, fb(), GetNumberFromPGProc, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), NUM_AUXILIARY_PROCS, PGPROC::pgxactoff, procArray, ProcGlobal, PGPROC::statusFlags, PROC_HDR::statusFlags, PROC_HDR::subxidStates, PGPROC::subxidStatus, PGPROC::xid, and PROC_HDR::xids.

Referenced by InitProcessPhase2(), and MarkAsPrepared().

◆ ProcArrayApplyRecoveryInfo()

void ProcArrayApplyRecoveryInfo ( RunningTransactions  running)
extern

Definition at line 1051 of file procarray.c.

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

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

◆ ProcArrayApplyXidAssignment()

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

Definition at line 1315 of file procarray.c.

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

Referenced by xact_redo().

◆ ProcArrayClearTransaction()

void ProcArrayClearTransaction ( PGPROC proc)
extern

Definition at line 905 of file procarray.c.

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

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

Referenced by PrepareTransaction().

◆ ProcArrayEndTransaction()

void ProcArrayEndTransaction ( PGPROC proc,
TransactionId  latestXid 
)
extern

Definition at line 669 of file procarray.c.

670{
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 */
687 {
690 }
691 else
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 /* must be cleared with xid/xmin: */
712 /* avoid unnecessarily dirtying shared cachelines */
714 {
721 }
722 }
723}
bool LWLockConditionalAcquire(LWLock *lock, LWLockMode mode)
Definition lwlock.c:1347
static void ProcArrayEndTransactionInternal(PGPROC *proc, TransactionId latestXid)
Definition procarray.c:731
static void ProcArrayGroupClearXid(PGPROC *proc, TransactionId latestXid)
Definition procarray.c:790

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

Referenced by AbortTransaction(), and CommitTransaction().

◆ ProcArrayGetReplicationSlotXmin()

void ProcArrayGetReplicationSlotXmin ( TransactionId xmin,
TransactionId catalog_xmin 
)
extern

Definition at line 3933 of file procarray.c.

3935{
3937
3938 if (xmin != NULL)
3940
3941 if (catalog_xmin != NULL)
3943
3945}

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

Referenced by logical_begin_heap_rewrite().

◆ ProcArrayInitRecovery()

void ProcArrayInitRecovery ( TransactionId  initializedUptoXID)
extern

Definition at line 1020 of file procarray.c.

1021{
1024
1025 /*
1026 * we set latestObservedXid to the xid SUBTRANS has been initialized up
1027 * to, so we can extend it from that point onwards in
1028 * RecordKnownAssignedTransactionIds, and when we get consistent in
1029 * ProcArrayApplyRecoveryInfo().
1030 */
1033}

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

Referenced by StartupXLOG().

◆ ProcArrayInstallImportedXmin()

bool ProcArrayInstallImportedXmin ( TransactionId  xmin,
VirtualTransactionId sourcevxid 
)
extern

Definition at line 2477 of file procarray.c.

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

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

Referenced by GetSerializableTransactionSnapshotInt(), and SetTransactionSnapshot().

◆ ProcArrayInstallRestoredXmin()

bool ProcArrayInstallRestoredXmin ( TransactionId  xmin,
PGPROC proc 
)
extern

Definition at line 2561 of file procarray.c.

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

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

Referenced by SetTransactionSnapshot().

◆ ProcArrayRemove()

void ProcArrayRemove ( PGPROC proc,
TransactionId  latestXid 
)
extern

Definition at line 567 of file procarray.c.

568{
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)
577#endif
578
579 /* See ProcGlobal comment explaining why both locks are held */
582
583 myoff = proc->pgxactoff;
584
585 Assert(myoff >= 0 && myoff < arrayP->numProcs);
587
589 {
591
592 /* Advance global latestCompletedXid while holding the lock */
594
595 /* Same with xactCompletionCount */
597
601 }
602 else
603 {
604 /* Shouldn't be trying to remove a live transaction here */
606 }
607
611
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));
620 &ProcGlobal->xids[myoff + 1],
621 movecount * sizeof(*ProcGlobal->xids));
624 movecount * sizeof(*ProcGlobal->subxidStates));
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 */
652}
static void MaintainLatestCompletedXid(TransactionId latestXid)
Definition procarray.c:964
PGPROC * allProcs
Definition proc.h:388

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

Referenced by FinishPreparedTransaction(), and RemoveProcFromArray().

◆ ProcArraySetReplicationSlotXmin()

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

Definition at line 3908 of file procarray.c.

3910{
3912
3913 if (!already_locked)
3915
3918
3919 if (!already_locked)
3921
3922 elog(DEBUG1, "xmin required by slots: data %u, catalog %u",
3923 xmin, catalog_xmin);
3924}

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

Referenced by ReplicationSlotsComputeRequiredXmin().

◆ ProcArrayShmemInit()

void ProcArrayShmemInit ( void  )
extern

Definition at line 420 of file procarray.c.

421{
422 bool found;
423
424 /* Create or attach to the ProcArray shared structure */
426 ShmemInitStruct("Proc Array",
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:482
Size mul_size(Size s1, Size s2)
Definition shmem.c:497
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition shmem.c:378
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, fb(), ProcArrayStruct::headKnownAssignedXids, InvalidTransactionId, KnownAssignedXids, KnownAssignedXidsValid, ProcArrayStruct::lastOverflowedXid, ProcArrayStruct::maxKnownAssignedXids, ProcArrayStruct::maxProcs, mul_size(), ProcArrayStruct::numKnownAssignedXids, ProcArrayStruct::numProcs, procArray, PROCARRAY_MAXPROCS, ProcGlobal, ProcArrayStruct::replication_slot_catalog_xmin, ProcArrayStruct::replication_slot_xmin, ShmemInitStruct(), ProcArrayStruct::tailKnownAssignedXids, TOTAL_MAX_CACHED_SUBXIDS, TransamVariables, and TransamVariablesData::xactCompletionCount.

Referenced by CreateOrAttachShmemStructs().

◆ ProcArrayShmemSize()

Size ProcArrayShmemSize ( void  )
extern

Definition at line 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:619

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

Referenced by CalculateShmemSize().

◆ ProcNumberGetProc()

PGPROC * ProcNumberGetProc ( int  procNumber)
extern

Definition at line 3096 of file procarray.c.

3097{
3098 PGPROC *result;
3099
3101 return NULL;
3102 result = GetPGProcByNumber(procNumber);
3103
3104 if (result->pid == 0)
3105 return NULL;
3106
3107 return result;
3108}
#define GetPGProcByNumber(n)
Definition proc.h:440
uint32 allProcCount
Definition proc.h:406

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

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

◆ ProcNumberGetTransactionIds()

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

Definition at line 3118 of file procarray.c.

3120{
3121 PGPROC *proc;
3122
3123 *xid = InvalidTransactionId;
3124 *xmin = InvalidTransactionId;
3125 *nsubxid = 0;
3126 *overflowed = false;
3127
3129 return;
3130 proc = GetPGProcByNumber(procNumber);
3131
3132 /* Need to lock out additions/removals of backends */
3134
3135 if (proc->pid != 0)
3136 {
3137 *xid = proc->xid;
3138 *xmin = proc->xmin;
3139 *nsubxid = proc->subxidStatus.count;
3140 *overflowed = proc->subxidStatus.overflowed;
3141 }
3142
3144}

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

Referenced by pgstat_read_current_status().

◆ RecordKnownAssignedTransactionIds()

void RecordKnownAssignedTransactionIds ( TransactionId  xid)
extern

Definition at line 4368 of file procarray.c.

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

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

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

◆ SignalVirtualTransaction()

pid_t SignalVirtualTransaction ( VirtualTransactionId  vxid,
ProcSignalReason  sigmode 
)
extern

Definition at line 3448 of file procarray.c.

3449{
3451 int index;
3452 pid_t pid = 0;
3453
3455
3456 for (index = 0; index < arrayP->numProcs; index++)
3457 {
3458 int pgprocno = arrayP->pgprocnos[index];
3459 PGPROC *proc = &allProcs[pgprocno];
3461
3463
3464 if (procvxid.procNumber == vxid.procNumber &&
3465 procvxid.localTransactionId == vxid.localTransactionId)
3466 {
3467 pid = proc->pid;
3468 if (pid != 0)
3469 {
3470 /*
3471 * Kill the pid if it's still here. If not, that's what we
3472 * wanted so ignore any errors.
3473 */
3474 (void) SendProcSignal(pid, sigmode, vxid.procNumber);
3475 }
3476 break;
3477 }
3478 }
3479
3481
3482 return pid;
3483}
LocalTransactionId localTransactionId
Definition lock.h:64
ProcNumber procNumber
Definition lock.h:63

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

Referenced by ResolveRecoveryConflictWithLock(), and ResolveRecoveryConflictWithVirtualXIDs().

◆ TerminateOtherDBBackends()

void TerminateOtherDBBackends ( Oid  databaseId)
extern

Definition at line 3793 of file procarray.c.

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

Referenced by dropdb().

◆ TransactionIdIsInProgress()

bool TransactionIdIsInProgress ( TransactionId  xid)
extern

Definition at line 1399 of file procarray.c.

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

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

◆ XidCacheRemoveRunningXids()

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

Definition at line 3956 of file procarray.c.

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

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

Referenced by RecordTransactionAbort().