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

Go to the source code of this file.

Functions

Size ProcArrayShmemSize (void)
 
void CreateSharedProcArray (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)
 
bool TransactionIdIsActive (TransactionId xid)
 
TransactionId GetOldestNonRemovableTransactionId (Relation rel)
 
TransactionId GetOldestTransactionIdConsideredRunning (void)
 
TransactionId GetOldestActiveTransactionId (void)
 
TransactionId GetOldestSafeDecodingTransactionId (bool catalogOnly)
 
void GetReplicationHorizons (TransactionId *xmin, TransactionId *catalog_xmin)
 
VirtualTransactionIdGetVirtualXIDsDelayingChkpt (int *nvxids, int type)
 
bool HaveVirtualXIDsDelayingChkpt (VirtualTransactionId *vxids, int nvxids, int type)
 
PGPROCBackendPidGetProc (int pid)
 
PGPROCBackendPidGetProcWithLock (int pid)
 
int BackendXidGetPid (TransactionId xid)
 
bool IsBackendPid (int pid)
 
VirtualTransactionIdGetCurrentVirtualXIDs (TransactionId limitXmin, bool excludeXmin0, bool allDbs, int excludeVacuum, int *nvxids)
 
VirtualTransactionIdGetConflictingVirtualXIDs (TransactionId limitXmin, Oid dbOid)
 
pid_t CancelVirtualTransaction (VirtualTransactionId vxid, ProcSignalReason sigmode)
 
pid_t SignalVirtualTransaction (VirtualTransactionId vxid, ProcSignalReason sigmode, bool conflictPending)
 
bool MinimumActiveBackends (int min)
 
int CountDBBackends (Oid databaseid)
 
int CountDBConnections (Oid databaseid)
 
void CancelDBBackends (Oid databaseid, ProcSignalReason sigmode, bool conflictPending)
 
int CountUserBackends (Oid roleid)
 
bool CountOtherDBBackends (Oid databaseId, int *nbackends, int *nprepared)
 
void TerminateOtherDBBackends (Oid databaseId)
 
void XidCacheRemoveRunningXids (TransactionId xid, int nxids, const TransactionId *xids, TransactionId latestXid)
 
void ProcArraySetReplicationSlotXmin (TransactionId xmin, TransactionId catalog_xmin, bool already_locked)
 
void ProcArrayGetReplicationSlotXmin (TransactionId *xmin, TransactionId *catalog_xmin)
 

Function Documentation

◆ BackendPidGetProc()

PGPROC* BackendPidGetProc ( int  pid)

Definition at line 3162 of file procarray.c.

3163 {
3164  PGPROC *result;
3165 
3166  if (pid == 0) /* never match dummy PGPROCs */
3167  return NULL;
3168 
3169  LWLockAcquire(ProcArrayLock, LW_SHARED);
3170 
3171  result = BackendPidGetProcWithLock(pid);
3172 
3173  LWLockRelease(ProcArrayLock);
3174 
3175  return result;
3176 }
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1195
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1803
@ LW_SHARED
Definition: lwlock.h:116
PGPROC * BackendPidGetProcWithLock(int pid)
Definition: procarray.c:3185
Definition: proc.h:162

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

Referenced by IsBackendPid(), 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(), TerminateOtherDBBackends(), and test_shm_mq_main().

◆ BackendPidGetProcWithLock()

PGPROC* BackendPidGetProcWithLock ( int  pid)

Definition at line 3185 of file procarray.c.

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

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

Referenced by BackendPidGetProc(), and GetBlockerStatusData().

◆ BackendXidGetPid()

int BackendXidGetPid ( TransactionId  xid)

Definition at line 3222 of file procarray.c.

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

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

Referenced by pgrowlocks().

◆ CancelDBBackends()

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

Definition at line 3626 of file procarray.c.

3627 {
3628  ProcArrayStruct *arrayP = procArray;
3629  int index;
3630 
3631  /* tell all backends to die */
3632  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3633 
3634  for (index = 0; index < arrayP->numProcs; index++)
3635  {
3636  int pgprocno = arrayP->pgprocnos[index];
3637  PGPROC *proc = &allProcs[pgprocno];
3638 
3639  if (databaseid == InvalidOid || proc->databaseId == databaseid)
3640  {
3641  VirtualTransactionId procvxid;
3642  pid_t pid;
3643 
3644  GET_VXID_FROM_PGPROC(procvxid, *proc);
3645 
3646  proc->recoveryConflictPending = conflictPending;
3647  pid = proc->pid;
3648  if (pid != 0)
3649  {
3650  /*
3651  * Kill the pid if it's still here. If not, that's what we
3652  * wanted so ignore any errors.
3653  */
3654  (void) SendProcSignal(pid, sigmode, procvxid.backendId);
3655  }
3656  }
3657  }
3658 
3659  LWLockRelease(ProcArrayLock);
3660 }
#define GET_VXID_FROM_PGPROC(vxid, proc)
Definition: lock.h:77
@ LW_EXCLUSIVE
Definition: lwlock.h:115
#define InvalidOid
Definition: postgres_ext.h:36
int SendProcSignal(pid_t pid, ProcSignalReason reason, BackendId backendId)
Definition: procsignal.c:262
bool recoveryConflictPending
Definition: proc.h:211
Oid databaseId
Definition: proc.h:198
BackendId backendId
Definition: lock.h:61

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

Referenced by ResolveRecoveryConflictWithDatabase(), and SendRecoveryConflictWithBufferPin().

◆ CancelVirtualTransaction()

pid_t CancelVirtualTransaction ( VirtualTransactionId  vxid,
ProcSignalReason  sigmode 
)

Definition at line 3457 of file procarray.c.

3458 {
3459  return SignalVirtualTransaction(vxid, sigmode, true);
3460 }
pid_t SignalVirtualTransaction(VirtualTransactionId vxid, ProcSignalReason sigmode, bool conflictPending)
Definition: procarray.c:3463

References SignalVirtualTransaction().

Referenced by ResolveRecoveryConflictWithVirtualXIDs().

◆ CountDBBackends()

int CountDBBackends ( Oid  databaseid)

Definition at line 3565 of file procarray.c.

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

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

Referenced by ResolveRecoveryConflictWithDatabase().

◆ CountDBConnections()

int CountDBConnections ( Oid  databaseid)

Definition at line 3595 of file procarray.c.

3596 {
3597  ProcArrayStruct *arrayP = procArray;
3598  int count = 0;
3599  int index;
3600 
3601  LWLockAcquire(ProcArrayLock, LW_SHARED);
3602 
3603  for (index = 0; index < arrayP->numProcs; index++)
3604  {
3605  int pgprocno = arrayP->pgprocnos[index];
3606  PGPROC *proc = &allProcs[pgprocno];
3607 
3608  if (proc->pid == 0)
3609  continue; /* do not count prepared xacts */
3610  if (proc->isBackgroundWorker)
3611  continue; /* do not count background workers */
3612  if (!OidIsValid(databaseid) ||
3613  proc->databaseId == databaseid)
3614  count++;
3615  }
3616 
3617  LWLockRelease(ProcArrayLock);
3618 
3619  return count;
3620 }
bool isBackgroundWorker
Definition: proc.h:204

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

Referenced by CheckMyDatabase().

◆ CountOtherDBBackends()

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

Definition at line 3716 of file procarray.c.

3717 {
3718  ProcArrayStruct *arrayP = procArray;
3719 
3720 #define MAXAUTOVACPIDS 10 /* max autovacs to SIGTERM per iteration */
3721  int autovac_pids[MAXAUTOVACPIDS];
3722  int tries;
3723 
3724  /* 50 tries with 100ms sleep between tries makes 5 sec total wait */
3725  for (tries = 0; tries < 50; tries++)
3726  {
3727  int nautovacs = 0;
3728  bool found = false;
3729  int index;
3730 
3732 
3733  *nbackends = *nprepared = 0;
3734 
3735  LWLockAcquire(ProcArrayLock, LW_SHARED);
3736 
3737  for (index = 0; index < arrayP->numProcs; index++)
3738  {
3739  int pgprocno = arrayP->pgprocnos[index];
3740  PGPROC *proc = &allProcs[pgprocno];
3741  uint8 statusFlags = ProcGlobal->statusFlags[index];
3742 
3743  if (proc->databaseId != databaseId)
3744  continue;
3745  if (proc == MyProc)
3746  continue;
3747 
3748  found = true;
3749 
3750  if (proc->pid == 0)
3751  (*nprepared)++;
3752  else
3753  {
3754  (*nbackends)++;
3755  if ((statusFlags & PROC_IS_AUTOVACUUM) &&
3756  nautovacs < MAXAUTOVACPIDS)
3757  autovac_pids[nautovacs++] = proc->pid;
3758  }
3759  }
3760 
3761  LWLockRelease(ProcArrayLock);
3762 
3763  if (!found)
3764  return false; /* no conflicting backends, so done */
3765 
3766  /*
3767  * Send SIGTERM to any conflicting autovacuums before sleeping. We
3768  * postpone this step until after the loop because we don't want to
3769  * hold ProcArrayLock while issuing kill(). We have no idea what might
3770  * block kill() inside the kernel...
3771  */
3772  for (index = 0; index < nautovacs; index++)
3773  (void) kill(autovac_pids[index], SIGTERM); /* ignore any error */
3774 
3775  /* sleep, then try again */
3776  pg_usleep(100 * 1000L); /* 100ms */
3777  }
3778 
3779  return true; /* timed out, still conflicts */
3780 }
unsigned char uint8
Definition: c.h:488
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:121
#define PROC_IS_AUTOVACUUM
Definition: proc.h:56
#define MAXAUTOVACPIDS
void pg_usleep(long microsec)
Definition: signal.c:53
PGPROC * MyProc
Definition: proc.c:66
uint8 * statusFlags
Definition: proc.h:377
#define kill(pid, sig)
Definition: win32_port.h:482

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

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

◆ CountUserBackends()

int CountUserBackends ( Oid  roleid)

Definition at line 3666 of file procarray.c.

3667 {
3668  ProcArrayStruct *arrayP = procArray;
3669  int count = 0;
3670  int index;
3671 
3672  LWLockAcquire(ProcArrayLock, LW_SHARED);
3673 
3674  for (index = 0; index < arrayP->numProcs; index++)
3675  {
3676  int pgprocno = arrayP->pgprocnos[index];
3677  PGPROC *proc = &allProcs[pgprocno];
3678 
3679  if (proc->pid == 0)
3680  continue; /* do not count prepared xacts */
3681  if (proc->isBackgroundWorker)
3682  continue; /* do not count background workers */
3683  if (proc->roleId == roleid)
3684  count++;
3685  }
3686 
3687  LWLockRelease(ProcArrayLock);
3688 
3689  return count;
3690 }
Oid roleId
Definition: proc.h:199

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

Referenced by InitializeSessionUserId().

◆ CreateSharedProcArray()

void CreateSharedProcArray ( void  )

Definition at line 421 of file procarray.c.

422 {
423  bool found;
424 
425  /* Create or attach to the ProcArray shared structure */
427  ShmemInitStruct("Proc Array",
428  add_size(offsetof(ProcArrayStruct, pgprocnos),
429  mul_size(sizeof(int),
431  &found);
432 
433  if (!found)
434  {
435  /*
436  * We're the first - initialize.
437  */
438  procArray->numProcs = 0;
449  }
450 
452 
453  /* Create or attach to the KnownAssignedXids arrays too, if needed */
454  if (EnableHotStandby)
455  {
457  ShmemInitStruct("KnownAssignedXids",
458  mul_size(sizeof(TransactionId),
460  &found);
461  KnownAssignedXidsValid = (bool *)
462  ShmemInitStruct("KnownAssignedXidsValid",
463  mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS),
464  &found);
465  }
466 }
#define TOTAL_MAX_CACHED_SUBXIDS
#define PROCARRAY_MAXPROCS
static TransactionId * KnownAssignedXids
Definition: procarray.c:284
static bool * KnownAssignedXidsValid
Definition: procarray.c:285
Size add_size(Size s1, Size s2)
Definition: shmem.c:502
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition: shmem.c:396
Size mul_size(Size s1, Size s2)
Definition: shmem.c:519
#define SpinLockInit(lock)
Definition: spin.h:60
PGPROC * allProcs
Definition: proc.h:362
TransactionId replication_slot_xmin
Definition: procarray.c:97
int maxKnownAssignedXids
Definition: procarray.c:81
TransactionId replication_slot_catalog_xmin
Definition: procarray.c:99
slock_t known_assigned_xids_lck
Definition: procarray.c:85
int numKnownAssignedXids
Definition: procarray.c:82
TransactionId lastOverflowedXid
Definition: procarray.c:94
int tailKnownAssignedXids
Definition: procarray.c:83
int headKnownAssignedXids
Definition: procarray.c:84
uint64 xactCompletionCount
Definition: transam.h:248
VariableCache ShmemVariableCache
Definition: varsup.c:34
bool EnableHotStandby
Definition: xlog.c:124

References add_size(), allProcs, PROC_HDR::allProcs, EnableHotStandby, ProcArrayStruct::headKnownAssignedXids, InvalidTransactionId, ProcArrayStruct::known_assigned_xids_lck, 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(), ShmemVariableCache, SpinLockInit, ProcArrayStruct::tailKnownAssignedXids, TOTAL_MAX_CACHED_SUBXIDS, and VariableCacheData::xactCompletionCount.

Referenced by CreateSharedMemoryAndSemaphores().

◆ ExpireAllKnownAssignedTransactionIds()

void ExpireAllKnownAssignedTransactionIds ( void  )

Definition at line 4487 of file procarray.c.

4488 {
4489  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
4491 
4492  /*
4493  * Reset lastOverflowedXid. Currently, lastOverflowedXid has no use after
4494  * the call of this function. But do this for unification with what
4495  * ExpireOldKnownAssignedTransactionIds() do.
4496  */
4498  LWLockRelease(ProcArrayLock);
4499 }
static void KnownAssignedXidsRemovePreceding(TransactionId removeXid)
Definition: procarray.c:5015

References InvalidTransactionId, KnownAssignedXidsRemovePreceding(), ProcArrayStruct::lastOverflowedXid, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), and procArray.

Referenced by ShutdownRecoveryTransactionEnvironment().

◆ ExpireOldKnownAssignedTransactionIds()

void ExpireOldKnownAssignedTransactionIds ( TransactionId  xid)

Definition at line 4507 of file procarray.c.

4508 {
4509  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
4510 
4511  /*
4512  * Reset lastOverflowedXid if we know all transactions that have been
4513  * possibly running are being gone. Not doing so could cause an incorrect
4514  * lastOverflowedXid value, which makes extra snapshots be marked as
4515  * suboverflowed.
4516  */
4520  LWLockRelease(ProcArrayLock);
4521 }
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:280

References InvalidTransactionId, KnownAssignedXidsRemovePreceding(), ProcArrayStruct::lastOverflowedXid, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), procArray, and TransactionIdPrecedes().

Referenced by ProcArrayApplyRecoveryInfo().

◆ ExpireTreeKnownAssignedTransactionIds()

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

Definition at line 4461 of file procarray.c.

4463 {
4465 
4466  /*
4467  * Uses same locking as transaction commit
4468  */
4469  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
4470 
4471  KnownAssignedXidsRemoveTree(xid, nsubxids, subxids);
4472 
4473  /* As in ProcArrayEndTransaction, advance latestCompletedXid */
4475 
4476  /* ... and xactCompletionCount */
4478 
4479  LWLockRelease(ProcArrayLock);
4480 }
Assert(fmt[strlen(fmt) - 1] !='\n')
static void KnownAssignedXidsRemoveTree(TransactionId xid, int nsubxids, TransactionId *subxids)
Definition: procarray.c:4993
static void MaintainLatestCompletedXidRecovery(TransactionId latestXid)
Definition: procarray.c:991
HotStandbyState standbyState
Definition: xlogutils.c:56
@ STANDBY_INITIALIZED
Definition: xlogutils.h:50

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

Referenced by xact_redo_abort(), and xact_redo_commit().

◆ GetConflictingVirtualXIDs()

VirtualTransactionId* GetConflictingVirtualXIDs ( TransactionId  limitXmin,
Oid  dbOid 
)

Definition at line 3383 of file procarray.c.

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

References allProcs, VirtualTransactionId::backendId, PGPROC::databaseId, ereport, errcode(), errmsg(), ERROR, GET_VXID_FROM_PGPROC, InvalidBackendId, InvalidLocalTransactionId, VirtualTransactionId::localTransactionId, LW_SHARED, LWLockAcquire(), LWLockRelease(), malloc, ProcArrayStruct::maxProcs, ProcArrayStruct::numProcs, OidIsValid, ProcArrayStruct::pgprocnos, 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 
)

Definition at line 3290 of file procarray.c.

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

References allProcs, PGPROC::databaseId, GET_VXID_FROM_PGPROC, LW_SHARED, LWLockAcquire(), LWLockRelease(), ProcArrayStruct::maxProcs, MyDatabaseId, MyProc, ProcArrayStruct::numProcs, palloc(), ProcArrayStruct::pgprocnos, procArray, ProcGlobal, PROC_HDR::statusFlags, TransactionIdIsValid, TransactionIdPrecedesOrEquals(), UINT32_ACCESS_ONCE, VirtualTransactionIdIsValid, and PGPROC::xmin.

Referenced by WaitForOlderSnapshots().

◆ GetMaxSnapshotSubxidCount()

int GetMaxSnapshotSubxidCount ( void  )

Definition at line 2088 of file procarray.c.

2089 {
2090  return TOTAL_MAX_CACHED_SUBXIDS;
2091 }

References TOTAL_MAX_CACHED_SUBXIDS.

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

◆ GetMaxSnapshotXidCount()

int GetMaxSnapshotXidCount ( void  )

Definition at line 2077 of file procarray.c.

2078 {
2079  return procArray->maxProcs;
2080 }

References ProcArrayStruct::maxProcs, and procArray.

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

◆ GetOldestActiveTransactionId()

TransactionId GetOldestActiveTransactionId ( void  )

Definition at line 2904 of file procarray.c.

2905 {
2906  ProcArrayStruct *arrayP = procArray;
2907  TransactionId *other_xids = ProcGlobal->xids;
2908  TransactionId oldestRunningXid;
2909  int index;
2910 
2912 
2913  /*
2914  * Read nextXid, as the upper bound of what's still active.
2915  *
2916  * Reading a TransactionId is atomic, but we must grab the lock to make
2917  * sure that all XIDs < nextXid are already present in the proc array (or
2918  * have already completed), when we spin over it.
2919  */
2920  LWLockAcquire(XidGenLock, LW_SHARED);
2922  LWLockRelease(XidGenLock);
2923 
2924  /*
2925  * Spin over procArray collecting all xids and subxids.
2926  */
2927  LWLockAcquire(ProcArrayLock, LW_SHARED);
2928  for (index = 0; index < arrayP->numProcs; index++)
2929  {
2930  TransactionId xid;
2931 
2932  /* Fetch xid just once - see GetNewTransactionId */
2933  xid = UINT32_ACCESS_ONCE(other_xids[index]);
2934 
2935  if (!TransactionIdIsNormal(xid))
2936  continue;
2937 
2938  if (TransactionIdPrecedes(xid, oldestRunningXid))
2939  oldestRunningXid = xid;
2940 
2941  /*
2942  * Top-level XID of a transaction is always less than any of its
2943  * subxids, so we don't need to check if any of the subxids are
2944  * smaller than oldestRunningXid
2945  */
2946  }
2947  LWLockRelease(ProcArrayLock);
2948 
2949  return oldestRunningXid;
2950 }
FullTransactionId nextXid
Definition: transam.h:220
#define XidFromFullTransactionId(x)
Definition: transam.h:48
#define TransactionIdIsNormal(xid)
Definition: transam.h:42
bool RecoveryInProgress(void)
Definition: xlog.c:5908

References Assert(), LW_SHARED, LWLockAcquire(), LWLockRelease(), VariableCacheData::nextXid, ProcArrayStruct::numProcs, procArray, ProcGlobal, RecoveryInProgress(), ShmemVariableCache, TransactionIdIsNormal, TransactionIdPrecedes(), UINT32_ACCESS_ONCE, XidFromFullTransactionId, and PROC_HDR::xids.

Referenced by CreateCheckPoint().

◆ GetOldestNonRemovableTransactionId()

TransactionId GetOldestNonRemovableTransactionId ( Relation  rel)

Definition at line 2013 of file procarray.c.

2014 {
2015  ComputeXidHorizonsResult horizons;
2016 
2017  ComputeXidHorizons(&horizons);
2018 
2019  switch (GlobalVisHorizonKindForRel(rel))
2020  {
2021  case VISHORIZON_SHARED:
2022  return horizons.shared_oldest_nonremovable;
2023  case VISHORIZON_CATALOG:
2024  return horizons.catalog_oldest_nonremovable;
2025  case VISHORIZON_DATA:
2026  return horizons.data_oldest_nonremovable;
2027  case VISHORIZON_TEMP:
2028  return horizons.temp_oldest_nonremovable;
2029  }
2030 
2031  /* just to prevent compiler warnings */
2032  return InvalidTransactionId;
2033 }
static void ComputeXidHorizons(ComputeXidHorizonsResult *h)
Definition: procarray.c:1722
@ VISHORIZON_SHARED
Definition: procarray.c:254
@ VISHORIZON_DATA
Definition: procarray.c:256
@ VISHORIZON_CATALOG
Definition: procarray.c:255
@ VISHORIZON_TEMP
Definition: procarray.c:257
static GlobalVisHorizonKind GlobalVisHorizonKindForRel(Relation rel)
Definition: procarray.c:1979
TransactionId data_oldest_nonremovable
Definition: procarray.c:240
TransactionId temp_oldest_nonremovable
Definition: procarray.c:246
TransactionId shared_oldest_nonremovable
Definition: procarray.c:217
TransactionId catalog_oldest_nonremovable
Definition: procarray.c:234

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

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

◆ GetOldestSafeDecodingTransactionId()

TransactionId GetOldestSafeDecodingTransactionId ( bool  catalogOnly)

Definition at line 2969 of file procarray.c.

2970 {
2971  ProcArrayStruct *arrayP = procArray;
2972  TransactionId oldestSafeXid;
2973  int index;
2974  bool recovery_in_progress = RecoveryInProgress();
2975 
2976  Assert(LWLockHeldByMe(ProcArrayLock));
2977 
2978  /*
2979  * Acquire XidGenLock, so no transactions can acquire an xid while we're
2980  * running. If no transaction with xid were running concurrently a new xid
2981  * could influence the RecentXmin et al.
2982  *
2983  * We initialize the computation to nextXid since that's guaranteed to be
2984  * a safe, albeit pessimal, value.
2985  */
2986  LWLockAcquire(XidGenLock, LW_SHARED);
2988 
2989  /*
2990  * If there's already a slot pegging the xmin horizon, we can start with
2991  * that value, it's guaranteed to be safe since it's computed by this
2992  * routine initially and has been enforced since. We can always use the
2993  * slot's general xmin horizon, but the catalog horizon is only usable
2994  * when only catalog data is going to be looked at.
2995  */
2998  oldestSafeXid))
2999  oldestSafeXid = procArray->replication_slot_xmin;
3000 
3001  if (catalogOnly &&
3004  oldestSafeXid))
3005  oldestSafeXid = procArray->replication_slot_catalog_xmin;
3006 
3007  /*
3008  * If we're not in recovery, we walk over the procarray and collect the
3009  * lowest xid. Since we're called with ProcArrayLock held and have
3010  * acquired XidGenLock, no entries can vanish concurrently, since
3011  * ProcGlobal->xids[i] is only set with XidGenLock held and only cleared
3012  * with ProcArrayLock held.
3013  *
3014  * In recovery we can't lower the safe value besides what we've computed
3015  * above, so we'll have to wait a bit longer there. We unfortunately can
3016  * *not* use KnownAssignedXidsGetOldestXmin() since the KnownAssignedXids
3017  * machinery can miss values and return an older value than is safe.
3018  */
3019  if (!recovery_in_progress)
3020  {
3021  TransactionId *other_xids = ProcGlobal->xids;
3022 
3023  /*
3024  * Spin over procArray collecting min(ProcGlobal->xids[i])
3025  */
3026  for (index = 0; index < arrayP->numProcs; index++)
3027  {
3028  TransactionId xid;
3029 
3030  /* Fetch xid just once - see GetNewTransactionId */
3031  xid = UINT32_ACCESS_ONCE(other_xids[index]);
3032 
3033  if (!TransactionIdIsNormal(xid))
3034  continue;
3035 
3036  if (TransactionIdPrecedes(xid, oldestSafeXid))
3037  oldestSafeXid = xid;
3038  }
3039  }
3040 
3041  LWLockRelease(XidGenLock);
3042 
3043  return oldestSafeXid;
3044 }
bool LWLockHeldByMe(LWLock *lock)
Definition: lwlock.c:1919

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

Referenced by CreateInitDecodingContext(), and SnapBuildInitialSnapshot().

◆ GetOldestTransactionIdConsideredRunning()

TransactionId GetOldestTransactionIdConsideredRunning ( void  )

Definition at line 2042 of file procarray.c.

2043 {
2044  ComputeXidHorizonsResult horizons;
2045 
2046  ComputeXidHorizons(&horizons);
2047 
2048  return horizons.oldest_considered_running;
2049 }
TransactionId oldest_considered_running
Definition: procarray.c:208

References ComputeXidHorizons(), and ComputeXidHorizonsResult::oldest_considered_running.

Referenced by CreateCheckPoint(), and CreateRestartPoint().

◆ GetReplicationHorizons()

void GetReplicationHorizons ( TransactionId xmin,
TransactionId catalog_xmin 
)

Definition at line 2055 of file procarray.c.

2056 {
2057  ComputeXidHorizonsResult horizons;
2058 
2059  ComputeXidHorizons(&horizons);
2060 
2061  /*
2062  * Don't want to use shared_oldest_nonremovable here, as that contains the
2063  * effect of replication slot's catalog_xmin. We want to send a separate
2064  * feedback for the catalog horizon, so the primary can remove data table
2065  * contents more aggressively.
2066  */
2067  *xmin = horizons.shared_oldest_nonremovable_raw;
2068  *catalog_xmin = horizons.slot_catalog_xmin;
2069 }
TransactionId slot_catalog_xmin
Definition: procarray.c:195
TransactionId shared_oldest_nonremovable_raw
Definition: procarray.c:228

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

Referenced by XLogWalRcvSendHSFeedback().

◆ GetRunningTransactionData()

RunningTransactions GetRunningTransactionData ( void  )

Definition at line 2729 of file procarray.c.

2730 {
2731  /* result workspace */
2732  static RunningTransactionsData CurrentRunningXactsData;
2733 
2734  ProcArrayStruct *arrayP = procArray;
2735  TransactionId *other_xids = ProcGlobal->xids;
2736  RunningTransactions CurrentRunningXacts = &CurrentRunningXactsData;
2737  TransactionId latestCompletedXid;
2738  TransactionId oldestRunningXid;
2739  TransactionId *xids;
2740  int index;
2741  int count;
2742  int subcount;
2743  bool suboverflowed;
2744 
2746 
2747  /*
2748  * Allocating space for maxProcs xids is usually overkill; numProcs would
2749  * be sufficient. But it seems better to do the malloc while not holding
2750  * the lock, so we can't look at numProcs. Likewise, we allocate much
2751  * more subxip storage than is probably needed.
2752  *
2753  * Should only be allocated in bgwriter, since only ever executed during
2754  * checkpoints.
2755  */
2756  if (CurrentRunningXacts->xids == NULL)
2757  {
2758  /*
2759  * First call
2760  */
2761  CurrentRunningXacts->xids = (TransactionId *)
2763  if (CurrentRunningXacts->xids == NULL)
2764  ereport(ERROR,
2765  (errcode(ERRCODE_OUT_OF_MEMORY),
2766  errmsg("out of memory")));
2767  }
2768 
2769  xids = CurrentRunningXacts->xids;
2770 
2771  count = subcount = 0;
2772  suboverflowed = false;
2773 
2774  /*
2775  * Ensure that no xids enter or leave the procarray while we obtain
2776  * snapshot.
2777  */
2778  LWLockAcquire(ProcArrayLock, LW_SHARED);
2779  LWLockAcquire(XidGenLock, LW_SHARED);
2780 
2781  latestCompletedXid =
2783  oldestRunningXid =
2785 
2786  /*
2787  * Spin over procArray collecting all xids
2788  */
2789  for (index = 0; index < arrayP->numProcs; index++)
2790  {
2791  TransactionId xid;
2792 
2793  /* Fetch xid just once - see GetNewTransactionId */
2794  xid = UINT32_ACCESS_ONCE(other_xids[index]);
2795 
2796  /*
2797  * We don't need to store transactions that don't have a TransactionId
2798  * yet because they will not show as running on a standby server.
2799  */
2800  if (!TransactionIdIsValid(xid))
2801  continue;
2802 
2803  /*
2804  * Be careful not to exclude any xids before calculating the values of
2805  * oldestRunningXid and suboverflowed, since these are used to clean
2806  * up transaction information held on standbys.
2807  */
2808  if (TransactionIdPrecedes(xid, oldestRunningXid))
2809  oldestRunningXid = xid;
2810 
2812  suboverflowed = true;
2813 
2814  /*
2815  * If we wished to exclude xids this would be the right place for it.
2816  * Procs with the PROC_IN_VACUUM flag set don't usually assign xids,
2817  * but they do during truncation at the end when they get the lock and
2818  * truncate, so it is not much of a problem to include them if they
2819  * are seen and it is cleaner to include them.
2820  */
2821 
2822  xids[count++] = xid;
2823  }
2824 
2825  /*
2826  * Spin over procArray collecting all subxids, but only if there hasn't
2827  * been a suboverflow.
2828  */
2829  if (!suboverflowed)
2830  {
2831  XidCacheStatus *other_subxidstates = ProcGlobal->subxidStates;
2832 
2833  for (index = 0; index < arrayP->numProcs; index++)
2834  {
2835  int pgprocno = arrayP->pgprocnos[index];
2836  PGPROC *proc = &allProcs[pgprocno];
2837  int nsubxids;
2838 
2839  /*
2840  * Save subtransaction XIDs. Other backends can't add or remove
2841  * entries while we're holding XidGenLock.
2842  */
2843  nsubxids = other_subxidstates[index].count;
2844  if (nsubxids > 0)
2845  {
2846  /* barrier not really required, as XidGenLock is held, but ... */
2847  pg_read_barrier(); /* pairs with GetNewTransactionId */
2848 
2849  memcpy(&xids[count], (void *) proc->subxids.xids,
2850  nsubxids * sizeof(TransactionId));
2851  count += nsubxids;
2852  subcount += nsubxids;
2853 
2854  /*
2855  * Top-level XID of a transaction is always less than any of
2856  * its subxids, so we don't need to check if any of the
2857  * subxids are smaller than oldestRunningXid
2858  */
2859  }
2860  }
2861  }
2862 
2863  /*
2864  * It's important *not* to include the limits set by slots here because
2865  * snapbuild.c uses oldestRunningXid to manage its xmin horizon. If those
2866  * were to be included here the initial value could never increase because
2867  * of a circular dependency where slots only increase their limits when
2868  * running xacts increases oldestRunningXid and running xacts only
2869  * increases if slots do.
2870  */
2871 
2872  CurrentRunningXacts->xcnt = count - subcount;
2873  CurrentRunningXacts->subxcnt = subcount;
2874  CurrentRunningXacts->subxid_overflow = suboverflowed;
2876  CurrentRunningXacts->oldestRunningXid = oldestRunningXid;
2877  CurrentRunningXacts->latestCompletedXid = latestCompletedXid;
2878 
2879  Assert(TransactionIdIsValid(CurrentRunningXacts->nextXid));
2880  Assert(TransactionIdIsValid(CurrentRunningXacts->oldestRunningXid));
2881  Assert(TransactionIdIsNormal(CurrentRunningXacts->latestCompletedXid));
2882 
2883  /* We don't release the locks here, the caller is responsible for that */
2884 
2885  return CurrentRunningXacts;
2886 }
#define pg_read_barrier()
Definition: atomics.h:153
struct XidCache subxids
Definition: proc.h:256
XidCacheStatus * subxidStates
Definition: proc.h:371
TransactionId oldestRunningXid
Definition: standby.h:83
TransactionId nextXid
Definition: standby.h:82
TransactionId latestCompletedXid
Definition: standby.h:84
TransactionId * xids
Definition: standby.h:86
FullTransactionId latestCompletedXid
Definition: transam.h:238
bool overflowed
Definition: proc.h:45
uint8 count
Definition: proc.h:43
TransactionId xids[PGPROC_MAX_CACHED_SUBXIDS]
Definition: proc.h:50

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

Referenced by LogStandbySnapshot().

◆ GetSnapshotData()

Snapshot GetSnapshotData ( Snapshot  snapshot)

Definition at line 2214 of file procarray.c.

2215 {
2216  ProcArrayStruct *arrayP = procArray;
2217  TransactionId *other_xids = ProcGlobal->xids;
2218  TransactionId xmin;
2219  TransactionId xmax;
2220  int count = 0;
2221  int subcount = 0;
2222  bool suboverflowed = false;
2223  FullTransactionId latest_completed;
2224  TransactionId oldestxid;
2225  int mypgxactoff;
2226  TransactionId myxid;
2227  uint64 curXactCompletionCount;
2228 
2229  TransactionId replication_slot_xmin = InvalidTransactionId;
2230  TransactionId replication_slot_catalog_xmin = InvalidTransactionId;
2231 
2232  Assert(snapshot != NULL);
2233 
2234  /*
2235  * Allocating space for maxProcs xids is usually overkill; numProcs would
2236  * be sufficient. But it seems better to do the malloc while not holding
2237  * the lock, so we can't look at numProcs. Likewise, we allocate much
2238  * more subxip storage than is probably needed.
2239  *
2240  * This does open a possibility for avoiding repeated malloc/free: since
2241  * maxProcs does not change at runtime, we can simply reuse the previous
2242  * xip arrays if any. (This relies on the fact that all callers pass
2243  * static SnapshotData structs.)
2244  */
2245  if (snapshot->xip == NULL)
2246  {
2247  /*
2248  * First call for this snapshot. Snapshot is same size whether or not
2249  * we are in recovery, see later comments.
2250  */
2251  snapshot->xip = (TransactionId *)
2253  if (snapshot->xip == NULL)
2254  ereport(ERROR,
2255  (errcode(ERRCODE_OUT_OF_MEMORY),
2256  errmsg("out of memory")));
2257  Assert(snapshot->subxip == NULL);
2258  snapshot->subxip = (TransactionId *)
2260  if (snapshot->subxip == NULL)
2261  ereport(ERROR,
2262  (errcode(ERRCODE_OUT_OF_MEMORY),
2263  errmsg("out of memory")));
2264  }
2265 
2266  /*
2267  * It is sufficient to get shared lock on ProcArrayLock, even if we are
2268  * going to set MyProc->xmin.
2269  */
2270  LWLockAcquire(ProcArrayLock, LW_SHARED);
2271 
2272  if (GetSnapshotDataReuse(snapshot))
2273  {
2274  LWLockRelease(ProcArrayLock);
2275  return snapshot;
2276  }
2277 
2278  latest_completed = ShmemVariableCache->latestCompletedXid;
2279  mypgxactoff = MyProc->pgxactoff;
2280  myxid = other_xids[mypgxactoff];
2281  Assert(myxid == MyProc->xid);
2282 
2283  oldestxid = ShmemVariableCache->oldestXid;
2284  curXactCompletionCount = ShmemVariableCache->xactCompletionCount;
2285 
2286  /* xmax is always latestCompletedXid + 1 */
2287  xmax = XidFromFullTransactionId(latest_completed);
2288  TransactionIdAdvance(xmax);
2290 
2291  /* initialize xmin calculation with xmax */
2292  xmin = xmax;
2293 
2294  /* take own xid into account, saves a check inside the loop */
2295  if (TransactionIdIsNormal(myxid) && NormalTransactionIdPrecedes(myxid, xmin))
2296  xmin = myxid;
2297 
2299 
2300  if (!snapshot->takenDuringRecovery)
2301  {
2302  int numProcs = arrayP->numProcs;
2303  TransactionId *xip = snapshot->xip;
2304  int *pgprocnos = arrayP->pgprocnos;
2305  XidCacheStatus *subxidStates = ProcGlobal->subxidStates;
2306  uint8 *allStatusFlags = ProcGlobal->statusFlags;
2307 
2308  /*
2309  * First collect set of pgxactoff/xids that need to be included in the
2310  * snapshot.
2311  */
2312  for (int pgxactoff = 0; pgxactoff < numProcs; pgxactoff++)
2313  {
2314  /* Fetch xid just once - see GetNewTransactionId */
2315  TransactionId xid = UINT32_ACCESS_ONCE(other_xids[pgxactoff]);
2316  uint8 statusFlags;
2317 
2318  Assert(allProcs[arrayP->pgprocnos[pgxactoff]].pgxactoff == pgxactoff);
2319 
2320  /*
2321  * If the transaction has no XID assigned, we can skip it; it
2322  * won't have sub-XIDs either.
2323  */
2324  if (likely(xid == InvalidTransactionId))
2325  continue;
2326 
2327  /*
2328  * We don't include our own XIDs (if any) in the snapshot. It
2329  * needs to be included in the xmin computation, but we did so
2330  * outside the loop.
2331  */
2332  if (pgxactoff == mypgxactoff)
2333  continue;
2334 
2335  /*
2336  * The only way we are able to get here with a non-normal xid is
2337  * during bootstrap - with this backend using
2338  * BootstrapTransactionId. But the above test should filter that
2339  * out.
2340  */
2342 
2343  /*
2344  * If the XID is >= xmax, we can skip it; such transactions will
2345  * be treated as running anyway (and any sub-XIDs will also be >=
2346  * xmax).
2347  */
2348  if (!NormalTransactionIdPrecedes(xid, xmax))
2349  continue;
2350 
2351  /*
2352  * Skip over backends doing logical decoding which manages xmin
2353  * separately (check below) and ones running LAZY VACUUM.
2354  */
2355  statusFlags = allStatusFlags[pgxactoff];
2356  if (statusFlags & (PROC_IN_LOGICAL_DECODING | PROC_IN_VACUUM))
2357  continue;
2358 
2359  if (NormalTransactionIdPrecedes(xid, xmin))
2360  xmin = xid;
2361 
2362  /* Add XID to snapshot. */
2363  xip[count++] = xid;
2364 
2365  /*
2366  * Save subtransaction XIDs if possible (if we've already
2367  * overflowed, there's no point). Note that the subxact XIDs must
2368  * be later than their parent, so no need to check them against
2369  * xmin. We could filter against xmax, but it seems better not to
2370  * do that much work while holding the ProcArrayLock.
2371  *
2372  * The other backend can add more subxids concurrently, but cannot
2373  * remove any. Hence it's important to fetch nxids just once.
2374  * Should be safe to use memcpy, though. (We needn't worry about
2375  * missing any xids added concurrently, because they must postdate
2376  * xmax.)
2377  *
2378  * Again, our own XIDs are not included in the snapshot.
2379  */
2380  if (!suboverflowed)
2381  {
2382 
2383  if (subxidStates[pgxactoff].overflowed)
2384  suboverflowed = true;
2385  else
2386  {
2387  int nsubxids = subxidStates[pgxactoff].count;
2388 
2389  if (nsubxids > 0)
2390  {
2391  int pgprocno = pgprocnos[pgxactoff];
2392  PGPROC *proc = &allProcs[pgprocno];
2393 
2394  pg_read_barrier(); /* pairs with GetNewTransactionId */
2395 
2396  memcpy(snapshot->subxip + subcount,
2397  (void *) proc->subxids.xids,
2398  nsubxids * sizeof(TransactionId));
2399  subcount += nsubxids;
2400  }
2401  }
2402  }
2403  }
2404  }
2405  else
2406  {
2407  /*
2408  * We're in hot standby, so get XIDs from KnownAssignedXids.
2409  *
2410  * We store all xids directly into subxip[]. Here's why:
2411  *
2412  * In recovery we don't know which xids are top-level and which are
2413  * subxacts, a design choice that greatly simplifies xid processing.
2414  *
2415  * It seems like we would want to try to put xids into xip[] only, but
2416  * that is fairly small. We would either need to make that bigger or
2417  * to increase the rate at which we WAL-log xid assignment; neither is
2418  * an appealing choice.
2419  *
2420  * We could try to store xids into xip[] first and then into subxip[]
2421  * if there are too many xids. That only works if the snapshot doesn't
2422  * overflow because we do not search subxip[] in that case. A simpler
2423  * way is to just store all xids in the subxip array because this is
2424  * by far the bigger array. We just leave the xip array empty.
2425  *
2426  * Either way we need to change the way XidInMVCCSnapshot() works
2427  * depending upon when the snapshot was taken, or change normal
2428  * snapshot processing so it matches.
2429  *
2430  * Note: It is possible for recovery to end before we finish taking
2431  * the snapshot, and for newly assigned transaction ids to be added to
2432  * the ProcArray. xmax cannot change while we hold ProcArrayLock, so
2433  * those newly added transaction ids would be filtered away, so we
2434  * need not be concerned about them.
2435  */
2436  subcount = KnownAssignedXidsGetAndSetXmin(snapshot->subxip, &xmin,
2437  xmax);
2438 
2440  suboverflowed = true;
2441  }
2442 
2443 
2444  /*
2445  * Fetch into local variable while ProcArrayLock is held - the
2446  * LWLockRelease below is a barrier, ensuring this happens inside the
2447  * lock.
2448  */
2449  replication_slot_xmin = procArray->replication_slot_xmin;
2450  replication_slot_catalog_xmin = procArray->replication_slot_catalog_xmin;
2451 
2453  MyProc->xmin = TransactionXmin = xmin;
2454 
2455  LWLockRelease(ProcArrayLock);
2456 
2457  /* maintain state for GlobalVis* */
2458  {
2459  TransactionId def_vis_xid;
2460  TransactionId def_vis_xid_data;
2461  FullTransactionId def_vis_fxid;
2462  FullTransactionId def_vis_fxid_data;
2463  FullTransactionId oldestfxid;
2464 
2465  /*
2466  * Converting oldestXid is only safe when xid horizon cannot advance,
2467  * i.e. holding locks. While we don't hold the lock anymore, all the
2468  * necessary data has been gathered with lock held.
2469  */
2470  oldestfxid = FullXidRelativeTo(latest_completed, oldestxid);
2471 
2472  /* apply vacuum_defer_cleanup_age */
2473  def_vis_xid_data =
2475 
2476  /* Check whether there's a replication slot requiring an older xmin. */
2477  def_vis_xid_data =
2478  TransactionIdOlder(def_vis_xid_data, replication_slot_xmin);
2479 
2480  /*
2481  * Rows in non-shared, non-catalog tables possibly could be vacuumed
2482  * if older than this xid.
2483  */
2484  def_vis_xid = def_vis_xid_data;
2485 
2486  /*
2487  * Check whether there's a replication slot requiring an older catalog
2488  * xmin.
2489  */
2490  def_vis_xid =
2491  TransactionIdOlder(replication_slot_catalog_xmin, def_vis_xid);
2492 
2493  def_vis_fxid = FullXidRelativeTo(latest_completed, def_vis_xid);
2494  def_vis_fxid_data = FullXidRelativeTo(latest_completed, def_vis_xid_data);
2495 
2496  /*
2497  * Check if we can increase upper bound. As a previous
2498  * GlobalVisUpdate() might have computed more aggressive values, don't
2499  * overwrite them if so.
2500  */
2502  FullTransactionIdNewer(def_vis_fxid,
2505  FullTransactionIdNewer(def_vis_fxid,
2508  FullTransactionIdNewer(def_vis_fxid_data,
2510  /* See temp_oldest_nonremovable computation in ComputeXidHorizons() */
2511  if (TransactionIdIsNormal(myxid))
2513  FullXidRelativeTo(latest_completed, myxid);
2514  else
2515  {
2516  GlobalVisTempRels.definitely_needed = latest_completed;
2518  }
2519 
2520  /*
2521  * Check if we know that we can initialize or increase the lower
2522  * bound. Currently the only cheap way to do so is to use
2523  * ShmemVariableCache->oldestXid as input.
2524  *
2525  * We should definitely be able to do better. We could e.g. put a
2526  * global lower bound value into ShmemVariableCache.
2527  */
2530  oldestfxid);
2533  oldestfxid);
2536  oldestfxid);
2537  /* accurate value known */
2539  }
2540 
2541  RecentXmin = xmin;
2543 
2544  snapshot->xmin = xmin;
2545  snapshot->xmax = xmax;
2546  snapshot->xcnt = count;
2547  snapshot->subxcnt = subcount;
2548  snapshot->suboverflowed = suboverflowed;
2549  snapshot->snapXactCompletionCount = curXactCompletionCount;
2550 
2551  snapshot->curcid = GetCurrentCommandId(false);
2552 
2553  /*
2554  * This is a new snapshot, so set both refcounts are zero, and mark it as
2555  * not copied in persistent memory.
2556  */
2557  snapshot->active_count = 0;
2558  snapshot->regd_count = 0;
2559  snapshot->copied = false;
2560 
2562 
2563  return snapshot;
2564 }
#define likely(x)
Definition: c.h:294
#define PROC_IN_LOGICAL_DECODING
Definition: proc.h:60
#define PROC_IN_VACUUM
Definition: proc.h:57
static GlobalVisState GlobalVisDataRels
Definition: procarray.c:302
static void GetSnapshotDataInitOldSnapshot(Snapshot snapshot)
Definition: procarray.c:2097
static GlobalVisState GlobalVisSharedRels
Definition: procarray.c:300
static GlobalVisState GlobalVisCatalogRels
Definition: procarray.c:301
static FullTransactionId FullXidRelativeTo(FullTransactionId rel, TransactionId xid)
Definition: procarray.c:4310
static int KnownAssignedXidsGetAndSetXmin(TransactionId *xarray, TransactionId *xmin, TransactionId xmax)
Definition: procarray.c:5107
int GetMaxSnapshotSubxidCount(void)
Definition: procarray.c:2088
static GlobalVisState GlobalVisTempRels
Definition: procarray.c:303
int GetMaxSnapshotXidCount(void)
Definition: procarray.c:2077
static bool GetSnapshotDataReuse(Snapshot snapshot)
Definition: procarray.c:2131
TransactionId RecentXmin
Definition: snapmgr.c:114
TransactionId TransactionXmin
Definition: snapmgr.c:113
int vacuum_defer_cleanup_age
Definition: standby.c:40
FullTransactionId definitely_needed
Definition: procarray.c:173
FullTransactionId maybe_needed
Definition: procarray.c:176
int pgxactoff
Definition: proc.h:188
TransactionId xid
Definition: proc.h:173
TransactionId xmin
Definition: snapshot.h:157
int32 subxcnt
Definition: snapshot.h:181
bool copied
Definition: snapshot.h:185
uint32 regd_count
Definition: snapshot.h:205
uint32 active_count
Definition: snapshot.h:204
CommandId curcid
Definition: snapshot.h:187
uint32 xcnt
Definition: snapshot.h:169
TransactionId * subxip
Definition: snapshot.h:180
uint64 snapXactCompletionCount
Definition: snapshot.h:216
TransactionId xmax
Definition: snapshot.h:158
TransactionId * xip
Definition: snapshot.h:168
bool suboverflowed
Definition: snapshot.h:182
bool takenDuringRecovery
Definition: snapshot.h:184
TransactionId oldestXid
Definition: transam.h:222
static TransactionId TransactionIdRetreatedBy(TransactionId xid, uint32 amount)
Definition: transam.h:322
static FullTransactionId FullTransactionIdNewer(FullTransactionId a, FullTransactionId b)
Definition: transam.h:360
#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:334
CommandId GetCurrentCommandId(bool used)
Definition: xact.c:818

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

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

◆ GetVirtualXIDsDelayingChkpt()

VirtualTransactionId* GetVirtualXIDsDelayingChkpt ( int *  nvxids,
int  type 
)

Definition at line 3067 of file procarray.c.

3068 {
3069  VirtualTransactionId *vxids;
3070  ProcArrayStruct *arrayP = procArray;
3071  int count = 0;
3072  int index;
3073 
3074  Assert(type != 0);
3075 
3076  /* allocate what's certainly enough result space */
3077  vxids = (VirtualTransactionId *)
3078  palloc(sizeof(VirtualTransactionId) * arrayP->maxProcs);
3079 
3080  LWLockAcquire(ProcArrayLock, LW_SHARED);
3081 
3082  for (index = 0; index < arrayP->numProcs; index++)
3083  {
3084  int pgprocno = arrayP->pgprocnos[index];
3085  PGPROC *proc = &allProcs[pgprocno];
3086 
3087  if ((proc->delayChkptFlags & type) != 0)
3088  {
3089  VirtualTransactionId vxid;
3090 
3091  GET_VXID_FROM_PGPROC(vxid, *proc);
3092  if (VirtualTransactionIdIsValid(vxid))
3093  vxids[count++] = vxid;
3094  }
3095  }
3096 
3097  LWLockRelease(ProcArrayLock);
3098 
3099  *nvxids = count;
3100  return vxids;
3101 }
int delayChkptFlags
Definition: proc.h:231

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

Referenced by CreateCheckPoint().

◆ HaveVirtualXIDsDelayingChkpt()

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

Definition at line 3113 of file procarray.c.

3114 {
3115  bool result = false;
3116  ProcArrayStruct *arrayP = procArray;
3117  int index;
3118 
3119  Assert(type != 0);
3120 
3121  LWLockAcquire(ProcArrayLock, LW_SHARED);
3122 
3123  for (index = 0; index < arrayP->numProcs; index++)
3124  {
3125  int pgprocno = arrayP->pgprocnos[index];
3126  PGPROC *proc = &allProcs[pgprocno];
3127  VirtualTransactionId vxid;
3128 
3129  GET_VXID_FROM_PGPROC(vxid, *proc);
3130 
3131  if ((proc->delayChkptFlags & type) != 0 &&
3133  {
3134  int i;
3135 
3136  for (i = 0; i < nvxids; i++)
3137  {
3138  if (VirtualTransactionIdEquals(vxid, vxids[i]))
3139  {
3140  result = true;
3141  break;
3142  }
3143  }
3144  if (result)
3145  break;
3146  }
3147  }
3148 
3149  LWLockRelease(ProcArrayLock);
3150 
3151  return result;
3152 }
int i
Definition: isn.c:73
#define VirtualTransactionIdEquals(vxid1, vxid2)
Definition: lock.h:71

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

Referenced by CreateCheckPoint().

◆ IsBackendPid()

bool IsBackendPid ( int  pid)

Definition at line 3257 of file procarray.c.

3258 {
3259  return (BackendPidGetProc(pid) != NULL);
3260 }
PGPROC * BackendPidGetProc(int pid)
Definition: procarray.c:3162

References BackendPidGetProc().

Referenced by pg_stat_get_subscription().

◆ KnownAssignedTransactionIdsIdleMaintenance()

void KnownAssignedTransactionIdsIdleMaintenance ( void  )

Definition at line 4529 of file procarray.c.

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

References KAX_STARTUP_PROCESS_IDLE, and KnownAssignedXidsCompress().

Referenced by WaitForWALToBecomeAvailable().

◆ MinimumActiveBackends()

bool MinimumActiveBackends ( int  min)

Definition at line 3512 of file procarray.c.

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

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

Referenced by XLogFlush().

◆ ProcArrayAdd()

void ProcArrayAdd ( PGPROC proc)

Definition at line 472 of file procarray.c.

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

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

Referenced by InitProcessPhase2(), and MarkAsPrepared().

◆ ProcArrayApplyRecoveryInfo()

void ProcArrayApplyRecoveryInfo ( RunningTransactions  running)

Definition at line 1056 of file procarray.c.

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

References AdvanceNextFullTransactionIdPastXid(), Assert(), DEBUG1, DEBUG3, elog(), ERROR, ExpireOldKnownAssignedTransactionIds(), ExtendSUBTRANS(), FullTransactionIdIsValid, i, InvalidTransactionId, KnownAssignedXidsAdd(), KnownAssignedXidsDisplay(), KnownAssignedXidsReset(), ProcArrayStruct::lastOverflowedXid, RunningTransactionsData::latestCompletedXid, latestObservedXid, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MaintainLatestCompletedXidRecovery(), VariableCacheData::nextXid, RunningTransactionsData::nextXid, ProcArrayStruct::numKnownAssignedXids, RunningTransactionsData::oldestRunningXid, palloc(), pfree(), procArray, qsort, ShmemVariableCache, STANDBY_INITIALIZED, STANDBY_SNAPSHOT_PENDING, STANDBY_SNAPSHOT_READY, StandbyReleaseOldLocks(), standbySnapshotPendingXmin, standbyState, RunningTransactionsData::subxcnt, RunningTransactionsData::subxid_overflow, trace_recovery(), TransactionIdAdvance, TransactionIdDidAbort(), TransactionIdDidCommit(), TransactionIdEquals, TransactionIdIsNormal, TransactionIdIsValid, TransactionIdPrecedes(), TransactionIdRetreat, RunningTransactionsData::xcnt, xidLogicalComparator(), and RunningTransactionsData::xids.

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

◆ ProcArrayApplyXidAssignment()

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

Definition at line 1302 of file procarray.c.

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

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

Referenced by xact_redo().

◆ ProcArrayClearTransaction()

void ProcArrayClearTransaction ( PGPROC proc)

Definition at line 909 of file procarray.c.

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

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

Referenced by PrepareTransaction().

◆ ProcArrayEndTransaction()

void ProcArrayEndTransaction ( PGPROC proc,
TransactionId  latestXid 
)

Definition at line 670 of file procarray.c.

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

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

Referenced by AbortTransaction(), and CommitTransaction().

◆ ProcArrayGetReplicationSlotXmin()

void ProcArrayGetReplicationSlotXmin ( TransactionId xmin,
TransactionId catalog_xmin 
)

Definition at line 3927 of file procarray.c.

3929 {
3930  LWLockAcquire(ProcArrayLock, LW_SHARED);
3931 
3932  if (xmin != NULL)
3934 
3935  if (catalog_xmin != NULL)
3936  *catalog_xmin = procArray->replication_slot_catalog_xmin;
3937 
3938  LWLockRelease(ProcArrayLock);
3939 }

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

Referenced by logical_begin_heap_rewrite().

◆ ProcArrayInitRecovery()

void ProcArrayInitRecovery ( TransactionId  initializedUptoXID)

Definition at line 1025 of file procarray.c.

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

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

Referenced by StartupXLOG().

◆ ProcArrayInstallImportedXmin()

bool ProcArrayInstallImportedXmin ( TransactionId  xmin,
VirtualTransactionId sourcevxid 
)

Definition at line 2577 of file procarray.c.

2579 {
2580  bool result = false;
2581  ProcArrayStruct *arrayP = procArray;
2582  int index;
2583 
2585  if (!sourcevxid)
2586  return false;
2587 
2588  /* Get lock so source xact can't end while we're doing this */
2589  LWLockAcquire(ProcArrayLock, LW_SHARED);
2590 
2591  for (index = 0; index < arrayP->numProcs; index++)
2592  {
2593  int pgprocno = arrayP->pgprocnos[index];
2594  PGPROC *proc = &allProcs[pgprocno];
2595  int statusFlags = ProcGlobal->statusFlags[index];
2596  TransactionId xid;
2597 
2598  /* Ignore procs running LAZY VACUUM */
2599  if (statusFlags & PROC_IN_VACUUM)
2600  continue;
2601 
2602  /* We are only interested in the specific virtual transaction. */
2603  if (proc->backendId != sourcevxid->backendId)
2604  continue;
2605  if (proc->lxid != sourcevxid->localTransactionId)
2606  continue;
2607 
2608  /*
2609  * We check the transaction's database ID for paranoia's sake: if it's
2610  * in another DB then its xmin does not cover us. Caller should have
2611  * detected this already, so we just treat any funny cases as
2612  * "transaction not found".
2613  */
2614  if (proc->databaseId != MyDatabaseId)
2615  continue;
2616 
2617  /*
2618  * Likewise, let's just make real sure its xmin does cover us.
2619  */
2620  xid = UINT32_ACCESS_ONCE(proc->xmin);
2621  if (!TransactionIdIsNormal(xid) ||
2622  !TransactionIdPrecedesOrEquals(xid, xmin))
2623  continue;
2624 
2625  /*
2626  * We're good. Install the new xmin. As in GetSnapshotData, set
2627  * TransactionXmin too. (Note that because snapmgr.c called
2628  * GetSnapshotData first, we'll be overwriting a valid xmin here, so
2629  * we don't check that.)
2630  */
2631  MyProc->xmin = TransactionXmin = xmin;
2632 
2633  result = true;
2634  break;
2635  }
2636 
2637  LWLockRelease(ProcArrayLock);
2638 
2639  return result;
2640 }
BackendId backendId
Definition: proc.h:197

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

Referenced by GetSerializableTransactionSnapshotInt(), and SetTransactionSnapshot().

◆ ProcArrayInstallRestoredXmin()

bool ProcArrayInstallRestoredXmin ( TransactionId  xmin,
PGPROC proc 
)

Definition at line 2656 of file procarray.c.

2657 {
2658  bool result = false;
2659  TransactionId xid;
2660 
2662  Assert(proc != NULL);
2663 
2664  /*
2665  * Get an exclusive lock so that we can copy statusFlags from source proc.
2666  */
2667  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
2668 
2669  /*
2670  * Be certain that the referenced PGPROC has an advertised xmin which is
2671  * no later than the one we're installing, so that the system-wide xmin
2672  * can't go backwards. Also, make sure it's running in the same database,
2673  * so that the per-database xmin cannot go backwards.
2674  */
2675  xid = UINT32_ACCESS_ONCE(proc->xmin);
2676  if (proc->databaseId == MyDatabaseId &&
2677  TransactionIdIsNormal(xid) &&
2678  TransactionIdPrecedesOrEquals(xid, xmin))
2679  {
2680  /*
2681  * Install xmin and propagate the statusFlags that affect how the
2682  * value is interpreted by vacuum.
2683  */
2684  MyProc->xmin = TransactionXmin = xmin;
2686  (proc->statusFlags & PROC_XMIN_FLAGS);
2688 
2689  result = true;
2690  }
2691 
2692  LWLockRelease(ProcArrayLock);
2693 
2694  return result;
2695 }
#define PROC_XMIN_FLAGS
Definition: proc.h:71

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

Referenced by SetTransactionSnapshot().

◆ ProcArrayRemove()

void ProcArrayRemove ( PGPROC proc,
TransactionId  latestXid 
)

Definition at line 568 of file procarray.c.

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

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

Referenced by FinishPreparedTransaction(), and RemoveProcFromArray().

◆ ProcArraySetReplicationSlotXmin()

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

Definition at line 3902 of file procarray.c.

3904 {
3905  Assert(!already_locked || LWLockHeldByMe(ProcArrayLock));
3906 
3907  if (!already_locked)
3908  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3909 
3911  procArray->replication_slot_catalog_xmin = catalog_xmin;
3912 
3913  if (!already_locked)
3914  LWLockRelease(ProcArrayLock);
3915 
3916  elog(DEBUG1, "xmin required by slots: data %u, catalog %u",
3917  xmin, catalog_xmin);
3918 }

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

Referenced by ReplicationSlotsComputeRequiredXmin().

◆ ProcArrayShmemSize()

Size ProcArrayShmemSize ( void  )

Definition at line 379 of file procarray.c.

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

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

Referenced by CalculateShmemSize().

◆ RecordKnownAssignedTransactionIds()

void RecordKnownAssignedTransactionIds ( TransactionId  xid)

Definition at line 4392 of file procarray.c.

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

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

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

◆ SignalVirtualTransaction()

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

Definition at line 3463 of file procarray.c.

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

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

Referenced by CancelVirtualTransaction(), and ResolveRecoveryConflictWithLock().

◆ TerminateOtherDBBackends()

void TerminateOtherDBBackends ( Oid  databaseId)

Definition at line 3794 of file procarray.c.

3795 {
3796  ProcArrayStruct *arrayP = procArray;
3797  List *pids = NIL;
3798  int nprepared = 0;
3799  int i;
3800 
3801  LWLockAcquire(ProcArrayLock, LW_SHARED);
3802 
3803  for (i = 0; i < procArray->numProcs; i++)
3804  {
3805  int pgprocno = arrayP->pgprocnos[i];
3806  PGPROC *proc = &allProcs[pgprocno];
3807 
3808  if (proc->databaseId != databaseId)
3809  continue;
3810  if (proc == MyProc)
3811  continue;
3812 
3813  if (proc->pid != 0)
3814  pids = lappend_int(pids, proc->pid);
3815  else
3816  nprepared++;
3817  }
3818 
3819  LWLockRelease(ProcArrayLock);
3820 
3821  if (nprepared > 0)
3822  ereport(ERROR,
3823  (errcode(ERRCODE_OBJECT_IN_USE),
3824  errmsg("database \"%s\" is being used by prepared transactions",
3825  get_database_name(databaseId)),
3826  errdetail_plural("There is %d prepared transaction using the database.",
3827  "There are %d prepared transactions using the database.",
3828  nprepared,
3829  nprepared)));
3830 
3831  if (pids)
3832  {
3833  ListCell *lc;
3834 
3835  /*
3836  * Check whether we have the necessary rights to terminate other
3837  * sessions. We don't terminate any session until we ensure that we
3838  * have rights on all the sessions to be terminated. These checks are
3839  * the same as we do in pg_terminate_backend.
3840  *
3841  * In this case we don't raise some warnings - like "PID %d is not a
3842  * PostgreSQL server process", because for us already finished session
3843  * is not a problem.
3844  */
3845  foreach(lc, pids)
3846  {
3847  int pid = lfirst_int(lc);
3848  PGPROC *proc = BackendPidGetProc(pid);
3849 
3850  if (proc != NULL)
3851  {
3852  /* Only allow superusers to signal superuser-owned backends. */
3853  if (superuser_arg(proc->roleId) && !superuser())
3854  ereport(ERROR,
3855  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
3856  errmsg("must be a superuser to terminate superuser process")));
3857 
3858  /* Users can signal backends they have role membership in. */
3859  if (!has_privs_of_role(GetUserId(), proc->roleId) &&
3860  !has_privs_of_role(GetUserId(), ROLE_PG_SIGNAL_BACKEND))
3861  ereport(ERROR,
3862  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
3863  errmsg("must be a member of the role whose process is being terminated or member of pg_signal_backend")));
3864  }
3865  }
3866 
3867  /*
3868  * There's a race condition here: once we release the ProcArrayLock,
3869  * it's possible for the session to exit before we issue kill. That
3870  * race condition possibility seems too unlikely to worry about. See
3871  * pg_signal_backend.
3872  */
3873  foreach(lc, pids)
3874  {
3875  int pid = lfirst_int(lc);
3876  PGPROC *proc = BackendPidGetProc(pid);
3877 
3878  if (proc != NULL)
3879  {
3880  /*
3881  * If we have setsid(), signal the backend's whole process
3882  * group
3883  */
3884 #ifdef HAVE_SETSID
3885  (void) kill(-pid, SIGTERM);
3886 #else
3887  (void) kill(pid, SIGTERM);
3888 #endif
3889  }
3890  }
3891  }
3892 }
bool has_privs_of_role(Oid member, Oid role)
Definition: acl.c:4969
char * get_database_name(Oid dbid)
Definition: dbcommands.c:2980
int errdetail_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n,...)
Definition: elog.c:1294
List * lappend_int(List *list, int datum)
Definition: list.c:356
Oid GetUserId(void)
Definition: miscinit.c:502
#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_plural(), errmsg(), ERROR, get_database_name(), GetUserId(), has_privs_of_role(), i, kill, lappend_int(), lfirst_int, LW_SHARED, LWLockAcquire(), LWLockRelease(), MyProc, NIL, ProcArrayStruct::numProcs, ProcArrayStruct::pgprocnos, PGPROC::pid, procArray, PGPROC::roleId, superuser(), and superuser_arg().

Referenced by dropdb().

◆ TransactionIdIsActive()

bool TransactionIdIsActive ( TransactionId  xid)

Definition at line 1618 of file procarray.c.

1619 {
1620  bool result = false;
1621  ProcArrayStruct *arrayP = procArray;
1622  TransactionId *other_xids = ProcGlobal->xids;
1623  int i;
1624 
1625  /*
1626  * Don't bother checking a transaction older than RecentXmin; it could not
1627  * possibly still be running.
1628  */
1630  return false;
1631 
1632  LWLockAcquire(ProcArrayLock, LW_SHARED);
1633 
1634  for (i = 0; i < arrayP->numProcs; i++)
1635  {
1636  int pgprocno = arrayP->pgprocnos[i];
1637  PGPROC *proc = &allProcs[pgprocno];
1638  TransactionId pxid;
1639 
1640  /* Fetch xid just once - see GetNewTransactionId */
1641  pxid = UINT32_ACCESS_ONCE(other_xids[i]);
1642 
1643  if (!TransactionIdIsValid(pxid))
1644  continue;
1645 
1646  if (proc->pid == 0)
1647  continue; /* ignore prepared transactions */
1648 
1649  if (TransactionIdEquals(pxid, xid))
1650  {
1651  result = true;
1652  break;
1653  }
1654  }
1655 
1656  LWLockRelease(ProcArrayLock);
1657 
1658  return result;
1659 }

References allProcs, i, LW_SHARED, LWLockAcquire(), LWLockRelease(), ProcArrayStruct::numProcs, ProcArrayStruct::pgprocnos, PGPROC::pid, procArray, ProcGlobal, RecentXmin, TransactionIdEquals, TransactionIdIsValid, TransactionIdPrecedes(), UINT32_ACCESS_ONCE, and PROC_HDR::xids.

◆ TransactionIdIsInProgress()

bool TransactionIdIsInProgress ( TransactionId  xid)

Definition at line 1386 of file procarray.c.

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

References allProcs, Assert(), cachedXidIsNotInProgress, XidCacheStatus::count, ereport, errcode(), errmsg(), ERROR, j, KnownAssignedXidExists(), KnownAssignedXidsGet(), ProcArrayStruct::lastOverflowedXid, VariableCacheData::latestCompletedXid, LW_SHARED, LWLockAcquire(), LWLockRelease(), malloc, ProcArrayStruct::maxProcs, MyProc, ProcArrayStruct::numProcs, pg_lfind32(), pg_read_barrier, ProcArrayStruct::pgprocnos, PGPROC::pgxactoff, procArray, ProcGlobal, RecentXmin, RecoveryInProgress(), ShmemVariableCache, SubTransGetTopmostTransaction(), PGPROC::subxids, PROC_HDR::subxidStates, TOTAL_MAX_CACHED_SUBXIDS, TransactionIdDidAbort(), TransactionIdEquals, TransactionIdIsCurrentTransactionId(), TransactionIdIsValid, TransactionIdPrecedes(), TransactionIdPrecedesOrEquals(), 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(), HandleConcurrentAbort(), HeapTupleHeaderIsOnlyLocked(), HeapTupleSatisfiesDirty(), HeapTupleSatisfiesSelf(), HeapTupleSatisfiesToast(), HeapTupleSatisfiesUpdate(), HeapTupleSatisfiesVacuumHorizon(), MultiXactIdExpand(), MultiXactIdIsRunning(), pg_xact_status(), test_lockmode_for_conflict(), and XactLockTableWait().

◆ XidCacheRemoveRunningXids()

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

Definition at line 3950 of file procarray.c.

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

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

Referenced by RecordTransactionAbort().