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)
 
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 *slot_xmin, TransactionId *catalog_xmin)
 
VirtualTransactionIdGetVirtualXIDsDelayingChkpt (int *nvxids)
 
bool HaveVirtualXIDsDelayingChkpt (VirtualTransactionId *vxids, int nvxids)
 
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 3133 of file procarray.c.

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(), ProcSendSignal(), TerminateOtherDBBackends(), and test_shm_mq_main().

3134 {
3135  PGPROC *result;
3136 
3137  if (pid == 0) /* never match dummy PGPROCs */
3138  return NULL;
3139 
3140  LWLockAcquire(ProcArrayLock, LW_SHARED);
3141 
3142  result = BackendPidGetProcWithLock(pid);
3143 
3144  LWLockRelease(ProcArrayLock);
3145 
3146  return result;
3147 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1803
PGPROC * BackendPidGetProcWithLock(int pid)
Definition: procarray.c:3156
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1199
Definition: proc.h:121

◆ BackendPidGetProcWithLock()

PGPROC* BackendPidGetProcWithLock ( int  pid)

Definition at line 3156 of file procarray.c.

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

Referenced by BackendPidGetProc(), and GetBlockerStatusData().

3157 {
3158  PGPROC *result = NULL;
3159  ProcArrayStruct *arrayP = procArray;
3160  int index;
3161 
3162  if (pid == 0) /* never match dummy PGPROCs */
3163  return NULL;
3164 
3165  for (index = 0; index < arrayP->numProcs; index++)
3166  {
3167  PGPROC *proc = &allProcs[arrayP->pgprocnos[index]];
3168 
3169  if (proc->pid == pid)
3170  {
3171  result = proc;
3172  break;
3173  }
3174  }
3175 
3176  return result;
3177 }
Definition: type.h:89
static PGPROC * allProcs
Definition: procarray.c:263
static ProcArrayStruct * procArray
Definition: procarray.c:261
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
Definition: proc.h:121
int pid
Definition: proc.h:146

◆ BackendXidGetPid()

int BackendXidGetPid ( TransactionId  xid)

Definition at line 3193 of file procarray.c.

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

Referenced by pgrowlocks().

3194 {
3195  int result = 0;
3196  ProcArrayStruct *arrayP = procArray;
3197  TransactionId *other_xids = ProcGlobal->xids;
3198  int index;
3199 
3200  if (xid == InvalidTransactionId) /* never match invalid xid */
3201  return 0;
3202 
3203  LWLockAcquire(ProcArrayLock, LW_SHARED);
3204 
3205  for (index = 0; index < arrayP->numProcs; index++)
3206  {
3207  int pgprocno = arrayP->pgprocnos[index];
3208  PGPROC *proc = &allProcs[pgprocno];
3209 
3210  if (other_xids[index] == xid)
3211  {
3212  result = proc->pid;
3213  break;
3214  }
3215  }
3216 
3217  LWLockRelease(ProcArrayLock);
3218 
3219  return result;
3220 }
uint32 TransactionId
Definition: c.h:587
PROC_HDR * ProcGlobal
Definition: proc.c:80
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1803
#define InvalidTransactionId
Definition: transam.h:31
TransactionId * xids
Definition: proc.h:321
static PGPROC * allProcs
Definition: procarray.c:263
static ProcArrayStruct * procArray
Definition: procarray.c:261
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1199
Definition: proc.h:121
int pid
Definition: proc.h:146

◆ CancelDBBackends()

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

Definition at line 3592 of file procarray.c.

References 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().

3593 {
3594  ProcArrayStruct *arrayP = procArray;
3595  int index;
3596 
3597  /* tell all backends to die */
3598  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3599 
3600  for (index = 0; index < arrayP->numProcs; index++)
3601  {
3602  int pgprocno = arrayP->pgprocnos[index];
3603  PGPROC *proc = &allProcs[pgprocno];
3604 
3605  if (databaseid == InvalidOid || proc->databaseId == databaseid)
3606  {
3607  VirtualTransactionId procvxid;
3608  pid_t pid;
3609 
3610  GET_VXID_FROM_PGPROC(procvxid, *proc);
3611 
3612  proc->recoveryConflictPending = conflictPending;
3613  pid = proc->pid;
3614  if (pid != 0)
3615  {
3616  /*
3617  * Kill the pid if it's still here. If not, that's what we
3618  * wanted so ignore any errors.
3619  */
3620  (void) SendProcSignal(pid, sigmode, procvxid.backendId);
3621  }
3622  }
3623  }
3624 
3625  LWLockRelease(ProcArrayLock);
3626 }
#define GET_VXID_FROM_PGPROC(vxid, proc)
Definition: lock.h:81
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1803
int SendProcSignal(pid_t pid, ProcSignalReason reason, BackendId backendId)
Definition: procsignal.c:261
bool recoveryConflictPending
Definition: proc.h:167
static PGPROC * allProcs
Definition: procarray.c:263
Oid databaseId
Definition: proc.h:154
static ProcArrayStruct * procArray
Definition: procarray.c:261
#define InvalidOid
Definition: postgres_ext.h:36
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
BackendId backendId
Definition: lock.h:65
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1199
Definition: proc.h:121
int pid
Definition: proc.h:146

◆ CancelVirtualTransaction()

pid_t CancelVirtualTransaction ( VirtualTransactionId  vxid,
ProcSignalReason  sigmode 
)

Definition at line 3423 of file procarray.c.

References SignalVirtualTransaction().

Referenced by ResolveRecoveryConflictWithVirtualXIDs().

3424 {
3425  return SignalVirtualTransaction(vxid, sigmode, true);
3426 }
pid_t SignalVirtualTransaction(VirtualTransactionId vxid, ProcSignalReason sigmode, bool conflictPending)
Definition: procarray.c:3429

◆ CountDBBackends()

int CountDBBackends ( Oid  databaseid)

Definition at line 3531 of file procarray.c.

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

Referenced by ResolveRecoveryConflictWithDatabase().

3532 {
3533  ProcArrayStruct *arrayP = procArray;
3534  int count = 0;
3535  int index;
3536 
3537  LWLockAcquire(ProcArrayLock, LW_SHARED);
3538 
3539  for (index = 0; index < arrayP->numProcs; index++)
3540  {
3541  int pgprocno = arrayP->pgprocnos[index];
3542  PGPROC *proc = &allProcs[pgprocno];
3543 
3544  if (proc->pid == 0)
3545  continue; /* do not count prepared xacts */
3546  if (!OidIsValid(databaseid) ||
3547  proc->databaseId == databaseid)
3548  count++;
3549  }
3550 
3551  LWLockRelease(ProcArrayLock);
3552 
3553  return count;
3554 }
#define OidIsValid(objectId)
Definition: c.h:710
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1803
static PGPROC * allProcs
Definition: procarray.c:263
Oid databaseId
Definition: proc.h:154
static ProcArrayStruct * procArray
Definition: procarray.c:261
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1199
Definition: proc.h:121
int pid
Definition: proc.h:146

◆ CountDBConnections()

int CountDBConnections ( Oid  databaseid)

Definition at line 3561 of file procarray.c.

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

Referenced by CheckMyDatabase().

3562 {
3563  ProcArrayStruct *arrayP = procArray;
3564  int count = 0;
3565  int index;
3566 
3567  LWLockAcquire(ProcArrayLock, LW_SHARED);
3568 
3569  for (index = 0; index < arrayP->numProcs; index++)
3570  {
3571  int pgprocno = arrayP->pgprocnos[index];
3572  PGPROC *proc = &allProcs[pgprocno];
3573 
3574  if (proc->pid == 0)
3575  continue; /* do not count prepared xacts */
3576  if (proc->isBackgroundWorker)
3577  continue; /* do not count background workers */
3578  if (!OidIsValid(databaseid) ||
3579  proc->databaseId == databaseid)
3580  count++;
3581  }
3582 
3583  LWLockRelease(ProcArrayLock);
3584 
3585  return count;
3586 }
#define OidIsValid(objectId)
Definition: c.h:710
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1803
bool isBackgroundWorker
Definition: proc.h:160
static PGPROC * allProcs
Definition: procarray.c:263
Oid databaseId
Definition: proc.h:154
static ProcArrayStruct * procArray
Definition: procarray.c:261
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1199
Definition: proc.h:121
int pid
Definition: proc.h:146

◆ CountOtherDBBackends()

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

Definition at line 3682 of file procarray.c.

References 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().

3683 {
3684  ProcArrayStruct *arrayP = procArray;
3685 
3686 #define MAXAUTOVACPIDS 10 /* max autovacs to SIGTERM per iteration */
3687  int autovac_pids[MAXAUTOVACPIDS];
3688  int tries;
3689 
3690  /* 50 tries with 100ms sleep between tries makes 5 sec total wait */
3691  for (tries = 0; tries < 50; tries++)
3692  {
3693  int nautovacs = 0;
3694  bool found = false;
3695  int index;
3696 
3698 
3699  *nbackends = *nprepared = 0;
3700 
3701  LWLockAcquire(ProcArrayLock, LW_SHARED);
3702 
3703  for (index = 0; index < arrayP->numProcs; index++)
3704  {
3705  int pgprocno = arrayP->pgprocnos[index];
3706  PGPROC *proc = &allProcs[pgprocno];
3707  uint8 statusFlags = ProcGlobal->statusFlags[index];
3708 
3709  if (proc->databaseId != databaseId)
3710  continue;
3711  if (proc == MyProc)
3712  continue;
3713 
3714  found = true;
3715 
3716  if (proc->pid == 0)
3717  (*nprepared)++;
3718  else
3719  {
3720  (*nbackends)++;
3721  if ((statusFlags & PROC_IS_AUTOVACUUM) &&
3722  nautovacs < MAXAUTOVACPIDS)
3723  autovac_pids[nautovacs++] = proc->pid;
3724  }
3725  }
3726 
3727  LWLockRelease(ProcArrayLock);
3728 
3729  if (!found)
3730  return false; /* no conflicting backends, so done */
3731 
3732  /*
3733  * Send SIGTERM to any conflicting autovacuums before sleeping. We
3734  * postpone this step until after the loop because we don't want to
3735  * hold ProcArrayLock while issuing kill(). We have no idea what might
3736  * block kill() inside the kernel...
3737  */
3738  for (index = 0; index < nautovacs; index++)
3739  (void) kill(autovac_pids[index], SIGTERM); /* ignore any error */
3740 
3741  /* sleep, then try again */
3742  pg_usleep(100 * 1000L); /* 100ms */
3743  }
3744 
3745  return true; /* timed out, still conflicts */
3746 }
PGPROC * MyProc
Definition: proc.c:68
unsigned char uint8
Definition: c.h:439
PROC_HDR * ProcGlobal
Definition: proc.c:80
#define kill(pid, sig)
Definition: win32_port.h:454
#define MAXAUTOVACPIDS
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1803
void pg_usleep(long microsec)
Definition: signal.c:53
static PGPROC * allProcs
Definition: procarray.c:263
Oid databaseId
Definition: proc.h:154
static ProcArrayStruct * procArray
Definition: procarray.c:261
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1199
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:120
uint8 * statusFlags
Definition: proc.h:333
Definition: proc.h:121
int pid
Definition: proc.h:146
#define PROC_IS_AUTOVACUUM
Definition: proc.h:54

◆ CountUserBackends()

int CountUserBackends ( Oid  roleid)

Definition at line 3632 of file procarray.c.

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

Referenced by InitializeSessionUserId().

3633 {
3634  ProcArrayStruct *arrayP = procArray;
3635  int count = 0;
3636  int index;
3637 
3638  LWLockAcquire(ProcArrayLock, LW_SHARED);
3639 
3640  for (index = 0; index < arrayP->numProcs; index++)
3641  {
3642  int pgprocno = arrayP->pgprocnos[index];
3643  PGPROC *proc = &allProcs[pgprocno];
3644 
3645  if (proc->pid == 0)
3646  continue; /* do not count prepared xacts */
3647  if (proc->isBackgroundWorker)
3648  continue; /* do not count background workers */
3649  if (proc->roleId == roleid)
3650  count++;
3651  }
3652 
3653  LWLockRelease(ProcArrayLock);
3654 
3655  return count;
3656 }
Oid roleId
Definition: proc.h:155
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1803
bool isBackgroundWorker
Definition: proc.h:160
static PGPROC * allProcs
Definition: procarray.c:263
static ProcArrayStruct * procArray
Definition: procarray.c:261
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1199
Definition: proc.h:121
int pid
Definition: proc.h:146

◆ CreateSharedProcArray()

void CreateSharedProcArray ( void  )

Definition at line 405 of file procarray.c.

References add_size(), 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, offsetof, ProcArrayStruct::pgprocnos, 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().

406 {
407  bool found;
408 
409  /* Create or attach to the ProcArray shared structure */
411  ShmemInitStruct("Proc Array",
412  add_size(offsetof(ProcArrayStruct, pgprocnos),
413  mul_size(sizeof(int),
415  &found);
416 
417  if (!found)
418  {
419  /*
420  * We're the first - initialize.
421  */
422  procArray->numProcs = 0;
433  }
434 
436 
437  /* Create or attach to the KnownAssignedXids arrays too, if needed */
438  if (EnableHotStandby)
439  {
441  ShmemInitStruct("KnownAssignedXids",
442  mul_size(sizeof(TransactionId),
444  &found);
445  KnownAssignedXidsValid = (bool *)
446  ShmemInitStruct("KnownAssignedXidsValid",
447  mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS),
448  &found);
449  }
450 }
#define PROCARRAY_MAXPROCS
uint32 TransactionId
Definition: c.h:587
#define SpinLockInit(lock)
Definition: spin.h:60
TransactionId replication_slot_catalog_xmin
Definition: procarray.c:98
uint64 xactCompletionCount
Definition: transam.h:248
slock_t known_assigned_xids_lck
Definition: procarray.c:84
PROC_HDR * ProcGlobal
Definition: proc.c:80
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition: shmem.c:396
VariableCache ShmemVariableCache
Definition: varsup.c:34
int maxKnownAssignedXids
Definition: procarray.c:80
#define InvalidTransactionId
Definition: transam.h:31
static PGPROC * allProcs
Definition: procarray.c:263
int numKnownAssignedXids
Definition: procarray.c:81
static bool * KnownAssignedXidsValid
Definition: procarray.c:269
TransactionId lastOverflowedXid
Definition: procarray.c:93
static ProcArrayStruct * procArray
Definition: procarray.c:261
TransactionId replication_slot_xmin
Definition: procarray.c:96
Size mul_size(Size s1, Size s2)
Definition: shmem.c:519
Size add_size(Size s1, Size s2)
Definition: shmem.c:502
#define TOTAL_MAX_CACHED_SUBXIDS
static TransactionId * KnownAssignedXids
Definition: procarray.c:268
bool EnableHotStandby
Definition: xlog.c:98
PGPROC * allProcs
Definition: proc.h:318
int tailKnownAssignedXids
Definition: procarray.c:82
#define offsetof(type, field)
Definition: c.h:727
int headKnownAssignedXids
Definition: procarray.c:83

◆ ExpireAllKnownAssignedTransactionIds()

void ExpireAllKnownAssignedTransactionIds ( void  )

Definition at line 4450 of file procarray.c.

References InvalidTransactionId, KnownAssignedXidsRemovePreceding(), LW_EXCLUSIVE, LWLockAcquire(), and LWLockRelease().

Referenced by ShutdownRecoveryTransactionEnvironment().

4451 {
4452  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
4454  LWLockRelease(ProcArrayLock);
4455 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1803
static void KnownAssignedXidsRemovePreceding(TransactionId xid)
Definition: procarray.c:4899
#define InvalidTransactionId
Definition: transam.h:31
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1199

◆ ExpireOldKnownAssignedTransactionIds()

void ExpireOldKnownAssignedTransactionIds ( TransactionId  xid)

Definition at line 4462 of file procarray.c.

References KnownAssignedXidsRemovePreceding(), LW_EXCLUSIVE, LWLockAcquire(), and LWLockRelease().

Referenced by ProcArrayApplyRecoveryInfo().

4463 {
4464  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
4466  LWLockRelease(ProcArrayLock);
4467 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1803
static void KnownAssignedXidsRemovePreceding(TransactionId xid)
Definition: procarray.c:4899
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1199

◆ ExpireTreeKnownAssignedTransactionIds()

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

Definition at line 4424 of file procarray.c.

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

Referenced by xact_redo_abort(), and xact_redo_commit().

4426 {
4428 
4429  /*
4430  * Uses same locking as transaction commit
4431  */
4432  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
4433 
4434  KnownAssignedXidsRemoveTree(xid, nsubxids, subxids);
4435 
4436  /* As in ProcArrayEndTransaction, advance latestCompletedXid */
4438 
4439  /* ... and xactCompletionCount */
4441 
4442  LWLockRelease(ProcArrayLock);
4443 }
static void MaintainLatestCompletedXidRecovery(TransactionId latestXid)
Definition: procarray.c:969
uint64 xactCompletionCount
Definition: transam.h:248
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1803
HotStandbyState standbyState
Definition: xlogutils.c:55
VariableCache ShmemVariableCache
Definition: varsup.c:34
static void KnownAssignedXidsRemoveTree(TransactionId xid, int nsubxids, TransactionId *subxids)
Definition: procarray.c:4877
#define Assert(condition)
Definition: c.h:804
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1199

◆ GetConflictingVirtualXIDs()

VirtualTransactionId* GetConflictingVirtualXIDs ( TransactionId  limitXmin,
Oid  dbOid 
)

Definition at line 3349 of file procarray.c.

References 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().

3350 {
3351  static VirtualTransactionId *vxids;
3352  ProcArrayStruct *arrayP = procArray;
3353  int count = 0;
3354  int index;
3355 
3356  /*
3357  * If first time through, get workspace to remember main XIDs in. We
3358  * malloc it permanently to avoid repeated palloc/pfree overhead. Allow
3359  * result space, remembering room for a terminator.
3360  */
3361  if (vxids == NULL)
3362  {
3363  vxids = (VirtualTransactionId *)
3364  malloc(sizeof(VirtualTransactionId) * (arrayP->maxProcs + 1));
3365  if (vxids == NULL)
3366  ereport(ERROR,
3367  (errcode(ERRCODE_OUT_OF_MEMORY),
3368  errmsg("out of memory")));
3369  }
3370 
3371  LWLockAcquire(ProcArrayLock, LW_SHARED);
3372 
3373  for (index = 0; index < arrayP->numProcs; index++)
3374  {
3375  int pgprocno = arrayP->pgprocnos[index];
3376  PGPROC *proc = &allProcs[pgprocno];
3377 
3378  /* Exclude prepared transactions */
3379  if (proc->pid == 0)
3380  continue;
3381 
3382  if (!OidIsValid(dbOid) ||
3383  proc->databaseId == dbOid)
3384  {
3385  /* Fetch xmin just once - can't change on us, but good coding */
3386  TransactionId pxmin = UINT32_ACCESS_ONCE(proc->xmin);
3387 
3388  /*
3389  * We ignore an invalid pxmin because this means that backend has
3390  * no snapshot currently. We hold a Share lock to avoid contention
3391  * with users taking snapshots. That is not a problem because the
3392  * current xmin is always at least one higher than the latest
3393  * removed xid, so any new snapshot would never conflict with the
3394  * test here.
3395  */
3396  if (!TransactionIdIsValid(limitXmin) ||
3397  (TransactionIdIsValid(pxmin) && !TransactionIdFollows(pxmin, limitXmin)))
3398  {
3399  VirtualTransactionId vxid;
3400 
3401  GET_VXID_FROM_PGPROC(vxid, *proc);
3402  if (VirtualTransactionIdIsValid(vxid))
3403  vxids[count++] = vxid;
3404  }
3405  }
3406  }
3407 
3408  LWLockRelease(ProcArrayLock);
3409 
3410  /* add the terminator */
3411  vxids[count].backendId = InvalidBackendId;
3413 
3414  return vxids;
3415 }
#define GET_VXID_FROM_PGPROC(vxid, proc)
Definition: lock.h:81
bool TransactionIdFollows(TransactionId id1, TransactionId id2)
Definition: transam.c:334
uint32 TransactionId
Definition: c.h:587
#define UINT32_ACCESS_ONCE(var)
Definition: procarray.c:69
int errcode(int sqlerrcode)
Definition: elog.c:698
LocalTransactionId localTransactionId
Definition: lock.h:66
#define OidIsValid(objectId)
Definition: c.h:710
Definition: type.h:89
#define malloc(a)
Definition: header.h:50
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1803
#define ERROR
Definition: elog.h:46
TransactionId xmin
Definition: proc.h:138
static PGPROC * allProcs
Definition: procarray.c:263
Oid databaseId
Definition: proc.h:154
static ProcArrayStruct * procArray
Definition: procarray.c:261
#define VirtualTransactionIdIsValid(vxid)
Definition: lock.h:71
#define InvalidBackendId
Definition: backendid.h:23
#define ereport(elevel,...)
Definition: elog.h:157
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
BackendId backendId
Definition: lock.h:65
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1199
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define InvalidLocalTransactionId
Definition: lock.h:69
#define TransactionIdIsValid(xid)
Definition: transam.h:41
Definition: proc.h:121
int pid
Definition: proc.h:146

◆ GetCurrentVirtualXIDs()

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

Definition at line 3261 of file procarray.c.

References 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().

3264 {
3265  VirtualTransactionId *vxids;
3266  ProcArrayStruct *arrayP = procArray;
3267  int count = 0;
3268  int index;
3269 
3270  /* allocate what's certainly enough result space */
3271  vxids = (VirtualTransactionId *)
3272  palloc(sizeof(VirtualTransactionId) * arrayP->maxProcs);
3273 
3274  LWLockAcquire(ProcArrayLock, LW_SHARED);
3275 
3276  for (index = 0; index < arrayP->numProcs; index++)
3277  {
3278  int pgprocno = arrayP->pgprocnos[index];
3279  PGPROC *proc = &allProcs[pgprocno];
3280  uint8 statusFlags = ProcGlobal->statusFlags[index];
3281 
3282  if (proc == MyProc)
3283  continue;
3284 
3285  if (excludeVacuum & statusFlags)
3286  continue;
3287 
3288  if (allDbs || proc->databaseId == MyDatabaseId)
3289  {
3290  /* Fetch xmin just once - might change on us */
3291  TransactionId pxmin = UINT32_ACCESS_ONCE(proc->xmin);
3292 
3293  if (excludeXmin0 && !TransactionIdIsValid(pxmin))
3294  continue;
3295 
3296  /*
3297  * InvalidTransactionId precedes all other XIDs, so a proc that
3298  * hasn't set xmin yet will not be rejected by this test.
3299  */
3300  if (!TransactionIdIsValid(limitXmin) ||
3301  TransactionIdPrecedesOrEquals(pxmin, limitXmin))
3302  {
3303  VirtualTransactionId vxid;
3304 
3305  GET_VXID_FROM_PGPROC(vxid, *proc);
3306  if (VirtualTransactionIdIsValid(vxid))
3307  vxids[count++] = vxid;
3308  }
3309  }
3310  }
3311 
3312  LWLockRelease(ProcArrayLock);
3313 
3314  *nvxids = count;
3315  return vxids;
3316 }
#define GET_VXID_FROM_PGPROC(vxid, proc)
Definition: lock.h:81
uint32 TransactionId
Definition: c.h:587
PGPROC * MyProc
Definition: proc.c:68
#define UINT32_ACCESS_ONCE(var)
Definition: procarray.c:69
unsigned char uint8
Definition: c.h:439
PROC_HDR * ProcGlobal
Definition: proc.c:80
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1803
bool TransactionIdPrecedesOrEquals(TransactionId id1, TransactionId id2)
Definition: transam.c:319
TransactionId xmin
Definition: proc.h:138
static PGPROC * allProcs
Definition: procarray.c:263
Oid databaseId
Definition: proc.h:154
static ProcArrayStruct * procArray
Definition: procarray.c:261
#define VirtualTransactionIdIsValid(vxid)
Definition: lock.h:71
Oid MyDatabaseId
Definition: globals.c:88
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1199
void * palloc(Size size)
Definition: mcxt.c:1062
uint8 * statusFlags
Definition: proc.h:333
#define TransactionIdIsValid(xid)
Definition: transam.h:41
Definition: proc.h:121

◆ GetMaxSnapshotSubxidCount()

int GetMaxSnapshotSubxidCount ( void  )

Definition at line 2080 of file procarray.c.

References TOTAL_MAX_CACHED_SUBXIDS.

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

2081 {
2082  return TOTAL_MAX_CACHED_SUBXIDS;
2083 }
#define TOTAL_MAX_CACHED_SUBXIDS

◆ GetMaxSnapshotXidCount()

int GetMaxSnapshotXidCount ( void  )

Definition at line 2069 of file procarray.c.

References ProcArrayStruct::maxProcs.

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

2070 {
2071  return procArray->maxProcs;
2072 }
static ProcArrayStruct * procArray
Definition: procarray.c:261

◆ GetOldestActiveTransactionId()

TransactionId GetOldestActiveTransactionId ( void  )

Definition at line 2882 of file procarray.c.

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().

2883 {
2884  ProcArrayStruct *arrayP = procArray;
2885  TransactionId *other_xids = ProcGlobal->xids;
2886  TransactionId oldestRunningXid;
2887  int index;
2888 
2890 
2891  /*
2892  * Read nextXid, as the upper bound of what's still active.
2893  *
2894  * Reading a TransactionId is atomic, but we must grab the lock to make
2895  * sure that all XIDs < nextXid are already present in the proc array (or
2896  * have already completed), when we spin over it.
2897  */
2898  LWLockAcquire(XidGenLock, LW_SHARED);
2900  LWLockRelease(XidGenLock);
2901 
2902  /*
2903  * Spin over procArray collecting all xids and subxids.
2904  */
2905  LWLockAcquire(ProcArrayLock, LW_SHARED);
2906  for (index = 0; index < arrayP->numProcs; index++)
2907  {
2908  TransactionId xid;
2909 
2910  /* Fetch xid just once - see GetNewTransactionId */
2911  xid = UINT32_ACCESS_ONCE(other_xids[index]);
2912 
2913  if (!TransactionIdIsNormal(xid))
2914  continue;
2915 
2916  if (TransactionIdPrecedes(xid, oldestRunningXid))
2917  oldestRunningXid = xid;
2918 
2919  /*
2920  * Top-level XID of a transaction is always less than any of its
2921  * subxids, so we don't need to check if any of the subxids are
2922  * smaller than oldestRunningXid
2923  */
2924  }
2925  LWLockRelease(ProcArrayLock);
2926 
2927  return oldestRunningXid;
2928 }
uint32 TransactionId
Definition: c.h:587
#define UINT32_ACCESS_ONCE(var)
Definition: procarray.c:69
PROC_HDR * ProcGlobal
Definition: proc.c:80
bool RecoveryInProgress(void)
Definition: xlog.c:8217
FullTransactionId nextXid
Definition: transam.h:220
#define XidFromFullTransactionId(x)
Definition: transam.h:48
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1803
VariableCache ShmemVariableCache
Definition: varsup.c:34
TransactionId * xids
Definition: proc.h:321
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
static ProcArrayStruct * procArray
Definition: procarray.c:261
#define Assert(condition)
Definition: c.h:804
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1199
#define TransactionIdIsNormal(xid)
Definition: transam.h:42

◆ GetOldestNonRemovableTransactionId()

TransactionId GetOldestNonRemovableTransactionId ( Relation  rel)

Definition at line 2005 of file procarray.c.

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_set_xid_limits().

2006 {
2007  ComputeXidHorizonsResult horizons;
2008 
2009  ComputeXidHorizons(&horizons);
2010 
2011  switch (GlobalVisHorizonKindForRel(rel))
2012  {
2013  case VISHORIZON_SHARED:
2014  return horizons.shared_oldest_nonremovable;
2015  case VISHORIZON_CATALOG:
2016  return horizons.catalog_oldest_nonremovable;
2017  case VISHORIZON_DATA:
2018  return horizons.data_oldest_nonremovable;
2019  case VISHORIZON_TEMP:
2020  return horizons.temp_oldest_nonremovable;
2021  }
2022 
2023  /* just to prevent compiler warnings */
2024  return InvalidTransactionId;
2025 }
static void ComputeXidHorizons(ComputeXidHorizonsResult *h)
Definition: procarray.c:1701
TransactionId catalog_oldest_nonremovable
Definition: procarray.c:233
#define InvalidTransactionId
Definition: transam.h:31
TransactionId shared_oldest_nonremovable
Definition: procarray.c:216
TransactionId temp_oldest_nonremovable
Definition: procarray.c:245
TransactionId data_oldest_nonremovable
Definition: procarray.c:239
static GlobalVisHorizonKind GlobalVisHorizonKindForRel(Relation rel)
Definition: procarray.c:1971

◆ GetOldestSafeDecodingTransactionId()

TransactionId GetOldestSafeDecodingTransactionId ( bool  catalogOnly)

Definition at line 2947 of file procarray.c.

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().

2948 {
2949  ProcArrayStruct *arrayP = procArray;
2950  TransactionId oldestSafeXid;
2951  int index;
2952  bool recovery_in_progress = RecoveryInProgress();
2953 
2954  Assert(LWLockHeldByMe(ProcArrayLock));
2955 
2956  /*
2957  * Acquire XidGenLock, so no transactions can acquire an xid while we're
2958  * running. If no transaction with xid were running concurrently a new xid
2959  * could influence the RecentXmin et al.
2960  *
2961  * We initialize the computation to nextXid since that's guaranteed to be
2962  * a safe, albeit pessimal, value.
2963  */
2964  LWLockAcquire(XidGenLock, LW_SHARED);
2966 
2967  /*
2968  * If there's already a slot pegging the xmin horizon, we can start with
2969  * that value, it's guaranteed to be safe since it's computed by this
2970  * routine initially and has been enforced since. We can always use the
2971  * slot's general xmin horizon, but the catalog horizon is only usable
2972  * when only catalog data is going to be looked at.
2973  */
2976  oldestSafeXid))
2977  oldestSafeXid = procArray->replication_slot_xmin;
2978 
2979  if (catalogOnly &&
2982  oldestSafeXid))
2983  oldestSafeXid = procArray->replication_slot_catalog_xmin;
2984 
2985  /*
2986  * If we're not in recovery, we walk over the procarray and collect the
2987  * lowest xid. Since we're called with ProcArrayLock held and have
2988  * acquired XidGenLock, no entries can vanish concurrently, since
2989  * ProcGlobal->xids[i] is only set with XidGenLock held and only cleared
2990  * with ProcArrayLock held.
2991  *
2992  * In recovery we can't lower the safe value besides what we've computed
2993  * above, so we'll have to wait a bit longer there. We unfortunately can
2994  * *not* use KnownAssignedXidsGetOldestXmin() since the KnownAssignedXids
2995  * machinery can miss values and return an older value than is safe.
2996  */
2997  if (!recovery_in_progress)
2998  {
2999  TransactionId *other_xids = ProcGlobal->xids;
3000 
3001  /*
3002  * Spin over procArray collecting min(ProcGlobal->xids[i])
3003  */
3004  for (index = 0; index < arrayP->numProcs; index++)
3005  {
3006  TransactionId xid;
3007 
3008  /* Fetch xid just once - see GetNewTransactionId */
3009  xid = UINT32_ACCESS_ONCE(other_xids[index]);
3010 
3011  if (!TransactionIdIsNormal(xid))
3012  continue;
3013 
3014  if (TransactionIdPrecedes(xid, oldestSafeXid))
3015  oldestSafeXid = xid;
3016  }
3017  }
3018 
3019  LWLockRelease(XidGenLock);
3020 
3021  return oldestSafeXid;
3022 }
uint32 TransactionId
Definition: c.h:587
bool LWLockHeldByMe(LWLock *l)
Definition: lwlock.c:1919
#define UINT32_ACCESS_ONCE(var)
Definition: procarray.c:69
TransactionId replication_slot_catalog_xmin
Definition: procarray.c:98
PROC_HDR * ProcGlobal
Definition: proc.c:80
bool RecoveryInProgress(void)
Definition: xlog.c:8217
FullTransactionId nextXid
Definition: transam.h:220
#define XidFromFullTransactionId(x)
Definition: transam.h:48
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1803
VariableCache ShmemVariableCache
Definition: varsup.c:34
TransactionId * xids
Definition: proc.h:321
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
static ProcArrayStruct * procArray
Definition: procarray.c:261
TransactionId replication_slot_xmin
Definition: procarray.c:96
#define Assert(condition)
Definition: c.h:804
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1199
#define TransactionIdIsValid(xid)
Definition: transam.h:41
#define TransactionIdIsNormal(xid)
Definition: transam.h:42

◆ GetOldestTransactionIdConsideredRunning()

TransactionId GetOldestTransactionIdConsideredRunning ( void  )

Definition at line 2034 of file procarray.c.

References ComputeXidHorizons(), and ComputeXidHorizonsResult::oldest_considered_running.

Referenced by CreateCheckPoint(), and CreateRestartPoint().

2035 {
2036  ComputeXidHorizonsResult horizons;
2037 
2038  ComputeXidHorizons(&horizons);
2039 
2040  return horizons.oldest_considered_running;
2041 }
TransactionId oldest_considered_running
Definition: procarray.c:207
static void ComputeXidHorizons(ComputeXidHorizonsResult *h)
Definition: procarray.c:1701

◆ GetReplicationHorizons()

void GetReplicationHorizons ( TransactionId slot_xmin,
TransactionId catalog_xmin 
)

Definition at line 2047 of file procarray.c.

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

Referenced by XLogWalRcvSendHSFeedback().

2048 {
2049  ComputeXidHorizonsResult horizons;
2050 
2051  ComputeXidHorizons(&horizons);
2052 
2053  /*
2054  * Don't want to use shared_oldest_nonremovable here, as that contains the
2055  * effect of replication slot's catalog_xmin. We want to send a separate
2056  * feedback for the catalog horizon, so the primary can remove data table
2057  * contents more aggressively.
2058  */
2059  *xmin = horizons.shared_oldest_nonremovable_raw;
2060  *catalog_xmin = horizons.slot_catalog_xmin;
2061 }
static void ComputeXidHorizons(ComputeXidHorizonsResult *h)
Definition: procarray.c:1701
TransactionId shared_oldest_nonremovable_raw
Definition: procarray.c:227
TransactionId slot_catalog_xmin
Definition: procarray.c:194

◆ GetRunningTransactionData()

RunningTransactions GetRunningTransactionData ( void  )

Definition at line 2707 of file procarray.c.

References Assert, XidCacheStatus::count, ereport, errcode(), errmsg(), ERROR, RunningTransactionsData::latestCompletedXid, VariableCacheData::latestCompletedXid, LW_SHARED, LWLockAcquire(), malloc, RunningTransactionsData::nextXid, VariableCacheData::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, RunningTransactionsData::xids, and PROC_HDR::xids.

Referenced by LogStandbySnapshot().

2708 {
2709  /* result workspace */
2710  static RunningTransactionsData CurrentRunningXactsData;
2711 
2712  ProcArrayStruct *arrayP = procArray;
2713  TransactionId *other_xids = ProcGlobal->xids;
2714  RunningTransactions CurrentRunningXacts = &CurrentRunningXactsData;
2715  TransactionId latestCompletedXid;
2716  TransactionId oldestRunningXid;
2717  TransactionId *xids;
2718  int index;
2719  int count;
2720  int subcount;
2721  bool suboverflowed;
2722 
2724 
2725  /*
2726  * Allocating space for maxProcs xids is usually overkill; numProcs would
2727  * be sufficient. But it seems better to do the malloc while not holding
2728  * the lock, so we can't look at numProcs. Likewise, we allocate much
2729  * more subxip storage than is probably needed.
2730  *
2731  * Should only be allocated in bgwriter, since only ever executed during
2732  * checkpoints.
2733  */
2734  if (CurrentRunningXacts->xids == NULL)
2735  {
2736  /*
2737  * First call
2738  */
2739  CurrentRunningXacts->xids = (TransactionId *)
2741  if (CurrentRunningXacts->xids == NULL)
2742  ereport(ERROR,
2743  (errcode(ERRCODE_OUT_OF_MEMORY),
2744  errmsg("out of memory")));
2745  }
2746 
2747  xids = CurrentRunningXacts->xids;
2748 
2749  count = subcount = 0;
2750  suboverflowed = false;
2751 
2752  /*
2753  * Ensure that no xids enter or leave the procarray while we obtain
2754  * snapshot.
2755  */
2756  LWLockAcquire(ProcArrayLock, LW_SHARED);
2757  LWLockAcquire(XidGenLock, LW_SHARED);
2758 
2759  latestCompletedXid =
2761  oldestRunningXid =
2763 
2764  /*
2765  * Spin over procArray collecting all xids
2766  */
2767  for (index = 0; index < arrayP->numProcs; index++)
2768  {
2769  TransactionId xid;
2770 
2771  /* Fetch xid just once - see GetNewTransactionId */
2772  xid = UINT32_ACCESS_ONCE(other_xids[index]);
2773 
2774  /*
2775  * We don't need to store transactions that don't have a TransactionId
2776  * yet because they will not show as running on a standby server.
2777  */
2778  if (!TransactionIdIsValid(xid))
2779  continue;
2780 
2781  /*
2782  * Be careful not to exclude any xids before calculating the values of
2783  * oldestRunningXid and suboverflowed, since these are used to clean
2784  * up transaction information held on standbys.
2785  */
2786  if (TransactionIdPrecedes(xid, oldestRunningXid))
2787  oldestRunningXid = xid;
2788 
2789  if (ProcGlobal->subxidStates[index].overflowed)
2790  suboverflowed = true;
2791 
2792  /*
2793  * If we wished to exclude xids this would be the right place for it.
2794  * Procs with the PROC_IN_VACUUM flag set don't usually assign xids,
2795  * but they do during truncation at the end when they get the lock and
2796  * truncate, so it is not much of a problem to include them if they
2797  * are seen and it is cleaner to include them.
2798  */
2799 
2800  xids[count++] = xid;
2801  }
2802 
2803  /*
2804  * Spin over procArray collecting all subxids, but only if there hasn't
2805  * been a suboverflow.
2806  */
2807  if (!suboverflowed)
2808  {
2809  XidCacheStatus *other_subxidstates = ProcGlobal->subxidStates;
2810 
2811  for (index = 0; index < arrayP->numProcs; index++)
2812  {
2813  int pgprocno = arrayP->pgprocnos[index];
2814  PGPROC *proc = &allProcs[pgprocno];
2815  int nsubxids;
2816 
2817  /*
2818  * Save subtransaction XIDs. Other backends can't add or remove
2819  * entries while we're holding XidGenLock.
2820  */
2821  nsubxids = other_subxidstates[index].count;
2822  if (nsubxids > 0)
2823  {
2824  /* barrier not really required, as XidGenLock is held, but ... */
2825  pg_read_barrier(); /* pairs with GetNewTransactionId */
2826 
2827  memcpy(&xids[count], (void *) proc->subxids.xids,
2828  nsubxids * sizeof(TransactionId));
2829  count += nsubxids;
2830  subcount += nsubxids;
2831 
2832  /*
2833  * Top-level XID of a transaction is always less than any of
2834  * its subxids, so we don't need to check if any of the
2835  * subxids are smaller than oldestRunningXid
2836  */
2837  }
2838  }
2839  }
2840 
2841  /*
2842  * It's important *not* to include the limits set by slots here because
2843  * snapbuild.c uses oldestRunningXid to manage its xmin horizon. If those
2844  * were to be included here the initial value could never increase because
2845  * of a circular dependency where slots only increase their limits when
2846  * running xacts increases oldestRunningXid and running xacts only
2847  * increases if slots do.
2848  */
2849 
2850  CurrentRunningXacts->xcnt = count - subcount;
2851  CurrentRunningXacts->subxcnt = subcount;
2852  CurrentRunningXacts->subxid_overflow = suboverflowed;
2854  CurrentRunningXacts->oldestRunningXid = oldestRunningXid;
2855  CurrentRunningXacts->latestCompletedXid = latestCompletedXid;
2856 
2857  Assert(TransactionIdIsValid(CurrentRunningXacts->nextXid));
2858  Assert(TransactionIdIsValid(CurrentRunningXacts->oldestRunningXid));
2859  Assert(TransactionIdIsNormal(CurrentRunningXacts->latestCompletedXid));
2860 
2861  /* We don't release the locks here, the caller is responsible for that */
2862 
2863  return CurrentRunningXacts;
2864 }
TransactionId oldestRunningXid
Definition: standby.h:83
uint32 TransactionId
Definition: c.h:587
XidCacheStatus * subxidStates
Definition: proc.h:327
#define UINT32_ACCESS_ONCE(var)
Definition: procarray.c:69
int errcode(int sqlerrcode)
Definition: elog.c:698
PROC_HDR * ProcGlobal
Definition: proc.c:80
TransactionId * xids
Definition: standby.h:86
FullTransactionId latestCompletedXid
Definition: transam.h:238
bool RecoveryInProgress(void)
Definition: xlog.c:8217
FullTransactionId nextXid
Definition: transam.h:220
bool overflowed
Definition: proc.h:43
#define XidFromFullTransactionId(x)
Definition: transam.h:48
TransactionId latestCompletedXid
Definition: standby.h:84
Definition: type.h:89
#define malloc(a)
Definition: header.h:50
#define ERROR
Definition: elog.h:46
VariableCache ShmemVariableCache
Definition: varsup.c:34
TransactionId * xids
Definition: proc.h:321
static PGPROC * allProcs
Definition: procarray.c:263
struct XidCache subxids
Definition: proc.h:212
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
static ProcArrayStruct * procArray
Definition: procarray.c:261
#define ereport(elevel,...)
Definition: elog.h:157
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
TransactionId xids[PGPROC_MAX_CACHED_SUBXIDS]
Definition: proc.h:48
#define TOTAL_MAX_CACHED_SUBXIDS
#define Assert(condition)
Definition: c.h:804
#define pg_read_barrier()
Definition: atomics.h:158
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1199
uint8 count
Definition: proc.h:41
TransactionId nextXid
Definition: standby.h:82
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define TransactionIdIsValid(xid)
Definition: transam.h:41
#define TransactionIdIsNormal(xid)
Definition: transam.h:42
Definition: proc.h:121

◆ GetSnapshotData()

Snapshot GetSnapshotData ( Snapshot  snapshot)

Definition at line 2206 of file procarray.c.

References SnapshotData::active_count, Assert, SnapshotData::copied, XidCacheStatus::count, SnapshotData::curcid, GlobalVisState::definitely_needed, ereport, errcode(), errmsg(), ERROR, FullTransactionIdAdvance(), FullTransactionIdNewer(), FullXidRelativeTo(), GetCurrentCommandId(), GetMaxSnapshotSubxidCount(), GetMaxSnapshotXidCount(), GetSnapshotDataInitOldSnapshot(), GetSnapshotDataReuse(), 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().

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

◆ GetVirtualXIDsDelayingChkpt()

VirtualTransactionId* GetVirtualXIDsDelayingChkpt ( int *  nvxids)

Definition at line 3043 of file procarray.c.

References PGPROC::delayChkpt, GET_VXID_FROM_PGPROC, LW_SHARED, LWLockAcquire(), LWLockRelease(), ProcArrayStruct::maxProcs, ProcArrayStruct::numProcs, palloc(), ProcArrayStruct::pgprocnos, procArray, and VirtualTransactionIdIsValid.

Referenced by CreateCheckPoint().

3044 {
3045  VirtualTransactionId *vxids;
3046  ProcArrayStruct *arrayP = procArray;
3047  int count = 0;
3048  int index;
3049 
3050  /* allocate what's certainly enough result space */
3051  vxids = (VirtualTransactionId *)
3052  palloc(sizeof(VirtualTransactionId) * arrayP->maxProcs);
3053 
3054  LWLockAcquire(ProcArrayLock, LW_SHARED);
3055 
3056  for (index = 0; index < arrayP->numProcs; index++)
3057  {
3058  int pgprocno = arrayP->pgprocnos[index];
3059  PGPROC *proc = &allProcs[pgprocno];
3060 
3061  if (proc->delayChkpt)
3062  {
3063  VirtualTransactionId vxid;
3064 
3065  GET_VXID_FROM_PGPROC(vxid, *proc);
3066  if (VirtualTransactionIdIsValid(vxid))
3067  vxids[count++] = vxid;
3068  }
3069  }
3070 
3071  LWLockRelease(ProcArrayLock);
3072 
3073  *nvxids = count;
3074  return vxids;
3075 }
#define GET_VXID_FROM_PGPROC(vxid, proc)
Definition: lock.h:81
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1803
bool delayChkpt
Definition: proc.h:187
static PGPROC * allProcs
Definition: procarray.c:263
static ProcArrayStruct * procArray
Definition: procarray.c:261
#define VirtualTransactionIdIsValid(vxid)
Definition: lock.h:71
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1199
void * palloc(Size size)
Definition: mcxt.c:1062
Definition: proc.h:121

◆ HaveVirtualXIDsDelayingChkpt()

bool HaveVirtualXIDsDelayingChkpt ( VirtualTransactionId vxids,
int  nvxids 
)

Definition at line 3087 of file procarray.c.

References PGPROC::delayChkpt, GET_VXID_FROM_PGPROC, i, LW_SHARED, LWLockAcquire(), LWLockRelease(), ProcArrayStruct::numProcs, ProcArrayStruct::pgprocnos, procArray, VirtualTransactionIdEquals, and VirtualTransactionIdIsValid.

Referenced by CreateCheckPoint().

3088 {
3089  bool result = false;
3090  ProcArrayStruct *arrayP = procArray;
3091  int index;
3092 
3093  LWLockAcquire(ProcArrayLock, LW_SHARED);
3094 
3095  for (index = 0; index < arrayP->numProcs; index++)
3096  {
3097  int pgprocno = arrayP->pgprocnos[index];
3098  PGPROC *proc = &allProcs[pgprocno];
3099  VirtualTransactionId vxid;
3100 
3101  GET_VXID_FROM_PGPROC(vxid, *proc);
3102 
3103  if (proc->delayChkpt && VirtualTransactionIdIsValid(vxid))
3104  {
3105  int i;
3106 
3107  for (i = 0; i < nvxids; i++)
3108  {
3109  if (VirtualTransactionIdEquals(vxid, vxids[i]))
3110  {
3111  result = true;
3112  break;
3113  }
3114  }
3115  if (result)
3116  break;
3117  }
3118  }
3119 
3120  LWLockRelease(ProcArrayLock);
3121 
3122  return result;
3123 }
#define GET_VXID_FROM_PGPROC(vxid, proc)
Definition: lock.h:81
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1803
#define VirtualTransactionIdEquals(vxid1, vxid2)
Definition: lock.h:75
bool delayChkpt
Definition: proc.h:187
static PGPROC * allProcs
Definition: procarray.c:263
static ProcArrayStruct * procArray
Definition: procarray.c:261
#define VirtualTransactionIdIsValid(vxid)
Definition: lock.h:71
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1199
int i
Definition: proc.h:121

◆ IsBackendPid()

bool IsBackendPid ( int  pid)

Definition at line 3228 of file procarray.c.

References BackendPidGetProc().

Referenced by pg_stat_get_subscription().

3229 {
3230  return (BackendPidGetProc(pid) != NULL);
3231 }
PGPROC * BackendPidGetProc(int pid)
Definition: procarray.c:3133

◆ MinimumActiveBackends()

bool MinimumActiveBackends ( int  min)

Definition at line 3478 of file procarray.c.

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

Referenced by XLogFlush().

3479 {
3480  ProcArrayStruct *arrayP = procArray;
3481  int count = 0;
3482  int index;
3483 
3484  /* Quick short-circuit if no minimum is specified */
3485  if (min == 0)
3486  return true;
3487 
3488  /*
3489  * Note: for speed, we don't acquire ProcArrayLock. This is a little bit
3490  * bogus, but since we are only testing fields for zero or nonzero, it
3491  * should be OK. The result is only used for heuristic purposes anyway...
3492  */
3493  for (index = 0; index < arrayP->numProcs; index++)
3494  {
3495  int pgprocno = arrayP->pgprocnos[index];
3496  PGPROC *proc = &allProcs[pgprocno];
3497 
3498  /*
3499  * Since we're not holding a lock, need to be prepared to deal with
3500  * garbage, as someone could have incremented numProcs but not yet
3501  * filled the structure.
3502  *
3503  * If someone just decremented numProcs, 'proc' could also point to a
3504  * PGPROC entry that's no longer in the array. It still points to a
3505  * PGPROC struct, though, because freed PGPROC entries just go to the
3506  * free list and are recycled. Its contents are nonsense in that case,
3507  * but that's acceptable for this function.
3508  */
3509  if (pgprocno == -1)
3510  continue; /* do not count deleted entries */
3511  if (proc == MyProc)
3512  continue; /* do not count myself */
3513  if (proc->xid == InvalidTransactionId)
3514  continue; /* do not count if no XID assigned */
3515  if (proc->pid == 0)
3516  continue; /* do not count prepared xacts */
3517  if (proc->waitLock != NULL)
3518  continue; /* do not count if blocked on a lock */
3519  count++;
3520  if (count >= min)
3521  break;
3522  }
3523 
3524  return count >= min;
3525 }
PGPROC * MyProc
Definition: proc.c:68
Definition: type.h:89
#define InvalidTransactionId
Definition: transam.h:31
static PGPROC * allProcs
Definition: procarray.c:263
LOCK * waitLock
Definition: proc.h:179
static ProcArrayStruct * procArray
Definition: procarray.c:261
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
TransactionId xid
Definition: proc.h:133
Definition: proc.h:121
int pid
Definition: proc.h:146

◆ ProcArrayAdd()

void ProcArrayAdd ( PGPROC proc)

Definition at line 456 of file procarray.c.

References 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().

457 {
458  ProcArrayStruct *arrayP = procArray;
459  int index;
460  int movecount;
461 
462  /* See ProcGlobal comment explaining why both locks are held */
463  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
464  LWLockAcquire(XidGenLock, LW_EXCLUSIVE);
465 
466  if (arrayP->numProcs >= arrayP->maxProcs)
467  {
468  /*
469  * Oops, no room. (This really shouldn't happen, since there is a
470  * fixed supply of PGPROC structs too, and so we should have failed
471  * earlier.)
472  */
473  ereport(FATAL,
474  (errcode(ERRCODE_TOO_MANY_CONNECTIONS),
475  errmsg("sorry, too many clients already")));
476  }
477 
478  /*
479  * Keep the procs array sorted by (PGPROC *) so that we can utilize
480  * locality of references much better. This is useful while traversing the
481  * ProcArray because there is an increased likelihood of finding the next
482  * PGPROC structure in the cache.
483  *
484  * Since the occurrence of adding/removing a proc is much lower than the
485  * access to the ProcArray itself, the overhead should be marginal
486  */
487  for (index = 0; index < arrayP->numProcs; index++)
488  {
489  int procno PG_USED_FOR_ASSERTS_ONLY = arrayP->pgprocnos[index];
490 
491  Assert(procno >= 0 && procno < (arrayP->maxProcs + NUM_AUXILIARY_PROCS));
492  Assert(allProcs[procno].pgxactoff == index);
493 
494  /* If we have found our right position in the array, break */
495  if (arrayP->pgprocnos[index] > proc->pgprocno)
496  break;
497  }
498 
499  movecount = arrayP->numProcs - index;
500  memmove(&arrayP->pgprocnos[index + 1],
501  &arrayP->pgprocnos[index],
502  movecount * sizeof(*arrayP->pgprocnos));
503  memmove(&ProcGlobal->xids[index + 1],
504  &ProcGlobal->xids[index],
505  movecount * sizeof(*ProcGlobal->xids));
506  memmove(&ProcGlobal->subxidStates[index + 1],
507  &ProcGlobal->subxidStates[index],
508  movecount * sizeof(*ProcGlobal->subxidStates));
509  memmove(&ProcGlobal->statusFlags[index + 1],
510  &ProcGlobal->statusFlags[index],
511  movecount * sizeof(*ProcGlobal->statusFlags));
512 
513  arrayP->pgprocnos[index] = proc->pgprocno;
514  proc->pgxactoff = index;
515  ProcGlobal->xids[index] = proc->xid;
516  ProcGlobal->subxidStates[index] = proc->subxidStatus;
517  ProcGlobal->statusFlags[index] = proc->statusFlags;
518 
519  arrayP->numProcs++;
520 
521  /* adjust pgxactoff for all following PGPROCs */
522  index++;
523  for (; index < arrayP->numProcs; index++)
524  {
525  int procno = arrayP->pgprocnos[index];
526 
527  Assert(procno >= 0 && procno < (arrayP->maxProcs + NUM_AUXILIARY_PROCS));
528  Assert(allProcs[procno].pgxactoff == index - 1);
529 
530  allProcs[procno].pgxactoff = index;
531  }
532 
533  /*
534  * Release in reversed acquisition order, to reduce frequency of having to
535  * wait for XidGenLock while holding ProcArrayLock.
536  */
537  LWLockRelease(XidGenLock);
538  LWLockRelease(ProcArrayLock);
539 }
XidCacheStatus * subxidStates
Definition: proc.h:327
int errcode(int sqlerrcode)
Definition: elog.c:698
PROC_HDR * ProcGlobal
Definition: proc.c:80
uint8 statusFlags
Definition: proc.h:189
XidCacheStatus subxidStatus
Definition: proc.h:210
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1803
#define FATAL
Definition: elog.h:49
TransactionId * xids
Definition: proc.h:321
static PGPROC * allProcs
Definition: procarray.c:263
#define NUM_AUXILIARY_PROCS
Definition: proc.h:377
static ProcArrayStruct * procArray
Definition: procarray.c:261
#define ereport(elevel,...)
Definition: elog.h:157
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
#define Assert(condition)
Definition: c.h:804
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1199
TransactionId xid
Definition: proc.h:133
int pgprocno
Definition: proc.h:150
int errmsg(const char *fmt,...)
Definition: elog.c:909
int pgxactoff
Definition: proc.h:148
uint8 * statusFlags
Definition: proc.h:333
#define PG_USED_FOR_ASSERTS_ONLY
Definition: c.h:155

◆ ProcArrayApplyRecoveryInfo()

void ProcArrayApplyRecoveryInfo ( RunningTransactions  running)

Definition at line 1034 of file procarray.c.

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(), RunningTransactionsData::nextXid, VariableCacheData::nextXid, ProcArrayStruct::numKnownAssignedXids, RunningTransactionsData::oldestRunningXid, palloc(), pfree(), 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, xidComparator(), and RunningTransactionsData::xids.

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

1035 {
1036  TransactionId *xids;
1037  int nxids;
1038  int i;
1039 
1041  Assert(TransactionIdIsValid(running->nextXid));
1044 
1045  /*
1046  * Remove stale transactions, if any.
1047  */
1049 
1050  /*
1051  * Remove stale locks, if any.
1052  */
1054 
1055  /*
1056  * If our snapshot is already valid, nothing else to do...
1057  */
1059  return;
1060 
1061  /*
1062  * If our initial RunningTransactionsData had an overflowed snapshot then
1063  * we knew we were missing some subxids from our snapshot. If we continue
1064  * to see overflowed snapshots then we might never be able to start up, so
1065  * we make another test to see if our snapshot is now valid. We know that
1066  * the missing subxids are equal to or earlier than nextXid. After we
1067  * initialise we continue to apply changes during recovery, so once the
1068  * oldestRunningXid is later than the nextXid from the initial snapshot we
1069  * know that we no longer have missing information and can mark the
1070  * snapshot as valid.
1071  */
1073  {
1074  /*
1075  * If the snapshot isn't overflowed or if its empty we can reset our
1076  * pending state and use this snapshot instead.
1077  */
1078  if (!running->subxid_overflow || running->xcnt == 0)
1079  {
1080  /*
1081  * If we have already collected known assigned xids, we need to
1082  * throw them away before we apply the recovery snapshot.
1083  */
1086  }
1087  else
1088  {
1090  running->oldestRunningXid))
1091  {
1094  "recovery snapshots are now enabled");
1095  }
1096  else
1098  "recovery snapshot waiting for non-overflowed snapshot or "
1099  "until oldest active xid on standby is at least %u (now %u)",
1101  running->oldestRunningXid);
1102  return;
1103  }
1104  }
1105 
1107 
1108  /*
1109  * NB: this can be reached at least twice, so make sure new code can deal
1110  * with that.
1111  */
1112 
1113  /*
1114  * Nobody else is running yet, but take locks anyhow
1115  */
1116  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
1117 
1118  /*
1119  * KnownAssignedXids is sorted so we cannot just add the xids, we have to
1120  * sort them first.
1121  *
1122  * Some of the new xids are top-level xids and some are subtransactions.
1123  * We don't call SubTransSetParent because it doesn't matter yet. If we
1124  * aren't overflowed then all xids will fit in snapshot and so we don't
1125  * need subtrans. If we later overflow, an xid assignment record will add
1126  * xids to subtrans. If RunningTransactionsData is overflowed then we
1127  * don't have enough information to correctly update subtrans anyway.
1128  */
1129 
1130  /*
1131  * Allocate a temporary array to avoid modifying the array passed as
1132  * argument.
1133  */
1134  xids = palloc(sizeof(TransactionId) * (running->xcnt + running->subxcnt));
1135 
1136  /*
1137  * Add to the temp array any xids which have not already completed.
1138  */
1139  nxids = 0;
1140  for (i = 0; i < running->xcnt + running->subxcnt; i++)
1141  {
1142  TransactionId xid = running->xids[i];
1143 
1144  /*
1145  * The running-xacts snapshot can contain xids that were still visible
1146  * in the procarray when the snapshot was taken, but were already
1147  * WAL-logged as completed. They're not running anymore, so ignore
1148  * them.
1149  */
1151  continue;
1152 
1153  xids[nxids++] = xid;
1154  }
1155 
1156  if (nxids > 0)
1157  {
1158  if (procArray->numKnownAssignedXids != 0)
1159  {
1160  LWLockRelease(ProcArrayLock);
1161  elog(ERROR, "KnownAssignedXids is not empty");
1162  }
1163 
1164  /*
1165  * Sort the array so that we can add them safely into
1166  * KnownAssignedXids.
1167  */
1168  qsort(xids, nxids, sizeof(TransactionId), xidComparator);
1169 
1170  /*
1171  * Add the sorted snapshot into KnownAssignedXids. The running-xacts
1172  * snapshot may include duplicated xids because of prepared
1173  * transactions, so ignore them.
1174  */
1175  for (i = 0; i < nxids; i++)
1176  {
1177  if (i > 0 && TransactionIdEquals(xids[i - 1], xids[i]))
1178  {
1179  elog(DEBUG1,
1180  "found duplicated transaction %u for KnownAssignedXids insertion",
1181  xids[i]);
1182  continue;
1183  }
1184  KnownAssignedXidsAdd(xids[i], xids[i], true);
1185  }
1186 
1188  }
1189 
1190  pfree(xids);
1191 
1192  /*
1193  * latestObservedXid is at least set to the point where SUBTRANS was
1194  * started up to (cf. ProcArrayInitRecovery()) or to the biggest xid
1195  * RecordKnownAssignedTransactionIds() was called for. Initialize
1196  * subtrans from thereon, up to nextXid - 1.
1197  *
1198  * We need to duplicate parts of RecordKnownAssignedTransactionId() here,
1199  * because we've just added xids to the known assigned xids machinery that
1200  * haven't gone through RecordKnownAssignedTransactionId().
1201  */
1205  {
1208  }
1209  TransactionIdRetreat(latestObservedXid); /* = running->nextXid - 1 */
1210 
1211  /* ----------
1212  * Now we've got the running xids we need to set the global values that
1213  * are used to track snapshots as they evolve further.
1214  *
1215  * - latestCompletedXid which will be the xmax for snapshots
1216  * - lastOverflowedXid which shows whether snapshots overflow
1217  * - nextXid
1218  *
1219  * If the snapshot overflowed, then we still initialise with what we know,
1220  * but the recovery snapshot isn't fully valid yet because we know there
1221  * are some subxids missing. We don't know the specific subxids that are
1222  * missing, so conservatively assume the last one is latestObservedXid.
1223  * ----------
1224  */
1225  if (running->subxid_overflow)
1226  {
1228 
1231  }
1232  else
1233  {
1235 
1237  }
1238 
1239  /*
1240  * If a transaction wrote a commit record in the gap between taking and
1241  * logging the snapshot then latestCompletedXid may already be higher than
1242  * the value from the snapshot, so check before we use the incoming value.
1243  * It also might not yet be set at all.
1244  */
1246 
1247  /*
1248  * NB: No need to increment ShmemVariableCache->xactCompletionCount here,
1249  * nobody can see it yet.
1250  */
1251 
1252  LWLockRelease(ProcArrayLock);
1253 
1254  /* ShmemVariableCache->nextXid must be beyond any observed xid. */
1256 
1258 
1261  elog(trace_recovery(DEBUG1), "recovery snapshots are now enabled");
1262  else
1264  "recovery snapshot waiting for non-overflowed snapshot or "
1265  "until oldest active xid on standby is at least %u (now %u)",
1267  running->oldestRunningXid);
1268 }
#define TransactionIdAdvance(dest)
Definition: transam.h:91
static TransactionId latestObservedXid
Definition: procarray.c:270
TransactionId oldestRunningXid
Definition: standby.h:83
#define DEBUG1
Definition: elog.h:25
static void KnownAssignedXidsDisplay(int trace_level)
Definition: procarray.c:5084
#define TransactionIdEquals(id1, id2)
Definition: transam.h:43
uint32 TransactionId
Definition: c.h:587
void AdvanceNextFullTransactionIdPastXid(TransactionId xid)
Definition: varsup.c:277
#define DEBUG3
Definition: elog.h:23
#define FullTransactionIdIsValid(x)
Definition: transam.h:55
static void MaintainLatestCompletedXidRecovery(TransactionId latestXid)
Definition: procarray.c:969
TransactionId * xids
Definition: standby.h:86
bool TransactionIdDidCommit(TransactionId transactionId)
Definition: transam.c:125
#define TransactionIdRetreat(dest)
Definition: transam.h:141
FullTransactionId nextXid
Definition: transam.h:220
int trace_recovery(int trace_level)
Definition: elog.c:3609
TransactionId latestCompletedXid
Definition: standby.h:84
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1803
void pfree(void *pointer)
Definition: mcxt.c:1169
#define ERROR
Definition: elog.h:46
void ExtendSUBTRANS(TransactionId newestXact)
Definition: subtrans.c:308
HotStandbyState standbyState
Definition: xlogutils.c:55
VariableCache ShmemVariableCache
Definition: varsup.c:34
#define InvalidTransactionId
Definition: transam.h:31
static void KnownAssignedXidsReset(void)
Definition: procarray.c:5122
int numKnownAssignedXids
Definition: procarray.c:81
TransactionId lastOverflowedXid
Definition: procarray.c:93
bool TransactionIdDidAbort(TransactionId transactionId)
Definition: transam.c:181
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
static ProcArrayStruct * procArray
Definition: procarray.c:261
#define Assert(condition)
Definition: c.h:804
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1199
static void KnownAssignedXidsAdd(TransactionId from_xid, TransactionId to_xid, bool exclusive_lock)
Definition: procarray.c:4627
TransactionId nextXid
Definition: standby.h:82
void * palloc(Size size)
Definition: mcxt.c:1062
#define elog(elevel,...)
Definition: elog.h:232
int i
void ExpireOldKnownAssignedTransactionIds(TransactionId xid)
Definition: procarray.c:4462
#define qsort(a, b, c, d)
Definition: port.h:504
#define TransactionIdIsValid(xid)
Definition: transam.h:41
#define TransactionIdIsNormal(xid)
Definition: transam.h:42
static TransactionId standbySnapshotPendingXmin
Definition: procarray.c:277
void StandbyReleaseOldLocks(TransactionId oldxid)
Definition: standby.c:1070
int xidComparator(const void *arg1, const void *arg2)
Definition: xid.c:136

◆ ProcArrayApplyXidAssignment()

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

Definition at line 1275 of file procarray.c.

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

Referenced by xact_redo().

1277 {
1278  TransactionId max_xid;
1279  int i;
1280 
1282 
1283  max_xid = TransactionIdLatest(topxid, nsubxids, subxids);
1284 
1285  /*
1286  * Mark all the subtransactions as observed.
1287  *
1288  * NOTE: This will fail if the subxid contains too many previously
1289  * unobserved xids to fit into known-assigned-xids. That shouldn't happen
1290  * as the code stands, because xid-assignment records should never contain
1291  * more than PGPROC_MAX_CACHED_SUBXIDS entries.
1292  */
1294 
1295  /*
1296  * Notice that we update pg_subtrans with the top-level xid, rather than
1297  * the parent xid. This is a difference between normal processing and
1298  * recovery, yet is still correct in all cases. The reason is that
1299  * subtransaction commit is not marked in clog until commit processing, so
1300  * all aborted subtransactions have already been clearly marked in clog.
1301  * As a result we are able to refer directly to the top-level
1302  * transaction's state rather than skipping through all the intermediate
1303  * states in the subtransaction tree. This should be the first time we
1304  * have attempted to SubTransSetParent().
1305  */
1306  for (i = 0; i < nsubxids; i++)
1307  SubTransSetParent(subxids[i], topxid);
1308 
1309  /* KnownAssignedXids isn't maintained yet, so we're done for now */
1311  return;
1312 
1313  /*
1314  * Uses same locking as transaction commit
1315  */
1316  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
1317 
1318  /*
1319  * Remove subxids from known-assigned-xacts.
1320  */
1322 
1323  /*
1324  * Advance lastOverflowedXid to be at least the last of these subxids.
1325  */
1327  procArray->lastOverflowedXid = max_xid;
1328 
1329  LWLockRelease(ProcArrayLock);
1330 }
uint32 TransactionId
Definition: c.h:587
TransactionId TransactionIdLatest(TransactionId mainxid, int nxids, const TransactionId *xids)
Definition: transam.c:365
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1803
HotStandbyState standbyState
Definition: xlogutils.c:55
#define InvalidTransactionId
Definition: transam.h:31
TransactionId lastOverflowedXid
Definition: procarray.c:93
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
static void KnownAssignedXidsRemoveTree(TransactionId xid, int nsubxids, TransactionId *subxids)
Definition: procarray.c:4877
static ProcArrayStruct * procArray
Definition: procarray.c:261
#define Assert(condition)
Definition: c.h:804
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1199
int i
void RecordKnownAssignedTransactionIds(TransactionId xid)
Definition: procarray.c:4355
void SubTransSetParent(TransactionId xid, TransactionId parent)
Definition: subtrans.c:74

◆ ProcArrayClearTransaction()

void ProcArrayClearTransaction ( PGPROC proc)

Definition at line 887 of file procarray.c.

References Assert, XidCacheStatus::count, PGPROC::delayChkpt, 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().

888 {
889  size_t pgxactoff;
890 
891  /*
892  * Currently we need to lock ProcArrayLock exclusively here, as we
893  * increment xactCompletionCount below. We also need it at least in shared
894  * mode for pgproc->pgxactoff to stay the same below.
895  *
896  * We could however, as this action does not actually change anyone's view
897  * of the set of running XIDs (our entry is duplicate with the gxact that
898  * has already been inserted into the ProcArray), lower the lock level to
899  * shared if we were to make xactCompletionCount an atomic variable. But
900  * that doesn't seem worth it currently, as a 2PC commit is heavyweight
901  * enough for this not to be the bottleneck. If it ever becomes a
902  * bottleneck it may also be worth considering to combine this with the
903  * subsequent ProcArrayRemove()
904  */
905  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
906 
907  pgxactoff = proc->pgxactoff;
908 
909  ProcGlobal->xids[pgxactoff] = InvalidTransactionId;
910  proc->xid = InvalidTransactionId;
911 
913  proc->xmin = InvalidTransactionId;
914  proc->recoveryConflictPending = false;
915 
917  Assert(!proc->delayChkpt);
918 
919  /*
920  * Need to increment completion count even though transaction hasn't
921  * really committed yet. The reason for that is that GetSnapshotData()
922  * omits the xid of the current transaction, thus without the increment we
923  * otherwise could end up reusing the snapshot later. Which would be bad,
924  * because it might not count the prepared transaction as running.
925  */
927 
928  /* Clear the subtransaction-XID cache too */
929  Assert(ProcGlobal->subxidStates[pgxactoff].count == proc->subxidStatus.count &&
931  if (proc->subxidStatus.count > 0 || proc->subxidStatus.overflowed)
932  {
933  ProcGlobal->subxidStates[pgxactoff].count = 0;
934  ProcGlobal->subxidStates[pgxactoff].overflowed = false;
935  proc->subxidStatus.count = 0;
936  proc->subxidStatus.overflowed = false;
937  }
938 
939  LWLockRelease(ProcArrayLock);
940 }
XidCacheStatus * subxidStates
Definition: proc.h:327
uint64 xactCompletionCount
Definition: transam.h:248
PROC_HDR * ProcGlobal
Definition: proc.c:80
uint8 statusFlags
Definition: proc.h:189
XidCacheStatus subxidStatus
Definition: proc.h:210
#define PROC_VACUUM_STATE_MASK
Definition: proc.h:65
bool overflowed
Definition: proc.h:43
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1803
bool delayChkpt
Definition: proc.h:187
TransactionId xmin
Definition: proc.h:138
bool recoveryConflictPending
Definition: proc.h:167
VariableCache ShmemVariableCache
Definition: varsup.c:34
#define InvalidTransactionId
Definition: transam.h:31
TransactionId * xids
Definition: proc.h:321
#define Assert(condition)
Definition: c.h:804
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1199
uint8 count
Definition: proc.h:41
TransactionId xid
Definition: proc.h:133
#define InvalidLocalTransactionId
Definition: lock.h:69
int pgxactoff
Definition: proc.h:148
LocalTransactionId lxid
Definition: proc.h:143

◆ ProcArrayEndTransaction()

void ProcArrayEndTransaction ( PGPROC proc,
TransactionId  latestXid 
)

Definition at line 654 of file procarray.c.

References Assert, XidCacheStatus::count, PGPROC::delayChkpt, 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().

655 {
656  if (TransactionIdIsValid(latestXid))
657  {
658  /*
659  * We must lock ProcArrayLock while clearing our advertised XID, so
660  * that we do not exit the set of "running" transactions while someone
661  * else is taking a snapshot. See discussion in
662  * src/backend/access/transam/README.
663  */
665 
666  /*
667  * If we can immediately acquire ProcArrayLock, we clear our own XID
668  * and release the lock. If not, use group XID clearing to improve
669  * efficiency.
670  */
671  if (LWLockConditionalAcquire(ProcArrayLock, LW_EXCLUSIVE))
672  {
673  ProcArrayEndTransactionInternal(proc, latestXid);
674  LWLockRelease(ProcArrayLock);
675  }
676  else
677  ProcArrayGroupClearXid(proc, latestXid);
678  }
679  else
680  {
681  /*
682  * If we have no XID, we don't need to lock, since we won't affect
683  * anyone else's calculation of a snapshot. We might change their
684  * estimate of global xmin, but that's OK.
685  */
687  Assert(proc->subxidStatus.count == 0);
689 
691  proc->xmin = InvalidTransactionId;
692  proc->delayChkpt = false; /* be sure this is cleared in abort */
693  proc->recoveryConflictPending = false;
694 
695  /* must be cleared with xid/xmin: */
696  /* avoid unnecessarily dirtying shared cachelines */
698  {
699  Assert(!LWLockHeldByMe(ProcArrayLock));
700  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
704  LWLockRelease(ProcArrayLock);
705  }
706  }
707 }
bool LWLockHeldByMe(LWLock *l)
Definition: lwlock.c:1919
static void ProcArrayEndTransactionInternal(PGPROC *proc, TransactionId latestXid)
Definition: procarray.c:715
static void ProcArrayGroupClearXid(PGPROC *proc, TransactionId latestXid)
Definition: procarray.c:773
PROC_HDR * ProcGlobal
Definition: proc.c:80
uint8 statusFlags
Definition: proc.h:189
XidCacheStatus subxidStatus
Definition: proc.h:210
#define PROC_VACUUM_STATE_MASK
Definition: proc.h:65
bool overflowed
Definition: proc.h:43
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1803
bool delayChkpt
Definition: proc.h:187
TransactionId xmin
Definition: proc.h:138
bool LWLockConditionalAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1370
bool recoveryConflictPending
Definition: proc.h:167
#define InvalidTransactionId
Definition: transam.h:31
#define Assert(condition)
Definition: c.h:804
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1199
uint8 count
Definition: proc.h:41
TransactionId xid
Definition: proc.h:133
#define InvalidLocalTransactionId
Definition: lock.h:69
int pgxactoff
Definition: proc.h:148
uint8 * statusFlags
Definition: proc.h:333
#define TransactionIdIsValid(xid)
Definition: transam.h:41
LocalTransactionId lxid
Definition: proc.h:143

◆ ProcArrayGetReplicationSlotXmin()

void ProcArrayGetReplicationSlotXmin ( TransactionId xmin,
TransactionId catalog_xmin 
)

Definition at line 3890 of file procarray.c.

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

Referenced by logical_begin_heap_rewrite().

3892 {
3893  LWLockAcquire(ProcArrayLock, LW_SHARED);
3894 
3895  if (xmin != NULL)
3897 
3898  if (catalog_xmin != NULL)
3899  *catalog_xmin = procArray->replication_slot_catalog_xmin;
3900 
3901  LWLockRelease(ProcArrayLock);
3902 }
TransactionId replication_slot_catalog_xmin
Definition: procarray.c:98
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1803
static ProcArrayStruct * procArray
Definition: procarray.c:261
TransactionId replication_slot_xmin
Definition: procarray.c:96
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1199

◆ ProcArrayInitRecovery()

void ProcArrayInitRecovery ( TransactionId  initializedUptoXID)

Definition at line 1003 of file procarray.c.

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

Referenced by StartupXLOG().

1004 {
1006  Assert(TransactionIdIsNormal(initializedUptoXID));
1007 
1008  /*
1009  * we set latestObservedXid to the xid SUBTRANS has been initialized up
1010  * to, so we can extend it from that point onwards in
1011  * RecordKnownAssignedTransactionIds, and when we get consistent in
1012  * ProcArrayApplyRecoveryInfo().
1013  */
1014  latestObservedXid = initializedUptoXID;
1016 }
static TransactionId latestObservedXid
Definition: procarray.c:270
#define TransactionIdRetreat(dest)
Definition: transam.h:141
HotStandbyState standbyState
Definition: xlogutils.c:55
#define Assert(condition)
Definition: c.h:804
#define TransactionIdIsNormal(xid)
Definition: transam.h:42

◆ ProcArrayInstallImportedXmin()

bool ProcArrayInstallImportedXmin ( TransactionId  xmin,
VirtualTransactionId sourcevxid 
)

Definition at line 2569 of file procarray.c.

References 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().

2571 {
2572  bool result = false;
2573  ProcArrayStruct *arrayP = procArray;
2574  int index;
2575 
2577  if (!sourcevxid)
2578  return false;
2579 
2580  /* Get lock so source xact can't end while we're doing this */
2581  LWLockAcquire(ProcArrayLock, LW_SHARED);
2582 
2583  for (index = 0; index < arrayP->numProcs; index++)
2584  {
2585  int pgprocno = arrayP->pgprocnos[index];
2586  PGPROC *proc = &allProcs[pgprocno];
2587  int statusFlags = ProcGlobal->statusFlags[index];
2588  TransactionId xid;
2589 
2590  /* Ignore procs running LAZY VACUUM */
2591  if (statusFlags & PROC_IN_VACUUM)
2592  continue;
2593 
2594  /* We are only interested in the specific virtual transaction. */
2595  if (proc->backendId != sourcevxid->backendId)
2596  continue;
2597  if (proc->lxid != sourcevxid->localTransactionId)
2598  continue;
2599 
2600  /*
2601  * We check the transaction's database ID for paranoia's sake: if it's
2602  * in another DB then its xmin does not cover us. Caller should have
2603  * detected this already, so we just treat any funny cases as
2604  * "transaction not found".
2605  */
2606  if (proc->databaseId != MyDatabaseId)
2607  continue;
2608 
2609  /*
2610  * Likewise, let's just make real sure its xmin does cover us.
2611  */
2612  xid = UINT32_ACCESS_ONCE(proc->xmin);
2613  if (!TransactionIdIsNormal(xid) ||
2614  !TransactionIdPrecedesOrEquals(xid, xmin))
2615  continue;
2616 
2617  /*
2618  * We're good. Install the new xmin. As in GetSnapshotData, set
2619  * TransactionXmin too. (Note that because snapmgr.c called
2620  * GetSnapshotData first, we'll be overwriting a valid xmin here, so
2621  * we don't check that.)
2622  */
2623  MyProc->xmin = TransactionXmin = xmin;
2624 
2625  result = true;
2626  break;
2627  }
2628 
2629  LWLockRelease(ProcArrayLock);
2630 
2631  return result;
2632 }
BackendId backendId
Definition: proc.h:153
uint32 TransactionId
Definition: c.h:587
PGPROC * MyProc
Definition: proc.c:68
#define UINT32_ACCESS_ONCE(var)
Definition: procarray.c:69
PROC_HDR * ProcGlobal
Definition: proc.c:80
LocalTransactionId localTransactionId
Definition: lock.h:66
TransactionId TransactionXmin
Definition: snapmgr.c:112
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1803
#define PROC_IN_VACUUM
Definition: proc.h:55
bool TransactionIdPrecedesOrEquals(TransactionId id1, TransactionId id2)
Definition: transam.c:319
TransactionId xmin
Definition: proc.h:138
static PGPROC * allProcs
Definition: procarray.c:263
Oid databaseId
Definition: proc.h:154
static ProcArrayStruct * procArray
Definition: procarray.c:261
Oid MyDatabaseId
Definition: globals.c:88
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
#define Assert(condition)
Definition: c.h:804
BackendId backendId
Definition: lock.h:65
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1199
uint8 * statusFlags
Definition: proc.h:333
#define TransactionIdIsNormal(xid)
Definition: transam.h:42
Definition: proc.h:121
LocalTransactionId lxid
Definition: proc.h:143

◆ ProcArrayInstallRestoredXmin()

bool ProcArrayInstallRestoredXmin ( TransactionId  xmin,
PGPROC proc 
)

Definition at line 2644 of file procarray.c.

References Assert, PGPROC::databaseId, LW_SHARED, LWLockAcquire(), LWLockRelease(), MyDatabaseId, MyProc, TransactionIdIsNormal, TransactionIdPrecedesOrEquals(), TransactionXmin, UINT32_ACCESS_ONCE, and PGPROC::xmin.

Referenced by SetTransactionSnapshot().

2645 {
2646  bool result = false;
2647  TransactionId xid;
2648 
2650  Assert(proc != NULL);
2651 
2652  /* Get lock so source xact can't end while we're doing this */
2653  LWLockAcquire(ProcArrayLock, LW_SHARED);
2654 
2655  /*
2656  * Be certain that the referenced PGPROC has an advertised xmin which is
2657  * no later than the one we're installing, so that the system-wide xmin
2658  * can't go backwards. Also, make sure it's running in the same database,
2659  * so that the per-database xmin cannot go backwards.
2660  */
2661  xid = UINT32_ACCESS_ONCE(proc->xmin);
2662  if (proc->databaseId == MyDatabaseId &&
2663  TransactionIdIsNormal(xid) &&
2664  TransactionIdPrecedesOrEquals(xid, xmin))
2665  {
2666  MyProc->xmin = TransactionXmin = xmin;
2667  result = true;
2668  }
2669 
2670  LWLockRelease(ProcArrayLock);
2671 
2672  return result;
2673 }
uint32 TransactionId
Definition: c.h:587
PGPROC * MyProc
Definition: proc.c:68
#define UINT32_ACCESS_ONCE(var)
Definition: procarray.c:69
TransactionId TransactionXmin
Definition: snapmgr.c:112
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1803
bool TransactionIdPrecedesOrEquals(TransactionId id1, TransactionId id2)
Definition: transam.c:319
TransactionId xmin
Definition: proc.h:138
Oid databaseId
Definition: proc.h:154
Oid MyDatabaseId
Definition: globals.c:88
#define Assert(condition)
Definition: c.h:804
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1199
#define TransactionIdIsNormal(xid)
Definition: transam.h:42

◆ ProcArrayRemove()

void ProcArrayRemove ( PGPROC proc,
TransactionId  latestXid 
)

Definition at line 552 of file procarray.c.

References 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().

553 {
554  ProcArrayStruct *arrayP = procArray;
555  int myoff;
556  int movecount;
557 
558 #ifdef XIDCACHE_DEBUG
559  /* dump stats at backend shutdown, but not prepared-xact end */
560  if (proc->pid != 0)
561  DisplayXidCache();
562 #endif
563 
564  /* See ProcGlobal comment explaining why both locks are held */
565  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
566  LWLockAcquire(XidGenLock, LW_EXCLUSIVE);
567 
568  myoff = proc->pgxactoff;
569 
570  Assert(myoff >= 0 && myoff < arrayP->numProcs);
571  Assert(ProcGlobal->allProcs[arrayP->pgprocnos[myoff]].pgxactoff == myoff);
572 
573  if (TransactionIdIsValid(latestXid))
574  {
576 
577  /* Advance global latestCompletedXid while holding the lock */
578  MaintainLatestCompletedXid(latestXid);
579 
580  /* Same with xactCompletionCount */
582 
584  ProcGlobal->subxidStates[myoff].overflowed = false;
585  ProcGlobal->subxidStates[myoff].count = 0;
586  }
587  else
588  {
589  /* Shouldn't be trying to remove a live transaction here */
591  }
592 
594  Assert(ProcGlobal->subxidStates[myoff].count == 0);
595  Assert(ProcGlobal->subxidStates[myoff].overflowed == false);
596 
597  ProcGlobal->statusFlags[myoff] = 0;
598 
599  /* Keep the PGPROC array sorted. See notes above */
600  movecount = arrayP->numProcs - myoff - 1;
601  memmove(&arrayP->pgprocnos[myoff],
602  &arrayP->pgprocnos[myoff + 1],
603  movecount * sizeof(*arrayP->pgprocnos));
604  memmove(&ProcGlobal->xids[myoff],
605  &ProcGlobal->xids[myoff + 1],
606  movecount * sizeof(*ProcGlobal->xids));
607  memmove(&ProcGlobal->subxidStates[myoff],
608  &ProcGlobal->subxidStates[myoff + 1],
609  movecount * sizeof(*ProcGlobal->subxidStates));
610  memmove(&ProcGlobal->statusFlags[myoff],
611  &ProcGlobal->statusFlags[myoff + 1],
612  movecount * sizeof(*ProcGlobal->statusFlags));
613 
614  arrayP->pgprocnos[arrayP->numProcs - 1] = -1; /* for debugging */
615  arrayP->numProcs--;
616 
617  /*
618  * Adjust pgxactoff of following procs for removed PGPROC (note that
619  * numProcs already has been decremented).
620  */
621  for (int index = myoff; index < arrayP->numProcs; index++)
622  {
623  int procno = arrayP->pgprocnos[index];
624 
625  Assert(procno >= 0 && procno < (arrayP->maxProcs + NUM_AUXILIARY_PROCS));
626  Assert(allProcs[procno].pgxactoff - 1 == index);
627 
628  allProcs[procno].pgxactoff = index;
629  }
630 
631  /*
632  * Release in reversed acquisition order, to reduce frequency of having to
633  * wait for XidGenLock while holding ProcArrayLock.
634  */
635  LWLockRelease(XidGenLock);
636  LWLockRelease(ProcArrayLock);
637 }
XidCacheStatus * subxidStates
Definition: proc.h:327
uint64 xactCompletionCount
Definition: transam.h:248
PROC_HDR * ProcGlobal
Definition: proc.c:80
bool overflowed
Definition: proc.h:43
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1803
VariableCache ShmemVariableCache
Definition: varsup.c:34
#define InvalidTransactionId
Definition: transam.h:31
TransactionId * xids
Definition: proc.h:321
static PGPROC * allProcs
Definition: procarray.c:263
#define NUM_AUXILIARY_PROCS
Definition: proc.h:377
static ProcArrayStruct * procArray
Definition: procarray.c:261
static void MaintainLatestCompletedXid(TransactionId latestXid)
Definition: procarray.c:947
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
#define Assert(condition)
Definition: c.h:804
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1199
uint8 count
Definition: proc.h:41
int pgxactoff
Definition: proc.h:148
PGPROC * allProcs
Definition: proc.h:318
uint8 * statusFlags
Definition: proc.h:333
#define TransactionIdIsValid(xid)
Definition: transam.h:41
int pid
Definition: proc.h:146

◆ ProcArraySetReplicationSlotXmin()

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

Definition at line 3868 of file procarray.c.

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

Referenced by ReplicationSlotsComputeRequiredXmin().

3870 {
3871  Assert(!already_locked || LWLockHeldByMe(ProcArrayLock));
3872 
3873  if (!already_locked)
3874  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3875 
3877  procArray->replication_slot_catalog_xmin = catalog_xmin;
3878 
3879  if (!already_locked)
3880  LWLockRelease(ProcArrayLock);
3881 }
bool LWLockHeldByMe(LWLock *l)
Definition: lwlock.c:1919
TransactionId replication_slot_catalog_xmin
Definition: procarray.c:98
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1803
static ProcArrayStruct * procArray
Definition: procarray.c:261
TransactionId replication_slot_xmin
Definition: procarray.c:96
#define Assert(condition)
Definition: c.h:804
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1199

◆ ProcArrayShmemSize()

Size ProcArrayShmemSize ( void  )

Definition at line 363 of file procarray.c.

References add_size(), EnableHotStandby, mul_size(), offsetof, ProcArrayStruct::pgprocnos, PROCARRAY_MAXPROCS, and TOTAL_MAX_CACHED_SUBXIDS.

Referenced by CreateSharedMemoryAndSemaphores().

364 {
365  Size size;
366 
367  /* Size of the ProcArray structure itself */
368 #define PROCARRAY_MAXPROCS (MaxBackends + max_prepared_xacts)
369 
370  size = offsetof(ProcArrayStruct, pgprocnos);
371  size = add_size(size, mul_size(sizeof(int), PROCARRAY_MAXPROCS));
372 
373  /*
374  * During Hot Standby processing we have a data structure called
375  * KnownAssignedXids, created in shared memory. Local data structures are
376  * also created in various backends during GetSnapshotData(),
377  * TransactionIdIsInProgress() and GetRunningTransactionData(). All of the
378  * main structures created in those functions must be identically sized,
379  * since we may at times copy the whole of the data structures around. We
380  * refer to this size as TOTAL_MAX_CACHED_SUBXIDS.
381  *
382  * Ideally we'd only create this structure if we were actually doing hot
383  * standby in the current run, but we don't know that yet at the time
384  * shared memory is being set up.
385  */
386 #define TOTAL_MAX_CACHED_SUBXIDS \
387  ((PGPROC_MAX_CACHED_SUBXIDS + 1) * PROCARRAY_MAXPROCS)
388 
389  if (EnableHotStandby)
390  {
391  size = add_size(size,
392  mul_size(sizeof(TransactionId),
394  size = add_size(size,
395  mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS));
396  }
397 
398  return size;
399 }
#define PROCARRAY_MAXPROCS
uint32 TransactionId
Definition: c.h:587
Size mul_size(Size s1, Size s2)
Definition: shmem.c:519
Size add_size(Size s1, Size s2)
Definition: shmem.c:502
#define TOTAL_MAX_CACHED_SUBXIDS
size_t Size
Definition: c.h:540
bool EnableHotStandby
Definition: xlog.c:98
#define offsetof(type, field)
Definition: c.h:727

◆ RecordKnownAssignedTransactionIds()

void RecordKnownAssignedTransactionIds ( TransactionId  xid)

Definition at line 4355 of file procarray.c.

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

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

4356 {
4360 
4361  elog(trace_recovery(DEBUG4), "record known xact %u latestObservedXid %u",
4362  xid, latestObservedXid);
4363 
4364  /*
4365  * When a newly observed xid arrives, it is frequently the case that it is
4366  * *not* the next xid in sequence. When this occurs, we must treat the
4367  * intervening xids as running also.
4368  */
4370  {
4371  TransactionId next_expected_xid;
4372 
4373  /*
4374  * Extend subtrans like we do in GetNewTransactionId() during normal
4375  * operation using individual extend steps. Note that we do not need
4376  * to extend clog since its extensions are WAL logged.
4377  *
4378  * This part has to be done regardless of standbyState since we
4379  * immediately start assigning subtransactions to their toplevel
4380  * transactions.
4381  */
4382  next_expected_xid = latestObservedXid;
4383  while (TransactionIdPrecedes(next_expected_xid, xid))
4384  {
4385  TransactionIdAdvance(next_expected_xid);
4386  ExtendSUBTRANS(next_expected_xid);
4387  }
4388  Assert(next_expected_xid == xid);
4389 
4390  /*
4391  * If the KnownAssignedXids machinery isn't up yet, there's nothing
4392  * more to do since we don't track assigned xids yet.
4393  */
4395  {
4396  latestObservedXid = xid;
4397  return;
4398  }
4399 
4400  /*
4401  * Add (latestObservedXid, xid] onto the KnownAssignedXids array.
4402  */
4403  next_expected_xid = latestObservedXid;
4404  TransactionIdAdvance(next_expected_xid);
4405  KnownAssignedXidsAdd(next_expected_xid, xid, false);
4406 
4407  /*
4408  * Now we can advance latestObservedXid
4409  */
4410  latestObservedXid = xid;
4411 
4412  /* ShmemVariableCache->nextXid must be beyond any observed xid */
4414  }
4415 }
#define TransactionIdAdvance(dest)
Definition: transam.h:91
static TransactionId latestObservedXid
Definition: procarray.c:270
bool TransactionIdFollows(TransactionId id1, TransactionId id2)
Definition: transam.c:334
uint32 TransactionId
Definition: c.h:587
void AdvanceNextFullTransactionIdPastXid(TransactionId xid)
Definition: varsup.c:277
#define DEBUG4
Definition: elog.h:22
int trace_recovery(int trace_level)
Definition: elog.c:3609
void ExtendSUBTRANS(TransactionId newestXact)
Definition: subtrans.c:308
HotStandbyState standbyState
Definition: xlogutils.c:55
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
#define Assert(condition)
Definition: c.h:804
static void KnownAssignedXidsAdd(TransactionId from_xid, TransactionId to_xid, bool exclusive_lock)
Definition: procarray.c:4627
#define elog(elevel,...)
Definition: elog.h:232
#define TransactionIdIsValid(xid)
Definition: transam.h:41

◆ SignalVirtualTransaction()

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

Definition at line 3429 of file procarray.c.

References 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().

3431 {
3432  ProcArrayStruct *arrayP = procArray;
3433  int index;
3434  pid_t pid = 0;
3435 
3436  LWLockAcquire(ProcArrayLock, LW_SHARED);
3437 
3438  for (index = 0; index < arrayP->numProcs; index++)
3439  {
3440  int pgprocno = arrayP->pgprocnos[index];
3441  PGPROC *proc = &allProcs[pgprocno];
3442  VirtualTransactionId procvxid;
3443 
3444  GET_VXID_FROM_PGPROC(procvxid, *proc);
3445 
3446  if (procvxid.backendId == vxid.backendId &&
3447  procvxid.localTransactionId == vxid.localTransactionId)
3448  {
3449  proc->recoveryConflictPending = conflictPending;
3450  pid = proc->pid;
3451  if (pid != 0)
3452  {
3453  /*
3454  * Kill the pid if it's still here. If not, that's what we
3455  * wanted so ignore any errors.
3456  */
3457  (void) SendProcSignal(pid, sigmode, vxid.backendId);
3458  }
3459  break;
3460  }
3461  }
3462 
3463  LWLockRelease(ProcArrayLock);
3464 
3465  return pid;
3466 }
#define GET_VXID_FROM_PGPROC(vxid, proc)
Definition: lock.h:81
LocalTransactionId localTransactionId
Definition: lock.h:66
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1803
int SendProcSignal(pid_t pid, ProcSignalReason reason, BackendId backendId)
Definition: procsignal.c:261
bool recoveryConflictPending
Definition: proc.h:167
static PGPROC * allProcs
Definition: procarray.c:263
static ProcArrayStruct * procArray
Definition: procarray.c:261
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
BackendId backendId
Definition: lock.h:65
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1199
Definition: proc.h:121
int pid
Definition: proc.h:146

◆ TerminateOtherDBBackends()

void TerminateOtherDBBackends ( Oid  databaseId)

Definition at line 3760 of file procarray.c.

References 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().

3761 {
3762  ProcArrayStruct *arrayP = procArray;
3763  List *pids = NIL;
3764  int nprepared = 0;
3765  int i;
3766 
3767  LWLockAcquire(ProcArrayLock, LW_SHARED);
3768 
3769  for (i = 0; i < procArray->numProcs; i++)
3770  {
3771  int pgprocno = arrayP->pgprocnos[i];
3772  PGPROC *proc = &allProcs[pgprocno];
3773 
3774  if (proc->databaseId != databaseId)
3775  continue;
3776  if (proc == MyProc)
3777  continue;
3778 
3779  if (proc->pid != 0)
3780  pids = lappend_int(pids, proc->pid);
3781  else
3782  nprepared++;
3783  }
3784 
3785  LWLockRelease(ProcArrayLock);
3786 
3787  if (nprepared > 0)
3788  ereport(ERROR,
3789  (errcode(ERRCODE_OBJECT_IN_USE),
3790  errmsg("database \"%s\" is being used by prepared transactions",
3791  get_database_name(databaseId)),
3792  errdetail_plural("There is %d prepared transaction using the database.",
3793  "There are %d prepared transactions using the database.",
3794  nprepared,
3795  nprepared)));
3796 
3797  if (pids)
3798  {
3799  ListCell *lc;
3800 
3801  /*
3802  * Check whether we have the necessary rights to terminate other
3803  * sessions. We don't terminate any session until we ensure that we
3804  * have rights on all the sessions to be terminated. These checks are
3805  * the same as we do in pg_terminate_backend.
3806  *
3807  * In this case we don't raise some warnings - like "PID %d is not a
3808  * PostgreSQL server process", because for us already finished session
3809  * is not a problem.
3810  */
3811  foreach(lc, pids)
3812  {
3813  int pid = lfirst_int(lc);
3814  PGPROC *proc = BackendPidGetProc(pid);
3815 
3816  if (proc != NULL)
3817  {
3818  /* Only allow superusers to signal superuser-owned backends. */
3819  if (superuser_arg(proc->roleId) && !superuser())
3820  ereport(ERROR,
3821  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
3822  errmsg("must be a superuser to terminate superuser process")));
3823 
3824  /* Users can signal backends they have role membership in. */
3825  if (!has_privs_of_role(GetUserId(), proc->roleId) &&
3826  !has_privs_of_role(GetUserId(), ROLE_PG_SIGNAL_BACKEND))
3827  ereport(ERROR,
3828  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
3829  errmsg("must be a member of the role whose process is being terminated or member of pg_signal_backend")));
3830  }
3831  }
3832 
3833  /*
3834  * There's a race condition here: once we release the ProcArrayLock,
3835  * it's possible for the session to exit before we issue kill. That
3836  * race condition possibility seems too unlikely to worry about. See
3837  * pg_signal_backend.
3838  */
3839  foreach(lc, pids)
3840  {
3841  int pid = lfirst_int(lc);
3842  PGPROC *proc = BackendPidGetProc(pid);
3843 
3844  if (proc != NULL)
3845  {
3846  /*
3847  * If we have setsid(), signal the backend's whole process
3848  * group
3849  */
3850 #ifdef HAVE_SETSID
3851  (void) kill(-pid, SIGTERM);
3852 #else
3853  (void) kill(pid, SIGTERM);
3854 #endif
3855  }
3856  }
3857  }
3858 }
#define NIL
Definition: pg_list.h:65
Oid GetUserId(void)
Definition: miscinit.c:478
PGPROC * BackendPidGetProc(int pid)
Definition: procarray.c:3133
PGPROC * MyProc
Definition: proc.c:68
bool has_privs_of_role(Oid member, Oid role)
Definition: acl.c:4843
Oid roleId
Definition: proc.h:155
int errcode(int sqlerrcode)
Definition: elog.c:698
bool superuser(void)
Definition: superuser.c:46
#define kill(pid, sig)
Definition: win32_port.h:454
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1803
#define ERROR
Definition: elog.h:46
#define lfirst_int(lc)
Definition: pg_list.h:170
char * get_database_name(Oid dbid)
Definition: dbcommands.c:2113
static PGPROC * allProcs
Definition: procarray.c:263
Oid databaseId
Definition: proc.h:154
bool superuser_arg(Oid roleid)
Definition: superuser.c:56
List * lappend_int(List *list, int datum)
Definition: list.c:354
static ProcArrayStruct * procArray
Definition: procarray.c:261
#define ereport(elevel,...)
Definition: elog.h:157
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
int errdetail_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n,...)
Definition: elog.c:1134
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1199
int errmsg(const char *fmt,...)
Definition: elog.c:909
int i
Definition: proc.h:121
Definition: pg_list.h:50
int pid
Definition: proc.h:146

◆ TransactionIdIsActive()

bool TransactionIdIsActive ( TransactionId  xid)

Definition at line 1591 of file procarray.c.

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

1592 {
1593  bool result = false;
1594  ProcArrayStruct *arrayP = procArray;
1595  TransactionId *other_xids = ProcGlobal->xids;
1596  int i;
1597 
1598  /*
1599  * Don't bother checking a transaction older than RecentXmin; it could not
1600  * possibly still be running.
1601  */
1603  return false;
1604 
1605  LWLockAcquire(ProcArrayLock, LW_SHARED);
1606 
1607  for (i = 0; i < arrayP->numProcs; i++)
1608  {
1609  int pgprocno = arrayP->pgprocnos[i];
1610  PGPROC *proc = &allProcs[pgprocno];
1611  TransactionId pxid;
1612 
1613  /* Fetch xid just once - see GetNewTransactionId */
1614  pxid = UINT32_ACCESS_ONCE(other_xids[i]);
1615 
1616  if (!TransactionIdIsValid(pxid))
1617  continue;
1618 
1619  if (proc->pid == 0)
1620  continue; /* ignore prepared transactions */
1621 
1622  if (TransactionIdEquals(pxid, xid))
1623  {
1624  result = true;
1625  break;
1626  }
1627  }
1628 
1629  LWLockRelease(ProcArrayLock);
1630 
1631  return result;
1632 }
#define TransactionIdEquals(id1, id2)
Definition: transam.h:43
uint32 TransactionId
Definition: c.h:587
#define UINT32_ACCESS_ONCE(var)
Definition: procarray.c:69
TransactionId RecentXmin
Definition: snapmgr.c:113
PROC_HDR * ProcGlobal
Definition: proc.c:80
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1803
TransactionId * xids
Definition: proc.h:321
static PGPROC * allProcs
Definition: procarray.c:263
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
static ProcArrayStruct * procArray
Definition: procarray.c:261
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1199
int i
#define TransactionIdIsValid(xid)
Definition: transam.h:41
Definition: proc.h:121
int pid
Definition: proc.h:146

◆ TransactionIdIsInProgress()

bool TransactionIdIsInProgress ( TransactionId  xid)

Definition at line 1359 of file procarray.c.

References Assert, XidCacheStatus::count, ereport, errcode(), errmsg(), ERROR, i, KnownAssignedXidExists(), KnownAssignedXidsGet(), ProcArrayStruct::lastOverflowedXid, VariableCacheData::latestCompletedXid, LW_SHARED, LWLockAcquire(), LWLockRelease(), malloc, ProcArrayStruct::maxProcs, MyProc, ProcArrayStruct::numProcs, 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(), TransactionIdIsKnownCompleted(), 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(), get_xid_status(), HandleConcurrentAbort(), HeapTupleHeaderIsOnlyLocked(), HeapTupleSatisfiesDirty(), HeapTupleSatisfiesSelf(), HeapTupleSatisfiesToast(), HeapTupleSatisfiesUpdate(), HeapTupleSatisfiesVacuumHorizon(), MultiXactIdExpand(), MultiXactIdIsRunning(), test_lockmode_for_conflict(), and XactLockTableWait().

1360 {
1361  static TransactionId *xids = NULL;
1362  static TransactionId *other_xids;
1363  XidCacheStatus *other_subxidstates;
1364  int nxids = 0;
1365  ProcArrayStruct *arrayP = procArray;
1366  TransactionId topxid;
1367  TransactionId latestCompletedXid;
1368  int mypgxactoff;
1369  size_t numProcs;
1370  int j;
1371 
1372  /*
1373  * Don't bother checking a transaction older than RecentXmin; it could not
1374  * possibly still be running. (Note: in particular, this guarantees that
1375  * we reject InvalidTransactionId, FrozenTransactionId, etc as not
1376  * running.)
1377  */
1379  {
1381  return false;
1382  }
1383 
1384  /*
1385  * We may have just checked the status of this transaction, so if it is
1386  * already known to be completed, we can fall out without any access to
1387  * shared memory.
1388  */
1390  {
1392  return false;
1393  }
1394 
1395  /*
1396  * Also, we can handle our own transaction (and subtransactions) without
1397  * any access to shared memory.
1398  */
1400  {
1402  return true;
1403  }
1404 
1405  /*
1406  * If first time through, get workspace to remember main XIDs in. We
1407  * malloc it permanently to avoid repeated palloc/pfree overhead.
1408  */
1409  if (xids == NULL)
1410  {
1411  /*
1412  * In hot standby mode, reserve enough space to hold all xids in the
1413  * known-assigned list. If we later finish recovery, we no longer need
1414  * the bigger array, but we don't bother to shrink it.
1415  */
1416  int maxxids = RecoveryInProgress() ? TOTAL_MAX_CACHED_SUBXIDS : arrayP->maxProcs;
1417 
1418  xids = (TransactionId *) malloc(maxxids * sizeof(TransactionId));
1419  if (xids == NULL)
1420  ereport(ERROR,
1421  (errcode(ERRCODE_OUT_OF_MEMORY),
1422  errmsg("out of memory")));
1423  }
1424 
1425  other_xids = ProcGlobal->xids;
1426  other_subxidstates = ProcGlobal->subxidStates;
1427 
1428  LWLockAcquire(ProcArrayLock, LW_SHARED);
1429 
1430  /*
1431  * Now that we have the lock, we can check latestCompletedXid; if the
1432  * target Xid is after that, it's surely still running.
1433  */
1434  latestCompletedXid =
1436  if (TransactionIdPrecedes(latestCompletedXid, xid))
1437  {
1438  LWLockRelease(ProcArrayLock);
1440  return true;
1441  }
1442 
1443  /* No shortcuts, gotta grovel through the array */
1444  mypgxactoff = MyProc->pgxactoff;
1445  numProcs = arrayP->numProcs;
1446  for (size_t pgxactoff = 0; pgxactoff < numProcs; pgxactoff++)
1447  {
1448  int pgprocno;
1449  PGPROC *proc;
1450  TransactionId pxid;
1451  int pxids;
1452 
1453  /* Ignore ourselves --- dealt with it above */
1454  if (pgxactoff == mypgxactoff)
1455  continue;
1456 
1457  /* Fetch xid just once - see GetNewTransactionId */
1458  pxid = UINT32_ACCESS_ONCE(other_xids[pgxactoff]);
1459 
1460  if (!TransactionIdIsValid(pxid))
1461  continue;
1462 
1463  /*
1464  * Step 1: check the main Xid
1465  */
1466  if (TransactionIdEquals(pxid, xid))
1467  {
1468  LWLockRelease(ProcArrayLock);
1470  return true;
1471  }
1472 
1473  /*
1474  * We can ignore main Xids that are younger than the target Xid, since
1475  * the target could not possibly be their child.
1476  */
1477  if (TransactionIdPrecedes(xid, pxid))
1478  continue;
1479 
1480  /*
1481  * Step 2: check the cached child-Xids arrays
1482  */
1483  pxids = other_subxidstates[pgxactoff].count;
1484  pg_read_barrier(); /* pairs with barrier in GetNewTransactionId() */
1485  pgprocno = arrayP->pgprocnos[pgxactoff];
1486  proc = &allProcs[pgprocno];
1487  for (j = pxids - 1; j >= 0; j--)
1488  {
1489  /* Fetch xid just once - see GetNewTransactionId */
1490  TransactionId cxid = UINT32_ACCESS_ONCE(proc->subxids.xids[j]);
1491 
1492  if (TransactionIdEquals(cxid, xid))
1493  {
1494  LWLockRelease(ProcArrayLock);
1496  return true;
1497  }
1498  }
1499 
1500  /*
1501  * Save the main Xid for step 4. We only need to remember main Xids
1502  * that have uncached children. (Note: there is no race condition
1503  * here because the overflowed flag cannot be cleared, only set, while
1504  * we hold ProcArrayLock. So we can't miss an Xid that we need to
1505  * worry about.)
1506  */
1507  if (other_subxidstates[pgxactoff].overflowed)
1508  xids[nxids++] = pxid;
1509  }
1510 
1511  /*
1512  * Step 3: in hot standby mode, check the known-assigned-xids list. XIDs
1513  * in the list must be treated as running.
1514  */
1515  if (RecoveryInProgress())
1516  {
1517  /* none of the PGPROC entries should have XIDs in hot standby mode */
1518  Assert(nxids == 0);
1519 
1520  if (KnownAssignedXidExists(xid))
1521  {
1522  LWLockRelease(ProcArrayLock);
1524  return true;
1525  }
1526 
1527  /*
1528  * If the KnownAssignedXids overflowed, we have to check pg_subtrans
1529  * too. Fetch all xids from KnownAssignedXids that are lower than
1530  * xid, since if xid is a subtransaction its parent will always have a
1531  * lower value. Note we will collect both main and subXIDs here, but
1532  * there's no help for it.
1533  */
1535  nxids = KnownAssignedXidsGet(xids, xid);
1536  }
1537 
1538  LWLockRelease(ProcArrayLock);
1539 
1540  /*
1541  * If none of the relevant caches overflowed, we know the Xid is not
1542  * running without even looking at pg_subtrans.
1543  */
1544  if (nxids == 0)
1545  {
1547  return false;
1548  }
1549 
1550  /*
1551  * Step 4: have to check pg_subtrans.
1552  *
1553  * At this point, we know it's either a subtransaction of one of the Xids
1554  * in xids[], or it's not running. If it's an already-failed
1555  * subtransaction, we want to say "not running" even though its parent may
1556  * still be running. So first, check pg_xact to see if it's been aborted.
1557  */
1559 
1560  if (TransactionIdDidAbort(xid))
1561  return false;
1562 
1563  /*
1564  * It isn't aborted, so check whether the transaction tree it belongs to
1565  * is still running (or, more precisely, whether it was running when we
1566  * held ProcArrayLock).
1567  */
1568  topxid = SubTransGetTopmostTransaction(xid);
1569  Assert(TransactionIdIsValid(topxid));
1570  if (!TransactionIdEquals(topxid, xid))
1571  {
1572  for (int i = 0; i < nxids; i++)
1573  {
1574  if (TransactionIdEquals(xids[i], topxid))
1575  return true;
1576  }
1577  }
1578 
1579  return false;
1580 }
#define TransactionIdEquals(id1, id2)
Definition: transam.h:43
uint32 TransactionId
Definition: c.h:587
bool TransactionIdIsCurrentTransactionId(TransactionId xid)
Definition: xact.c:869
TransactionId SubTransGetTopmostTransaction(TransactionId xid)
Definition: subtrans.c:150
XidCacheStatus * subxidStates
Definition: proc.h:327
PGPROC * MyProc
Definition: proc.c:68
#define UINT32_ACCESS_ONCE(var)
Definition: procarray.c:69
#define xc_by_my_xact_inc()
Definition: procarray.c:324
int errcode(int sqlerrcode)
Definition: elog.c:698
TransactionId RecentXmin
Definition: snapmgr.c:113
PROC_HDR * ProcGlobal
Definition: proc.c:80
FullTransactionId latestCompletedXid
Definition: transam.h:238
bool RecoveryInProgress(void)
Definition: xlog.c:8217
#define xc_by_child_xid_inc()
Definition: procarray.c:327
bool TransactionIdIsKnownCompleted(TransactionId transactionId)
Definition: transam.c:238
#define XidFromFullTransactionId(x)
Definition: transam.h:48
#define malloc(a)
Definition: header.h:50
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1803
#define xc_by_recent_xmin_inc()
Definition: procarray.c:322
#define xc_by_known_xact_inc()
Definition: procarray.c:323
bool TransactionIdPrecedesOrEquals(TransactionId id1, TransactionId id2)
Definition: transam.c:319
#define ERROR
Definition: elog.h:46
#define xc_by_main_xid_inc()
Definition: procarray.c:326
#define xc_by_known_assigned_inc()
Definition: procarray.c:328
VariableCache ShmemVariableCache
Definition: varsup.c:34
TransactionId * xids
Definition: proc.h:321
static PGPROC * allProcs
Definition: procarray.c:263
struct XidCache subxids
Definition: proc.h:212
TransactionId lastOverflowedXid
Definition: procarray.c:93
bool TransactionIdDidAbort(TransactionId transactionId)
Definition: transam.c:181
#define xc_by_latest_xid_inc()
Definition: procarray.c:325
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
static ProcArrayStruct * procArray
Definition: procarray.c:261
static int KnownAssignedXidsGet(TransactionId *xarray, TransactionId xmax)
Definition: procarray.c:4977
#define ereport(elevel,...)
Definition: elog.h:157
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
TransactionId xids[PGPROC_MAX_CACHED_SUBXIDS]
Definition: proc.h:48
#define TOTAL_MAX_CACHED_SUBXIDS
#define Assert(condition)
Definition: c.h:804
#define pg_read_barrier()
Definition: atomics.h:158
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1199
#define xc_no_overflow_inc()
Definition: procarray.c:329
uint8 count
Definition: proc.h:41
static bool KnownAssignedXidExists(TransactionId xid)
Definition: procarray.c:4838
#define xc_slow_answer_inc()
Definition: procarray.c:330
int errmsg(const char *fmt,...)
Definition: elog.c:909
int i
int pgxactoff
Definition: proc.h:148
#define TransactionIdIsValid(xid)
Definition: transam.h:41
Definition: proc.h:121

◆ XidCacheRemoveRunningXids()

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

Definition at line 3913 of file procarray.c.

References Assert, XidCacheStatus::count, elog, fprintf, i, 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().

3916 {
3917  int i,
3918  j;
3919  XidCacheStatus *mysubxidstat;
3920 
3922 
3923  /*
3924  * We must hold ProcArrayLock exclusively in order to remove transactions
3925  * from the PGPROC array. (See src/backend/access/transam/README.) It's
3926  * possible this could be relaxed since we know this routine is only used
3927  * to abort subtransactions, but pending closer analysis we'd best be
3928  * conservative.
3929  *
3930  * Note that we do not have to be careful about memory ordering of our own
3931  * reads wrt. GetNewTransactionId() here - only this process can modify
3932  * relevant fields of MyProc/ProcGlobal->xids[]. But we do have to be
3933  * careful about our own writes being well ordered.
3934  */
3935  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3936 
3937  mysubxidstat = &ProcGlobal->subxidStates[MyProc->pgxactoff];
3938 
3939  /*
3940  * Under normal circumstances xid and xids[] will be in increasing order,
3941  * as will be the entries in subxids. Scan backwards to avoid O(N^2)
3942  * behavior when removing a lot of xids.
3943  */
3944  for (i = nxids - 1; i >= 0; i--)
3945  {
3946  TransactionId anxid = xids[i];
3947 
3948  for (j = MyProc->subxidStatus.count - 1; j >= 0; j--)
3949  {
3950  if (TransactionIdEquals(MyProc->subxids.xids[j], anxid))
3951  {
3953  pg_write_barrier();
3954  mysubxidstat->count--;
3956  break;
3957  }
3958  }
3959 
3960  /*
3961  * Ordinarily we should have found it, unless the cache has
3962  * overflowed. However it's also possible for this routine to be
3963  * invoked multiple times for the same subtransaction, in case of an
3964  * error during AbortSubTransaction. So instead of Assert, emit a
3965  * debug warning.
3966  */
3967  if (j < 0 && !MyProc->subxidStatus.overflowed)
3968  elog(WARNING, "did not find subXID %u in MyProc", anxid);
3969  }
3970 
3971  for (j = MyProc->subxidStatus.count - 1; j >= 0; j--)
3972  {
3973  if (TransactionIdEquals(MyProc->subxids.xids[j], xid))
3974  {
3976  pg_write_barrier();
3977  mysubxidstat->count--;
3979  break;
3980  }
3981  }
3982  /* Ordinarily we should have found it, unless the cache has overflowed */
3983  if (j < 0 && !MyProc->subxidStatus.overflowed)
3984  elog(WARNING, "did not find subXID %u in MyProc", xid);
3985 
3986  /* Also advance global latestCompletedXid while holding the lock */
3987  MaintainLatestCompletedXid(latestXid);
3988 
3989  /* ... and xactCompletionCount */
3991 
3992  LWLockRelease(ProcArrayLock);
3993 }
#define TransactionIdEquals(id1, id2)
Definition: transam.h:43
uint32 TransactionId
Definition: c.h:587
XidCacheStatus * subxidStates
Definition: proc.h:327
PGPROC * MyProc
Definition: proc.c:68
uint64 xactCompletionCount
Definition: transam.h:248
PROC_HDR * ProcGlobal
Definition: proc.c:80
XidCacheStatus subxidStatus
Definition: proc.h:210
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1803
VariableCache ShmemVariableCache
Definition: varsup.c:34
struct XidCache subxids
Definition: proc.h:212
#define WARNING
Definition: elog.h:40
static void MaintainLatestCompletedXid(TransactionId latestXid)
Definition: procarray.c:947
TransactionId xids[PGPROC_MAX_CACHED_SUBXIDS]
Definition: proc.h:48
#define Assert(condition)
Definition: c.h:804
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1199
uint8 count
Definition: proc.h:41
#define elog(elevel,...)
Definition: elog.h:232
int i
int pgxactoff
Definition: proc.h:148
#define pg_write_barrier()
Definition: atomics.h:159
#define TransactionIdIsValid(xid)
Definition: transam.h:41