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

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

Referenced by IsBackendPid(), pg_signal_backend(), pg_stat_get_activity(), pg_stat_get_backend_wait_event(), pg_stat_get_backend_wait_event_type(), ProcSendSignal(), TerminateOtherDBBackends(), and test_shm_mq_main().

3033 {
3034  PGPROC *result;
3035 
3036  if (pid == 0) /* never match dummy PGPROCs */
3037  return NULL;
3038 
3039  LWLockAcquire(ProcArrayLock, LW_SHARED);
3040 
3041  result = BackendPidGetProcWithLock(pid);
3042 
3043  LWLockRelease(ProcArrayLock);
3044 
3045  return result;
3046 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
PGPROC * BackendPidGetProcWithLock(int pid)
Definition: procarray.c:3055
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
Definition: proc.h:112

◆ BackendPidGetProcWithLock()

PGPROC* BackendPidGetProcWithLock ( int  pid)

Definition at line 3055 of file procarray.c.

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

Referenced by BackendPidGetProc(), and GetBlockerStatusData().

3056 {
3057  PGPROC *result = NULL;
3058  ProcArrayStruct *arrayP = procArray;
3059  int index;
3060 
3061  if (pid == 0) /* never match dummy PGPROCs */
3062  return NULL;
3063 
3064  for (index = 0; index < arrayP->numProcs; index++)
3065  {
3066  PGPROC *proc = &allProcs[arrayP->pgprocnos[index]];
3067 
3068  if (proc->pid == pid)
3069  {
3070  result = proc;
3071  break;
3072  }
3073  }
3074 
3075  return result;
3076 }
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:112
int pid
Definition: proc.h:137

◆ BackendXidGetPid()

int BackendXidGetPid ( TransactionId  xid)

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

3093 {
3094  int result = 0;
3095  ProcArrayStruct *arrayP = procArray;
3096  TransactionId *other_xids = ProcGlobal->xids;
3097  int index;
3098 
3099  if (xid == InvalidTransactionId) /* never match invalid xid */
3100  return 0;
3101 
3102  LWLockAcquire(ProcArrayLock, LW_SHARED);
3103 
3104  for (index = 0; index < arrayP->numProcs; index++)
3105  {
3106  int pgprocno = arrayP->pgprocnos[index];
3107  PGPROC *proc = &allProcs[pgprocno];
3108 
3109  if (other_xids[index] == xid)
3110  {
3111  result = proc->pid;
3112  break;
3113  }
3114  }
3115 
3116  LWLockRelease(ProcArrayLock);
3117 
3118  return result;
3119 }
uint32 TransactionId
Definition: c.h:521
PROC_HDR * ProcGlobal
Definition: proc.c:79
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
#define InvalidTransactionId
Definition: transam.h:31
TransactionId * xids
Definition: proc.h:309
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:1208
Definition: proc.h:112
int pid
Definition: proc.h:137

◆ CancelDBBackends()

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

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

3485 {
3486  ProcArrayStruct *arrayP = procArray;
3487  int index;
3488 
3489  /* tell all backends to die */
3490  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3491 
3492  for (index = 0; index < arrayP->numProcs; index++)
3493  {
3494  int pgprocno = arrayP->pgprocnos[index];
3495  PGPROC *proc = &allProcs[pgprocno];
3496 
3497  if (databaseid == InvalidOid || proc->databaseId == databaseid)
3498  {
3499  VirtualTransactionId procvxid;
3500  pid_t pid;
3501 
3502  GET_VXID_FROM_PGPROC(procvxid, *proc);
3503 
3504  proc->recoveryConflictPending = conflictPending;
3505  pid = proc->pid;
3506  if (pid != 0)
3507  {
3508  /*
3509  * Kill the pid if it's still here. If not, that's what we
3510  * wanted so ignore any errors.
3511  */
3512  (void) SendProcSignal(pid, sigmode, procvxid.backendId);
3513  }
3514  }
3515  }
3516 
3517  LWLockRelease(ProcArrayLock);
3518 }
#define GET_VXID_FROM_PGPROC(vxid, proc)
Definition: lock.h:79
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
int SendProcSignal(pid_t pid, ProcSignalReason reason, BackendId backendId)
Definition: procsignal.c:250
bool recoveryConflictPending
Definition: proc.h:158
static PGPROC * allProcs
Definition: procarray.c:252
Oid databaseId
Definition: proc.h:145
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:64
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
Definition: proc.h:112
int pid
Definition: proc.h:137

◆ CancelVirtualTransaction()

pid_t CancelVirtualTransaction ( VirtualTransactionId  vxid,
ProcSignalReason  sigmode 
)

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

3323 {
3324  ProcArrayStruct *arrayP = procArray;
3325  int index;
3326  pid_t pid = 0;
3327 
3328  LWLockAcquire(ProcArrayLock, LW_SHARED);
3329 
3330  for (index = 0; index < arrayP->numProcs; index++)
3331  {
3332  int pgprocno = arrayP->pgprocnos[index];
3333  PGPROC *proc = &allProcs[pgprocno];
3334  VirtualTransactionId procvxid;
3335 
3336  GET_VXID_FROM_PGPROC(procvxid, *proc);
3337 
3338  if (procvxid.backendId == vxid.backendId &&
3339  procvxid.localTransactionId == vxid.localTransactionId)
3340  {
3341  proc->recoveryConflictPending = true;
3342  pid = proc->pid;
3343  if (pid != 0)
3344  {
3345  /*
3346  * Kill the pid if it's still here. If not, that's what we
3347  * wanted so ignore any errors.
3348  */
3349  (void) SendProcSignal(pid, sigmode, vxid.backendId);
3350  }
3351  break;
3352  }
3353  }
3354 
3355  LWLockRelease(ProcArrayLock);
3356 
3357  return pid;
3358 }
#define GET_VXID_FROM_PGPROC(vxid, proc)
Definition: lock.h:79
LocalTransactionId localTransactionId
Definition: lock.h:65
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
int SendProcSignal(pid_t pid, ProcSignalReason reason, BackendId backendId)
Definition: procsignal.c:250
bool recoveryConflictPending
Definition: proc.h:158
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:64
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
Definition: proc.h:112
int pid
Definition: proc.h:137

◆ CountDBBackends()

int CountDBBackends ( Oid  databaseid)

Definition at line 3423 of file procarray.c.

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

Referenced by ResolveRecoveryConflictWithDatabase().

3424 {
3425  ProcArrayStruct *arrayP = procArray;
3426  int count = 0;
3427  int index;
3428 
3429  LWLockAcquire(ProcArrayLock, LW_SHARED);
3430 
3431  for (index = 0; index < arrayP->numProcs; index++)
3432  {
3433  int pgprocno = arrayP->pgprocnos[index];
3434  PGPROC *proc = &allProcs[pgprocno];
3435 
3436  if (proc->pid == 0)
3437  continue; /* do not count prepared xacts */
3438  if (!OidIsValid(databaseid) ||
3439  proc->databaseId == databaseid)
3440  count++;
3441  }
3442 
3443  LWLockRelease(ProcArrayLock);
3444 
3445  return count;
3446 }
#define OidIsValid(objectId)
Definition: c.h:652
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
static PGPROC * allProcs
Definition: procarray.c:252
Oid databaseId
Definition: proc.h:145
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:1208
Definition: proc.h:112
int pid
Definition: proc.h:137

◆ CountDBConnections()

int CountDBConnections ( Oid  databaseid)

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

3454 {
3455  ProcArrayStruct *arrayP = procArray;
3456  int count = 0;
3457  int index;
3458 
3459  LWLockAcquire(ProcArrayLock, LW_SHARED);
3460 
3461  for (index = 0; index < arrayP->numProcs; index++)
3462  {
3463  int pgprocno = arrayP->pgprocnos[index];
3464  PGPROC *proc = &allProcs[pgprocno];
3465 
3466  if (proc->pid == 0)
3467  continue; /* do not count prepared xacts */
3468  if (proc->isBackgroundWorker)
3469  continue; /* do not count background workers */
3470  if (!OidIsValid(databaseid) ||
3471  proc->databaseId == databaseid)
3472  count++;
3473  }
3474 
3475  LWLockRelease(ProcArrayLock);
3476 
3477  return count;
3478 }
#define OidIsValid(objectId)
Definition: c.h:652
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
bool isBackgroundWorker
Definition: proc.h:151
static PGPROC * allProcs
Definition: procarray.c:252
Oid databaseId
Definition: proc.h:145
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:1208
Definition: proc.h:112
int pid
Definition: proc.h:137

◆ CountOtherDBBackends()

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

Definition at line 3574 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::vacuumFlags.

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

3575 {
3576  ProcArrayStruct *arrayP = procArray;
3577 
3578 #define MAXAUTOVACPIDS 10 /* max autovacs to SIGTERM per iteration */
3579  int autovac_pids[MAXAUTOVACPIDS];
3580  int tries;
3581 
3582  /* 50 tries with 100ms sleep between tries makes 5 sec total wait */
3583  for (tries = 0; tries < 50; tries++)
3584  {
3585  int nautovacs = 0;
3586  bool found = false;
3587  int index;
3588 
3590 
3591  *nbackends = *nprepared = 0;
3592 
3593  LWLockAcquire(ProcArrayLock, LW_SHARED);
3594 
3595  for (index = 0; index < arrayP->numProcs; index++)
3596  {
3597  int pgprocno = arrayP->pgprocnos[index];
3598  PGPROC *proc = &allProcs[pgprocno];
3599  uint8 vacuumFlags = ProcGlobal->vacuumFlags[index];
3600 
3601  if (proc->databaseId != databaseId)
3602  continue;
3603  if (proc == MyProc)
3604  continue;
3605 
3606  found = true;
3607 
3608  if (proc->pid == 0)
3609  (*nprepared)++;
3610  else
3611  {
3612  (*nbackends)++;
3613  if ((vacuumFlags & PROC_IS_AUTOVACUUM) &&
3614  nautovacs < MAXAUTOVACPIDS)
3615  autovac_pids[nautovacs++] = proc->pid;
3616  }
3617  }
3618 
3619  LWLockRelease(ProcArrayLock);
3620 
3621  if (!found)
3622  return false; /* no conflicting backends, so done */
3623 
3624  /*
3625  * Send SIGTERM to any conflicting autovacuums before sleeping. We
3626  * postpone this step until after the loop because we don't want to
3627  * hold ProcArrayLock while issuing kill(). We have no idea what might
3628  * block kill() inside the kernel...
3629  */
3630  for (index = 0; index < nautovacs; index++)
3631  (void) kill(autovac_pids[index], SIGTERM); /* ignore any error */
3632 
3633  /* sleep, then try again */
3634  pg_usleep(100 * 1000L); /* 100ms */
3635  }
3636 
3637  return true; /* timed out, still conflicts */
3638 }
PGPROC * MyProc
Definition: proc.c:67
unsigned char uint8
Definition: c.h:373
PROC_HDR * ProcGlobal
Definition: proc.c:79
#define kill(pid, sig)
Definition: win32_port.h:454
#define MAXAUTOVACPIDS
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
void pg_usleep(long microsec)
Definition: signal.c:53
static PGPROC * allProcs
Definition: procarray.c:252
Oid databaseId
Definition: proc.h:145
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:1208
uint8 * vacuumFlags
Definition: proc.h:321
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:99
Definition: proc.h:112
int pid
Definition: proc.h:137
#define PROC_IS_AUTOVACUUM
Definition: proc.h:54

◆ CountUserBackends()

int CountUserBackends ( Oid  roleid)

Definition at line 3524 of file procarray.c.

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

Referenced by InitializeSessionUserId().

3525 {
3526  ProcArrayStruct *arrayP = procArray;
3527  int count = 0;
3528  int index;
3529 
3530  LWLockAcquire(ProcArrayLock, LW_SHARED);
3531 
3532  for (index = 0; index < arrayP->numProcs; index++)
3533  {
3534  int pgprocno = arrayP->pgprocnos[index];
3535  PGPROC *proc = &allProcs[pgprocno];
3536 
3537  if (proc->pid == 0)
3538  continue; /* do not count prepared xacts */
3539  if (proc->isBackgroundWorker)
3540  continue; /* do not count background workers */
3541  if (proc->roleId == roleid)
3542  count++;
3543  }
3544 
3545  LWLockRelease(ProcArrayLock);
3546 
3547  return count;
3548 }
Oid roleId
Definition: proc.h:146
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
bool isBackgroundWorker
Definition: proc.h:151
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:1208
Definition: proc.h:112
int pid
Definition: proc.h:137

◆ 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:521
#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:79
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition: shmem.c:392
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:515
Size add_size(Size s1, Size s2)
Definition: shmem.c:498
#define TOTAL_MAX_CACHED_SUBXIDS
static TransactionId * KnownAssignedXids
Definition: procarray.c:257
bool EnableHotStandby
Definition: xlog.c:97
PGPROC * allProcs
Definition: proc.h:306
int tailKnownAssignedXids
Definition: procarray.c:82
#define offsetof(type, field)
Definition: c.h:669
int headKnownAssignedXids
Definition: procarray.c:83

◆ ExpireAllKnownAssignedTransactionIds()

void ExpireAllKnownAssignedTransactionIds ( void  )

Definition at line 4352 of file procarray.c.

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

Referenced by ShutdownRecoveryTransactionEnvironment().

4353 {
4354  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
4356  LWLockRelease(ProcArrayLock);
4357 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
static void KnownAssignedXidsRemovePreceding(TransactionId xid)
Definition: procarray.c:4801
#define InvalidTransactionId
Definition: transam.h:31
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208

◆ ExpireOldKnownAssignedTransactionIds()

void ExpireOldKnownAssignedTransactionIds ( TransactionId  xid)

Definition at line 4364 of file procarray.c.

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

Referenced by ProcArrayApplyRecoveryInfo().

4365 {
4366  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
4368  LWLockRelease(ProcArrayLock);
4369 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
static void KnownAssignedXidsRemovePreceding(TransactionId xid)
Definition: procarray.c:4801
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208

◆ ExpireTreeKnownAssignedTransactionIds()

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

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

4328 {
4330 
4331  /*
4332  * Uses same locking as transaction commit
4333  */
4334  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
4335 
4336  KnownAssignedXidsRemoveTree(xid, nsubxids, subxids);
4337 
4338  /* As in ProcArrayEndTransaction, advance latestCompletedXid */
4340 
4341  /* ... and xactCompletionCount */
4343 
4344  LWLockRelease(ProcArrayLock);
4345 }
static void MaintainLatestCompletedXidRecovery(TransactionId latestXid)
Definition: procarray.c:931
uint64 xactCompletionCount
Definition: transam.h:241
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
VariableCache ShmemVariableCache
Definition: varsup.c:34
static void KnownAssignedXidsRemoveTree(TransactionId xid, int nsubxids, TransactionId *subxids)
Definition: procarray.c:4779
#define Assert(condition)
Definition: c.h:746
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
HotStandbyState standbyState
Definition: xlog.c:208

◆ GetConflictingVirtualXIDs()

VirtualTransactionId* GetConflictingVirtualXIDs ( TransactionId  limitXmin,
Oid  dbOid 
)

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

3249 {
3250  static VirtualTransactionId *vxids;
3251  ProcArrayStruct *arrayP = procArray;
3252  int count = 0;
3253  int index;
3254 
3255  /*
3256  * If first time through, get workspace to remember main XIDs in. We
3257  * malloc it permanently to avoid repeated palloc/pfree overhead. Allow
3258  * result space, remembering room for a terminator.
3259  */
3260  if (vxids == NULL)
3261  {
3262  vxids = (VirtualTransactionId *)
3263  malloc(sizeof(VirtualTransactionId) * (arrayP->maxProcs + 1));
3264  if (vxids == NULL)
3265  ereport(ERROR,
3266  (errcode(ERRCODE_OUT_OF_MEMORY),
3267  errmsg("out of memory")));
3268  }
3269 
3270  LWLockAcquire(ProcArrayLock, LW_SHARED);
3271 
3272  for (index = 0; index < arrayP->numProcs; index++)
3273  {
3274  int pgprocno = arrayP->pgprocnos[index];
3275  PGPROC *proc = &allProcs[pgprocno];
3276 
3277  /* Exclude prepared transactions */
3278  if (proc->pid == 0)
3279  continue;
3280 
3281  if (!OidIsValid(dbOid) ||
3282  proc->databaseId == dbOid)
3283  {
3284  /* Fetch xmin just once - can't change on us, but good coding */
3285  TransactionId pxmin = UINT32_ACCESS_ONCE(proc->xmin);
3286 
3287  /*
3288  * We ignore an invalid pxmin because this means that backend has
3289  * no snapshot currently. We hold a Share lock to avoid contention
3290  * with users taking snapshots. That is not a problem because the
3291  * current xmin is always at least one higher than the latest
3292  * removed xid, so any new snapshot would never conflict with the
3293  * test here.
3294  */
3295  if (!TransactionIdIsValid(limitXmin) ||
3296  (TransactionIdIsValid(pxmin) && !TransactionIdFollows(pxmin, limitXmin)))
3297  {
3298  VirtualTransactionId vxid;
3299 
3300  GET_VXID_FROM_PGPROC(vxid, *proc);
3301  if (VirtualTransactionIdIsValid(vxid))
3302  vxids[count++] = vxid;
3303  }
3304  }
3305  }
3306 
3307  LWLockRelease(ProcArrayLock);
3308 
3309  /* add the terminator */
3310  vxids[count].backendId = InvalidBackendId;
3312 
3313  return vxids;
3314 }
#define GET_VXID_FROM_PGPROC(vxid, proc)
Definition: lock.h:79
bool TransactionIdFollows(TransactionId id1, TransactionId id2)
Definition: transam.c:334
uint32 TransactionId
Definition: c.h:521
#define UINT32_ACCESS_ONCE(var)
Definition: procarray.c:69
int errcode(int sqlerrcode)
Definition: elog.c:610
LocalTransactionId localTransactionId
Definition: lock.h:65
#define OidIsValid(objectId)
Definition: c.h:652
Definition: type.h:89
#define malloc(a)
Definition: header.h:50
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
#define ERROR
Definition: elog.h:43
TransactionId xmin
Definition: proc.h:129
static PGPROC * allProcs
Definition: procarray.c:252
Oid databaseId
Definition: proc.h:145
static ProcArrayStruct * procArray
Definition: procarray.c:250
#define VirtualTransactionIdIsValid(vxid)
Definition: lock.h:70
#define InvalidBackendId
Definition: backendid.h:23
#define ereport(elevel,...)
Definition: elog.h:144
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
BackendId backendId
Definition: lock.h:64
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
int errmsg(const char *fmt,...)
Definition: elog.c:821
#define InvalidLocalTransactionId
Definition: lock.h:68
#define TransactionIdIsValid(xid)
Definition: transam.h:41
Definition: proc.h:112
int pid
Definition: proc.h:137

◆ GetCurrentVirtualXIDs()

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

Definition at line 3160 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, TransactionIdIsValid, TransactionIdPrecedesOrEquals(), UINT32_ACCESS_ONCE, PROC_HDR::vacuumFlags, VirtualTransactionIdIsValid, and PGPROC::xmin.

Referenced by WaitForOlderSnapshots().

3163 {
3164  VirtualTransactionId *vxids;
3165  ProcArrayStruct *arrayP = procArray;
3166  int count = 0;
3167  int index;
3168 
3169  /* allocate what's certainly enough result space */
3170  vxids = (VirtualTransactionId *)
3171  palloc(sizeof(VirtualTransactionId) * arrayP->maxProcs);
3172 
3173  LWLockAcquire(ProcArrayLock, LW_SHARED);
3174 
3175  for (index = 0; index < arrayP->numProcs; index++)
3176  {
3177  int pgprocno = arrayP->pgprocnos[index];
3178  PGPROC *proc = &allProcs[pgprocno];
3179  uint8 vacuumFlags = ProcGlobal->vacuumFlags[index];
3180 
3181  if (proc == MyProc)
3182  continue;
3183 
3184  if (excludeVacuum & vacuumFlags)
3185  continue;
3186 
3187  if (allDbs || proc->databaseId == MyDatabaseId)
3188  {
3189  /* Fetch xmin just once - might change on us */
3190  TransactionId pxmin = UINT32_ACCESS_ONCE(proc->xmin);
3191 
3192  if (excludeXmin0 && !TransactionIdIsValid(pxmin))
3193  continue;
3194 
3195  /*
3196  * InvalidTransactionId precedes all other XIDs, so a proc that
3197  * hasn't set xmin yet will not be rejected by this test.
3198  */
3199  if (!TransactionIdIsValid(limitXmin) ||
3200  TransactionIdPrecedesOrEquals(pxmin, limitXmin))
3201  {
3202  VirtualTransactionId vxid;
3203 
3204  GET_VXID_FROM_PGPROC(vxid, *proc);
3205  if (VirtualTransactionIdIsValid(vxid))
3206  vxids[count++] = vxid;
3207  }
3208  }
3209  }
3210 
3211  LWLockRelease(ProcArrayLock);
3212 
3213  *nvxids = count;
3214  return vxids;
3215 }
#define GET_VXID_FROM_PGPROC(vxid, proc)
Definition: lock.h:79
uint32 TransactionId
Definition: c.h:521
PGPROC * MyProc
Definition: proc.c:67
#define UINT32_ACCESS_ONCE(var)
Definition: procarray.c:69
unsigned char uint8
Definition: c.h:373
PROC_HDR * ProcGlobal
Definition: proc.c:79
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
bool TransactionIdPrecedesOrEquals(TransactionId id1, TransactionId id2)
Definition: transam.c:319
TransactionId xmin
Definition: proc.h:129
static PGPROC * allProcs
Definition: procarray.c:252
Oid databaseId
Definition: proc.h:145
static ProcArrayStruct * procArray
Definition: procarray.c:250
#define VirtualTransactionIdIsValid(vxid)
Definition: lock.h:70
Oid MyDatabaseId
Definition: globals.c:85
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
void * palloc(Size size)
Definition: mcxt.c:950
uint8 * vacuumFlags
Definition: proc.h:321
#define TransactionIdIsValid(xid)
Definition: transam.h:41
Definition: proc.h:112

◆ GetMaxSnapshotSubxidCount()

int GetMaxSnapshotSubxidCount ( void  )

Definition at line 1979 of file procarray.c.

References TOTAL_MAX_CACHED_SUBXIDS.

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

1980 {
1981  return TOTAL_MAX_CACHED_SUBXIDS;
1982 }
#define TOTAL_MAX_CACHED_SUBXIDS

◆ GetMaxSnapshotXidCount()

int GetMaxSnapshotXidCount ( void  )

Definition at line 1968 of file procarray.c.

References ProcArrayStruct::maxProcs.

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

1969 {
1970  return procArray->maxProcs;
1971 }
static ProcArrayStruct * procArray
Definition: procarray.c:250

◆ GetOldestActiveTransactionId()

TransactionId GetOldestActiveTransactionId ( void  )

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

2782 {
2783  ProcArrayStruct *arrayP = procArray;
2784  TransactionId *other_xids = ProcGlobal->xids;
2785  TransactionId oldestRunningXid;
2786  int index;
2787 
2789 
2790  /*
2791  * Read nextXid, as the upper bound of what's still active.
2792  *
2793  * Reading a TransactionId is atomic, but we must grab the lock to make
2794  * sure that all XIDs < nextXid are already present in the proc array (or
2795  * have already completed), when we spin over it.
2796  */
2797  LWLockAcquire(XidGenLock, LW_SHARED);
2799  LWLockRelease(XidGenLock);
2800 
2801  /*
2802  * Spin over procArray collecting all xids and subxids.
2803  */
2804  LWLockAcquire(ProcArrayLock, LW_SHARED);
2805  for (index = 0; index < arrayP->numProcs; index++)
2806  {
2807  TransactionId xid;
2808 
2809  /* Fetch xid just once - see GetNewTransactionId */
2810  xid = UINT32_ACCESS_ONCE(other_xids[index]);
2811 
2812  if (!TransactionIdIsNormal(xid))
2813  continue;
2814 
2815  if (TransactionIdPrecedes(xid, oldestRunningXid))
2816  oldestRunningXid = xid;
2817 
2818  /*
2819  * Top-level XID of a transaction is always less than any of its
2820  * subxids, so we don't need to check if any of the subxids are
2821  * smaller than oldestRunningXid
2822  */
2823  }
2824  LWLockRelease(ProcArrayLock);
2825 
2826  return oldestRunningXid;
2827 }
uint32 TransactionId
Definition: c.h:521
#define UINT32_ACCESS_ONCE(var)
Definition: procarray.c:69
PROC_HDR * ProcGlobal
Definition: proc.c:79
bool RecoveryInProgress(void)
Definition: xlog.c:8076
FullTransactionId nextXid
Definition: transam.h:213
#define XidFromFullTransactionId(x)
Definition: transam.h:48
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
VariableCache ShmemVariableCache
Definition: varsup.c:34
TransactionId * xids
Definition: proc.h:309
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
static ProcArrayStruct * procArray
Definition: procarray.c:250
#define Assert(condition)
Definition: c.h:746
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
#define TransactionIdIsNormal(xid)
Definition: transam.h:42

◆ GetOldestNonRemovableTransactionId()

TransactionId GetOldestNonRemovableTransactionId ( Relation  rel)

Definition at line 1909 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 acquire_sample_rows(), collect_corrupt_items(), heapam_index_build_range_scan(), statapprox_heap(), vac_update_datfrozenxid(), and vacuum_set_xid_limits().

1910 {
1911  ComputeXidHorizonsResult horizons;
1912 
1913  ComputeXidHorizons(&horizons);
1914 
1915  /* select horizon appropriate for relation */
1916  if (rel == NULL || rel->rd_rel->relisshared)
1917  return horizons.shared_oldest_nonremovable;
1919  return horizons.catalog_oldest_nonremovable;
1920  else if (RELATION_IS_LOCAL(rel))
1921  return horizons.temp_oldest_nonremovable;
1922  else
1923  return horizons.data_oldest_nonremovable;
1924 }
static void ComputeXidHorizons(ComputeXidHorizonsResult *h)
Definition: procarray.c:1652
#define RELATION_IS_LOCAL(relation)
Definition: rel.h:583
Form_pg_class rd_rel
Definition: rel.h:109
TransactionId catalog_oldest_nonremovable
Definition: procarray.c:233
TransactionId shared_oldest_nonremovable
Definition: procarray.c:216
#define RelationIsAccessibleInLogicalDecoding(relation)
Definition: rel.h:619
TransactionId temp_oldest_nonremovable
Definition: procarray.c:245
TransactionId data_oldest_nonremovable
Definition: procarray.c:239

◆ GetOldestSafeDecodingTransactionId()

TransactionId GetOldestSafeDecodingTransactionId ( bool  catalogOnly)

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

2847 {
2848  ProcArrayStruct *arrayP = procArray;
2849  TransactionId oldestSafeXid;
2850  int index;
2851  bool recovery_in_progress = RecoveryInProgress();
2852 
2853  Assert(LWLockHeldByMe(ProcArrayLock));
2854 
2855  /*
2856  * Acquire XidGenLock, so no transactions can acquire an xid while we're
2857  * running. If no transaction with xid were running concurrently a new xid
2858  * could influence the RecentXmin et al.
2859  *
2860  * We initialize the computation to nextXid since that's guaranteed to be
2861  * a safe, albeit pessimal, value.
2862  */
2863  LWLockAcquire(XidGenLock, LW_SHARED);
2865 
2866  /*
2867  * If there's already a slot pegging the xmin horizon, we can start with
2868  * that value, it's guaranteed to be safe since it's computed by this
2869  * routine initially and has been enforced since. We can always use the
2870  * slot's general xmin horizon, but the catalog horizon is only usable
2871  * when only catalog data is going to be looked at.
2872  */
2875  oldestSafeXid))
2876  oldestSafeXid = procArray->replication_slot_xmin;
2877 
2878  if (catalogOnly &&
2881  oldestSafeXid))
2882  oldestSafeXid = procArray->replication_slot_catalog_xmin;
2883 
2884  /*
2885  * If we're not in recovery, we walk over the procarray and collect the
2886  * lowest xid. Since we're called with ProcArrayLock held and have
2887  * acquired XidGenLock, no entries can vanish concurrently, since
2888  * ProcGlobal->xids[i] is only set with XidGenLock held and only cleared
2889  * with ProcArrayLock held.
2890  *
2891  * In recovery we can't lower the safe value besides what we've computed
2892  * above, so we'll have to wait a bit longer there. We unfortunately can
2893  * *not* use KnownAssignedXidsGetOldestXmin() since the KnownAssignedXids
2894  * machinery can miss values and return an older value than is safe.
2895  */
2896  if (!recovery_in_progress)
2897  {
2898  TransactionId *other_xids = ProcGlobal->xids;
2899 
2900  /*
2901  * Spin over procArray collecting min(ProcGlobal->xids[i])
2902  */
2903  for (index = 0; index < arrayP->numProcs; index++)
2904  {
2905  TransactionId xid;
2906 
2907  /* Fetch xid just once - see GetNewTransactionId */
2908  xid = UINT32_ACCESS_ONCE(other_xids[index]);
2909 
2910  if (!TransactionIdIsNormal(xid))
2911  continue;
2912 
2913  if (TransactionIdPrecedes(xid, oldestSafeXid))
2914  oldestSafeXid = xid;
2915  }
2916  }
2917 
2918  LWLockRelease(XidGenLock);
2919 
2920  return oldestSafeXid;
2921 }
uint32 TransactionId
Definition: c.h:521
bool LWLockHeldByMe(LWLock *l)
Definition: lwlock.c:1928
#define UINT32_ACCESS_ONCE(var)
Definition: procarray.c:69
TransactionId replication_slot_catalog_xmin
Definition: procarray.c:98
PROC_HDR * ProcGlobal
Definition: proc.c:79
bool RecoveryInProgress(void)
Definition: xlog.c:8076
FullTransactionId nextXid
Definition: transam.h:213
#define XidFromFullTransactionId(x)
Definition: transam.h:48
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
VariableCache ShmemVariableCache
Definition: varsup.c:34
TransactionId * xids
Definition: proc.h:309
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:746
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
#define TransactionIdIsValid(xid)
Definition: transam.h:41
#define TransactionIdIsNormal(xid)
Definition: transam.h:42

◆ GetOldestTransactionIdConsideredRunning()

TransactionId GetOldestTransactionIdConsideredRunning ( void  )

Definition at line 1933 of file procarray.c.

References ComputeXidHorizons(), and ComputeXidHorizonsResult::oldest_considered_running.

Referenced by CreateCheckPoint(), and CreateRestartPoint().

1934 {
1935  ComputeXidHorizonsResult horizons;
1936 
1937  ComputeXidHorizons(&horizons);
1938 
1939  return horizons.oldest_considered_running;
1940 }
TransactionId oldest_considered_running
Definition: procarray.c:207
static void ComputeXidHorizons(ComputeXidHorizonsResult *h)
Definition: procarray.c:1652

◆ GetReplicationHorizons()

void GetReplicationHorizons ( TransactionId slot_xmin,
TransactionId catalog_xmin 
)

Definition at line 1946 of file procarray.c.

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

Referenced by XLogWalRcvSendHSFeedback().

1947 {
1948  ComputeXidHorizonsResult horizons;
1949 
1950  ComputeXidHorizons(&horizons);
1951 
1952  /*
1953  * Don't want to use shared_oldest_nonremovable here, as that contains the
1954  * effect of replication slot's catalog_xmin. We want to send a separate
1955  * feedback for the catalog horizon, so the primary can remove data table
1956  * contents more aggressively.
1957  */
1958  *xmin = horizons.shared_oldest_nonremovable_raw;
1959  *catalog_xmin = horizons.slot_catalog_xmin;
1960 }
static void ComputeXidHorizons(ComputeXidHorizonsResult *h)
Definition: procarray.c:1652
TransactionId shared_oldest_nonremovable_raw
Definition: procarray.c:227
TransactionId slot_catalog_xmin
Definition: procarray.c:194

◆ GetRunningTransactionData()

RunningTransactions GetRunningTransactionData ( void  )

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

2607 {
2608  /* result workspace */
2609  static RunningTransactionsData CurrentRunningXactsData;
2610 
2611  ProcArrayStruct *arrayP = procArray;
2612  TransactionId *other_xids = ProcGlobal->xids;
2613  RunningTransactions CurrentRunningXacts = &CurrentRunningXactsData;
2614  TransactionId latestCompletedXid;
2615  TransactionId oldestRunningXid;
2616  TransactionId *xids;
2617  int index;
2618  int count;
2619  int subcount;
2620  bool suboverflowed;
2621 
2623 
2624  /*
2625  * Allocating space for maxProcs xids is usually overkill; numProcs would
2626  * be sufficient. But it seems better to do the malloc while not holding
2627  * the lock, so we can't look at numProcs. Likewise, we allocate much
2628  * more subxip storage than is probably needed.
2629  *
2630  * Should only be allocated in bgwriter, since only ever executed during
2631  * checkpoints.
2632  */
2633  if (CurrentRunningXacts->xids == NULL)
2634  {
2635  /*
2636  * First call
2637  */
2638  CurrentRunningXacts->xids = (TransactionId *)
2640  if (CurrentRunningXacts->xids == NULL)
2641  ereport(ERROR,
2642  (errcode(ERRCODE_OUT_OF_MEMORY),
2643  errmsg("out of memory")));
2644  }
2645 
2646  xids = CurrentRunningXacts->xids;
2647 
2648  count = subcount = 0;
2649  suboverflowed = false;
2650 
2651  /*
2652  * Ensure that no xids enter or leave the procarray while we obtain
2653  * snapshot.
2654  */
2655  LWLockAcquire(ProcArrayLock, LW_SHARED);
2656  LWLockAcquire(XidGenLock, LW_SHARED);
2657 
2658  latestCompletedXid =
2660  oldestRunningXid =
2662 
2663  /*
2664  * Spin over procArray collecting all xids
2665  */
2666  for (index = 0; index < arrayP->numProcs; index++)
2667  {
2668  TransactionId xid;
2669 
2670  /* Fetch xid just once - see GetNewTransactionId */
2671  xid = UINT32_ACCESS_ONCE(other_xids[index]);
2672 
2673  /*
2674  * We don't need to store transactions that don't have a TransactionId
2675  * yet because they will not show as running on a standby server.
2676  */
2677  if (!TransactionIdIsValid(xid))
2678  continue;
2679 
2680  /*
2681  * Be careful not to exclude any xids before calculating the values of
2682  * oldestRunningXid and suboverflowed, since these are used to clean
2683  * up transaction information held on standbys.
2684  */
2685  if (TransactionIdPrecedes(xid, oldestRunningXid))
2686  oldestRunningXid = xid;
2687 
2688  if (ProcGlobal->subxidStates[index].overflowed)
2689  suboverflowed = true;
2690 
2691  /*
2692  * If we wished to exclude xids this would be the right place for it.
2693  * Procs with the PROC_IN_VACUUM flag set don't usually assign xids,
2694  * but they do during truncation at the end when they get the lock and
2695  * truncate, so it is not much of a problem to include them if they
2696  * are seen and it is cleaner to include them.
2697  */
2698 
2699  xids[count++] = xid;
2700  }
2701 
2702  /*
2703  * Spin over procArray collecting all subxids, but only if there hasn't
2704  * been a suboverflow.
2705  */
2706  if (!suboverflowed)
2707  {
2708  XidCacheStatus *other_subxidstates = ProcGlobal->subxidStates;
2709 
2710  for (index = 0; index < arrayP->numProcs; index++)
2711  {
2712  int pgprocno = arrayP->pgprocnos[index];
2713  PGPROC *proc = &allProcs[pgprocno];
2714  int nsubxids;
2715 
2716  /*
2717  * Save subtransaction XIDs. Other backends can't add or remove
2718  * entries while we're holding XidGenLock.
2719  */
2720  nsubxids = other_subxidstates[index].count;
2721  if (nsubxids > 0)
2722  {
2723  /* barrier not really required, as XidGenLock is held, but ... */
2724  pg_read_barrier(); /* pairs with GetNewTransactionId */
2725 
2726  memcpy(&xids[count], (void *) proc->subxids.xids,
2727  nsubxids * sizeof(TransactionId));
2728  count += nsubxids;
2729  subcount += nsubxids;
2730 
2731  /*
2732  * Top-level XID of a transaction is always less than any of
2733  * its subxids, so we don't need to check if any of the
2734  * subxids are smaller than oldestRunningXid
2735  */
2736  }
2737  }
2738  }
2739 
2740  /*
2741  * It's important *not* to include the limits set by slots here because
2742  * snapbuild.c uses oldestRunningXid to manage its xmin horizon. If those
2743  * were to be included here the initial value could never increase because
2744  * of a circular dependency where slots only increase their limits when
2745  * running xacts increases oldestRunningXid and running xacts only
2746  * increases if slots do.
2747  */
2748 
2749  CurrentRunningXacts->xcnt = count - subcount;
2750  CurrentRunningXacts->subxcnt = subcount;
2751  CurrentRunningXacts->subxid_overflow = suboverflowed;
2753  CurrentRunningXacts->oldestRunningXid = oldestRunningXid;
2754  CurrentRunningXacts->latestCompletedXid = latestCompletedXid;
2755 
2756  Assert(TransactionIdIsValid(CurrentRunningXacts->nextXid));
2757  Assert(TransactionIdIsValid(CurrentRunningXacts->oldestRunningXid));
2758  Assert(TransactionIdIsNormal(CurrentRunningXacts->latestCompletedXid));
2759 
2760  /* We don't release the locks here, the caller is responsible for that */
2761 
2762  return CurrentRunningXacts;
2763 }
TransactionId oldestRunningXid
Definition: standby.h:76
uint32 TransactionId
Definition: c.h:521
XidCacheStatus * subxidStates
Definition: proc.h:315
#define UINT32_ACCESS_ONCE(var)
Definition: procarray.c:69
int errcode(int sqlerrcode)
Definition: elog.c:610
PROC_HDR * ProcGlobal
Definition: proc.c:79
TransactionId * xids
Definition: standby.h:79
FullTransactionId latestCompletedXid
Definition: transam.h:231
bool RecoveryInProgress(void)
Definition: xlog.c:8076
FullTransactionId nextXid
Definition: transam.h:213
bool overflowed
Definition: proc.h:43
#define XidFromFullTransactionId(x)
Definition: transam.h:48
TransactionId latestCompletedXid
Definition: standby.h:77
Definition: type.h:89
#define malloc(a)
Definition: header.h:50
#define ERROR
Definition: elog.h:43
VariableCache ShmemVariableCache
Definition: varsup.c:34
TransactionId * xids
Definition: proc.h:309
static PGPROC * allProcs
Definition: procarray.c:252
struct XidCache subxids
Definition: proc.h:200
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
static ProcArrayStruct * procArray
Definition: procarray.c:250
#define ereport(elevel,...)
Definition: elog.h:144
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:746
#define pg_read_barrier()
Definition: atomics.h:158
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
uint8 count
Definition: proc.h:41
TransactionId nextXid
Definition: standby.h:75
int errmsg(const char *fmt,...)
Definition: elog.c:821
#define TransactionIdIsValid(xid)
Definition: transam.h:41
#define TransactionIdIsNormal(xid)
Definition: transam.h:42
Definition: proc.h:112

◆ GetSnapshotData()

Snapshot GetSnapshotData ( Snapshot  snapshot)

Definition at line 2105 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, 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, PROC_HDR::vacuumFlags, 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().

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

2943 {
2944  VirtualTransactionId *vxids;
2945  ProcArrayStruct *arrayP = procArray;
2946  int count = 0;
2947  int index;
2948 
2949  /* allocate what's certainly enough result space */
2950  vxids = (VirtualTransactionId *)
2951  palloc(sizeof(VirtualTransactionId) * arrayP->maxProcs);
2952 
2953  LWLockAcquire(ProcArrayLock, LW_SHARED);
2954 
2955  for (index = 0; index < arrayP->numProcs; index++)
2956  {
2957  int pgprocno = arrayP->pgprocnos[index];
2958  PGPROC *proc = &allProcs[pgprocno];
2959 
2960  if (proc->delayChkpt)
2961  {
2962  VirtualTransactionId vxid;
2963 
2964  GET_VXID_FROM_PGPROC(vxid, *proc);
2965  if (VirtualTransactionIdIsValid(vxid))
2966  vxids[count++] = vxid;
2967  }
2968  }
2969 
2970  LWLockRelease(ProcArrayLock);
2971 
2972  *nvxids = count;
2973  return vxids;
2974 }
#define GET_VXID_FROM_PGPROC(vxid, proc)
Definition: lock.h:79
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
bool delayChkpt
Definition: proc.h:176
static PGPROC * allProcs
Definition: procarray.c:252
static ProcArrayStruct * procArray
Definition: procarray.c:250
#define VirtualTransactionIdIsValid(vxid)
Definition: lock.h:70
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
void * palloc(Size size)
Definition: mcxt.c:950
Definition: proc.h:112

◆ HaveVirtualXIDsDelayingChkpt()

bool HaveVirtualXIDsDelayingChkpt ( VirtualTransactionId vxids,
int  nvxids 
)

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

2987 {
2988  bool result = false;
2989  ProcArrayStruct *arrayP = procArray;
2990  int index;
2991 
2992  LWLockAcquire(ProcArrayLock, LW_SHARED);
2993 
2994  for (index = 0; index < arrayP->numProcs; index++)
2995  {
2996  int pgprocno = arrayP->pgprocnos[index];
2997  PGPROC *proc = &allProcs[pgprocno];
2998  VirtualTransactionId vxid;
2999 
3000  GET_VXID_FROM_PGPROC(vxid, *proc);
3001 
3002  if (proc->delayChkpt && VirtualTransactionIdIsValid(vxid))
3003  {
3004  int i;
3005 
3006  for (i = 0; i < nvxids; i++)
3007  {
3008  if (VirtualTransactionIdEquals(vxid, vxids[i]))
3009  {
3010  result = true;
3011  break;
3012  }
3013  }
3014  if (result)
3015  break;
3016  }
3017  }
3018 
3019  LWLockRelease(ProcArrayLock);
3020 
3021  return result;
3022 }
#define GET_VXID_FROM_PGPROC(vxid, proc)
Definition: lock.h:79
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
#define VirtualTransactionIdEquals(vxid1, vxid2)
Definition: lock.h:73
bool delayChkpt
Definition: proc.h:176
static PGPROC * allProcs
Definition: procarray.c:252
static ProcArrayStruct * procArray
Definition: procarray.c:250
#define VirtualTransactionIdIsValid(vxid)
Definition: lock.h:70
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
int i
Definition: proc.h:112

◆ IsBackendPid()

bool IsBackendPid ( int  pid)

Definition at line 3127 of file procarray.c.

References BackendPidGetProc().

Referenced by pg_stat_get_subscription().

3128 {
3129  return (BackendPidGetProc(pid) != NULL);
3130 }
PGPROC * BackendPidGetProc(int pid)
Definition: procarray.c:3032

◆ MinimumActiveBackends()

bool MinimumActiveBackends ( int  min)

Definition at line 3370 of file procarray.c.

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

Referenced by XLogFlush().

3371 {
3372  ProcArrayStruct *arrayP = procArray;
3373  int count = 0;
3374  int index;
3375 
3376  /* Quick short-circuit if no minimum is specified */
3377  if (min == 0)
3378  return true;
3379 
3380  /*
3381  * Note: for speed, we don't acquire ProcArrayLock. This is a little bit
3382  * bogus, but since we are only testing fields for zero or nonzero, it
3383  * should be OK. The result is only used for heuristic purposes anyway...
3384  */
3385  for (index = 0; index < arrayP->numProcs; index++)
3386  {
3387  int pgprocno = arrayP->pgprocnos[index];
3388  PGPROC *proc = &allProcs[pgprocno];
3389 
3390  /*
3391  * Since we're not holding a lock, need to be prepared to deal with
3392  * garbage, as someone could have incremented numProcs but not yet
3393  * filled the structure.
3394  *
3395  * If someone just decremented numProcs, 'proc' could also point to a
3396  * PGPROC entry that's no longer in the array. It still points to a
3397  * PGPROC struct, though, because freed PGPROC entries just go to the
3398  * free list and are recycled. Its contents are nonsense in that case,
3399  * but that's acceptable for this function.
3400  */
3401  if (pgprocno == -1)
3402  continue; /* do not count deleted entries */
3403  if (proc == MyProc)
3404  continue; /* do not count myself */
3405  if (proc->xid == InvalidTransactionId)
3406  continue; /* do not count if no XID assigned */
3407  if (proc->pid == 0)
3408  continue; /* do not count prepared xacts */
3409  if (proc->waitLock != NULL)
3410  continue; /* do not count if blocked on a lock */
3411  count++;
3412  if (count >= min)
3413  break;
3414  }
3415 
3416  return count >= min;
3417 }
PGPROC * MyProc
Definition: proc.c:67
Definition: type.h:89
#define InvalidTransactionId
Definition: transam.h:31
static PGPROC * allProcs
Definition: procarray.c:252
LOCK * waitLock
Definition: proc.h:170
static ProcArrayStruct * procArray
Definition: procarray.c:250
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
TransactionId xid
Definition: proc.h:124
Definition: proc.h:112
int pid
Definition: proc.h:137

◆ 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, PROC_HDR::subxidStates, PGPROC::subxidStatus, PGPROC::vacuumFlags, PROC_HDR::vacuumFlags, 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->vacuumFlags[index + 1], &ProcGlobal->vacuumFlags[index],
492  (arrayP->numProcs - index) * sizeof(*ProcGlobal->vacuumFlags));
493 
494  arrayP->pgprocnos[index] = proc->pgprocno;
495  ProcGlobal->xids[index] = proc->xid;
496  ProcGlobal->subxidStates[index] = proc->subxidStatus;
497  ProcGlobal->vacuumFlags[index] = proc->vacuumFlags;
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:315
int errcode(int sqlerrcode)
Definition: elog.c:610
PROC_HDR * ProcGlobal
Definition: proc.c:79
XidCacheStatus subxidStatus
Definition: proc.h:198
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
#define FATAL
Definition: elog.h:52
TransactionId * xids
Definition: proc.h:309
static PGPROC * allProcs
Definition: procarray.c:252
static ProcArrayStruct * procArray
Definition: procarray.c:250
#define ereport(elevel,...)
Definition: elog.h:144
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
TransactionId xid
Definition: proc.h:124
int pgprocno
Definition: proc.h:141
int errmsg(const char *fmt,...)
Definition: elog.c:821
int pgxactoff
Definition: proc.h:139
uint8 * vacuumFlags
Definition: proc.h:321
uint8 vacuumFlags
Definition: proc.h:178

◆ ProcArrayApplyRecoveryInfo()

void ProcArrayApplyRecoveryInfo ( RunningTransactions  running)

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

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

◆ ProcArrayApplyXidAssignment()

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

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

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

◆ ProcArrayClearTransaction()

void ProcArrayClearTransaction ( PGPROC proc)

Definition at line 849 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, PROC_HDR::subxidStates, PGPROC::subxidStatus, PGPROC::vacuumFlags, VariableCacheData::xactCompletionCount, PGPROC::xid, PROC_HDR::xids, and PGPROC::xmin.

Referenced by PrepareTransaction().

850 {
851  size_t pgxactoff;
852 
853  /*
854  * Currently we need to lock ProcArrayLock exclusively here, as we
855  * increment xactCompletionCount below. We also need it at least in shared
856  * mode for pgproc->pgxactoff to stay the same below.
857  *
858  * We could however, as this action does not actually change anyone's view
859  * of the set of running XIDs (our entry is duplicate with the gxact that
860  * has already been inserted into the ProcArray), lower the lock level to
861  * shared if we were to make xactCompletionCount an atomic variable. But
862  * that doesn't seem worth it currently, as a 2PC commit is heavyweight
863  * enough for this not to be the bottleneck. If it ever becomes a
864  * bottleneck it may also be worth considering to combine this with the
865  * subsequent ProcArrayRemove()
866  */
867  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
868 
869  pgxactoff = proc->pgxactoff;
870 
871  ProcGlobal->xids[pgxactoff] = InvalidTransactionId;
872  proc->xid = InvalidTransactionId;
873 
875  proc->xmin = InvalidTransactionId;
876  proc->recoveryConflictPending = false;
877 
879  Assert(!proc->delayChkpt);
880 
881  /*
882  * Need to increment completion count even though transaction hasn't
883  * really committed yet. The reason for that is that GetSnapshotData()
884  * omits the xid of the current transaction, thus without the increment we
885  * otherwise could end up reusing the snapshot later. Which would be bad,
886  * because it might not count the prepared transaction as running.
887  */
889 
890  /* Clear the subtransaction-XID cache too */
891  Assert(ProcGlobal->subxidStates[pgxactoff].count == proc->subxidStatus.count &&
893  if (proc->subxidStatus.count > 0 || proc->subxidStatus.overflowed)
894  {
895  ProcGlobal->subxidStates[pgxactoff].count = 0;
896  ProcGlobal->subxidStates[pgxactoff].overflowed = false;
897  proc->subxidStatus.count = 0;
898  proc->subxidStatus.overflowed = false;
899  }
900 
901  LWLockRelease(ProcArrayLock);
902 }
XidCacheStatus * subxidStates
Definition: proc.h:315
uint64 xactCompletionCount
Definition: transam.h:241
PROC_HDR * ProcGlobal
Definition: proc.c:79
XidCacheStatus subxidStatus
Definition: proc.h:198
#define PROC_VACUUM_STATE_MASK
Definition: proc.h:61
bool overflowed
Definition: proc.h:43
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
bool delayChkpt
Definition: proc.h:176
TransactionId xmin
Definition: proc.h:129
bool recoveryConflictPending
Definition: proc.h:158
VariableCache ShmemVariableCache
Definition: varsup.c:34
#define InvalidTransactionId
Definition: transam.h:31
TransactionId * xids
Definition: proc.h:309
#define Assert(condition)
Definition: c.h:746
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
uint8 count
Definition: proc.h:41
TransactionId xid
Definition: proc.h:124
#define InvalidLocalTransactionId
Definition: lock.h:68
int pgxactoff
Definition: proc.h:139
uint8 vacuumFlags
Definition: proc.h:178
LocalTransactionId lxid
Definition: proc.h:134

◆ 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, LW_SHARED, LWLockAcquire(), LWLockConditionalAcquire(), LWLockHeldByMe(), LWLockRelease(), PGPROC::lxid, XidCacheStatus::overflowed, PGPROC::pgxactoff, PROC_VACUUM_STATE_MASK, ProcArrayEndTransactionInternal(), ProcArrayGroupClearXid(), ProcGlobal, PGPROC::recoveryConflictPending, PGPROC::subxidStatus, TransactionIdIsValid, PGPROC::vacuumFlags, PROC_HDR::vacuumFlags, 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_SHARED);
670  LWLockRelease(ProcArrayLock);
671  }
672  }
673 }
bool LWLockHeldByMe(LWLock *l)
Definition: lwlock.c:1928
static void ProcArrayEndTransactionInternal(PGPROC *proc, TransactionId latestXid)
Definition: procarray.c:681
static void ProcArrayGroupClearXid(PGPROC *proc, TransactionId latestXid)
Definition: procarray.c:735
PROC_HDR * ProcGlobal
Definition: proc.c:79
XidCacheStatus subxidStatus
Definition: proc.h:198
#define PROC_VACUUM_STATE_MASK
Definition: proc.h:61
bool overflowed
Definition: proc.h:43
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
bool delayChkpt
Definition: proc.h:176
TransactionId xmin
Definition: proc.h:129
bool LWLockConditionalAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1380
bool recoveryConflictPending
Definition: proc.h:158
#define InvalidTransactionId
Definition: transam.h:31
#define Assert(condition)
Definition: c.h:746
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
uint8 count
Definition: proc.h:41
TransactionId xid
Definition: proc.h:124
#define InvalidLocalTransactionId
Definition: lock.h:68
int pgxactoff
Definition: proc.h:139
uint8 * vacuumFlags
Definition: proc.h:321
uint8 vacuumFlags
Definition: proc.h:178
#define TransactionIdIsValid(xid)
Definition: transam.h:41
LocalTransactionId lxid
Definition: proc.h:134

◆ ProcArrayGetReplicationSlotXmin()

void ProcArrayGetReplicationSlotXmin ( TransactionId xmin,
TransactionId catalog_xmin 
)

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

3784 {
3785  LWLockAcquire(ProcArrayLock, LW_SHARED);
3786 
3787  if (xmin != NULL)
3789 
3790  if (catalog_xmin != NULL)
3791  *catalog_xmin = procArray->replication_slot_catalog_xmin;
3792 
3793  LWLockRelease(ProcArrayLock);
3794 }
TransactionId replication_slot_catalog_xmin
Definition: procarray.c:98
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
static ProcArrayStruct * procArray
Definition: procarray.c:250
TransactionId replication_slot_xmin
Definition: procarray.c:96
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208

◆ ProcArrayInitRecovery()

void ProcArrayInitRecovery ( TransactionId  initializedUptoXID)

Definition at line 965 of file procarray.c.

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

Referenced by StartupXLOG().

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

◆ ProcArrayInstallImportedXmin()

bool ProcArrayInstallImportedXmin ( TransactionId  xmin,
VirtualTransactionId sourcevxid 
)

Definition at line 2468 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, TransactionIdIsNormal, TransactionIdPrecedesOrEquals(), TransactionXmin, UINT32_ACCESS_ONCE, PROC_HDR::vacuumFlags, and PGPROC::xmin.

Referenced by GetSerializableTransactionSnapshotInt(), and SetTransactionSnapshot().

2470 {
2471  bool result = false;
2472  ProcArrayStruct *arrayP = procArray;
2473  int index;
2474 
2476  if (!sourcevxid)
2477  return false;
2478 
2479  /* Get lock so source xact can't end while we're doing this */
2480  LWLockAcquire(ProcArrayLock, LW_SHARED);
2481 
2482  for (index = 0; index < arrayP->numProcs; index++)
2483  {
2484  int pgprocno = arrayP->pgprocnos[index];
2485  PGPROC *proc = &allProcs[pgprocno];
2486  int vacuumFlags = ProcGlobal->vacuumFlags[index];
2487  TransactionId xid;
2488 
2489  /* Ignore procs running LAZY VACUUM */
2490  if (vacuumFlags & PROC_IN_VACUUM)
2491  continue;
2492 
2493  /* We are only interested in the specific virtual transaction. */
2494  if (proc->backendId != sourcevxid->backendId)
2495  continue;
2496  if (proc->lxid != sourcevxid->localTransactionId)
2497  continue;
2498 
2499  /*
2500  * We check the transaction's database ID for paranoia's sake: if it's
2501  * in another DB then its xmin does not cover us. Caller should have
2502  * detected this already, so we just treat any funny cases as
2503  * "transaction not found".
2504  */
2505  if (proc->databaseId != MyDatabaseId)
2506  continue;
2507 
2508  /*
2509  * Likewise, let's just make real sure its xmin does cover us.
2510  */
2511  xid = UINT32_ACCESS_ONCE(proc->xmin);
2512  if (!TransactionIdIsNormal(xid) ||
2513  !TransactionIdPrecedesOrEquals(xid, xmin))
2514  continue;
2515 
2516  /*
2517  * We're good. Install the new xmin. As in GetSnapshotData, set
2518  * TransactionXmin too. (Note that because snapmgr.c called
2519  * GetSnapshotData first, we'll be overwriting a valid xmin here, so
2520  * we don't check that.)
2521  */
2522  MyProc->xmin = TransactionXmin = xmin;
2523 
2524  result = true;
2525  break;
2526  }
2527 
2528  LWLockRelease(ProcArrayLock);
2529 
2530  return result;
2531 }
BackendId backendId
Definition: proc.h:144
uint32 TransactionId
Definition: c.h:521
PGPROC * MyProc
Definition: proc.c:67
#define UINT32_ACCESS_ONCE(var)
Definition: procarray.c:69
PROC_HDR * ProcGlobal
Definition: proc.c:79
LocalTransactionId localTransactionId
Definition: lock.h:65
TransactionId TransactionXmin
Definition: snapmgr.c:112
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
#define PROC_IN_VACUUM
Definition: proc.h:55
bool TransactionIdPrecedesOrEquals(TransactionId id1, TransactionId id2)
Definition: transam.c:319
TransactionId xmin
Definition: proc.h:129
static PGPROC * allProcs
Definition: procarray.c:252
Oid databaseId
Definition: proc.h:145
static ProcArrayStruct * procArray
Definition: procarray.c:250
Oid MyDatabaseId
Definition: globals.c:85
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
#define Assert(condition)
Definition: c.h:746
BackendId backendId
Definition: lock.h:64
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
uint8 * vacuumFlags
Definition: proc.h:321
#define TransactionIdIsNormal(xid)
Definition: transam.h:42
Definition: proc.h:112
LocalTransactionId lxid
Definition: proc.h:134

◆ ProcArrayInstallRestoredXmin()

bool ProcArrayInstallRestoredXmin ( TransactionId  xmin,
PGPROC proc 
)

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

2544 {
2545  bool result = false;
2546  TransactionId xid;
2547 
2549  Assert(proc != NULL);
2550 
2551  /* Get lock so source xact can't end while we're doing this */
2552  LWLockAcquire(ProcArrayLock, LW_SHARED);
2553 
2554  /*
2555  * Be certain that the referenced PGPROC has an advertised xmin which is
2556  * no later than the one we're installing, so that the system-wide xmin
2557  * can't go backwards. Also, make sure it's running in the same database,
2558  * so that the per-database xmin cannot go backwards.
2559  */
2560  xid = UINT32_ACCESS_ONCE(proc->xmin);
2561  if (proc->databaseId == MyDatabaseId &&
2562  TransactionIdIsNormal(xid) &&
2563  TransactionIdPrecedesOrEquals(xid, xmin))
2564  {
2565  MyProc->xmin = TransactionXmin = xmin;
2566  result = true;
2567  }
2568 
2569  LWLockRelease(ProcArrayLock);
2570 
2571  return result;
2572 }
uint32 TransactionId
Definition: c.h:521
PGPROC * MyProc
Definition: proc.c:67
#define UINT32_ACCESS_ONCE(var)
Definition: procarray.c:69
TransactionId TransactionXmin
Definition: snapmgr.c:112
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
bool TransactionIdPrecedesOrEquals(TransactionId id1, TransactionId id2)
Definition: transam.c:319
TransactionId xmin
Definition: proc.h:129
Oid databaseId
Definition: proc.h:145
Oid MyDatabaseId
Definition: globals.c:85
#define Assert(condition)
Definition: c.h:746
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
#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::subxidStates, TransactionIdIsValid, PROC_HDR::vacuumFlags, 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->vacuumFlags[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->vacuumFlags[index], &ProcGlobal->vacuumFlags[index + 1],
579  (arrayP->numProcs - index - 1) * sizeof(*ProcGlobal->vacuumFlags));
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:315
uint64 xactCompletionCount
Definition: transam.h:241
PROC_HDR * ProcGlobal
Definition: proc.c:79
#define LOG
Definition: elog.h:26
bool overflowed
Definition: proc.h:43
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
VariableCache ShmemVariableCache
Definition: varsup.c:34
TransactionId * xids
Definition: proc.h:309
static PGPROC * allProcs
Definition: procarray.c:252
static ProcArrayStruct * procArray
Definition: procarray.c:250
static void MaintainLatestCompletedXid(TransactionId latestXid)
Definition: procarray.c:909
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
#define Assert(condition)
Definition: c.h:746
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
uint8 count
Definition: proc.h:41
int pgprocno
Definition: proc.h:141
#define elog(elevel,...)
Definition: elog.h:214
int pgxactoff
Definition: proc.h:139
uint8 * vacuumFlags
Definition: proc.h:321
PGPROC * allProcs
Definition: proc.h:306
#define TransactionIdIsValid(xid)
Definition: transam.h:41
int pid
Definition: proc.h:137

◆ ProcArraySetReplicationSlotXmin()

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

Definition at line 3760 of file procarray.c.

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

Referenced by ReplicationSlotsComputeRequiredXmin().

3762 {
3763  Assert(!already_locked || LWLockHeldByMe(ProcArrayLock));
3764 
3765  if (!already_locked)
3766  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3767 
3769  procArray->replication_slot_catalog_xmin = catalog_xmin;
3770 
3771  if (!already_locked)
3772  LWLockRelease(ProcArrayLock);
3773 }
bool LWLockHeldByMe(LWLock *l)
Definition: lwlock.c:1928
TransactionId replication_slot_catalog_xmin
Definition: procarray.c:98
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
static ProcArrayStruct * procArray
Definition: procarray.c:250
TransactionId replication_slot_xmin
Definition: procarray.c:96
#define Assert(condition)
Definition: c.h:746
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208

◆ 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:521
Size mul_size(Size s1, Size s2)
Definition: shmem.c:515
Size add_size(Size s1, Size s2)
Definition: shmem.c:498
#define TOTAL_MAX_CACHED_SUBXIDS
size_t Size
Definition: c.h:474
bool EnableHotStandby
Definition: xlog.c:97
#define offsetof(type, field)
Definition: c.h:669

◆ RecordKnownAssignedTransactionIds()

void RecordKnownAssignedTransactionIds ( TransactionId  xid)

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

4256 {
4260 
4261  elog(trace_recovery(DEBUG4), "record known xact %u latestObservedXid %u",
4262  xid, latestObservedXid);
4263 
4264  /*
4265  * When a newly observed xid arrives, it is frequently the case that it is
4266  * *not* the next xid in sequence. When this occurs, we must treat the
4267  * intervening xids as running also.
4268  */
4270  {
4271  TransactionId next_expected_xid;
4272 
4273  /*
4274  * Extend subtrans like we do in GetNewTransactionId() during normal
4275  * operation using individual extend steps. Note that we do not need
4276  * to extend clog since its extensions are WAL logged.
4277  *
4278  * This part has to be done regardless of standbyState since we
4279  * immediately start assigning subtransactions to their toplevel
4280  * transactions.
4281  */
4282  next_expected_xid = latestObservedXid;
4283  while (TransactionIdPrecedes(next_expected_xid, xid))
4284  {
4285  TransactionIdAdvance(next_expected_xid);
4286  ExtendSUBTRANS(next_expected_xid);
4287  }
4288  Assert(next_expected_xid == xid);
4289 
4290  /*
4291  * If the KnownAssignedXids machinery isn't up yet, there's nothing
4292  * more to do since we don't track assigned xids yet.
4293  */
4295  {
4296  latestObservedXid = xid;
4297  return;
4298  }
4299 
4300  /*
4301  * Add (latestObservedXid, xid] onto the KnownAssignedXids array.
4302  */
4303  next_expected_xid = latestObservedXid;
4304  TransactionIdAdvance(next_expected_xid);
4305  KnownAssignedXidsAdd(next_expected_xid, xid, false);
4306 
4307  /*
4308  * Now we can advance latestObservedXid
4309  */
4310  latestObservedXid = xid;
4311 
4312  /* ShmemVariableCache->nextXid must be beyond any observed xid */
4314  next_expected_xid = latestObservedXid;
4315  TransactionIdAdvance(next_expected_xid);
4316  }
4317 }
#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:521
void AdvanceNextFullTransactionIdPastXid(TransactionId xid)
Definition: varsup.c:277
#define DEBUG4
Definition: elog.h:22
int trace_recovery(int trace_level)
Definition: elog.c:3540
void ExtendSUBTRANS(TransactionId newestXact)
Definition: subtrans.c:307
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
#define Assert(condition)
Definition: c.h:746
static void KnownAssignedXidsAdd(TransactionId from_xid, TransactionId to_xid, bool exclusive_lock)
Definition: procarray.c:4529
#define elog(elevel,...)
Definition: elog.h:214
#define TransactionIdIsValid(xid)
Definition: transam.h:41
HotStandbyState standbyState
Definition: xlog.c:208

◆ TerminateOtherDBBackends()

void TerminateOtherDBBackends ( Oid  databaseId)

Definition at line 3652 of file procarray.c.

References BackendPidGetProc(), PGPROC::databaseId, ereport, errcode(), ERRCODE_INSUFFICIENT_PRIVILEGE, 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().

3653 {
3654  ProcArrayStruct *arrayP = procArray;
3655  List *pids = NIL;
3656  int nprepared = 0;
3657  int i;
3658 
3659  LWLockAcquire(ProcArrayLock, LW_SHARED);
3660 
3661  for (i = 0; i < procArray->numProcs; i++)
3662  {
3663  int pgprocno = arrayP->pgprocnos[i];
3664  PGPROC *proc = &allProcs[pgprocno];
3665 
3666  if (proc->databaseId != databaseId)
3667  continue;
3668  if (proc == MyProc)
3669  continue;
3670 
3671  if (proc->pid != 0)
3672  pids = lappend_int(pids, proc->pid);
3673  else
3674  nprepared++;
3675  }
3676 
3677  LWLockRelease(ProcArrayLock);
3678 
3679  if (nprepared > 0)
3680  ereport(ERROR,
3681  (errcode(ERRCODE_OBJECT_IN_USE),
3682  errmsg("database \"%s\" is being used by prepared transactions",
3683  get_database_name(databaseId)),
3684  errdetail_plural("There is %d prepared transaction using the database.",
3685  "There are %d prepared transactions using the database.",
3686  nprepared,
3687  nprepared)));
3688 
3689  if (pids)
3690  {
3691  ListCell *lc;
3692 
3693  /*
3694  * Check whether we have the necessary rights to terminate other
3695  * sessions. We don't terminate any session until we ensure that we
3696  * have rights on all the sessions to be terminated. These checks are
3697  * the same as we do in pg_terminate_backend.
3698  *
3699  * In this case we don't raise some warnings - like "PID %d is not a
3700  * PostgreSQL server process", because for us already finished session
3701  * is not a problem.
3702  */
3703  foreach(lc, pids)
3704  {
3705  int pid = lfirst_int(lc);
3706  PGPROC *proc = BackendPidGetProc(pid);
3707 
3708  if (proc != NULL)
3709  {
3710  /* Only allow superusers to signal superuser-owned backends. */
3711  if (superuser_arg(proc->roleId) && !superuser())
3712  ereport(ERROR,
3714  errmsg("must be a superuser to terminate superuser process")));
3715 
3716  /* Users can signal backends they have role membership in. */
3717  if (!has_privs_of_role(GetUserId(), proc->roleId) &&
3718  !has_privs_of_role(GetUserId(), DEFAULT_ROLE_SIGNAL_BACKENDID))
3719  ereport(ERROR,
3721  errmsg("must be a member of the role whose process is being terminated or member of pg_signal_backend")));
3722  }
3723  }
3724 
3725  /*
3726  * There's a race condition here: once we release the ProcArrayLock,
3727  * it's possible for the session to exit before we issue kill. That
3728  * race condition possibility seems too unlikely to worry about. See
3729  * pg_signal_backend.
3730  */
3731  foreach(lc, pids)
3732  {
3733  int pid = lfirst_int(lc);
3734  PGPROC *proc = BackendPidGetProc(pid);
3735 
3736  if (proc != NULL)
3737  {
3738  /*
3739  * If we have setsid(), signal the backend's whole process
3740  * group
3741  */
3742 #ifdef HAVE_SETSID
3743  (void) kill(-pid, SIGTERM);
3744 #else
3745  (void) kill(pid, SIGTERM);
3746 #endif
3747  }
3748  }
3749  }
3750 }
#define NIL
Definition: pg_list.h:65
Oid GetUserId(void)
Definition: miscinit.c:476
PGPROC * BackendPidGetProc(int pid)
Definition: procarray.c:3032
PGPROC * MyProc
Definition: proc.c:67
bool has_privs_of_role(Oid member, Oid role)
Definition: acl.c:4892
Oid roleId
Definition: proc.h:146
int errcode(int sqlerrcode)
Definition: elog.c:610
bool superuser(void)
Definition: superuser.c:46
#define kill(pid, sig)
Definition: win32_port.h:454
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
#define ERRCODE_INSUFFICIENT_PRIVILEGE
#define ERROR
Definition: elog.h:43
#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:145
bool superuser_arg(Oid roleid)
Definition: superuser.c:56
List * lappend_int(List *list, int datum)
Definition: list.c:339
static ProcArrayStruct * procArray
Definition: procarray.c:250
#define ereport(elevel,...)
Definition: elog.h:144
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:1046
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
int errmsg(const char *fmt,...)
Definition: elog.c:821
int i
Definition: proc.h:112
Definition: pg_list.h:50
int pid
Definition: proc.h:137

◆ TransactionIdIsActive()

bool TransactionIdIsActive ( TransactionId  xid)

Definition at line 1548 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.

1549 {
1550  bool result = false;
1551  ProcArrayStruct *arrayP = procArray;
1552  TransactionId *other_xids = ProcGlobal->xids;
1553  int i;
1554 
1555  /*
1556  * Don't bother checking a transaction older than RecentXmin; it could not
1557  * possibly still be running.
1558  */
1560  return false;
1561 
1562  LWLockAcquire(ProcArrayLock, LW_SHARED);
1563 
1564  for (i = 0; i < arrayP->numProcs; i++)
1565  {
1566  int pgprocno = arrayP->pgprocnos[i];
1567  PGPROC *proc = &allProcs[pgprocno];
1568  TransactionId pxid;
1569 
1570  /* Fetch xid just once - see GetNewTransactionId */
1571  pxid = UINT32_ACCESS_ONCE(other_xids[i]);
1572 
1573  if (!TransactionIdIsValid(pxid))
1574  continue;
1575 
1576  if (proc->pid == 0)
1577  continue; /* ignore prepared transactions */
1578 
1579  if (TransactionIdEquals(pxid, xid))
1580  {
1581  result = true;
1582  break;
1583  }
1584  }
1585 
1586  LWLockRelease(ProcArrayLock);
1587 
1588  return result;
1589 }
#define TransactionIdEquals(id1, id2)
Definition: transam.h:43
uint32 TransactionId
Definition: c.h:521
#define UINT32_ACCESS_ONCE(var)
Definition: procarray.c:69
TransactionId RecentXmin
Definition: snapmgr.c:113
PROC_HDR * ProcGlobal
Definition: proc.c:79
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
TransactionId * xids
Definition: proc.h:309
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:1208
int i
#define TransactionIdIsValid(xid)
Definition: transam.h:41
Definition: proc.h:112
int pid
Definition: proc.h:137

◆ TransactionIdIsInProgress()

bool TransactionIdIsInProgress ( TransactionId  xid)

Definition at line 1316 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(), HandleConcurrentAbort(), HeapTupleHeaderIsOnlyLocked(), HeapTupleSatisfiesDirty(), HeapTupleSatisfiesSelf(), HeapTupleSatisfiesToast(), HeapTupleSatisfiesUpdate(), HeapTupleSatisfiesVacuumHorizon(), MultiXactIdExpand(), MultiXactIdIsRunning(), test_lockmode_for_conflict(), and XactLockTableWait().

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

◆ XidCacheRemoveRunningXids()

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

Definition at line 3805 of file procarray.c.

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

Referenced by RecordTransactionAbort().

3808 {
3809  int i,
3810  j;
3811  XidCacheStatus *mysubxidstat;
3812 
3814 
3815  /*
3816  * We must hold ProcArrayLock exclusively in order to remove transactions
3817  * from the PGPROC array. (See src/backend/access/transam/README.) It's
3818  * possible this could be relaxed since we know this routine is only used
3819  * to abort subtransactions, but pending closer analysis we'd best be
3820  * conservative.
3821  *
3822  * Note that we do not have to be careful about memory ordering of our own
3823  * reads wrt. GetNewTransactionId() here - only this process can modify
3824  * relevant fields of MyProc/ProcGlobal->xids[]. But we do have to be
3825  * careful about our own writes being well ordered.
3826  */
3827  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3828 
3829  mysubxidstat = &ProcGlobal->subxidStates[MyProc->pgxactoff];
3830 
3831  /*
3832  * Under normal circumstances xid and xids[] will be in increasing order,
3833  * as will be the entries in subxids. Scan backwards to avoid O(N^2)
3834  * behavior when removing a lot of xids.
3835  */
3836  for (i = nxids - 1; i >= 0; i--)
3837  {
3838  TransactionId anxid = xids[i];
3839 
3840  for (j = MyProc->subxidStatus.count - 1; j >= 0; j--)
3841  {
3842  if (TransactionIdEquals(MyProc->subxids.xids[j], anxid))
3843  {
3845  pg_write_barrier();
3846  mysubxidstat->count--;
3848  break;
3849  }
3850  }
3851 
3852  /*
3853  * Ordinarily we should have found it, unless the cache has
3854  * overflowed. However it's also possible for this routine to be
3855  * invoked multiple times for the same subtransaction, in case of an
3856  * error during AbortSubTransaction. So instead of Assert, emit a
3857  * debug warning.
3858  */
3859  if (j < 0 && !MyProc->subxidStatus.overflowed)
3860  elog(WARNING, "did not find subXID %u in MyProc", anxid);
3861  }
3862 
3863  for (j = MyProc->subxidStatus.count - 1; j >= 0; j--)
3864  {
3865  if (TransactionIdEquals(MyProc->subxids.xids[j], xid))
3866  {
3868  pg_write_barrier();
3869  mysubxidstat->count--;
3871  break;
3872  }
3873  }
3874  /* Ordinarily we should have found it, unless the cache has overflowed */
3875  if (j < 0 && !MyProc->subxidStatus.overflowed)
3876  elog(WARNING, "did not find subXID %u in MyProc", xid);
3877 
3878  /* Also advance global latestCompletedXid while holding the lock */
3879  MaintainLatestCompletedXid(latestXid);
3880 
3881  LWLockRelease(ProcArrayLock);
3882 }
#define TransactionIdEquals(id1, id2)
Definition: transam.h:43
uint32 TransactionId
Definition: c.h:521
XidCacheStatus * subxidStates
Definition: proc.h:315
PGPROC * MyProc
Definition: proc.c:67
PROC_HDR * ProcGlobal
Definition: proc.c:79
XidCacheStatus subxidStatus
Definition: proc.h:198
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
struct XidCache subxids
Definition: proc.h:200
#define WARNING
Definition: elog.h:40
static void MaintainLatestCompletedXid(TransactionId latestXid)
Definition: procarray.c:909
TransactionId xids[PGPROC_MAX_CACHED_SUBXIDS]
Definition: proc.h:48
#define Assert(condition)
Definition: c.h:746
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
uint8 count
Definition: proc.h:41
#define elog(elevel,...)
Definition: elog.h:214
int i
int pgxactoff
Definition: proc.h:139
#define pg_write_barrier()
Definition: atomics.h:159
#define TransactionIdIsValid(xid)
Definition: transam.h:41