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 CancelVirtualTransaction (VirtualTransactionId vxid, ProcSignalReason sigmode)
 
pid_t SignalVirtualTransaction (VirtualTransactionId vxid, ProcSignalReason sigmode, bool conflictPending)
 
bool MinimumActiveBackends (int min)
 
int CountDBBackends (Oid databaseid)
 
int CountDBConnections (Oid databaseid)
 
void CancelDBBackends (Oid databaseid, ProcSignalReason sigmode, bool conflictPending)
 
int CountUserBackends (Oid roleid)
 
bool CountOtherDBBackends (Oid databaseId, int *nbackends, int *nprepared)
 
void TerminateOtherDBBackends (Oid databaseId)
 
void XidCacheRemoveRunningXids (TransactionId xid, int nxids, const TransactionId *xids, TransactionId latestXid)
 
void ProcArraySetReplicationSlotXmin (TransactionId xmin, TransactionId catalog_xmin, bool already_locked)
 
void ProcArrayGetReplicationSlotXmin (TransactionId *xmin, TransactionId *catalog_xmin)
 

Function Documentation

◆ BackendPidGetProc()

PGPROC * BackendPidGetProc ( int  pid)
extern

Definition at line 3159 of file procarray.c.

3160{
3161 PGPROC *result;
3162
3163 if (pid == 0) /* never match dummy PGPROCs */
3164 return NULL;
3165
3167
3168 result = BackendPidGetProcWithLock(pid);
3169
3171
3172 return result;
3173}
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:3182
Definition proc.h:179

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

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

3220{
3221 int result = 0;
3224 int index;
3225
3226 if (xid == InvalidTransactionId) /* never match invalid xid */
3227 return 0;
3228
3230
3231 for (index = 0; index < arrayP->numProcs; index++)
3232 {
3233 if (other_xids[index] == xid)
3234 {
3235 int pgprocno = arrayP->pgprocnos[index];
3236 PGPROC *proc = &allProcs[pgprocno];
3237
3238 result = proc->pid;
3239 break;
3240 }
3241 }
3242
3244
3245 return result;
3246}
uint32 TransactionId
Definition c.h:666
PROC_HDR * ProcGlobal
Definition proc.c:79
TransactionId * xids
Definition proc.h:397
#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,
bool  conflictPending 
)
extern

Definition at line 3621 of file procarray.c.

3622{
3624 int index;
3625
3626 /* tell all backends to die */
3628
3629 for (index = 0; index < arrayP->numProcs; index++)
3630 {
3631 int pgprocno = arrayP->pgprocnos[index];
3632 PGPROC *proc = &allProcs[pgprocno];
3633
3634 if (databaseid == InvalidOid || proc->databaseId == databaseid)
3635 {
3637 pid_t pid;
3638
3640
3642 pid = proc->pid;
3643 if (pid != 0)
3644 {
3645 /*
3646 * Kill the pid if it's still here. If not, that's what we
3647 * wanted so ignore any errors.
3648 */
3649 (void) SendProcSignal(pid, sigmode, procvxid.procNumber);
3650 }
3651 }
3652 }
3653
3655}
#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
bool recoveryConflictPending
Definition proc.h:237
Oid databaseId
Definition proc.h:224

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

Referenced by ResolveRecoveryConflictWithDatabase(), and SendRecoveryConflictWithBufferPin().

◆ CancelVirtualTransaction()

pid_t CancelVirtualTransaction ( VirtualTransactionId  vxid,
ProcSignalReason  sigmode 
)
extern

Definition at line 3453 of file procarray.c.

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

References fb(), and SignalVirtualTransaction().

Referenced by ResolveRecoveryConflictWithVirtualXIDs().

◆ CountDBBackends()

int CountDBBackends ( Oid  databaseid)
extern

Definition at line 3561 of file procarray.c.

3562{
3564 int count = 0;
3565 int index;
3566
3568
3569 for (index = 0; index < arrayP->numProcs; index++)
3570 {
3571 int pgprocno = arrayP->pgprocnos[index];
3572 PGPROC *proc = &allProcs[pgprocno];
3573
3574 if (proc->pid == 0)
3575 continue; /* do not count prepared xacts */
3576 if (!OidIsValid(databaseid) ||
3577 proc->databaseId == databaseid)
3578 count++;
3579 }
3580
3582
3583 return count;
3584}
#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 3590 of file procarray.c.

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

References allProcs, PGPROC::databaseId, fb(), PGPROC::isRegularBackend, 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 3714 of file procarray.c.

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

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

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

Referenced by InitializeSessionUserId().

◆ ExpireAllKnownAssignedTransactionIds()

void ExpireAllKnownAssignedTransactionIds ( void  )
extern

Definition at line 4477 of file procarray.c.

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

References Assert, 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 4511 of file procarray.c.

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

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

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

References Assert, 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 3379 of file procarray.c.

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

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

References allProcs, PGPROC::databaseId, 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 2030 of file procarray.c.

2031{
2033}
#define TOTAL_MAX_CACHED_SUBXIDS

References TOTAL_MAX_CACHED_SUBXIDS.

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

◆ GetMaxSnapshotXidCount()

int GetMaxSnapshotXidCount ( void  )
extern

Definition at line 2019 of file procarray.c.

2020{
2021 return procArray->maxProcs;
2022}

References ProcArrayStruct::maxProcs, and procArray.

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

◆ GetOldestActiveTransactionId()

TransactionId GetOldestActiveTransactionId ( bool  inCommitOnly,
bool  allDbs 
)
extern

Definition at line 2835 of file procarray.c.

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

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

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

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

1985{
1987
1989
1990 return horizons.oldest_considered_running;
1991}

References ComputeXidHorizons(), and fb().

Referenced by CreateCheckPoint(), and CreateRestartPoint().

◆ GetReplicationHorizons()

void GetReplicationHorizons ( TransactionId xmin,
TransactionId catalog_xmin 
)
extern

Definition at line 1997 of file procarray.c.

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

References ComputeXidHorizons(), and fb().

Referenced by XLogWalRcvSendHSFeedback().

◆ GetRunningTransactionData()

RunningTransactions GetRunningTransactionData ( void  )
extern

Definition at line 2639 of file procarray.c.

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

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

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

3008{
3011 int count = 0;
3012 int index;
3013
3014 Assert(type != 0);
3015
3016 /* allocate what's certainly enough result space */
3018
3020
3021 for (index = 0; index < arrayP->numProcs; index++)
3022 {
3023 int pgprocno = arrayP->pgprocnos[index];
3024 PGPROC *proc = &allProcs[pgprocno];
3025
3026 if ((proc->delayChkptFlags & type) != 0)
3027 {
3029
3030 GET_VXID_FROM_PGPROC(vxid, *proc);
3032 vxids[count++] = vxid;
3033 }
3034 }
3035
3037
3038 *nvxids = count;
3039 return vxids;
3040}
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 3052 of file procarray.c.

3053{
3054 bool result = false;
3056 int index;
3057
3058 Assert(type != 0);
3059
3061
3062 for (index = 0; index < arrayP->numProcs; index++)
3063 {
3064 int pgprocno = arrayP->pgprocnos[index];
3065 PGPROC *proc = &allProcs[pgprocno];
3067
3068 GET_VXID_FROM_PGPROC(vxid, *proc);
3069
3070 if ((proc->delayChkptFlags & type) != 0 &&
3072 {
3073 int i;
3074
3075 for (i = 0; i < nvxids; i++)
3076 {
3078 {
3079 result = true;
3080 break;
3081 }
3082 }
3083 if (result)
3084 break;
3085 }
3086 }
3087
3089
3090 return result;
3091}
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 3254 of file procarray.c.

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

References BackendPidGetProc(), and fb().

Referenced by pg_stat_get_subscription().

◆ KnownAssignedTransactionIdsIdleMaintenance()

void KnownAssignedTransactionIdsIdleMaintenance ( void  )
extern

Definition at line 4543 of file procarray.c.

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

References KAX_STARTUP_PROCESS_IDLE, and KnownAssignedXidsCompress().

Referenced by WaitForWALToBecomeAvailable().

◆ MinimumActiveBackends()

bool MinimumActiveBackends ( int  min)
extern

Definition at line 3508 of file procarray.c.

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

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:469
#define GetNumberFromPGProc(proc)
Definition proc.h:447
uint8 statusFlags
Definition proc.h:265
XidCacheStatus subxidStatus
Definition proc.h:286

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

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

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

References Assert, 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 909 of file procarray.c.

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

Referenced by PrepareTransaction().

◆ ProcArrayEndTransaction()

void ProcArrayEndTransaction ( PGPROC proc,
TransactionId  latestXid 
)
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 proc->recoveryConflictPending = false;
712
713 /* must be cleared with xid/xmin: */
714 /* avoid unnecessarily dirtying shared cachelines */
716 {
723 }
724 }
725}
bool LWLockConditionalAcquire(LWLock *lock, LWLockMode mode)
Definition lwlock.c:1347
static void ProcArrayEndTransactionInternal(PGPROC *proc, TransactionId latestXid)
Definition procarray.c:733
static void ProcArrayGroupClearXid(PGPROC *proc, TransactionId latestXid)
Definition procarray.c:794

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

Referenced by AbortTransaction(), and CommitTransaction().

◆ ProcArrayGetReplicationSlotXmin()

void ProcArrayGetReplicationSlotXmin ( TransactionId xmin,
TransactionId catalog_xmin 
)
extern

Definition at line 3947 of file procarray.c.

3949{
3951
3952 if (xmin != NULL)
3954
3955 if (catalog_xmin != NULL)
3957
3959}

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

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

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

Referenced by StartupXLOG().

◆ ProcArrayInstallImportedXmin()

bool ProcArrayInstallImportedXmin ( TransactionId  xmin,
VirtualTransactionId sourcevxid 
)
extern

Definition at line 2482 of file procarray.c.

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

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

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

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:969
PGPROC * allProcs
Definition proc.h:394

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

3924{
3926
3927 if (!already_locked)
3929
3932
3933 if (!already_locked)
3935
3936 elog(DEBUG1, "xmin required by slots: data %u, catalog %u",
3937 xmin, catalog_xmin);
3938}

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:495
Size mul_size(Size s1, Size s2)
Definition shmem.c:510
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition shmem.c:389
int maxKnownAssignedXids
Definition procarray.c:81
int tailKnownAssignedXids
Definition procarray.c:83
int headKnownAssignedXids
Definition procarray.c:84
bool EnableHotStandby
Definition xlog.c:124

References add_size(), allProcs, PROC_HDR::allProcs, EnableHotStandby, 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 3101 of file procarray.c.

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

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

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

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

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

References AdvanceNextFullTransactionIdPastXid(), Assert, DEBUG4, elog, ExtendSUBTRANS(), 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,
bool  conflictPending 
)
extern

Definition at line 3459 of file procarray.c.

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

Referenced by CancelVirtualTransaction(), and ResolveRecoveryConflictWithLock().

◆ TerminateOtherDBBackends()

void TerminateOtherDBBackends ( Oid  databaseId)
extern

Definition at line 3807 of file procarray.c.

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

References allProcs, BackendPidGetProc(), PGPROC::databaseId, ereport, errcode(), errdetail(), errdetail_plural(), errmsg(), ERROR, 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 1404 of file procarray.c.

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

References allProcs, Assert, cachedXidIsNotInProgress, 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 3970 of file procarray.c.

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