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

3068 {
3069  PGPROC *result;
3070 
3071  if (pid == 0) /* never match dummy PGPROCs */
3072  return NULL;
3073 
3074  LWLockAcquire(ProcArrayLock, LW_SHARED);
3075 
3076  result = BackendPidGetProcWithLock(pid);
3077 
3078  LWLockRelease(ProcArrayLock);
3079 
3080  return result;
3081 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1805
PGPROC * BackendPidGetProcWithLock(int pid)
Definition: procarray.c:3090
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1203
Definition: proc.h:121

◆ BackendPidGetProcWithLock()

PGPROC* BackendPidGetProcWithLock ( int  pid)

Definition at line 3090 of file procarray.c.

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

Referenced by BackendPidGetProc(), and GetBlockerStatusData().

3091 {
3092  PGPROC *result = NULL;
3093  ProcArrayStruct *arrayP = procArray;
3094  int index;
3095 
3096  if (pid == 0) /* never match dummy PGPROCs */
3097  return NULL;
3098 
3099  for (index = 0; index < arrayP->numProcs; index++)
3100  {
3101  PGPROC *proc = &allProcs[arrayP->pgprocnos[index]];
3102 
3103  if (proc->pid == pid)
3104  {
3105  result = proc;
3106  break;
3107  }
3108  }
3109 
3110  return result;
3111 }
Definition: type.h:89
static PGPROC * allProcs
Definition: procarray.c:252
static ProcArrayStruct * procArray
Definition: procarray.c:250
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 3127 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().

3128 {
3129  int result = 0;
3130  ProcArrayStruct *arrayP = procArray;
3131  TransactionId *other_xids = ProcGlobal->xids;
3132  int index;
3133 
3134  if (xid == InvalidTransactionId) /* never match invalid xid */
3135  return 0;
3136 
3137  LWLockAcquire(ProcArrayLock, LW_SHARED);
3138 
3139  for (index = 0; index < arrayP->numProcs; index++)
3140  {
3141  int pgprocno = arrayP->pgprocnos[index];
3142  PGPROC *proc = &allProcs[pgprocno];
3143 
3144  if (other_xids[index] == xid)
3145  {
3146  result = proc->pid;
3147  break;
3148  }
3149  }
3150 
3151  LWLockRelease(ProcArrayLock);
3152 
3153  return result;
3154 }
uint32 TransactionId
Definition: c.h:587
PROC_HDR * ProcGlobal
Definition: proc.c:80
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1805
#define InvalidTransactionId
Definition: transam.h:31
TransactionId * xids
Definition: proc.h:321
static PGPROC * allProcs
Definition: procarray.c:252
static ProcArrayStruct * procArray
Definition: procarray.c:250
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1203
Definition: proc.h:121
int pid
Definition: proc.h:146

◆ CancelDBBackends()

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

Definition at line 3526 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().

3527 {
3528  ProcArrayStruct *arrayP = procArray;
3529  int index;
3530 
3531  /* tell all backends to die */
3532  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3533 
3534  for (index = 0; index < arrayP->numProcs; index++)
3535  {
3536  int pgprocno = arrayP->pgprocnos[index];
3537  PGPROC *proc = &allProcs[pgprocno];
3538 
3539  if (databaseid == InvalidOid || proc->databaseId == databaseid)
3540  {
3541  VirtualTransactionId procvxid;
3542  pid_t pid;
3543 
3544  GET_VXID_FROM_PGPROC(procvxid, *proc);
3545 
3546  proc->recoveryConflictPending = conflictPending;
3547  pid = proc->pid;
3548  if (pid != 0)
3549  {
3550  /*
3551  * Kill the pid if it's still here. If not, that's what we
3552  * wanted so ignore any errors.
3553  */
3554  (void) SendProcSignal(pid, sigmode, procvxid.backendId);
3555  }
3556  }
3557  }
3558 
3559  LWLockRelease(ProcArrayLock);
3560 }
#define GET_VXID_FROM_PGPROC(vxid, proc)
Definition: lock.h:81
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1805
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:252
Oid databaseId
Definition: proc.h:154
static ProcArrayStruct * procArray
Definition: procarray.c:250
#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:1203
Definition: proc.h:121
int pid
Definition: proc.h:146

◆ CancelVirtualTransaction()

pid_t CancelVirtualTransaction ( VirtualTransactionId  vxid,
ProcSignalReason  sigmode 
)

Definition at line 3357 of file procarray.c.

References SignalVirtualTransaction().

Referenced by ResolveRecoveryConflictWithVirtualXIDs().

3358 {
3359  return SignalVirtualTransaction(vxid, sigmode, true);
3360 }
pid_t SignalVirtualTransaction(VirtualTransactionId vxid, ProcSignalReason sigmode, bool conflictPending)
Definition: procarray.c:3363

◆ CountDBBackends()

int CountDBBackends ( Oid  databaseid)

Definition at line 3465 of file procarray.c.

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

Referenced by ResolveRecoveryConflictWithDatabase().

3466 {
3467  ProcArrayStruct *arrayP = procArray;
3468  int count = 0;
3469  int index;
3470 
3471  LWLockAcquire(ProcArrayLock, LW_SHARED);
3472 
3473  for (index = 0; index < arrayP->numProcs; index++)
3474  {
3475  int pgprocno = arrayP->pgprocnos[index];
3476  PGPROC *proc = &allProcs[pgprocno];
3477 
3478  if (proc->pid == 0)
3479  continue; /* do not count prepared xacts */
3480  if (!OidIsValid(databaseid) ||
3481  proc->databaseId == databaseid)
3482  count++;
3483  }
3484 
3485  LWLockRelease(ProcArrayLock);
3486 
3487  return count;
3488 }
#define OidIsValid(objectId)
Definition: c.h:710
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1805
static PGPROC * allProcs
Definition: procarray.c:252
Oid databaseId
Definition: proc.h:154
static ProcArrayStruct * procArray
Definition: procarray.c:250
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1203
Definition: proc.h:121
int pid
Definition: proc.h:146

◆ CountDBConnections()

int CountDBConnections ( Oid  databaseid)

Definition at line 3495 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().

3496 {
3497  ProcArrayStruct *arrayP = procArray;
3498  int count = 0;
3499  int index;
3500 
3501  LWLockAcquire(ProcArrayLock, LW_SHARED);
3502 
3503  for (index = 0; index < arrayP->numProcs; index++)
3504  {
3505  int pgprocno = arrayP->pgprocnos[index];
3506  PGPROC *proc = &allProcs[pgprocno];
3507 
3508  if (proc->pid == 0)
3509  continue; /* do not count prepared xacts */
3510  if (proc->isBackgroundWorker)
3511  continue; /* do not count background workers */
3512  if (!OidIsValid(databaseid) ||
3513  proc->databaseId == databaseid)
3514  count++;
3515  }
3516 
3517  LWLockRelease(ProcArrayLock);
3518 
3519  return count;
3520 }
#define OidIsValid(objectId)
Definition: c.h:710
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1805
bool isBackgroundWorker
Definition: proc.h:160
static PGPROC * allProcs
Definition: procarray.c:252
Oid databaseId
Definition: proc.h:154
static ProcArrayStruct * procArray
Definition: procarray.c:250
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1203
Definition: proc.h:121
int pid
Definition: proc.h:146

◆ CountOtherDBBackends()

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

Definition at line 3616 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().

3617 {
3618  ProcArrayStruct *arrayP = procArray;
3619 
3620 #define MAXAUTOVACPIDS 10 /* max autovacs to SIGTERM per iteration */
3621  int autovac_pids[MAXAUTOVACPIDS];
3622  int tries;
3623 
3624  /* 50 tries with 100ms sleep between tries makes 5 sec total wait */
3625  for (tries = 0; tries < 50; tries++)
3626  {
3627  int nautovacs = 0;
3628  bool found = false;
3629  int index;
3630 
3632 
3633  *nbackends = *nprepared = 0;
3634 
3635  LWLockAcquire(ProcArrayLock, LW_SHARED);
3636 
3637  for (index = 0; index < arrayP->numProcs; index++)
3638  {
3639  int pgprocno = arrayP->pgprocnos[index];
3640  PGPROC *proc = &allProcs[pgprocno];
3641  uint8 statusFlags = ProcGlobal->statusFlags[index];
3642 
3643  if (proc->databaseId != databaseId)
3644  continue;
3645  if (proc == MyProc)
3646  continue;
3647 
3648  found = true;
3649 
3650  if (proc->pid == 0)
3651  (*nprepared)++;
3652  else
3653  {
3654  (*nbackends)++;
3655  if ((statusFlags & PROC_IS_AUTOVACUUM) &&
3656  nautovacs < MAXAUTOVACPIDS)
3657  autovac_pids[nautovacs++] = proc->pid;
3658  }
3659  }
3660 
3661  LWLockRelease(ProcArrayLock);
3662 
3663  if (!found)
3664  return false; /* no conflicting backends, so done */
3665 
3666  /*
3667  * Send SIGTERM to any conflicting autovacuums before sleeping. We
3668  * postpone this step until after the loop because we don't want to
3669  * hold ProcArrayLock while issuing kill(). We have no idea what might
3670  * block kill() inside the kernel...
3671  */
3672  for (index = 0; index < nautovacs; index++)
3673  (void) kill(autovac_pids[index], SIGTERM); /* ignore any error */
3674 
3675  /* sleep, then try again */
3676  pg_usleep(100 * 1000L); /* 100ms */
3677  }
3678 
3679  return true; /* timed out, still conflicts */
3680 }
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:1805
void pg_usleep(long microsec)
Definition: signal.c:53
static PGPROC * allProcs
Definition: procarray.c:252
Oid databaseId
Definition: proc.h:154
static ProcArrayStruct * procArray
Definition: procarray.c:250
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1203
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:102
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 3566 of file procarray.c.

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

Referenced by InitializeSessionUserId().

3567 {
3568  ProcArrayStruct *arrayP = procArray;
3569  int count = 0;
3570  int index;
3571 
3572  LWLockAcquire(ProcArrayLock, LW_SHARED);
3573 
3574  for (index = 0; index < arrayP->numProcs; index++)
3575  {
3576  int pgprocno = arrayP->pgprocnos[index];
3577  PGPROC *proc = &allProcs[pgprocno];
3578 
3579  if (proc->pid == 0)
3580  continue; /* do not count prepared xacts */
3581  if (proc->isBackgroundWorker)
3582  continue; /* do not count background workers */
3583  if (proc->roleId == roleid)
3584  count++;
3585  }
3586 
3587  LWLockRelease(ProcArrayLock);
3588 
3589  return count;
3590 }
Oid roleId
Definition: proc.h:155
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1805
bool isBackgroundWorker
Definition: proc.h:160
static PGPROC * allProcs
Definition: procarray.c:252
static ProcArrayStruct * procArray
Definition: procarray.c:250
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1203
Definition: proc.h:121
int pid
Definition: proc.h:146

◆ CreateSharedProcArray()

void CreateSharedProcArray ( void  )

Definition at line 394 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().

395 {
396  bool found;
397 
398  /* Create or attach to the ProcArray shared structure */
400  ShmemInitStruct("Proc Array",
401  add_size(offsetof(ProcArrayStruct, pgprocnos),
402  mul_size(sizeof(int),
404  &found);
405 
406  if (!found)
407  {
408  /*
409  * We're the first - initialize.
410  */
411  procArray->numProcs = 0;
422  }
423 
425 
426  /* Create or attach to the KnownAssignedXids arrays too, if needed */
427  if (EnableHotStandby)
428  {
430  ShmemInitStruct("KnownAssignedXids",
431  mul_size(sizeof(TransactionId),
433  &found);
434  KnownAssignedXidsValid = (bool *)
435  ShmemInitStruct("KnownAssignedXidsValid",
436  mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS),
437  &found);
438  }
439 }
#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:241
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:252
int numKnownAssignedXids
Definition: procarray.c:81
static bool * KnownAssignedXidsValid
Definition: procarray.c:258
TransactionId lastOverflowedXid
Definition: procarray.c:93
static ProcArrayStruct * procArray
Definition: procarray.c:250
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:257
bool EnableHotStandby
Definition: xlog.c:99
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 4397 of file procarray.c.

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

Referenced by ShutdownRecoveryTransactionEnvironment().

4398 {
4399  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
4401  LWLockRelease(ProcArrayLock);
4402 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1805
static void KnownAssignedXidsRemovePreceding(TransactionId xid)
Definition: procarray.c:4846
#define InvalidTransactionId
Definition: transam.h:31
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1203

◆ ExpireOldKnownAssignedTransactionIds()

void ExpireOldKnownAssignedTransactionIds ( TransactionId  xid)

Definition at line 4409 of file procarray.c.

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

Referenced by ProcArrayApplyRecoveryInfo().

4410 {
4411  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
4413  LWLockRelease(ProcArrayLock);
4414 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1805
static void KnownAssignedXidsRemovePreceding(TransactionId xid)
Definition: procarray.c:4846
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1203

◆ ExpireTreeKnownAssignedTransactionIds()

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

Definition at line 4371 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().

4373 {
4375 
4376  /*
4377  * Uses same locking as transaction commit
4378  */
4379  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
4380 
4381  KnownAssignedXidsRemoveTree(xid, nsubxids, subxids);
4382 
4383  /* As in ProcArrayEndTransaction, advance latestCompletedXid */
4385 
4386  /* ... and xactCompletionCount */
4388 
4389  LWLockRelease(ProcArrayLock);
4390 }
static void MaintainLatestCompletedXidRecovery(TransactionId latestXid)
Definition: procarray.c:935
uint64 xactCompletionCount
Definition: transam.h:241
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1805
VariableCache ShmemVariableCache
Definition: varsup.c:34
static void KnownAssignedXidsRemoveTree(TransactionId xid, int nsubxids, TransactionId *subxids)
Definition: procarray.c:4824
#define Assert(condition)
Definition: c.h:804
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1203
HotStandbyState standbyState
Definition: xlog.c:212

◆ GetConflictingVirtualXIDs()

VirtualTransactionId* GetConflictingVirtualXIDs ( TransactionId  limitXmin,
Oid  dbOid 
)

Definition at line 3283 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().

3284 {
3285  static VirtualTransactionId *vxids;
3286  ProcArrayStruct *arrayP = procArray;
3287  int count = 0;
3288  int index;
3289 
3290  /*
3291  * If first time through, get workspace to remember main XIDs in. We
3292  * malloc it permanently to avoid repeated palloc/pfree overhead. Allow
3293  * result space, remembering room for a terminator.
3294  */
3295  if (vxids == NULL)
3296  {
3297  vxids = (VirtualTransactionId *)
3298  malloc(sizeof(VirtualTransactionId) * (arrayP->maxProcs + 1));
3299  if (vxids == NULL)
3300  ereport(ERROR,
3301  (errcode(ERRCODE_OUT_OF_MEMORY),
3302  errmsg("out of memory")));
3303  }
3304 
3305  LWLockAcquire(ProcArrayLock, LW_SHARED);
3306 
3307  for (index = 0; index < arrayP->numProcs; index++)
3308  {
3309  int pgprocno = arrayP->pgprocnos[index];
3310  PGPROC *proc = &allProcs[pgprocno];
3311 
3312  /* Exclude prepared transactions */
3313  if (proc->pid == 0)
3314  continue;
3315 
3316  if (!OidIsValid(dbOid) ||
3317  proc->databaseId == dbOid)
3318  {
3319  /* Fetch xmin just once - can't change on us, but good coding */
3320  TransactionId pxmin = UINT32_ACCESS_ONCE(proc->xmin);
3321 
3322  /*
3323  * We ignore an invalid pxmin because this means that backend has
3324  * no snapshot currently. We hold a Share lock to avoid contention
3325  * with users taking snapshots. That is not a problem because the
3326  * current xmin is always at least one higher than the latest
3327  * removed xid, so any new snapshot would never conflict with the
3328  * test here.
3329  */
3330  if (!TransactionIdIsValid(limitXmin) ||
3331  (TransactionIdIsValid(pxmin) && !TransactionIdFollows(pxmin, limitXmin)))
3332  {
3333  VirtualTransactionId vxid;
3334 
3335  GET_VXID_FROM_PGPROC(vxid, *proc);
3336  if (VirtualTransactionIdIsValid(vxid))
3337  vxids[count++] = vxid;
3338  }
3339  }
3340  }
3341 
3342  LWLockRelease(ProcArrayLock);
3343 
3344  /* add the terminator */
3345  vxids[count].backendId = InvalidBackendId;
3347 
3348  return vxids;
3349 }
#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:1805
#define ERROR
Definition: elog.h:46
TransactionId xmin
Definition: proc.h:138
static PGPROC * allProcs
Definition: procarray.c:252
Oid databaseId
Definition: proc.h:154
static ProcArrayStruct * procArray
Definition: procarray.c:250
#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:1203
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 3195 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().

3198 {
3199  VirtualTransactionId *vxids;
3200  ProcArrayStruct *arrayP = procArray;
3201  int count = 0;
3202  int index;
3203 
3204  /* allocate what's certainly enough result space */
3205  vxids = (VirtualTransactionId *)
3206  palloc(sizeof(VirtualTransactionId) * arrayP->maxProcs);
3207 
3208  LWLockAcquire(ProcArrayLock, LW_SHARED);
3209 
3210  for (index = 0; index < arrayP->numProcs; index++)
3211  {
3212  int pgprocno = arrayP->pgprocnos[index];
3213  PGPROC *proc = &allProcs[pgprocno];
3214  uint8 statusFlags = ProcGlobal->statusFlags[index];
3215 
3216  if (proc == MyProc)
3217  continue;
3218 
3219  if (excludeVacuum & statusFlags)
3220  continue;
3221 
3222  if (allDbs || proc->databaseId == MyDatabaseId)
3223  {
3224  /* Fetch xmin just once - might change on us */
3225  TransactionId pxmin = UINT32_ACCESS_ONCE(proc->xmin);
3226 
3227  if (excludeXmin0 && !TransactionIdIsValid(pxmin))
3228  continue;
3229 
3230  /*
3231  * InvalidTransactionId precedes all other XIDs, so a proc that
3232  * hasn't set xmin yet will not be rejected by this test.
3233  */
3234  if (!TransactionIdIsValid(limitXmin) ||
3235  TransactionIdPrecedesOrEquals(pxmin, limitXmin))
3236  {
3237  VirtualTransactionId vxid;
3238 
3239  GET_VXID_FROM_PGPROC(vxid, *proc);
3240  if (VirtualTransactionIdIsValid(vxid))
3241  vxids[count++] = vxid;
3242  }
3243  }
3244  }
3245 
3246  LWLockRelease(ProcArrayLock);
3247 
3248  *nvxids = count;
3249  return vxids;
3250 }
#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:1805
bool TransactionIdPrecedesOrEquals(TransactionId id1, TransactionId id2)
Definition: transam.c:319
TransactionId xmin
Definition: proc.h:138
static PGPROC * allProcs
Definition: procarray.c:252
Oid databaseId
Definition: proc.h:154
static ProcArrayStruct * procArray
Definition: procarray.c:250
#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:1203
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 2014 of file procarray.c.

References TOTAL_MAX_CACHED_SUBXIDS.

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

2015 {
2016  return TOTAL_MAX_CACHED_SUBXIDS;
2017 }
#define TOTAL_MAX_CACHED_SUBXIDS

◆ GetMaxSnapshotXidCount()

int GetMaxSnapshotXidCount ( void  )

Definition at line 2003 of file procarray.c.

References ProcArrayStruct::maxProcs.

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

2004 {
2005  return procArray->maxProcs;
2006 }
static ProcArrayStruct * procArray
Definition: procarray.c:250

◆ GetOldestActiveTransactionId()

TransactionId GetOldestActiveTransactionId ( void  )

Definition at line 2816 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().

2817 {
2818  ProcArrayStruct *arrayP = procArray;
2819  TransactionId *other_xids = ProcGlobal->xids;
2820  TransactionId oldestRunningXid;
2821  int index;
2822 
2824 
2825  /*
2826  * Read nextXid, as the upper bound of what's still active.
2827  *
2828  * Reading a TransactionId is atomic, but we must grab the lock to make
2829  * sure that all XIDs < nextXid are already present in the proc array (or
2830  * have already completed), when we spin over it.
2831  */
2832  LWLockAcquire(XidGenLock, LW_SHARED);
2834  LWLockRelease(XidGenLock);
2835 
2836  /*
2837  * Spin over procArray collecting all xids and subxids.
2838  */
2839  LWLockAcquire(ProcArrayLock, LW_SHARED);
2840  for (index = 0; index < arrayP->numProcs; index++)
2841  {
2842  TransactionId xid;
2843 
2844  /* Fetch xid just once - see GetNewTransactionId */
2845  xid = UINT32_ACCESS_ONCE(other_xids[index]);
2846 
2847  if (!TransactionIdIsNormal(xid))
2848  continue;
2849 
2850  if (TransactionIdPrecedes(xid, oldestRunningXid))
2851  oldestRunningXid = xid;
2852 
2853  /*
2854  * Top-level XID of a transaction is always less than any of its
2855  * subxids, so we don't need to check if any of the subxids are
2856  * smaller than oldestRunningXid
2857  */
2858  }
2859  LWLockRelease(ProcArrayLock);
2860 
2861  return oldestRunningXid;
2862 }
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:8237
FullTransactionId nextXid
Definition: transam.h:213
#define XidFromFullTransactionId(x)
Definition: transam.h:48
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1805
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:250
#define Assert(condition)
Definition: c.h:804
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1203
#define TransactionIdIsNormal(xid)
Definition: transam.h:42

◆ GetOldestNonRemovableTransactionId()

TransactionId GetOldestNonRemovableTransactionId ( Relation  rel)

Definition at line 1944 of file procarray.c.

References ComputeXidHorizonsResult::catalog_oldest_nonremovable, ComputeXidHorizons(), ComputeXidHorizonsResult::data_oldest_nonremovable, RelationData::rd_rel, RELATION_IS_LOCAL, RelationIsAccessibleInLogicalDecoding, ComputeXidHorizonsResult::shared_oldest_nonremovable, and ComputeXidHorizonsResult::temp_oldest_nonremovable.

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

1945 {
1946  ComputeXidHorizonsResult horizons;
1947 
1948  ComputeXidHorizons(&horizons);
1949 
1950  /* select horizon appropriate for relation */
1951  if (rel == NULL || rel->rd_rel->relisshared)
1952  return horizons.shared_oldest_nonremovable;
1954  return horizons.catalog_oldest_nonremovable;
1955  else if (RELATION_IS_LOCAL(rel))
1956  return horizons.temp_oldest_nonremovable;
1957  else
1958  return horizons.data_oldest_nonremovable;
1959 }
static void ComputeXidHorizons(ComputeXidHorizonsResult *h)
Definition: procarray.c:1667
#define RELATION_IS_LOCAL(relation)
Definition: rel.h:590
Form_pg_class rd_rel
Definition: rel.h:110
TransactionId catalog_oldest_nonremovable
Definition: procarray.c:233
TransactionId shared_oldest_nonremovable
Definition: procarray.c:216
#define RelationIsAccessibleInLogicalDecoding(relation)
Definition: rel.h:626
TransactionId temp_oldest_nonremovable
Definition: procarray.c:245
TransactionId data_oldest_nonremovable
Definition: procarray.c:239

◆ GetOldestSafeDecodingTransactionId()

TransactionId GetOldestSafeDecodingTransactionId ( bool  catalogOnly)

Definition at line 2881 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().

2882 {
2883  ProcArrayStruct *arrayP = procArray;
2884  TransactionId oldestSafeXid;
2885  int index;
2886  bool recovery_in_progress = RecoveryInProgress();
2887 
2888  Assert(LWLockHeldByMe(ProcArrayLock));
2889 
2890  /*
2891  * Acquire XidGenLock, so no transactions can acquire an xid while we're
2892  * running. If no transaction with xid were running concurrently a new xid
2893  * could influence the RecentXmin et al.
2894  *
2895  * We initialize the computation to nextXid since that's guaranteed to be
2896  * a safe, albeit pessimal, value.
2897  */
2898  LWLockAcquire(XidGenLock, LW_SHARED);
2900 
2901  /*
2902  * If there's already a slot pegging the xmin horizon, we can start with
2903  * that value, it's guaranteed to be safe since it's computed by this
2904  * routine initially and has been enforced since. We can always use the
2905  * slot's general xmin horizon, but the catalog horizon is only usable
2906  * when only catalog data is going to be looked at.
2907  */
2910  oldestSafeXid))
2911  oldestSafeXid = procArray->replication_slot_xmin;
2912 
2913  if (catalogOnly &&
2916  oldestSafeXid))
2917  oldestSafeXid = procArray->replication_slot_catalog_xmin;
2918 
2919  /*
2920  * If we're not in recovery, we walk over the procarray and collect the
2921  * lowest xid. Since we're called with ProcArrayLock held and have
2922  * acquired XidGenLock, no entries can vanish concurrently, since
2923  * ProcGlobal->xids[i] is only set with XidGenLock held and only cleared
2924  * with ProcArrayLock held.
2925  *
2926  * In recovery we can't lower the safe value besides what we've computed
2927  * above, so we'll have to wait a bit longer there. We unfortunately can
2928  * *not* use KnownAssignedXidsGetOldestXmin() since the KnownAssignedXids
2929  * machinery can miss values and return an older value than is safe.
2930  */
2931  if (!recovery_in_progress)
2932  {
2933  TransactionId *other_xids = ProcGlobal->xids;
2934 
2935  /*
2936  * Spin over procArray collecting min(ProcGlobal->xids[i])
2937  */
2938  for (index = 0; index < arrayP->numProcs; index++)
2939  {
2940  TransactionId xid;
2941 
2942  /* Fetch xid just once - see GetNewTransactionId */
2943  xid = UINT32_ACCESS_ONCE(other_xids[index]);
2944 
2945  if (!TransactionIdIsNormal(xid))
2946  continue;
2947 
2948  if (TransactionIdPrecedes(xid, oldestSafeXid))
2949  oldestSafeXid = xid;
2950  }
2951  }
2952 
2953  LWLockRelease(XidGenLock);
2954 
2955  return oldestSafeXid;
2956 }
uint32 TransactionId
Definition: c.h:587
bool LWLockHeldByMe(LWLock *l)
Definition: lwlock.c:1920
#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:8237
FullTransactionId nextXid
Definition: transam.h:213
#define XidFromFullTransactionId(x)
Definition: transam.h:48
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1805
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:250
TransactionId replication_slot_xmin
Definition: procarray.c:96
#define Assert(condition)
Definition: c.h:804
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1203
#define TransactionIdIsValid(xid)
Definition: transam.h:41
#define TransactionIdIsNormal(xid)
Definition: transam.h:42

◆ GetOldestTransactionIdConsideredRunning()

TransactionId GetOldestTransactionIdConsideredRunning ( void  )

Definition at line 1968 of file procarray.c.

References ComputeXidHorizons(), and ComputeXidHorizonsResult::oldest_considered_running.

Referenced by CreateCheckPoint(), and CreateRestartPoint().

1969 {
1970  ComputeXidHorizonsResult horizons;
1971 
1972  ComputeXidHorizons(&horizons);
1973 
1974  return horizons.oldest_considered_running;
1975 }
TransactionId oldest_considered_running
Definition: procarray.c:207
static void ComputeXidHorizons(ComputeXidHorizonsResult *h)
Definition: procarray.c:1667

◆ GetReplicationHorizons()

void GetReplicationHorizons ( TransactionId slot_xmin,
TransactionId catalog_xmin 
)

Definition at line 1981 of file procarray.c.

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

Referenced by XLogWalRcvSendHSFeedback().

1982 {
1983  ComputeXidHorizonsResult horizons;
1984 
1985  ComputeXidHorizons(&horizons);
1986 
1987  /*
1988  * Don't want to use shared_oldest_nonremovable here, as that contains the
1989  * effect of replication slot's catalog_xmin. We want to send a separate
1990  * feedback for the catalog horizon, so the primary can remove data table
1991  * contents more aggressively.
1992  */
1993  *xmin = horizons.shared_oldest_nonremovable_raw;
1994  *catalog_xmin = horizons.slot_catalog_xmin;
1995 }
static void ComputeXidHorizons(ComputeXidHorizonsResult *h)
Definition: procarray.c:1667
TransactionId shared_oldest_nonremovable_raw
Definition: procarray.c:227
TransactionId slot_catalog_xmin
Definition: procarray.c:194

◆ GetRunningTransactionData()

RunningTransactions GetRunningTransactionData ( void  )

Definition at line 2641 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().

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

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

2978 {
2979  VirtualTransactionId *vxids;
2980  ProcArrayStruct *arrayP = procArray;
2981  int count = 0;
2982  int index;
2983 
2984  /* allocate what's certainly enough result space */
2985  vxids = (VirtualTransactionId *)
2986  palloc(sizeof(VirtualTransactionId) * arrayP->maxProcs);
2987 
2988  LWLockAcquire(ProcArrayLock, LW_SHARED);
2989 
2990  for (index = 0; index < arrayP->numProcs; index++)
2991  {
2992  int pgprocno = arrayP->pgprocnos[index];
2993  PGPROC *proc = &allProcs[pgprocno];
2994 
2995  if (proc->delayChkpt)
2996  {
2997  VirtualTransactionId vxid;
2998 
2999  GET_VXID_FROM_PGPROC(vxid, *proc);
3000  if (VirtualTransactionIdIsValid(vxid))
3001  vxids[count++] = vxid;
3002  }
3003  }
3004 
3005  LWLockRelease(ProcArrayLock);
3006 
3007  *nvxids = count;
3008  return vxids;
3009 }
#define GET_VXID_FROM_PGPROC(vxid, proc)
Definition: lock.h:81
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1805
bool delayChkpt
Definition: proc.h:187
static PGPROC * allProcs
Definition: procarray.c:252
static ProcArrayStruct * procArray
Definition: procarray.c:250
#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:1203
void * palloc(Size size)
Definition: mcxt.c:1062
Definition: proc.h:121

◆ HaveVirtualXIDsDelayingChkpt()

bool HaveVirtualXIDsDelayingChkpt ( VirtualTransactionId vxids,
int  nvxids 
)

Definition at line 3021 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().

3022 {
3023  bool result = false;
3024  ProcArrayStruct *arrayP = procArray;
3025  int index;
3026 
3027  LWLockAcquire(ProcArrayLock, LW_SHARED);
3028 
3029  for (index = 0; index < arrayP->numProcs; index++)
3030  {
3031  int pgprocno = arrayP->pgprocnos[index];
3032  PGPROC *proc = &allProcs[pgprocno];
3033  VirtualTransactionId vxid;
3034 
3035  GET_VXID_FROM_PGPROC(vxid, *proc);
3036 
3037  if (proc->delayChkpt && VirtualTransactionIdIsValid(vxid))
3038  {
3039  int i;
3040 
3041  for (i = 0; i < nvxids; i++)
3042  {
3043  if (VirtualTransactionIdEquals(vxid, vxids[i]))
3044  {
3045  result = true;
3046  break;
3047  }
3048  }
3049  if (result)
3050  break;
3051  }
3052  }
3053 
3054  LWLockRelease(ProcArrayLock);
3055 
3056  return result;
3057 }
#define GET_VXID_FROM_PGPROC(vxid, proc)
Definition: lock.h:81
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1805
#define VirtualTransactionIdEquals(vxid1, vxid2)
Definition: lock.h:75
bool delayChkpt
Definition: proc.h:187
static PGPROC * allProcs
Definition: procarray.c:252
static ProcArrayStruct * procArray
Definition: procarray.c:250
#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:1203
int i
Definition: proc.h:121

◆ IsBackendPid()

bool IsBackendPid ( int  pid)

Definition at line 3162 of file procarray.c.

References BackendPidGetProc().

Referenced by pg_stat_get_subscription().

3163 {
3164  return (BackendPidGetProc(pid) != NULL);
3165 }
PGPROC * BackendPidGetProc(int pid)
Definition: procarray.c:3067

◆ MinimumActiveBackends()

bool MinimumActiveBackends ( int  min)

Definition at line 3412 of file procarray.c.

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

Referenced by XLogFlush().

3413 {
3414  ProcArrayStruct *arrayP = procArray;
3415  int count = 0;
3416  int index;
3417 
3418  /* Quick short-circuit if no minimum is specified */
3419  if (min == 0)
3420  return true;
3421 
3422  /*
3423  * Note: for speed, we don't acquire ProcArrayLock. This is a little bit
3424  * bogus, but since we are only testing fields for zero or nonzero, it
3425  * should be OK. The result is only used for heuristic purposes anyway...
3426  */
3427  for (index = 0; index < arrayP->numProcs; index++)
3428  {
3429  int pgprocno = arrayP->pgprocnos[index];
3430  PGPROC *proc = &allProcs[pgprocno];
3431 
3432  /*
3433  * Since we're not holding a lock, need to be prepared to deal with
3434  * garbage, as someone could have incremented numProcs but not yet
3435  * filled the structure.
3436  *
3437  * If someone just decremented numProcs, 'proc' could also point to a
3438  * PGPROC entry that's no longer in the array. It still points to a
3439  * PGPROC struct, though, because freed PGPROC entries just go to the
3440  * free list and are recycled. Its contents are nonsense in that case,
3441  * but that's acceptable for this function.
3442  */
3443  if (pgprocno == -1)
3444  continue; /* do not count deleted entries */
3445  if (proc == MyProc)
3446  continue; /* do not count myself */
3447  if (proc->xid == InvalidTransactionId)
3448  continue; /* do not count if no XID assigned */
3449  if (proc->pid == 0)
3450  continue; /* do not count prepared xacts */
3451  if (proc->waitLock != NULL)
3452  continue; /* do not count if blocked on a lock */
3453  count++;
3454  if (count >= min)
3455  break;
3456  }
3457 
3458  return count >= min;
3459 }
PGPROC * MyProc
Definition: proc.c:68
Definition: type.h:89
#define InvalidTransactionId
Definition: transam.h:31
static PGPROC * allProcs
Definition: procarray.c:252
LOCK * waitLock
Definition: proc.h:179
static ProcArrayStruct * procArray
Definition: procarray.c:250
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 445 of file procarray.c.

References ereport, errcode(), errmsg(), FATAL, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), ProcArrayStruct::maxProcs, ProcArrayStruct::numProcs, 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().

446 {
447  ProcArrayStruct *arrayP = procArray;
448  int index;
449 
450  /* See ProcGlobal comment explaining why both locks are held */
451  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
452  LWLockAcquire(XidGenLock, LW_EXCLUSIVE);
453 
454  if (arrayP->numProcs >= arrayP->maxProcs)
455  {
456  /*
457  * Oops, no room. (This really shouldn't happen, since there is a
458  * fixed supply of PGPROC structs too, and so we should have failed
459  * earlier.)
460  */
461  ereport(FATAL,
462  (errcode(ERRCODE_TOO_MANY_CONNECTIONS),
463  errmsg("sorry, too many clients already")));
464  }
465 
466  /*
467  * Keep the procs array sorted by (PGPROC *) so that we can utilize
468  * locality of references much better. This is useful while traversing the
469  * ProcArray because there is an increased likelihood of finding the next
470  * PGPROC structure in the cache.
471  *
472  * Since the occurrence of adding/removing a proc is much lower than the
473  * access to the ProcArray itself, the overhead should be marginal
474  */
475  for (index = 0; index < arrayP->numProcs; index++)
476  {
477  /*
478  * If we are the first PGPROC or if we have found our right position
479  * in the array, break
480  */
481  if ((arrayP->pgprocnos[index] == -1) || (arrayP->pgprocnos[index] > proc->pgprocno))
482  break;
483  }
484 
485  memmove(&arrayP->pgprocnos[index + 1], &arrayP->pgprocnos[index],
486  (arrayP->numProcs - index) * sizeof(*arrayP->pgprocnos));
487  memmove(&ProcGlobal->xids[index + 1], &ProcGlobal->xids[index],
488  (arrayP->numProcs - index) * sizeof(*ProcGlobal->xids));
489  memmove(&ProcGlobal->subxidStates[index + 1], &ProcGlobal->subxidStates[index],
490  (arrayP->numProcs - index) * sizeof(*ProcGlobal->subxidStates));
491  memmove(&ProcGlobal->statusFlags[index + 1], &ProcGlobal->statusFlags[index],
492  (arrayP->numProcs - index) * sizeof(*ProcGlobal->statusFlags));
493 
494  arrayP->pgprocnos[index] = proc->pgprocno;
495  ProcGlobal->xids[index] = proc->xid;
496  ProcGlobal->subxidStates[index] = proc->subxidStatus;
497  ProcGlobal->statusFlags[index] = proc->statusFlags;
498 
499  arrayP->numProcs++;
500 
501  for (; index < arrayP->numProcs; index++)
502  {
503  allProcs[arrayP->pgprocnos[index]].pgxactoff = index;
504  }
505 
506  /*
507  * Release in reversed acquisition order, to reduce frequency of having to
508  * wait for XidGenLock while holding ProcArrayLock.
509  */
510  LWLockRelease(XidGenLock);
511  LWLockRelease(ProcArrayLock);
512 }
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:1805
#define FATAL
Definition: elog.h:49
TransactionId * xids
Definition: proc.h:321
static PGPROC * allProcs
Definition: procarray.c:252
static ProcArrayStruct * procArray
Definition: procarray.c:250
#define ereport(elevel,...)
Definition: elog.h:157
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1203
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

◆ ProcArrayApplyRecoveryInfo()

void ProcArrayApplyRecoveryInfo ( RunningTransactions  running)

Definition at line 1000 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().

1001 {
1002  TransactionId *xids;
1003  int nxids;
1004  int i;
1005 
1007  Assert(TransactionIdIsValid(running->nextXid));
1010 
1011  /*
1012  * Remove stale transactions, if any.
1013  */
1015 
1016  /*
1017  * Remove stale locks, if any.
1018  */
1020 
1021  /*
1022  * If our snapshot is already valid, nothing else to do...
1023  */
1025  return;
1026 
1027  /*
1028  * If our initial RunningTransactionsData had an overflowed snapshot then
1029  * we knew we were missing some subxids from our snapshot. If we continue
1030  * to see overflowed snapshots then we might never be able to start up, so
1031  * we make another test to see if our snapshot is now valid. We know that
1032  * the missing subxids are equal to or earlier than nextXid. After we
1033  * initialise we continue to apply changes during recovery, so once the
1034  * oldestRunningXid is later than the nextXid from the initial snapshot we
1035  * know that we no longer have missing information and can mark the
1036  * snapshot as valid.
1037  */
1039  {
1040  /*
1041  * If the snapshot isn't overflowed or if its empty we can reset our
1042  * pending state and use this snapshot instead.
1043  */
1044  if (!running->subxid_overflow || running->xcnt == 0)
1045  {
1046  /*
1047  * If we have already collected known assigned xids, we need to
1048  * throw them away before we apply the recovery snapshot.
1049  */
1052  }
1053  else
1054  {
1056  running->oldestRunningXid))
1057  {
1060  "recovery snapshots are now enabled");
1061  }
1062  else
1064  "recovery snapshot waiting for non-overflowed snapshot or "
1065  "until oldest active xid on standby is at least %u (now %u)",
1067  running->oldestRunningXid);
1068  return;
1069  }
1070  }
1071 
1073 
1074  /*
1075  * NB: this can be reached at least twice, so make sure new code can deal
1076  * with that.
1077  */
1078 
1079  /*
1080  * Nobody else is running yet, but take locks anyhow
1081  */
1082  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
1083 
1084  /*
1085  * KnownAssignedXids is sorted so we cannot just add the xids, we have to
1086  * sort them first.
1087  *
1088  * Some of the new xids are top-level xids and some are subtransactions.
1089  * We don't call SubTransSetParent because it doesn't matter yet. If we
1090  * aren't overflowed then all xids will fit in snapshot and so we don't
1091  * need subtrans. If we later overflow, an xid assignment record will add
1092  * xids to subtrans. If RunningTransactionsData is overflowed then we
1093  * don't have enough information to correctly update subtrans anyway.
1094  */
1095 
1096  /*
1097  * Allocate a temporary array to avoid modifying the array passed as
1098  * argument.
1099  */
1100  xids = palloc(sizeof(TransactionId) * (running->xcnt + running->subxcnt));
1101 
1102  /*
1103  * Add to the temp array any xids which have not already completed.
1104  */
1105  nxids = 0;
1106  for (i = 0; i < running->xcnt + running->subxcnt; i++)
1107  {
1108  TransactionId xid = running->xids[i];
1109 
1110  /*
1111  * The running-xacts snapshot can contain xids that were still visible
1112  * in the procarray when the snapshot was taken, but were already
1113  * WAL-logged as completed. They're not running anymore, so ignore
1114  * them.
1115  */
1117  continue;
1118 
1119  xids[nxids++] = xid;
1120  }
1121 
1122  if (nxids > 0)
1123  {
1124  if (procArray->numKnownAssignedXids != 0)
1125  {
1126  LWLockRelease(ProcArrayLock);
1127  elog(ERROR, "KnownAssignedXids is not empty");
1128  }
1129 
1130  /*
1131  * Sort the array so that we can add them safely into
1132  * KnownAssignedXids.
1133  */
1134  qsort(xids, nxids, sizeof(TransactionId), xidComparator);
1135 
1136  /*
1137  * Add the sorted snapshot into KnownAssignedXids. The running-xacts
1138  * snapshot may include duplicated xids because of prepared
1139  * transactions, so ignore them.
1140  */
1141  for (i = 0; i < nxids; i++)
1142  {
1143  if (i > 0 && TransactionIdEquals(xids[i - 1], xids[i]))
1144  {
1145  elog(DEBUG1,
1146  "found duplicated transaction %u for KnownAssignedXids insertion",
1147  xids[i]);
1148  continue;
1149  }
1150  KnownAssignedXidsAdd(xids[i], xids[i], true);
1151  }
1152 
1154  }
1155 
1156  pfree(xids);
1157 
1158  /*
1159  * latestObservedXid is at least set to the point where SUBTRANS was
1160  * started up to (cf. ProcArrayInitRecovery()) or to the biggest xid
1161  * RecordKnownAssignedTransactionIds() was called for. Initialize
1162  * subtrans from thereon, up to nextXid - 1.
1163  *
1164  * We need to duplicate parts of RecordKnownAssignedTransactionId() here,
1165  * because we've just added xids to the known assigned xids machinery that
1166  * haven't gone through RecordKnownAssignedTransactionId().
1167  */
1171  {
1174  }
1175  TransactionIdRetreat(latestObservedXid); /* = running->nextXid - 1 */
1176 
1177  /* ----------
1178  * Now we've got the running xids we need to set the global values that
1179  * are used to track snapshots as they evolve further.
1180  *
1181  * - latestCompletedXid which will be the xmax for snapshots
1182  * - lastOverflowedXid which shows whether snapshots overflow
1183  * - nextXid
1184  *
1185  * If the snapshot overflowed, then we still initialise with what we know,
1186  * but the recovery snapshot isn't fully valid yet because we know there
1187  * are some subxids missing. We don't know the specific subxids that are
1188  * missing, so conservatively assume the last one is latestObservedXid.
1189  * ----------
1190  */
1191  if (running->subxid_overflow)
1192  {
1194 
1197  }
1198  else
1199  {
1201 
1203  }
1204 
1205  /*
1206  * If a transaction wrote a commit record in the gap between taking and
1207  * logging the snapshot then latestCompletedXid may already be higher than
1208  * the value from the snapshot, so check before we use the incoming value.
1209  * It also might not yet be set at all.
1210  */
1212 
1213  /*
1214  * NB: No need to increment ShmemVariableCache->xactCompletionCount here,
1215  * nobody can see it yet.
1216  */
1217 
1218  LWLockRelease(ProcArrayLock);
1219 
1220  /* ShmemVariableCache->nextXid must be beyond any observed xid. */
1222 
1224 
1227  elog(trace_recovery(DEBUG1), "recovery snapshots are now enabled");
1228  else
1230  "recovery snapshot waiting for non-overflowed snapshot or "
1231  "until oldest active xid on standby is at least %u (now %u)",
1233  running->oldestRunningXid);
1234 }
#define TransactionIdAdvance(dest)
Definition: transam.h:91
static TransactionId latestObservedXid
Definition: procarray.c:259
TransactionId oldestRunningXid
Definition: standby.h:83
#define DEBUG1
Definition: elog.h:25
static void KnownAssignedXidsDisplay(int trace_level)
Definition: procarray.c:5031
#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:935
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:213
int trace_recovery(int trace_level)
Definition: elog.c:3609
TransactionId latestCompletedXid
Definition: standby.h:84
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1805
void pfree(void *pointer)
Definition: mcxt.c:1169
#define ERROR
Definition: elog.h:46
void ExtendSUBTRANS(TransactionId newestXact)
Definition: subtrans.c:308
VariableCache ShmemVariableCache
Definition: varsup.c:34
#define InvalidTransactionId
Definition: transam.h:31
static void KnownAssignedXidsReset(void)
Definition: procarray.c:5069
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:250
#define Assert(condition)
Definition: c.h:804
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1203
static void KnownAssignedXidsAdd(TransactionId from_xid, TransactionId to_xid, bool exclusive_lock)
Definition: procarray.c:4574
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:4409
#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:266
HotStandbyState standbyState
Definition: xlog.c:212
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 1241 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().

1243 {
1244  TransactionId max_xid;
1245  int i;
1246 
1248 
1249  max_xid = TransactionIdLatest(topxid, nsubxids, subxids);
1250 
1251  /*
1252  * Mark all the subtransactions as observed.
1253  *
1254  * NOTE: This will fail if the subxid contains too many previously
1255  * unobserved xids to fit into known-assigned-xids. That shouldn't happen
1256  * as the code stands, because xid-assignment records should never contain
1257  * more than PGPROC_MAX_CACHED_SUBXIDS entries.
1258  */
1260 
1261  /*
1262  * Notice that we update pg_subtrans with the top-level xid, rather than
1263  * the parent xid. This is a difference between normal processing and
1264  * recovery, yet is still correct in all cases. The reason is that
1265  * subtransaction commit is not marked in clog until commit processing, so
1266  * all aborted subtransactions have already been clearly marked in clog.
1267  * As a result we are able to refer directly to the top-level
1268  * transaction's state rather than skipping through all the intermediate
1269  * states in the subtransaction tree. This should be the first time we
1270  * have attempted to SubTransSetParent().
1271  */
1272  for (i = 0; i < nsubxids; i++)
1273  SubTransSetParent(subxids[i], topxid);
1274 
1275  /* KnownAssignedXids isn't maintained yet, so we're done for now */
1277  return;
1278 
1279  /*
1280  * Uses same locking as transaction commit
1281  */
1282  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
1283 
1284  /*
1285  * Remove subxids from known-assigned-xacts.
1286  */
1288 
1289  /*
1290  * Advance lastOverflowedXid to be at least the last of these subxids.
1291  */
1293  procArray->lastOverflowedXid = max_xid;
1294 
1295  LWLockRelease(ProcArrayLock);
1296 }
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:1805
#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:4824
static ProcArrayStruct * procArray
Definition: procarray.c:250
#define Assert(condition)
Definition: c.h:804
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1203
int i
void RecordKnownAssignedTransactionIds(TransactionId xid)
Definition: procarray.c:4300
void SubTransSetParent(TransactionId xid, TransactionId parent)
Definition: subtrans.c:74
HotStandbyState standbyState
Definition: xlog.c:212

◆ ProcArrayClearTransaction()

void ProcArrayClearTransaction ( PGPROC proc)

Definition at line 853 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().

854 {
855  size_t pgxactoff;
856 
857  /*
858  * Currently we need to lock ProcArrayLock exclusively here, as we
859  * increment xactCompletionCount below. We also need it at least in shared
860  * mode for pgproc->pgxactoff to stay the same below.
861  *
862  * We could however, as this action does not actually change anyone's view
863  * of the set of running XIDs (our entry is duplicate with the gxact that
864  * has already been inserted into the ProcArray), lower the lock level to
865  * shared if we were to make xactCompletionCount an atomic variable. But
866  * that doesn't seem worth it currently, as a 2PC commit is heavyweight
867  * enough for this not to be the bottleneck. If it ever becomes a
868  * bottleneck it may also be worth considering to combine this with the
869  * subsequent ProcArrayRemove()
870  */
871  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
872 
873  pgxactoff = proc->pgxactoff;
874 
875  ProcGlobal->xids[pgxactoff] = InvalidTransactionId;
876  proc->xid = InvalidTransactionId;
877 
879  proc->xmin = InvalidTransactionId;
880  proc->recoveryConflictPending = false;
881 
883  Assert(!proc->delayChkpt);
884 
885  /*
886  * Need to increment completion count even though transaction hasn't
887  * really committed yet. The reason for that is that GetSnapshotData()
888  * omits the xid of the current transaction, thus without the increment we
889  * otherwise could end up reusing the snapshot later. Which would be bad,
890  * because it might not count the prepared transaction as running.
891  */
893 
894  /* Clear the subtransaction-XID cache too */
895  Assert(ProcGlobal->subxidStates[pgxactoff].count == proc->subxidStatus.count &&
897  if (proc->subxidStatus.count > 0 || proc->subxidStatus.overflowed)
898  {
899  ProcGlobal->subxidStates[pgxactoff].count = 0;
900  ProcGlobal->subxidStates[pgxactoff].overflowed = false;
901  proc->subxidStatus.count = 0;
902  proc->subxidStatus.overflowed = false;
903  }
904 
905  LWLockRelease(ProcArrayLock);
906 }
XidCacheStatus * subxidStates
Definition: proc.h:327
uint64 xactCompletionCount
Definition: transam.h:241
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:1805
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:1203
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 620 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().

621 {
622  if (TransactionIdIsValid(latestXid))
623  {
624  /*
625  * We must lock ProcArrayLock while clearing our advertised XID, so
626  * that we do not exit the set of "running" transactions while someone
627  * else is taking a snapshot. See discussion in
628  * src/backend/access/transam/README.
629  */
631 
632  /*
633  * If we can immediately acquire ProcArrayLock, we clear our own XID
634  * and release the lock. If not, use group XID clearing to improve
635  * efficiency.
636  */
637  if (LWLockConditionalAcquire(ProcArrayLock, LW_EXCLUSIVE))
638  {
639  ProcArrayEndTransactionInternal(proc, latestXid);
640  LWLockRelease(ProcArrayLock);
641  }
642  else
643  ProcArrayGroupClearXid(proc, latestXid);
644  }
645  else
646  {
647  /*
648  * If we have no XID, we don't need to lock, since we won't affect
649  * anyone else's calculation of a snapshot. We might change their
650  * estimate of global xmin, but that's OK.
651  */
653  Assert(proc->subxidStatus.count == 0);
655 
657  proc->xmin = InvalidTransactionId;
658  proc->delayChkpt = false; /* be sure this is cleared in abort */
659  proc->recoveryConflictPending = false;
660 
661  /* must be cleared with xid/xmin: */
662  /* avoid unnecessarily dirtying shared cachelines */
664  {
665  Assert(!LWLockHeldByMe(ProcArrayLock));
666  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
670  LWLockRelease(ProcArrayLock);
671  }
672  }
673 }
bool LWLockHeldByMe(LWLock *l)
Definition: lwlock.c:1920
static void ProcArrayEndTransactionInternal(PGPROC *proc, TransactionId latestXid)
Definition: procarray.c:681
static void ProcArrayGroupClearXid(PGPROC *proc, TransactionId latestXid)
Definition: procarray.c:739
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:1805
bool delayChkpt
Definition: proc.h:187
TransactionId xmin
Definition: proc.h:138
bool LWLockConditionalAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1375
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:1203
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 3824 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().

3826 {
3827  LWLockAcquire(ProcArrayLock, LW_SHARED);
3828 
3829  if (xmin != NULL)
3831 
3832  if (catalog_xmin != NULL)
3833  *catalog_xmin = procArray->replication_slot_catalog_xmin;
3834 
3835  LWLockRelease(ProcArrayLock);
3836 }
TransactionId replication_slot_catalog_xmin
Definition: procarray.c:98
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1805
static ProcArrayStruct * procArray
Definition: procarray.c:250
TransactionId replication_slot_xmin
Definition: procarray.c:96
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1203

◆ ProcArrayInitRecovery()

void ProcArrayInitRecovery ( TransactionId  initializedUptoXID)

Definition at line 969 of file procarray.c.

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

Referenced by StartupXLOG().

970 {
972  Assert(TransactionIdIsNormal(initializedUptoXID));
973 
974  /*
975  * we set latestObservedXid to the xid SUBTRANS has been initialized up
976  * to, so we can extend it from that point onwards in
977  * RecordKnownAssignedTransactionIds, and when we get consistent in
978  * ProcArrayApplyRecoveryInfo().
979  */
980  latestObservedXid = initializedUptoXID;
982 }
static TransactionId latestObservedXid
Definition: procarray.c:259
#define TransactionIdRetreat(dest)
Definition: transam.h:141
#define Assert(condition)
Definition: c.h:804
#define TransactionIdIsNormal(xid)
Definition: transam.h:42
HotStandbyState standbyState
Definition: xlog.c:212

◆ ProcArrayInstallImportedXmin()

bool ProcArrayInstallImportedXmin ( TransactionId  xmin,
VirtualTransactionId sourcevxid 
)

Definition at line 2503 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().

2505 {
2506  bool result = false;
2507  ProcArrayStruct *arrayP = procArray;
2508  int index;
2509 
2511  if (!sourcevxid)
2512  return false;
2513 
2514  /* Get lock so source xact can't end while we're doing this */
2515  LWLockAcquire(ProcArrayLock, LW_SHARED);
2516 
2517  for (index = 0; index < arrayP->numProcs; index++)
2518  {
2519  int pgprocno = arrayP->pgprocnos[index];
2520  PGPROC *proc = &allProcs[pgprocno];
2521  int statusFlags = ProcGlobal->statusFlags[index];
2522  TransactionId xid;
2523 
2524  /* Ignore procs running LAZY VACUUM */
2525  if (statusFlags & PROC_IN_VACUUM)
2526  continue;
2527 
2528  /* We are only interested in the specific virtual transaction. */
2529  if (proc->backendId != sourcevxid->backendId)
2530  continue;
2531  if (proc->lxid != sourcevxid->localTransactionId)
2532  continue;
2533 
2534  /*
2535  * We check the transaction's database ID for paranoia's sake: if it's
2536  * in another DB then its xmin does not cover us. Caller should have
2537  * detected this already, so we just treat any funny cases as
2538  * "transaction not found".
2539  */
2540  if (proc->databaseId != MyDatabaseId)
2541  continue;
2542 
2543  /*
2544  * Likewise, let's just make real sure its xmin does cover us.
2545  */
2546  xid = UINT32_ACCESS_ONCE(proc->xmin);
2547  if (!TransactionIdIsNormal(xid) ||
2548  !TransactionIdPrecedesOrEquals(xid, xmin))
2549  continue;
2550 
2551  /*
2552  * We're good. Install the new xmin. As in GetSnapshotData, set
2553  * TransactionXmin too. (Note that because snapmgr.c called
2554  * GetSnapshotData first, we'll be overwriting a valid xmin here, so
2555  * we don't check that.)
2556  */
2557  MyProc->xmin = TransactionXmin = xmin;
2558 
2559  result = true;
2560  break;
2561  }
2562 
2563  LWLockRelease(ProcArrayLock);
2564 
2565  return result;
2566 }
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:1805
#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:252
Oid databaseId
Definition: proc.h:154
static ProcArrayStruct * procArray
Definition: procarray.c:250
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:1203
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 2578 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().

2579 {
2580  bool result = false;
2581  TransactionId xid;
2582 
2584  Assert(proc != NULL);
2585 
2586  /* Get lock so source xact can't end while we're doing this */
2587  LWLockAcquire(ProcArrayLock, LW_SHARED);
2588 
2589  /*
2590  * Be certain that the referenced PGPROC has an advertised xmin which is
2591  * no later than the one we're installing, so that the system-wide xmin
2592  * can't go backwards. Also, make sure it's running in the same database,
2593  * so that the per-database xmin cannot go backwards.
2594  */
2595  xid = UINT32_ACCESS_ONCE(proc->xmin);
2596  if (proc->databaseId == MyDatabaseId &&
2597  TransactionIdIsNormal(xid) &&
2598  TransactionIdPrecedesOrEquals(xid, xmin))
2599  {
2600  MyProc->xmin = TransactionXmin = xmin;
2601  result = true;
2602  }
2603 
2604  LWLockRelease(ProcArrayLock);
2605 
2606  return result;
2607 }
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:1805
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:1203
#define TransactionIdIsNormal(xid)
Definition: transam.h:42

◆ ProcArrayRemove()

void ProcArrayRemove ( PGPROC proc,
TransactionId  latestXid 
)

Definition at line 525 of file procarray.c.

References PROC_HDR::allProcs, Assert, XidCacheStatus::count, elog, LOG, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MaintainLatestCompletedXid(), ProcArrayStruct::numProcs, XidCacheStatus::overflowed, PGPROC::pgprocno, 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().

526 {
527  ProcArrayStruct *arrayP = procArray;
528  int index;
529 
530 #ifdef XIDCACHE_DEBUG
531  /* dump stats at backend shutdown, but not prepared-xact end */
532  if (proc->pid != 0)
533  DisplayXidCache();
534 #endif
535 
536  /* See ProcGlobal comment explaining why both locks are held */
537  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
538  LWLockAcquire(XidGenLock, LW_EXCLUSIVE);
539 
540  Assert(ProcGlobal->allProcs[arrayP->pgprocnos[proc->pgxactoff]].pgxactoff == proc->pgxactoff);
541 
542  if (TransactionIdIsValid(latestXid))
543  {
545 
546  /* Advance global latestCompletedXid while holding the lock */
547  MaintainLatestCompletedXid(latestXid);
548 
549  /* Same with xactCompletionCount */
551 
552  ProcGlobal->xids[proc->pgxactoff] = 0;
555  }
556  else
557  {
558  /* Shouldn't be trying to remove a live transaction here */
560  }
561 
565  ProcGlobal->statusFlags[proc->pgxactoff] = 0;
566 
567  for (index = 0; index < arrayP->numProcs; index++)
568  {
569  if (arrayP->pgprocnos[index] == proc->pgprocno)
570  {
571  /* Keep the PGPROC array sorted. See notes above */
572  memmove(&arrayP->pgprocnos[index], &arrayP->pgprocnos[index + 1],
573  (arrayP->numProcs - index - 1) * sizeof(*arrayP->pgprocnos));
574  memmove(&ProcGlobal->xids[index], &ProcGlobal->xids[index + 1],
575  (arrayP->numProcs - index - 1) * sizeof(*ProcGlobal->xids));
576  memmove(&ProcGlobal->subxidStates[index], &ProcGlobal->subxidStates[index + 1],
577  (arrayP->numProcs - index - 1) * sizeof(*ProcGlobal->subxidStates));
578  memmove(&ProcGlobal->statusFlags[index], &ProcGlobal->statusFlags[index + 1],
579  (arrayP->numProcs - index - 1) * sizeof(*ProcGlobal->statusFlags));
580 
581  arrayP->pgprocnos[arrayP->numProcs - 1] = -1; /* for debugging */
582  arrayP->numProcs--;
583 
584  /* adjust for removed PGPROC */
585  for (; index < arrayP->numProcs; index++)
586  allProcs[arrayP->pgprocnos[index]].pgxactoff--;
587 
588  /*
589  * Release in reversed acquisition order, to reduce frequency of
590  * having to wait for XidGenLock while holding ProcArrayLock.
591  */
592  LWLockRelease(XidGenLock);
593  LWLockRelease(ProcArrayLock);
594  return;
595  }
596  }
597 
598  /* Oops */
599  LWLockRelease(XidGenLock);
600  LWLockRelease(ProcArrayLock);
601 
602  elog(LOG, "failed to find proc %p in ProcArray", proc);
603 }
XidCacheStatus * subxidStates
Definition: proc.h:327
uint64 xactCompletionCount
Definition: transam.h:241
PROC_HDR * ProcGlobal
Definition: proc.c:80
#define LOG
Definition: elog.h:26
bool overflowed
Definition: proc.h:43
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1805
VariableCache ShmemVariableCache
Definition: varsup.c:34
TransactionId * xids
Definition: proc.h:321
static PGPROC * allProcs
Definition: procarray.c:252
static ProcArrayStruct * procArray
Definition: procarray.c:250
static void MaintainLatestCompletedXid(TransactionId latestXid)
Definition: procarray.c:913
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:1203
uint8 count
Definition: proc.h:41
int pgprocno
Definition: proc.h:150
#define elog(elevel,...)
Definition: elog.h:232
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 3802 of file procarray.c.

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

Referenced by ReplicationSlotsComputeRequiredXmin().

3804 {
3805  Assert(!already_locked || LWLockHeldByMe(ProcArrayLock));
3806 
3807  if (!already_locked)
3808  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3809 
3811  procArray->replication_slot_catalog_xmin = catalog_xmin;
3812 
3813  if (!already_locked)
3814  LWLockRelease(ProcArrayLock);
3815 }
bool LWLockHeldByMe(LWLock *l)
Definition: lwlock.c:1920
TransactionId replication_slot_catalog_xmin
Definition: procarray.c:98
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1805
static ProcArrayStruct * procArray
Definition: procarray.c:250
TransactionId replication_slot_xmin
Definition: procarray.c:96
#define Assert(condition)
Definition: c.h:804
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1203

◆ ProcArrayShmemSize()

Size ProcArrayShmemSize ( void  )

Definition at line 352 of file procarray.c.

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

Referenced by CreateSharedMemoryAndSemaphores().

353 {
354  Size size;
355 
356  /* Size of the ProcArray structure itself */
357 #define PROCARRAY_MAXPROCS (MaxBackends + max_prepared_xacts)
358 
359  size = offsetof(ProcArrayStruct, pgprocnos);
360  size = add_size(size, mul_size(sizeof(int), PROCARRAY_MAXPROCS));
361 
362  /*
363  * During Hot Standby processing we have a data structure called
364  * KnownAssignedXids, created in shared memory. Local data structures are
365  * also created in various backends during GetSnapshotData(),
366  * TransactionIdIsInProgress() and GetRunningTransactionData(). All of the
367  * main structures created in those functions must be identically sized,
368  * since we may at times copy the whole of the data structures around. We
369  * refer to this size as TOTAL_MAX_CACHED_SUBXIDS.
370  *
371  * Ideally we'd only create this structure if we were actually doing hot
372  * standby in the current run, but we don't know that yet at the time
373  * shared memory is being set up.
374  */
375 #define TOTAL_MAX_CACHED_SUBXIDS \
376  ((PGPROC_MAX_CACHED_SUBXIDS + 1) * PROCARRAY_MAXPROCS)
377 
378  if (EnableHotStandby)
379  {
380  size = add_size(size,
381  mul_size(sizeof(TransactionId),
383  size = add_size(size,
384  mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS));
385  }
386 
387  return size;
388 }
#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:99
#define offsetof(type, field)
Definition: c.h:727

◆ RecordKnownAssignedTransactionIds()

void RecordKnownAssignedTransactionIds ( TransactionId  xid)

Definition at line 4300 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().

4301 {
4305 
4306  elog(trace_recovery(DEBUG4), "record known xact %u latestObservedXid %u",
4307  xid, latestObservedXid);
4308 
4309  /*
4310  * When a newly observed xid arrives, it is frequently the case that it is
4311  * *not* the next xid in sequence. When this occurs, we must treat the
4312  * intervening xids as running also.
4313  */
4315  {
4316  TransactionId next_expected_xid;
4317 
4318  /*
4319  * Extend subtrans like we do in GetNewTransactionId() during normal
4320  * operation using individual extend steps. Note that we do not need
4321  * to extend clog since its extensions are WAL logged.
4322  *
4323  * This part has to be done regardless of standbyState since we
4324  * immediately start assigning subtransactions to their toplevel
4325  * transactions.
4326  */
4327  next_expected_xid = latestObservedXid;
4328  while (TransactionIdPrecedes(next_expected_xid, xid))
4329  {
4330  TransactionIdAdvance(next_expected_xid);
4331  ExtendSUBTRANS(next_expected_xid);
4332  }
4333  Assert(next_expected_xid == xid);
4334 
4335  /*
4336  * If the KnownAssignedXids machinery isn't up yet, there's nothing
4337  * more to do since we don't track assigned xids yet.
4338  */
4340  {
4341  latestObservedXid = xid;
4342  return;
4343  }
4344 
4345  /*
4346  * Add (latestObservedXid, xid] onto the KnownAssignedXids array.
4347  */
4348  next_expected_xid = latestObservedXid;
4349  TransactionIdAdvance(next_expected_xid);
4350  KnownAssignedXidsAdd(next_expected_xid, xid, false);
4351 
4352  /*
4353  * Now we can advance latestObservedXid
4354  */
4355  latestObservedXid = xid;
4356 
4357  /* ShmemVariableCache->nextXid must be beyond any observed xid */
4359  next_expected_xid = latestObservedXid;
4360  TransactionIdAdvance(next_expected_xid);
4361  }
4362 }
#define TransactionIdAdvance(dest)
Definition: transam.h:91
static TransactionId latestObservedXid
Definition: procarray.c:259
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
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:4574
#define elog(elevel,...)
Definition: elog.h:232
#define TransactionIdIsValid(xid)
Definition: transam.h:41
HotStandbyState standbyState
Definition: xlog.c:212

◆ SignalVirtualTransaction()

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

Definition at line 3363 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().

3365 {
3366  ProcArrayStruct *arrayP = procArray;
3367  int index;
3368  pid_t pid = 0;
3369 
3370  LWLockAcquire(ProcArrayLock, LW_SHARED);
3371 
3372  for (index = 0; index < arrayP->numProcs; index++)
3373  {
3374  int pgprocno = arrayP->pgprocnos[index];
3375  PGPROC *proc = &allProcs[pgprocno];
3376  VirtualTransactionId procvxid;
3377 
3378  GET_VXID_FROM_PGPROC(procvxid, *proc);
3379 
3380  if (procvxid.backendId == vxid.backendId &&
3381  procvxid.localTransactionId == vxid.localTransactionId)
3382  {
3383  proc->recoveryConflictPending = conflictPending;
3384  pid = proc->pid;
3385  if (pid != 0)
3386  {
3387  /*
3388  * Kill the pid if it's still here. If not, that's what we
3389  * wanted so ignore any errors.
3390  */
3391  (void) SendProcSignal(pid, sigmode, vxid.backendId);
3392  }
3393  break;
3394  }
3395  }
3396 
3397  LWLockRelease(ProcArrayLock);
3398 
3399  return pid;
3400 }
#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:1805
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:252
static ProcArrayStruct * procArray
Definition: procarray.c:250
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
BackendId backendId
Definition: lock.h:65
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1203
Definition: proc.h:121
int pid
Definition: proc.h:146

◆ TerminateOtherDBBackends()

void TerminateOtherDBBackends ( Oid  databaseId)

Definition at line 3694 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().

3695 {
3696  ProcArrayStruct *arrayP = procArray;
3697  List *pids = NIL;
3698  int nprepared = 0;
3699  int i;
3700 
3701  LWLockAcquire(ProcArrayLock, LW_SHARED);
3702 
3703  for (i = 0; i < procArray->numProcs; i++)
3704  {
3705  int pgprocno = arrayP->pgprocnos[i];
3706  PGPROC *proc = &allProcs[pgprocno];
3707 
3708  if (proc->databaseId != databaseId)
3709  continue;
3710  if (proc == MyProc)
3711  continue;
3712 
3713  if (proc->pid != 0)
3714  pids = lappend_int(pids, proc->pid);
3715  else
3716  nprepared++;
3717  }
3718 
3719  LWLockRelease(ProcArrayLock);
3720 
3721  if (nprepared > 0)
3722  ereport(ERROR,
3723  (errcode(ERRCODE_OBJECT_IN_USE),
3724  errmsg("database \"%s\" is being used by prepared transactions",
3725  get_database_name(databaseId)),
3726  errdetail_plural("There is %d prepared transaction using the database.",
3727  "There are %d prepared transactions using the database.",
3728  nprepared,
3729  nprepared)));
3730 
3731  if (pids)
3732  {
3733  ListCell *lc;
3734 
3735  /*
3736  * Check whether we have the necessary rights to terminate other
3737  * sessions. We don't terminate any session until we ensure that we
3738  * have rights on all the sessions to be terminated. These checks are
3739  * the same as we do in pg_terminate_backend.
3740  *
3741  * In this case we don't raise some warnings - like "PID %d is not a
3742  * PostgreSQL server process", because for us already finished session
3743  * is not a problem.
3744  */
3745  foreach(lc, pids)
3746  {
3747  int pid = lfirst_int(lc);
3748  PGPROC *proc = BackendPidGetProc(pid);
3749 
3750  if (proc != NULL)
3751  {
3752  /* Only allow superusers to signal superuser-owned backends. */
3753  if (superuser_arg(proc->roleId) && !superuser())
3754  ereport(ERROR,
3755  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
3756  errmsg("must be a superuser to terminate superuser process")));
3757 
3758  /* Users can signal backends they have role membership in. */
3759  if (!has_privs_of_role(GetUserId(), proc->roleId) &&
3760  !has_privs_of_role(GetUserId(), ROLE_PG_SIGNAL_BACKEND))
3761  ereport(ERROR,
3762  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
3763  errmsg("must be a member of the role whose process is being terminated or member of pg_signal_backend")));
3764  }
3765  }
3766 
3767  /*
3768  * There's a race condition here: once we release the ProcArrayLock,
3769  * it's possible for the session to exit before we issue kill. That
3770  * race condition possibility seems too unlikely to worry about. See
3771  * pg_signal_backend.
3772  */
3773  foreach(lc, pids)
3774  {
3775  int pid = lfirst_int(lc);
3776  PGPROC *proc = BackendPidGetProc(pid);
3777 
3778  if (proc != NULL)
3779  {
3780  /*
3781  * If we have setsid(), signal the backend's whole process
3782  * group
3783  */
3784 #ifdef HAVE_SETSID
3785  (void) kill(-pid, SIGTERM);
3786 #else
3787  (void) kill(pid, SIGTERM);
3788 #endif
3789  }
3790  }
3791  }
3792 }
#define NIL
Definition: pg_list.h:65
Oid GetUserId(void)
Definition: miscinit.c:478
PGPROC * BackendPidGetProc(int pid)
Definition: procarray.c:3067
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:1805
#define ERROR
Definition: elog.h:46
#define lfirst_int(lc)
Definition: pg_list.h:170
char * get_database_name(Oid dbid)
Definition: dbcommands.c:2155
static PGPROC * allProcs
Definition: procarray.c:252
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:250
#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:1203
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 1557 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.

1558 {
1559  bool result = false;
1560  ProcArrayStruct *arrayP = procArray;
1561  TransactionId *other_xids = ProcGlobal->xids;
1562  int i;
1563 
1564  /*
1565  * Don't bother checking a transaction older than RecentXmin; it could not
1566  * possibly still be running.
1567  */
1569  return false;
1570 
1571  LWLockAcquire(ProcArrayLock, LW_SHARED);
1572 
1573  for (i = 0; i < arrayP->numProcs; i++)
1574  {
1575  int pgprocno = arrayP->pgprocnos[i];
1576  PGPROC *proc = &allProcs[pgprocno];
1577  TransactionId pxid;
1578 
1579  /* Fetch xid just once - see GetNewTransactionId */
1580  pxid = UINT32_ACCESS_ONCE(other_xids[i]);
1581 
1582  if (!TransactionIdIsValid(pxid))
1583  continue;
1584 
1585  if (proc->pid == 0)
1586  continue; /* ignore prepared transactions */
1587 
1588  if (TransactionIdEquals(pxid, xid))
1589  {
1590  result = true;
1591  break;
1592  }
1593  }
1594 
1595  LWLockRelease(ProcArrayLock);
1596 
1597  return result;
1598 }
#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:1805
TransactionId * xids
Definition: proc.h:321
static PGPROC * allProcs
Definition: procarray.c:252
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
static ProcArrayStruct * procArray
Definition: procarray.c:250
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1203
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 1325 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().

1326 {
1327  static TransactionId *xids = NULL;
1328  static TransactionId *other_xids;
1329  XidCacheStatus *other_subxidstates;
1330  int nxids = 0;
1331  ProcArrayStruct *arrayP = procArray;
1332  TransactionId topxid;
1333  TransactionId latestCompletedXid;
1334  int mypgxactoff;
1335  size_t numProcs;
1336  int j;
1337 
1338  /*
1339  * Don't bother checking a transaction older than RecentXmin; it could not
1340  * possibly still be running. (Note: in particular, this guarantees that
1341  * we reject InvalidTransactionId, FrozenTransactionId, etc as not
1342  * running.)
1343  */
1345  {
1347  return false;
1348  }
1349 
1350  /*
1351  * We may have just checked the status of this transaction, so if it is
1352  * already known to be completed, we can fall out without any access to
1353  * shared memory.
1354  */
1356  {
1358  return false;
1359  }
1360 
1361  /*
1362  * Also, we can handle our own transaction (and subtransactions) without
1363  * any access to shared memory.
1364  */
1366  {
1368  return true;
1369  }
1370 
1371  /*
1372  * If first time through, get workspace to remember main XIDs in. We
1373  * malloc it permanently to avoid repeated palloc/pfree overhead.
1374  */
1375  if (xids == NULL)
1376  {
1377  /*
1378  * In hot standby mode, reserve enough space to hold all xids in the
1379  * known-assigned list. If we later finish recovery, we no longer need
1380  * the bigger array, but we don't bother to shrink it.
1381  */
1382  int maxxids = RecoveryInProgress() ? TOTAL_MAX_CACHED_SUBXIDS : arrayP->maxProcs;
1383 
1384  xids = (TransactionId *) malloc(maxxids * sizeof(TransactionId));
1385  if (xids == NULL)
1386  ereport(ERROR,
1387  (errcode(ERRCODE_OUT_OF_MEMORY),
1388  errmsg("out of memory")));
1389  }
1390 
1391  other_xids = ProcGlobal->xids;
1392  other_subxidstates = ProcGlobal->subxidStates;
1393 
1394  LWLockAcquire(ProcArrayLock, LW_SHARED);
1395 
1396  /*
1397  * Now that we have the lock, we can check latestCompletedXid; if the
1398  * target Xid is after that, it's surely still running.
1399  */
1400  latestCompletedXid =
1402  if (TransactionIdPrecedes(latestCompletedXid, xid))
1403  {
1404  LWLockRelease(ProcArrayLock);
1406  return true;
1407  }
1408 
1409  /* No shortcuts, gotta grovel through the array */
1410  mypgxactoff = MyProc->pgxactoff;
1411  numProcs = arrayP->numProcs;
1412  for (size_t pgxactoff = 0; pgxactoff < numProcs; pgxactoff++)
1413  {
1414  int pgprocno;
1415  PGPROC *proc;
1416  TransactionId pxid;
1417  int pxids;
1418 
1419  /* Ignore ourselves --- dealt with it above */
1420  if (pgxactoff == mypgxactoff)
1421  continue;
1422 
1423  /* Fetch xid just once - see GetNewTransactionId */
1424  pxid = UINT32_ACCESS_ONCE(other_xids[pgxactoff]);
1425 
1426  if (!TransactionIdIsValid(pxid))
1427  continue;
1428 
1429  /*
1430  * Step 1: check the main Xid
1431  */
1432  if (TransactionIdEquals(pxid, xid))
1433  {
1434  LWLockRelease(ProcArrayLock);
1436  return true;
1437  }
1438 
1439  /*
1440  * We can ignore main Xids that are younger than the target Xid, since
1441  * the target could not possibly be their child.
1442  */
1443  if (TransactionIdPrecedes(xid, pxid))
1444  continue;
1445 
1446  /*
1447  * Step 2: check the cached child-Xids arrays
1448  */
1449  pxids = other_subxidstates[pgxactoff].count;
1450  pg_read_barrier(); /* pairs with barrier in GetNewTransactionId() */
1451  pgprocno = arrayP->pgprocnos[pgxactoff];
1452  proc = &allProcs[pgprocno];
1453  for (j = pxids - 1; j >= 0; j--)
1454  {
1455  /* Fetch xid just once - see GetNewTransactionId */
1456  TransactionId cxid = UINT32_ACCESS_ONCE(proc->subxids.xids[j]);
1457 
1458  if (TransactionIdEquals(cxid, xid))
1459  {
1460  LWLockRelease(ProcArrayLock);
1462  return true;
1463  }
1464  }
1465 
1466  /*
1467  * Save the main Xid for step 4. We only need to remember main Xids
1468  * that have uncached children. (Note: there is no race condition
1469  * here because the overflowed flag cannot be cleared, only set, while
1470  * we hold ProcArrayLock. So we can't miss an Xid that we need to
1471  * worry about.)
1472  */
1473  if (other_subxidstates[pgxactoff].overflowed)
1474  xids[nxids++] = pxid;
1475  }
1476 
1477  /*
1478  * Step 3: in hot standby mode, check the known-assigned-xids list. XIDs
1479  * in the list must be treated as running.
1480  */
1481  if (RecoveryInProgress())
1482  {
1483  /* none of the PGPROC entries should have XIDs in hot standby mode */
1484  Assert(nxids == 0);
1485 
1486  if (KnownAssignedXidExists(xid))
1487  {
1488  LWLockRelease(ProcArrayLock);
1490  return true;
1491  }
1492 
1493  /*
1494  * If the KnownAssignedXids overflowed, we have to check pg_subtrans
1495  * too. Fetch all xids from KnownAssignedXids that are lower than
1496  * xid, since if xid is a subtransaction its parent will always have a
1497  * lower value. Note we will collect both main and subXIDs here, but
1498  * there's no help for it.
1499  */
1501  nxids = KnownAssignedXidsGet(xids, xid);
1502  }
1503 
1504  LWLockRelease(ProcArrayLock);
1505 
1506  /*
1507  * If none of the relevant caches overflowed, we know the Xid is not
1508  * running without even looking at pg_subtrans.
1509  */
1510  if (nxids == 0)
1511  {
1513  return false;
1514  }
1515 
1516  /*
1517  * Step 4: have to check pg_subtrans.
1518  *
1519  * At this point, we know it's either a subtransaction of one of the Xids
1520  * in xids[], or it's not running. If it's an already-failed
1521  * subtransaction, we want to say "not running" even though its parent may
1522  * still be running. So first, check pg_xact to see if it's been aborted.
1523  */
1525 
1526  if (TransactionIdDidAbort(xid))
1527  return false;
1528 
1529  /*
1530  * It isn't aborted, so check whether the transaction tree it belongs to
1531  * is still running (or, more precisely, whether it was running when we
1532  * held ProcArrayLock).
1533  */
1534  topxid = SubTransGetTopmostTransaction(xid);
1535  Assert(TransactionIdIsValid(topxid));
1536  if (!TransactionIdEquals(topxid, xid))
1537  {
1538  for (int i = 0; i < nxids; i++)
1539  {
1540  if (TransactionIdEquals(xids[i], topxid))
1541  return true;
1542  }
1543  }
1544 
1545  return false;
1546 }
#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:313
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:231
bool RecoveryInProgress(void)
Definition: xlog.c:8237
#define xc_by_child_xid_inc()
Definition: procarray.c:316
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:1805
#define xc_by_recent_xmin_inc()
Definition: procarray.c:311
#define xc_by_known_xact_inc()
Definition: procarray.c:312
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:315
#define xc_by_known_assigned_inc()
Definition: procarray.c:317
VariableCache ShmemVariableCache
Definition: varsup.c:34
TransactionId * xids
Definition: proc.h:321
static PGPROC * allProcs
Definition: procarray.c:252
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:314
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
static ProcArrayStruct * procArray
Definition: procarray.c:250
static int KnownAssignedXidsGet(TransactionId *xarray, TransactionId xmax)
Definition: procarray.c:4924
#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:1203
#define xc_no_overflow_inc()
Definition: procarray.c:318
uint8 count
Definition: proc.h:41
static bool KnownAssignedXidExists(TransactionId xid)
Definition: procarray.c:4785
#define xc_slow_answer_inc()
Definition: procarray.c:319
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 3847 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().

3850 {
3851  int i,
3852  j;
3853  XidCacheStatus *mysubxidstat;
3854 
3856 
3857  /*
3858  * We must hold ProcArrayLock exclusively in order to remove transactions
3859  * from the PGPROC array. (See src/backend/access/transam/README.) It's
3860  * possible this could be relaxed since we know this routine is only used
3861  * to abort subtransactions, but pending closer analysis we'd best be
3862  * conservative.
3863  *
3864  * Note that we do not have to be careful about memory ordering of our own
3865  * reads wrt. GetNewTransactionId() here - only this process can modify
3866  * relevant fields of MyProc/ProcGlobal->xids[]. But we do have to be
3867  * careful about our own writes being well ordered.
3868  */
3869  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3870 
3871  mysubxidstat = &ProcGlobal->subxidStates[MyProc->pgxactoff];
3872 
3873  /*
3874  * Under normal circumstances xid and xids[] will be in increasing order,
3875  * as will be the entries in subxids. Scan backwards to avoid O(N^2)
3876  * behavior when removing a lot of xids.
3877  */
3878  for (i = nxids - 1; i >= 0; i--)
3879  {
3880  TransactionId anxid = xids[i];
3881 
3882  for (j = MyProc->subxidStatus.count - 1; j >= 0; j--)
3883  {
3884  if (TransactionIdEquals(MyProc->subxids.xids[j], anxid))
3885  {
3887  pg_write_barrier();
3888  mysubxidstat->count--;
3890  break;
3891  }
3892  }
3893 
3894  /*
3895  * Ordinarily we should have found it, unless the cache has
3896  * overflowed. However it's also possible for this routine to be
3897  * invoked multiple times for the same subtransaction, in case of an
3898  * error during AbortSubTransaction. So instead of Assert, emit a
3899  * debug warning.
3900  */
3901  if (j < 0 && !MyProc->subxidStatus.overflowed)
3902  elog(WARNING, "did not find subXID %u in MyProc", anxid);
3903  }
3904 
3905  for (j = MyProc->subxidStatus.count - 1; j >= 0; j--)
3906  {
3907  if (TransactionIdEquals(MyProc->subxids.xids[j], xid))
3908  {
3910  pg_write_barrier();
3911  mysubxidstat->count--;
3913  break;
3914  }
3915  }
3916  /* Ordinarily we should have found it, unless the cache has overflowed */
3917  if (j < 0 && !MyProc->subxidStatus.overflowed)
3918  elog(WARNING, "did not find subXID %u in MyProc", xid);
3919 
3920  /* Also advance global latestCompletedXid while holding the lock */
3921  MaintainLatestCompletedXid(latestXid);
3922 
3923  /* ... and xactCompletionCount */
3925 
3926  LWLockRelease(ProcArrayLock);
3927 }
#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:241
PROC_HDR * ProcGlobal
Definition: proc.c:80
XidCacheStatus subxidStatus
Definition: proc.h:210
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1805
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:913
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:1203
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