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

Go to the source code of this file.

Functions

Size ProcArrayShmemSize (void)
 
void CreateSharedProcArray (void)
 
void ProcArrayAdd (PGPROC *proc)
 
void ProcArrayRemove (PGPROC *proc, TransactionId latestXid)
 
void ProcArrayEndTransaction (PGPROC *proc, TransactionId latestXid)
 
void ProcArrayClearTransaction (PGPROC *proc)
 
void ProcArrayInitRecovery (TransactionId initializedUptoXID)
 
void ProcArrayApplyRecoveryInfo (RunningTransactions running)
 
void ProcArrayApplyXidAssignment (TransactionId topxid, int nsubxids, TransactionId *subxids)
 
void RecordKnownAssignedTransactionIds (TransactionId xid)
 
void ExpireTreeKnownAssignedTransactionIds (TransactionId xid, int nsubxids, TransactionId *subxids, TransactionId max_xid)
 
void ExpireAllKnownAssignedTransactionIds (void)
 
void ExpireOldKnownAssignedTransactionIds (TransactionId xid)
 
void KnownAssignedTransactionIdsIdleMaintenance (void)
 
int GetMaxSnapshotXidCount (void)
 
int GetMaxSnapshotSubxidCount (void)
 
Snapshot GetSnapshotData (Snapshot snapshot)
 
bool ProcArrayInstallImportedXmin (TransactionId xmin, VirtualTransactionId *sourcevxid)
 
bool ProcArrayInstallRestoredXmin (TransactionId xmin, PGPROC *proc)
 
RunningTransactions GetRunningTransactionData (void)
 
bool TransactionIdIsInProgress (TransactionId xid)
 
bool TransactionIdIsActive (TransactionId xid)
 
TransactionId GetOldestNonRemovableTransactionId (Relation rel)
 
TransactionId GetOldestTransactionIdConsideredRunning (void)
 
TransactionId GetOldestActiveTransactionId (void)
 
TransactionId GetOldestSafeDecodingTransactionId (bool catalogOnly)
 
void GetReplicationHorizons (TransactionId *xmin, TransactionId *catalog_xmin)
 
VirtualTransactionIdGetVirtualXIDsDelayingChkpt (int *nvxids, int type)
 
bool HaveVirtualXIDsDelayingChkpt (VirtualTransactionId *vxids, int nvxids, int type)
 
PGPROCProcNumberGetProc (int procNumber)
 
void ProcNumberGetTransactionIds (int procNumber, TransactionId *xid, TransactionId *xmin, int *nsubxid, bool *overflowed)
 
PGPROCBackendPidGetProc (int pid)
 
PGPROCBackendPidGetProcWithLock (int pid)
 
int BackendXidGetPid (TransactionId xid)
 
bool IsBackendPid (int pid)
 
VirtualTransactionIdGetCurrentVirtualXIDs (TransactionId limitXmin, bool excludeXmin0, bool allDbs, int excludeVacuum, int *nvxids)
 
VirtualTransactionIdGetConflictingVirtualXIDs (TransactionId limitXmin, Oid dbOid)
 
pid_t CancelVirtualTransaction (VirtualTransactionId vxid, ProcSignalReason sigmode)
 
pid_t SignalVirtualTransaction (VirtualTransactionId vxid, ProcSignalReason sigmode, bool conflictPending)
 
bool MinimumActiveBackends (int min)
 
int CountDBBackends (Oid databaseid)
 
int CountDBConnections (Oid databaseid)
 
void CancelDBBackends (Oid databaseid, ProcSignalReason sigmode, bool conflictPending)
 
int CountUserBackends (Oid roleid)
 
bool CountOtherDBBackends (Oid databaseId, int *nbackends, int *nprepared)
 
void TerminateOtherDBBackends (Oid databaseId)
 
void XidCacheRemoveRunningXids (TransactionId xid, int nxids, const TransactionId *xids, TransactionId latestXid)
 
void ProcArraySetReplicationSlotXmin (TransactionId xmin, TransactionId catalog_xmin, bool already_locked)
 
void ProcArrayGetReplicationSlotXmin (TransactionId *xmin, TransactionId *catalog_xmin)
 

Function Documentation

◆ BackendPidGetProc()

PGPROC* BackendPidGetProc ( int  pid)

Definition at line 3200 of file procarray.c.

3201 {
3202  PGPROC *result;
3203 
3204  if (pid == 0) /* never match dummy PGPROCs */
3205  return NULL;
3206 
3207  LWLockAcquire(ProcArrayLock, LW_SHARED);
3208 
3209  result = BackendPidGetProcWithLock(pid);
3210 
3211  LWLockRelease(ProcArrayLock);
3212 
3213  return result;
3214 }
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1168
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1781
@ LW_SHARED
Definition: lwlock.h:115
PGPROC * BackendPidGetProcWithLock(int pid)
Definition: procarray.c:3223
Definition: proc.h:157

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

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

◆ BackendPidGetProcWithLock()

PGPROC* BackendPidGetProcWithLock ( int  pid)

Definition at line 3223 of file procarray.c.

3224 {
3225  PGPROC *result = NULL;
3226  ProcArrayStruct *arrayP = procArray;
3227  int index;
3228 
3229  if (pid == 0) /* never match dummy PGPROCs */
3230  return NULL;
3231 
3232  for (index = 0; index < arrayP->numProcs; index++)
3233  {
3234  PGPROC *proc = &allProcs[arrayP->pgprocnos[index]];
3235 
3236  if (proc->pid == pid)
3237  {
3238  result = proc;
3239  break;
3240  }
3241  }
3242 
3243  return result;
3244 }
static PGPROC * allProcs
Definition: procarray.c:271
static ProcArrayStruct * procArray
Definition: procarray.c:269
int pid
Definition: proc.h:177
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:99
Definition: type.h:95

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

Referenced by BackendPidGetProc(), and GetBlockerStatusData().

◆ BackendXidGetPid()

int BackendXidGetPid ( TransactionId  xid)

Definition at line 3260 of file procarray.c.

3261 {
3262  int result = 0;
3263  ProcArrayStruct *arrayP = procArray;
3264  TransactionId *other_xids = ProcGlobal->xids;
3265  int index;
3266 
3267  if (xid == InvalidTransactionId) /* never match invalid xid */
3268  return 0;
3269 
3270  LWLockAcquire(ProcArrayLock, LW_SHARED);
3271 
3272  for (index = 0; index < arrayP->numProcs; index++)
3273  {
3274  if (other_xids[index] == xid)
3275  {
3276  int pgprocno = arrayP->pgprocnos[index];
3277  PGPROC *proc = &allProcs[pgprocno];
3278 
3279  result = proc->pid;
3280  break;
3281  }
3282  }
3283 
3284  LWLockRelease(ProcArrayLock);
3285 
3286  return result;
3287 }
uint32 TransactionId
Definition: c.h:652
PROC_HDR * ProcGlobal
Definition: proc.c:78
TransactionId * xids
Definition: proc.h:382
#define InvalidTransactionId
Definition: transam.h:31

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

Referenced by pgrowlocks().

◆ CancelDBBackends()

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

Definition at line 3664 of file procarray.c.

3665 {
3666  ProcArrayStruct *arrayP = procArray;
3667  int index;
3668 
3669  /* tell all backends to die */
3670  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3671 
3672  for (index = 0; index < arrayP->numProcs; index++)
3673  {
3674  int pgprocno = arrayP->pgprocnos[index];
3675  PGPROC *proc = &allProcs[pgprocno];
3676 
3677  if (databaseid == InvalidOid || proc->databaseId == databaseid)
3678  {
3679  VirtualTransactionId procvxid;
3680  pid_t pid;
3681 
3682  GET_VXID_FROM_PGPROC(procvxid, *proc);
3683 
3684  proc->recoveryConflictPending = conflictPending;
3685  pid = proc->pid;
3686  if (pid != 0)
3687  {
3688  /*
3689  * Kill the pid if it's still here. If not, that's what we
3690  * wanted so ignore any errors.
3691  */
3692  (void) SendProcSignal(pid, sigmode, procvxid.procNumber);
3693  }
3694  }
3695  }
3696 
3697  LWLockRelease(ProcArrayLock);
3698 }
#define GET_VXID_FROM_PGPROC(vxid_dst, proc)
Definition: lock.h:77
@ LW_EXCLUSIVE
Definition: lwlock.h:114
#define InvalidOid
Definition: postgres_ext.h:36
int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber)
Definition: procsignal.c:257
bool recoveryConflictPending
Definition: proc.h:215
Oid databaseId
Definition: proc.h:202
ProcNumber procNumber
Definition: lock.h:61

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

Referenced by ResolveRecoveryConflictWithDatabase(), and SendRecoveryConflictWithBufferPin().

◆ CancelVirtualTransaction()

pid_t CancelVirtualTransaction ( VirtualTransactionId  vxid,
ProcSignalReason  sigmode 
)

Definition at line 3495 of file procarray.c.

3496 {
3497  return SignalVirtualTransaction(vxid, sigmode, true);
3498 }
pid_t SignalVirtualTransaction(VirtualTransactionId vxid, ProcSignalReason sigmode, bool conflictPending)
Definition: procarray.c:3501

References SignalVirtualTransaction().

Referenced by ResolveRecoveryConflictWithVirtualXIDs().

◆ CountDBBackends()

int CountDBBackends ( Oid  databaseid)

Definition at line 3603 of file procarray.c.

3604 {
3605  ProcArrayStruct *arrayP = procArray;
3606  int count = 0;
3607  int index;
3608 
3609  LWLockAcquire(ProcArrayLock, LW_SHARED);
3610 
3611  for (index = 0; index < arrayP->numProcs; index++)
3612  {
3613  int pgprocno = arrayP->pgprocnos[index];
3614  PGPROC *proc = &allProcs[pgprocno];
3615 
3616  if (proc->pid == 0)
3617  continue; /* do not count prepared xacts */
3618  if (!OidIsValid(databaseid) ||
3619  proc->databaseId == databaseid)
3620  count++;
3621  }
3622 
3623  LWLockRelease(ProcArrayLock);
3624 
3625  return count;
3626 }
#define OidIsValid(objectId)
Definition: c.h:775

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

Referenced by ResolveRecoveryConflictWithDatabase().

◆ CountDBConnections()

int CountDBConnections ( Oid  databaseid)

Definition at line 3633 of file procarray.c.

3634 {
3635  ProcArrayStruct *arrayP = procArray;
3636  int count = 0;
3637  int index;
3638 
3639  LWLockAcquire(ProcArrayLock, LW_SHARED);
3640 
3641  for (index = 0; index < arrayP->numProcs; index++)
3642  {
3643  int pgprocno = arrayP->pgprocnos[index];
3644  PGPROC *proc = &allProcs[pgprocno];
3645 
3646  if (proc->pid == 0)
3647  continue; /* do not count prepared xacts */
3648  if (proc->isBackgroundWorker)
3649  continue; /* do not count background workers */
3650  if (!OidIsValid(databaseid) ||
3651  proc->databaseId == databaseid)
3652  count++;
3653  }
3654 
3655  LWLockRelease(ProcArrayLock);
3656 
3657  return count;
3658 }
bool isBackgroundWorker
Definition: proc.h:208

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

Referenced by CheckMyDatabase().

◆ CountOtherDBBackends()

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

Definition at line 3754 of file procarray.c.

3755 {
3756  ProcArrayStruct *arrayP = procArray;
3757 
3758 #define MAXAUTOVACPIDS 10 /* max autovacs to SIGTERM per iteration */
3759  int autovac_pids[MAXAUTOVACPIDS];
3760  int tries;
3761 
3762  /* 50 tries with 100ms sleep between tries makes 5 sec total wait */
3763  for (tries = 0; tries < 50; tries++)
3764  {
3765  int nautovacs = 0;
3766  bool found = false;
3767  int index;
3768 
3770 
3771  *nbackends = *nprepared = 0;
3772 
3773  LWLockAcquire(ProcArrayLock, LW_SHARED);
3774 
3775  for (index = 0; index < arrayP->numProcs; index++)
3776  {
3777  int pgprocno = arrayP->pgprocnos[index];
3778  PGPROC *proc = &allProcs[pgprocno];
3779  uint8 statusFlags = ProcGlobal->statusFlags[index];
3780 
3781  if (proc->databaseId != databaseId)
3782  continue;
3783  if (proc == MyProc)
3784  continue;
3785 
3786  found = true;
3787 
3788  if (proc->pid == 0)
3789  (*nprepared)++;
3790  else
3791  {
3792  (*nbackends)++;
3793  if ((statusFlags & PROC_IS_AUTOVACUUM) &&
3794  nautovacs < MAXAUTOVACPIDS)
3795  autovac_pids[nautovacs++] = proc->pid;
3796  }
3797  }
3798 
3799  LWLockRelease(ProcArrayLock);
3800 
3801  if (!found)
3802  return false; /* no conflicting backends, so done */
3803 
3804  /*
3805  * Send SIGTERM to any conflicting autovacuums before sleeping. We
3806  * postpone this step until after the loop because we don't want to
3807  * hold ProcArrayLock while issuing kill(). We have no idea what might
3808  * block kill() inside the kernel...
3809  */
3810  for (index = 0; index < nautovacs; index++)
3811  (void) kill(autovac_pids[index], SIGTERM); /* ignore any error */
3812 
3813  /* sleep, then try again */
3814  pg_usleep(100 * 1000L); /* 100ms */
3815  }
3816 
3817  return true; /* timed out, still conflicts */
3818 }
unsigned char uint8
Definition: c.h:504
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:122
#define PROC_IS_AUTOVACUUM
Definition: proc.h:57
#define MAXAUTOVACPIDS
void pg_usleep(long microsec)
Definition: signal.c:53
PGPROC * MyProc
Definition: proc.c:66
uint8 * statusFlags
Definition: proc.h:394
#define kill(pid, sig)
Definition: win32_port.h:490

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

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

◆ CountUserBackends()

int CountUserBackends ( Oid  roleid)

Definition at line 3704 of file procarray.c.

3705 {
3706  ProcArrayStruct *arrayP = procArray;
3707  int count = 0;
3708  int index;
3709 
3710  LWLockAcquire(ProcArrayLock, LW_SHARED);
3711 
3712  for (index = 0; index < arrayP->numProcs; index++)
3713  {
3714  int pgprocno = arrayP->pgprocnos[index];
3715  PGPROC *proc = &allProcs[pgprocno];
3716 
3717  if (proc->pid == 0)
3718  continue; /* do not count prepared xacts */
3719  if (proc->isBackgroundWorker)
3720  continue; /* do not count background workers */
3721  if (proc->roleId == roleid)
3722  count++;
3723  }
3724 
3725  LWLockRelease(ProcArrayLock);
3726 
3727  return count;
3728 }
Oid roleId
Definition: proc.h:203

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

Referenced by InitializeSessionUserId().

◆ CreateSharedProcArray()

void CreateSharedProcArray ( void  )

Definition at line 418 of file procarray.c.

419 {
420  bool found;
421 
422  /* Create or attach to the ProcArray shared structure */
424  ShmemInitStruct("Proc Array",
425  add_size(offsetof(ProcArrayStruct, pgprocnos),
426  mul_size(sizeof(int),
428  &found);
429 
430  if (!found)
431  {
432  /*
433  * We're the first - initialize.
434  */
435  procArray->numProcs = 0;
445  }
446 
448 
449  /* Create or attach to the KnownAssignedXids arrays too, if needed */
450  if (EnableHotStandby)
451  {
453  ShmemInitStruct("KnownAssignedXids",
454  mul_size(sizeof(TransactionId),
456  &found);
457  KnownAssignedXidsValid = (bool *)
458  ShmemInitStruct("KnownAssignedXidsValid",
459  mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS),
460  &found);
461  }
462 }
#define TOTAL_MAX_CACHED_SUBXIDS
#define PROCARRAY_MAXPROCS
static TransactionId * KnownAssignedXids
Definition: procarray.c:281
static bool * KnownAssignedXidsValid
Definition: procarray.c:282
Size add_size(Size s1, Size s2)
Definition: shmem.c:493
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition: shmem.c:387
Size mul_size(Size s1, Size s2)
Definition: shmem.c:510
PGPROC * allProcs
Definition: proc.h:379
TransactionId replication_slot_xmin
Definition: procarray.c:94
int maxKnownAssignedXids
Definition: procarray.c:79
TransactionId replication_slot_catalog_xmin
Definition: procarray.c:96
int numKnownAssignedXids
Definition: procarray.c:80
TransactionId lastOverflowedXid
Definition: procarray.c:91
int tailKnownAssignedXids
Definition: procarray.c:81
int headKnownAssignedXids
Definition: procarray.c:82
uint64 xactCompletionCount
Definition: transam.h:248
TransamVariablesData * TransamVariables
Definition: varsup.c:34
bool EnableHotStandby
Definition: xlog.c:119

References add_size(), allProcs, PROC_HDR::allProcs, EnableHotStandby, ProcArrayStruct::headKnownAssignedXids, InvalidTransactionId, KnownAssignedXids, KnownAssignedXidsValid, ProcArrayStruct::lastOverflowedXid, ProcArrayStruct::maxKnownAssignedXids, ProcArrayStruct::maxProcs, mul_size(), ProcArrayStruct::numKnownAssignedXids, ProcArrayStruct::numProcs, procArray, PROCARRAY_MAXPROCS, ProcGlobal, ProcArrayStruct::replication_slot_catalog_xmin, ProcArrayStruct::replication_slot_xmin, ShmemInitStruct(), ProcArrayStruct::tailKnownAssignedXids, TOTAL_MAX_CACHED_SUBXIDS, TransamVariables, and TransamVariablesData::xactCompletionCount.

Referenced by CreateOrAttachShmemStructs().

◆ ExpireAllKnownAssignedTransactionIds()

void ExpireAllKnownAssignedTransactionIds ( void  )

Definition at line 4502 of file procarray.c.

4503 {
4504  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
4506 
4507  /*
4508  * Reset lastOverflowedXid. Currently, lastOverflowedXid has no use after
4509  * the call of this function. But do this for unification with what
4510  * ExpireOldKnownAssignedTransactionIds() do.
4511  */
4513  LWLockRelease(ProcArrayLock);
4514 }
static void KnownAssignedXidsRemovePreceding(TransactionId removeXid)
Definition: procarray.c:5015

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

Referenced by ShutdownRecoveryTransactionEnvironment().

◆ ExpireOldKnownAssignedTransactionIds()

void ExpireOldKnownAssignedTransactionIds ( TransactionId  xid)

Definition at line 4522 of file procarray.c.

4523 {
4524  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
4525 
4526  /*
4527  * Reset lastOverflowedXid if we know all transactions that have been
4528  * possibly running are being gone. Not doing so could cause an incorrect
4529  * lastOverflowedXid value, which makes extra snapshots be marked as
4530  * suboverflowed.
4531  */
4535  LWLockRelease(ProcArrayLock);
4536 }
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:280

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

Referenced by ProcArrayApplyRecoveryInfo().

◆ ExpireTreeKnownAssignedTransactionIds()

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

Definition at line 4476 of file procarray.c.

4478 {
4480 
4481  /*
4482  * Uses same locking as transaction commit
4483  */
4484  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
4485 
4486  KnownAssignedXidsRemoveTree(xid, nsubxids, subxids);
4487 
4488  /* As in ProcArrayEndTransaction, advance latestCompletedXid */
4490 
4491  /* ... and xactCompletionCount */
4493 
4494  LWLockRelease(ProcArrayLock);
4495 }
#define Assert(condition)
Definition: c.h:858
static void KnownAssignedXidsRemoveTree(TransactionId xid, int nsubxids, TransactionId *subxids)
Definition: procarray.c:4993
static void MaintainLatestCompletedXidRecovery(TransactionId latestXid)
Definition: procarray.c:989
HotStandbyState standbyState
Definition: xlogutils.c:53
@ STANDBY_INITIALIZED
Definition: xlogutils.h:53

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

Referenced by xact_redo_abort(), and xact_redo_commit().

◆ GetConflictingVirtualXIDs()

VirtualTransactionId* GetConflictingVirtualXIDs ( TransactionId  limitXmin,
Oid  dbOid 
)

Definition at line 3421 of file procarray.c.

3422 {
3423  static VirtualTransactionId *vxids;
3424  ProcArrayStruct *arrayP = procArray;
3425  int count = 0;
3426  int index;
3427 
3428  /*
3429  * If first time through, get workspace to remember main XIDs in. We
3430  * malloc it permanently to avoid repeated palloc/pfree overhead. Allow
3431  * result space, remembering room for a terminator.
3432  */
3433  if (vxids == NULL)
3434  {
3435  vxids = (VirtualTransactionId *)
3436  malloc(sizeof(VirtualTransactionId) * (arrayP->maxProcs + 1));
3437  if (vxids == NULL)
3438  ereport(ERROR,
3439  (errcode(ERRCODE_OUT_OF_MEMORY),
3440  errmsg("out of memory")));
3441  }
3442 
3443  LWLockAcquire(ProcArrayLock, LW_SHARED);
3444 
3445  for (index = 0; index < arrayP->numProcs; index++)
3446  {
3447  int pgprocno = arrayP->pgprocnos[index];
3448  PGPROC *proc = &allProcs[pgprocno];
3449 
3450  /* Exclude prepared transactions */
3451  if (proc->pid == 0)
3452  continue;
3453 
3454  if (!OidIsValid(dbOid) ||
3455  proc->databaseId == dbOid)
3456  {
3457  /* Fetch xmin just once - can't change on us, but good coding */
3458  TransactionId pxmin = UINT32_ACCESS_ONCE(proc->xmin);
3459 
3460  /*
3461  * We ignore an invalid pxmin because this means that backend has
3462  * no snapshot currently. We hold a Share lock to avoid contention
3463  * with users taking snapshots. That is not a problem because the
3464  * current xmin is always at least one higher than the latest
3465  * removed xid, so any new snapshot would never conflict with the
3466  * test here.
3467  */
3468  if (!TransactionIdIsValid(limitXmin) ||
3469  (TransactionIdIsValid(pxmin) && !TransactionIdFollows(pxmin, limitXmin)))
3470  {
3471  VirtualTransactionId vxid;
3472 
3473  GET_VXID_FROM_PGPROC(vxid, *proc);
3474  if (VirtualTransactionIdIsValid(vxid))
3475  vxids[count++] = vxid;
3476  }
3477  }
3478  }
3479 
3480  LWLockRelease(ProcArrayLock);
3481 
3482  /* add the terminator */
3483  vxids[count].procNumber = INVALID_PROC_NUMBER;
3485 
3486  return vxids;
3487 }
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
#define malloc(a)
Definition: header.h:50
#define VirtualTransactionIdIsValid(vxid)
Definition: lock.h:67
#define InvalidLocalTransactionId
Definition: lock.h:65
#define UINT32_ACCESS_ONCE(var)
Definition: procarray.c:68
#define INVALID_PROC_NUMBER
Definition: procnumber.h:26
TransactionId xmin
Definition: proc.h:172
LocalTransactionId localTransactionId
Definition: lock.h:62
bool TransactionIdFollows(TransactionId id1, TransactionId id2)
Definition: transam.c:314
#define TransactionIdIsValid(xid)
Definition: transam.h:41

References allProcs, PGPROC::databaseId, ereport, errcode(), errmsg(), ERROR, GET_VXID_FROM_PGPROC, INVALID_PROC_NUMBER, InvalidLocalTransactionId, VirtualTransactionId::localTransactionId, LW_SHARED, LWLockAcquire(), LWLockRelease(), malloc, ProcArrayStruct::maxProcs, ProcArrayStruct::numProcs, OidIsValid, ProcArrayStruct::pgprocnos, PGPROC::pid, procArray, VirtualTransactionId::procNumber, TransactionIdFollows(), TransactionIdIsValid, UINT32_ACCESS_ONCE, VirtualTransactionIdIsValid, and PGPROC::xmin.

Referenced by ResolveRecoveryConflictWithSnapshot(), and ResolveRecoveryConflictWithTablespace().

◆ GetCurrentVirtualXIDs()

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

Definition at line 3328 of file procarray.c.

3331 {
3332  VirtualTransactionId *vxids;
3333  ProcArrayStruct *arrayP = procArray;
3334  int count = 0;
3335  int index;
3336 
3337  /* allocate what's certainly enough result space */
3338  vxids = (VirtualTransactionId *)
3339  palloc(sizeof(VirtualTransactionId) * arrayP->maxProcs);
3340 
3341  LWLockAcquire(ProcArrayLock, LW_SHARED);
3342 
3343  for (index = 0; index < arrayP->numProcs; index++)
3344  {
3345  int pgprocno = arrayP->pgprocnos[index];
3346  PGPROC *proc = &allProcs[pgprocno];
3347  uint8 statusFlags = ProcGlobal->statusFlags[index];
3348 
3349  if (proc == MyProc)
3350  continue;
3351 
3352  if (excludeVacuum & statusFlags)
3353  continue;
3354 
3355  if (allDbs || proc->databaseId == MyDatabaseId)
3356  {
3357  /* Fetch xmin just once - might change on us */
3358  TransactionId pxmin = UINT32_ACCESS_ONCE(proc->xmin);
3359 
3360  if (excludeXmin0 && !TransactionIdIsValid(pxmin))
3361  continue;
3362 
3363  /*
3364  * InvalidTransactionId precedes all other XIDs, so a proc that
3365  * hasn't set xmin yet will not be rejected by this test.
3366  */
3367  if (!TransactionIdIsValid(limitXmin) ||
3368  TransactionIdPrecedesOrEquals(pxmin, limitXmin))
3369  {
3370  VirtualTransactionId vxid;
3371 
3372  GET_VXID_FROM_PGPROC(vxid, *proc);
3373  if (VirtualTransactionIdIsValid(vxid))
3374  vxids[count++] = vxid;
3375  }
3376  }
3377  }
3378 
3379  LWLockRelease(ProcArrayLock);
3380 
3381  *nvxids = count;
3382  return vxids;
3383 }
Oid MyDatabaseId
Definition: globals.c:92
void * palloc(Size size)
Definition: mcxt.c:1317
bool TransactionIdPrecedesOrEquals(TransactionId id1, TransactionId id2)
Definition: transam.c:299

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

Referenced by WaitForOlderSnapshots().

◆ GetMaxSnapshotSubxidCount()

int GetMaxSnapshotSubxidCount ( void  )

Definition at line 2080 of file procarray.c.

2081 {
2082  return TOTAL_MAX_CACHED_SUBXIDS;
2083 }

References TOTAL_MAX_CACHED_SUBXIDS.

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

◆ GetMaxSnapshotXidCount()

int GetMaxSnapshotXidCount ( void  )

Definition at line 2069 of file procarray.c.

2070 {
2071  return procArray->maxProcs;
2072 }

References ProcArrayStruct::maxProcs, and procArray.

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

◆ GetOldestActiveTransactionId()

TransactionId GetOldestActiveTransactionId ( void  )

Definition at line 2884 of file procarray.c.

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

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

Referenced by CreateCheckPoint().

◆ GetOldestNonRemovableTransactionId()

TransactionId GetOldestNonRemovableTransactionId ( Relation  rel)

Definition at line 2005 of file procarray.c.

2006 {
2007  ComputeXidHorizonsResult horizons;
2008 
2009  ComputeXidHorizons(&horizons);
2010 
2011  switch (GlobalVisHorizonKindForRel(rel))
2012  {
2013  case VISHORIZON_SHARED:
2014  return horizons.shared_oldest_nonremovable;
2015  case VISHORIZON_CATALOG:
2016  return horizons.catalog_oldest_nonremovable;
2017  case VISHORIZON_DATA:
2018  return horizons.data_oldest_nonremovable;
2019  case VISHORIZON_TEMP:
2020  return horizons.temp_oldest_nonremovable;
2021  }
2022 
2023  /* just to prevent compiler warnings */
2024  return InvalidTransactionId;
2025 }
static void ComputeXidHorizons(ComputeXidHorizonsResult *h)
Definition: procarray.c:1735
@ VISHORIZON_SHARED
Definition: procarray.c:251
@ VISHORIZON_DATA
Definition: procarray.c:253
@ VISHORIZON_CATALOG
Definition: procarray.c:252
@ VISHORIZON_TEMP
Definition: procarray.c:254
static GlobalVisHorizonKind GlobalVisHorizonKindForRel(Relation rel)
Definition: procarray.c:1971
TransactionId data_oldest_nonremovable
Definition: procarray.c:237
TransactionId temp_oldest_nonremovable
Definition: procarray.c:243
TransactionId shared_oldest_nonremovable
Definition: procarray.c:214
TransactionId catalog_oldest_nonremovable
Definition: procarray.c:231

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

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

◆ GetOldestSafeDecodingTransactionId()

TransactionId GetOldestSafeDecodingTransactionId ( bool  catalogOnly)

Definition at line 2949 of file procarray.c.

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

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

Referenced by CreateInitDecodingContext(), SnapBuildInitialSnapshot(), and synchronize_one_slot().

◆ GetOldestTransactionIdConsideredRunning()

TransactionId GetOldestTransactionIdConsideredRunning ( void  )

Definition at line 2034 of file procarray.c.

2035 {
2036  ComputeXidHorizonsResult horizons;
2037 
2038  ComputeXidHorizons(&horizons);
2039 
2040  return horizons.oldest_considered_running;
2041 }
TransactionId oldest_considered_running
Definition: procarray.c:205

References ComputeXidHorizons(), and ComputeXidHorizonsResult::oldest_considered_running.

Referenced by CreateCheckPoint(), and CreateRestartPoint().

◆ GetReplicationHorizons()

void GetReplicationHorizons ( TransactionId xmin,
TransactionId catalog_xmin 
)

Definition at line 2047 of file procarray.c.

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

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

Referenced by XLogWalRcvSendHSFeedback().

◆ GetRunningTransactionData()

RunningTransactions GetRunningTransactionData ( void  )

Definition at line 2693 of file procarray.c.

2694 {
2695  /* result workspace */
2696  static RunningTransactionsData CurrentRunningXactsData;
2697 
2698  ProcArrayStruct *arrayP = procArray;
2699  TransactionId *other_xids = ProcGlobal->xids;
2700  RunningTransactions CurrentRunningXacts = &CurrentRunningXactsData;
2701  TransactionId latestCompletedXid;
2702  TransactionId oldestRunningXid;
2703  TransactionId oldestDatabaseRunningXid;
2704  TransactionId *xids;
2705  int index;
2706  int count;
2707  int subcount;
2708  bool suboverflowed;
2709 
2711 
2712  /*
2713  * Allocating space for maxProcs xids is usually overkill; numProcs would
2714  * be sufficient. But it seems better to do the malloc while not holding
2715  * the lock, so we can't look at numProcs. Likewise, we allocate much
2716  * more subxip storage than is probably needed.
2717  *
2718  * Should only be allocated in bgwriter, since only ever executed during
2719  * checkpoints.
2720  */
2721  if (CurrentRunningXacts->xids == NULL)
2722  {
2723  /*
2724  * First call
2725  */
2726  CurrentRunningXacts->xids = (TransactionId *)
2728  if (CurrentRunningXacts->xids == NULL)
2729  ereport(ERROR,
2730  (errcode(ERRCODE_OUT_OF_MEMORY),
2731  errmsg("out of memory")));
2732  }
2733 
2734  xids = CurrentRunningXacts->xids;
2735 
2736  count = subcount = 0;
2737  suboverflowed = false;
2738 
2739  /*
2740  * Ensure that no xids enter or leave the procarray while we obtain
2741  * snapshot.
2742  */
2743  LWLockAcquire(ProcArrayLock, LW_SHARED);
2744  LWLockAcquire(XidGenLock, LW_SHARED);
2745 
2746  latestCompletedXid =
2748  oldestDatabaseRunningXid = oldestRunningXid =
2750 
2751  /*
2752  * Spin over procArray collecting all xids
2753  */
2754  for (index = 0; index < arrayP->numProcs; index++)
2755  {
2756  TransactionId xid;
2757 
2758  /* Fetch xid just once - see GetNewTransactionId */
2759  xid = UINT32_ACCESS_ONCE(other_xids[index]);
2760 
2761  /*
2762  * We don't need to store transactions that don't have a TransactionId
2763  * yet because they will not show as running on a standby server.
2764  */
2765  if (!TransactionIdIsValid(xid))
2766  continue;
2767 
2768  /*
2769  * Be careful not to exclude any xids before calculating the values of
2770  * oldestRunningXid and suboverflowed, since these are used to clean
2771  * up transaction information held on standbys.
2772  */
2773  if (TransactionIdPrecedes(xid, oldestRunningXid))
2774  oldestRunningXid = xid;
2775 
2776  /*
2777  * Also, update the oldest running xid within the current database. As
2778  * fetching pgprocno and PGPROC could cause cache misses, we do cheap
2779  * TransactionId comparison first.
2780  */
2781  if (TransactionIdPrecedes(xid, oldestDatabaseRunningXid))
2782  {
2783  int pgprocno = arrayP->pgprocnos[index];
2784  PGPROC *proc = &allProcs[pgprocno];
2785 
2786  if (proc->databaseId == MyDatabaseId)
2787  oldestDatabaseRunningXid = xid;
2788  }
2789 
2791  suboverflowed = true;
2792 
2793  /*
2794  * If we wished to exclude xids this would be the right place for it.
2795  * Procs with the PROC_IN_VACUUM flag set don't usually assign xids,
2796  * but they do during truncation at the end when they get the lock and
2797  * truncate, so it is not much of a problem to include them if they
2798  * are seen and it is cleaner to include them.
2799  */
2800 
2801  xids[count++] = xid;
2802  }
2803 
2804  /*
2805  * Spin over procArray collecting all subxids, but only if there hasn't
2806  * been a suboverflow.
2807  */
2808  if (!suboverflowed)
2809  {
2810  XidCacheStatus *other_subxidstates = ProcGlobal->subxidStates;
2811 
2812  for (index = 0; index < arrayP->numProcs; index++)
2813  {
2814  int pgprocno = arrayP->pgprocnos[index];
2815  PGPROC *proc = &allProcs[pgprocno];
2816  int nsubxids;
2817 
2818  /*
2819  * Save subtransaction XIDs. Other backends can't add or remove
2820  * entries while we're holding XidGenLock.
2821  */
2822  nsubxids = other_subxidstates[index].count;
2823  if (nsubxids > 0)
2824  {
2825  /* barrier not really required, as XidGenLock is held, but ... */
2826  pg_read_barrier(); /* pairs with GetNewTransactionId */
2827 
2828  memcpy(&xids[count], proc->subxids.xids,
2829  nsubxids * sizeof(TransactionId));
2830  count += nsubxids;
2831  subcount += nsubxids;
2832 
2833  /*
2834  * Top-level XID of a transaction is always less than any of
2835  * its subxids, so we don't need to check if any of the
2836  * subxids are smaller than oldestRunningXid
2837  */
2838  }
2839  }
2840  }
2841 
2842  /*
2843  * It's important *not* to include the limits set by slots here because
2844  * snapbuild.c uses oldestRunningXid to manage its xmin horizon. If those
2845  * were to be included here the initial value could never increase because
2846  * of a circular dependency where slots only increase their limits when
2847  * running xacts increases oldestRunningXid and running xacts only
2848  * increases if slots do.
2849  */
2850 
2851  CurrentRunningXacts->xcnt = count - subcount;
2852  CurrentRunningXacts->subxcnt = subcount;
2853  CurrentRunningXacts->subxid_status = suboverflowed ? SUBXIDS_IN_SUBTRANS : SUBXIDS_IN_ARRAY;
2854  CurrentRunningXacts->nextXid = XidFromFullTransactionId(TransamVariables->nextXid);
2855  CurrentRunningXacts->oldestRunningXid = oldestRunningXid;
2856  CurrentRunningXacts->oldestDatabaseRunningXid = oldestDatabaseRunningXid;
2857  CurrentRunningXacts->latestCompletedXid = latestCompletedXid;
2858 
2859  Assert(TransactionIdIsValid(CurrentRunningXacts->nextXid));
2860  Assert(TransactionIdIsValid(CurrentRunningXacts->oldestRunningXid));
2861  Assert(TransactionIdIsNormal(CurrentRunningXacts->latestCompletedXid));
2862 
2863  /* We don't release the locks here, the caller is responsible for that */
2864 
2865  return CurrentRunningXacts;
2866 }
#define pg_read_barrier()
Definition: atomics.h:149
@ SUBXIDS_IN_SUBTRANS
Definition: standby.h:82
@ SUBXIDS_IN_ARRAY
Definition: standby.h:80
struct XidCache subxids
Definition: proc.h:260
XidCacheStatus * subxidStates
Definition: proc.h:388
TransactionId oldestRunningXid
Definition: standby.h:92
TransactionId nextXid
Definition: standby.h:91
TransactionId oldestDatabaseRunningXid
Definition: standby.h:93
TransactionId latestCompletedXid
Definition: standby.h:95
subxids_array_status subxid_status
Definition: standby.h:90
TransactionId * xids
Definition: standby.h:97
FullTransactionId latestCompletedXid
Definition: transam.h:238
bool overflowed
Definition: proc.h:46
uint8 count
Definition: proc.h:44
TransactionId xids[PGPROC_MAX_CACHED_SUBXIDS]
Definition: proc.h:51

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

Referenced by GetStrictOldestNonRemovableTransactionId(), and LogStandbySnapshot().

◆ GetSnapshotData()

Snapshot GetSnapshotData ( Snapshot  snapshot)

Definition at line 2177 of file procarray.c.

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

References SnapshotData::active_count, allProcs, Assert, SnapshotData::copied, XidCacheStatus::count, SnapshotData::curcid, GlobalVisState::definitely_needed, ereport, errcode(), errmsg(), ERROR, FullTransactionIdAdvance(), FullTransactionIdNewer(), FullXidRelativeTo(), GetCurrentCommandId(), GetMaxSnapshotSubxidCount(), GetMaxSnapshotXidCount(), GetSnapshotDataReuse(), GlobalVisCatalogRels, GlobalVisDataRels, GlobalVisSharedRels, GlobalVisTempRels, InvalidTransactionId, InvalidXLogRecPtr, KnownAssignedXidsGetAndSetXmin(), ProcArrayStruct::lastOverflowedXid, TransamVariablesData::latestCompletedXid, likely, SnapshotData::lsn, LW_SHARED, LWLockAcquire(), LWLockRelease(), malloc, GlobalVisState::maybe_needed, MyProc, NormalTransactionIdPrecedes, ProcArrayStruct::numProcs, TransamVariablesData::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, SnapshotData::snapXactCompletionCount, PROC_HDR::statusFlags, SnapshotData::suboverflowed, SnapshotData::subxcnt, PGPROC::subxids, PROC_HDR::subxidStates, SnapshotData::subxip, SnapshotData::takenDuringRecovery, TransactionIdAdvance, TransactionIdIsNormal, TransactionIdIsValid, TransactionIdOlder(), TransactionIdPrecedesOrEquals(), TransactionXmin, TransamVariables, UINT32_ACCESS_ONCE, SnapshotData::whenTaken, TransamVariablesData::xactCompletionCount, SnapshotData::xcnt, PGPROC::xid, XidFromFullTransactionId, XidCache::xids, PROC_HDR::xids, SnapshotData::xip, SnapshotData::xmax, PGPROC::xmin, and SnapshotData::xmin.

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

◆ GetVirtualXIDsDelayingChkpt()

VirtualTransactionId* GetVirtualXIDsDelayingChkpt ( int *  nvxids,
int  type 
)

Definition at line 3047 of file procarray.c.

3048 {
3049  VirtualTransactionId *vxids;
3050  ProcArrayStruct *arrayP = procArray;
3051  int count = 0;
3052  int index;
3053 
3054  Assert(type != 0);
3055 
3056  /* allocate what's certainly enough result space */
3057  vxids = (VirtualTransactionId *)
3058  palloc(sizeof(VirtualTransactionId) * arrayP->maxProcs);
3059 
3060  LWLockAcquire(ProcArrayLock, LW_SHARED);
3061 
3062  for (index = 0; index < arrayP->numProcs; index++)
3063  {
3064  int pgprocno = arrayP->pgprocnos[index];
3065  PGPROC *proc = &allProcs[pgprocno];
3066 
3067  if ((proc->delayChkptFlags & type) != 0)
3068  {
3069  VirtualTransactionId vxid;
3070 
3071  GET_VXID_FROM_PGPROC(vxid, *proc);
3072  if (VirtualTransactionIdIsValid(vxid))
3073  vxids[count++] = vxid;
3074  }
3075  }
3076 
3077  LWLockRelease(ProcArrayLock);
3078 
3079  *nvxids = count;
3080  return vxids;
3081 }
int delayChkptFlags
Definition: proc.h:235
const char * type

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

Referenced by CreateCheckPoint().

◆ HaveVirtualXIDsDelayingChkpt()

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

Definition at line 3093 of file procarray.c.

3094 {
3095  bool result = false;
3096  ProcArrayStruct *arrayP = procArray;
3097  int index;
3098 
3099  Assert(type != 0);
3100 
3101  LWLockAcquire(ProcArrayLock, LW_SHARED);
3102 
3103  for (index = 0; index < arrayP->numProcs; index++)
3104  {
3105  int pgprocno = arrayP->pgprocnos[index];
3106  PGPROC *proc = &allProcs[pgprocno];
3107  VirtualTransactionId vxid;
3108 
3109  GET_VXID_FROM_PGPROC(vxid, *proc);
3110 
3111  if ((proc->delayChkptFlags & type) != 0 &&
3113  {
3114  int i;
3115 
3116  for (i = 0; i < nvxids; i++)
3117  {
3118  if (VirtualTransactionIdEquals(vxid, vxids[i]))
3119  {
3120  result = true;
3121  break;
3122  }
3123  }
3124  if (result)
3125  break;
3126  }
3127  }
3128 
3129  LWLockRelease(ProcArrayLock);
3130 
3131  return result;
3132 }
int i
Definition: isn.c:73
#define VirtualTransactionIdEquals(vxid1, vxid2)
Definition: lock.h:71

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

Referenced by CreateCheckPoint().

◆ IsBackendPid()

bool IsBackendPid ( int  pid)

Definition at line 3295 of file procarray.c.

3296 {
3297  return (BackendPidGetProc(pid) != NULL);
3298 }
PGPROC * BackendPidGetProc(int pid)
Definition: procarray.c:3200

References BackendPidGetProc().

Referenced by pg_stat_get_subscription().

◆ KnownAssignedTransactionIdsIdleMaintenance()

void KnownAssignedTransactionIdsIdleMaintenance ( void  )

Definition at line 4544 of file procarray.c.

4545 {
4547 }
@ KAX_STARTUP_PROCESS_IDLE
Definition: procarray.c:265
static void KnownAssignedXidsCompress(KAXCompressReason reason, bool haveLock)
Definition: procarray.c:4645

References KAX_STARTUP_PROCESS_IDLE, and KnownAssignedXidsCompress().

Referenced by WaitForWALToBecomeAvailable().

◆ MinimumActiveBackends()

bool MinimumActiveBackends ( int  min)

Definition at line 3550 of file procarray.c.

3551 {
3552  ProcArrayStruct *arrayP = procArray;
3553  int count = 0;
3554  int index;
3555 
3556  /* Quick short-circuit if no minimum is specified */
3557  if (min == 0)
3558  return true;
3559 
3560  /*
3561  * Note: for speed, we don't acquire ProcArrayLock. This is a little bit
3562  * bogus, but since we are only testing fields for zero or nonzero, it
3563  * should be OK. The result is only used for heuristic purposes anyway...
3564  */
3565  for (index = 0; index < arrayP->numProcs; index++)
3566  {
3567  int pgprocno = arrayP->pgprocnos[index];
3568  PGPROC *proc = &allProcs[pgprocno];
3569 
3570  /*
3571  * Since we're not holding a lock, need to be prepared to deal with
3572  * garbage, as someone could have incremented numProcs but not yet
3573  * filled the structure.
3574  *
3575  * If someone just decremented numProcs, 'proc' could also point to a
3576  * PGPROC entry that's no longer in the array. It still points to a
3577  * PGPROC struct, though, because freed PGPROC entries just go to the
3578  * free list and are recycled. Its contents are nonsense in that case,
3579  * but that's acceptable for this function.
3580  */
3581  if (pgprocno == -1)
3582  continue; /* do not count deleted entries */
3583  if (proc == MyProc)
3584  continue; /* do not count myself */
3585  if (proc->xid == InvalidTransactionId)
3586  continue; /* do not count if no XID assigned */
3587  if (proc->pid == 0)
3588  continue; /* do not count prepared xacts */
3589  if (proc->waitLock != NULL)
3590  continue; /* do not count if blocked on a lock */
3591  count++;
3592  if (count >= min)
3593  break;
3594  }
3595 
3596  return count >= min;
3597 }
LOCK * waitLock
Definition: proc.h:227

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

Referenced by XLogFlush().

◆ ProcArrayAdd()

void ProcArrayAdd ( PGPROC proc)

Definition at line 468 of file procarray.c.

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

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

Referenced by InitProcessPhase2(), and MarkAsPrepared().

◆ ProcArrayApplyRecoveryInfo()

void ProcArrayApplyRecoveryInfo ( RunningTransactions  running)

Definition at line 1054 of file procarray.c.

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

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(), TransamVariablesData::nextXid, RunningTransactionsData::nextXid, ProcArrayStruct::numKnownAssignedXids, RunningTransactionsData::oldestRunningXid, palloc(), pfree(), procArray, qsort, STANDBY_INITIALIZED, STANDBY_SNAPSHOT_PENDING, STANDBY_SNAPSHOT_READY, StandbyReleaseOldLocks(), standbySnapshotPendingXmin, standbyState, RunningTransactionsData::subxcnt, RunningTransactionsData::subxid_status, SUBXIDS_IN_ARRAY, SUBXIDS_IN_SUBTRANS, SUBXIDS_MISSING, TransactionIdAdvance, TransactionIdDidAbort(), TransactionIdDidCommit(), TransactionIdEquals, TransactionIdIsNormal, TransactionIdIsValid, TransactionIdPrecedes(), TransactionIdRetreat, TransamVariables, RunningTransactionsData::xcnt, xidLogicalComparator(), and RunningTransactionsData::xids.

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

◆ ProcArrayApplyXidAssignment()

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

Definition at line 1318 of file procarray.c.

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

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

Referenced by xact_redo().

◆ ProcArrayClearTransaction()

void ProcArrayClearTransaction ( PGPROC proc)

Definition at line 907 of file procarray.c.

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

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

Referenced by PrepareTransaction().

◆ ProcArrayEndTransaction()

void ProcArrayEndTransaction ( PGPROC proc,
TransactionId  latestXid 
)

Definition at line 667 of file procarray.c.

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

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

Referenced by AbortTransaction(), and CommitTransaction().

◆ ProcArrayGetReplicationSlotXmin()

void ProcArrayGetReplicationSlotXmin ( TransactionId xmin,
TransactionId catalog_xmin 
)

Definition at line 3972 of file procarray.c.

3974 {
3975  LWLockAcquire(ProcArrayLock, LW_SHARED);
3976 
3977  if (xmin != NULL)
3979 
3980  if (catalog_xmin != NULL)
3981  *catalog_xmin = procArray->replication_slot_catalog_xmin;
3982 
3983  LWLockRelease(ProcArrayLock);
3984 }

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

Referenced by logical_begin_heap_rewrite().

◆ ProcArrayInitRecovery()

void ProcArrayInitRecovery ( TransactionId  initializedUptoXID)

Definition at line 1023 of file procarray.c.

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

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

Referenced by StartupXLOG().

◆ ProcArrayInstallImportedXmin()

bool ProcArrayInstallImportedXmin ( TransactionId  xmin,
VirtualTransactionId sourcevxid 
)

Definition at line 2536 of file procarray.c.

2538 {
2539  bool result = false;
2540  ProcArrayStruct *arrayP = procArray;
2541  int index;
2542 
2544  if (!sourcevxid)
2545  return false;
2546 
2547  /* Get lock so source xact can't end while we're doing this */
2548  LWLockAcquire(ProcArrayLock, LW_SHARED);
2549 
2550  /*
2551  * Find the PGPROC entry of the source transaction. (This could use
2552  * GetPGProcByNumber(), unless it's a prepared xact. But this isn't
2553  * performance critical.)
2554  */
2555  for (index = 0; index < arrayP->numProcs; index++)
2556  {
2557  int pgprocno = arrayP->pgprocnos[index];
2558  PGPROC *proc = &allProcs[pgprocno];
2559  int statusFlags = ProcGlobal->statusFlags[index];
2560  TransactionId xid;
2561 
2562  /* Ignore procs running LAZY VACUUM */
2563  if (statusFlags & PROC_IN_VACUUM)
2564  continue;
2565 
2566  /* We are only interested in the specific virtual transaction. */
2567  if (proc->vxid.procNumber != sourcevxid->procNumber)
2568  continue;
2569  if (proc->vxid.lxid != sourcevxid->localTransactionId)
2570  continue;
2571 
2572  /*
2573  * We check the transaction's database ID for paranoia's sake: if it's
2574  * in another DB then its xmin does not cover us. Caller should have
2575  * detected this already, so we just treat any funny cases as
2576  * "transaction not found".
2577  */
2578  if (proc->databaseId != MyDatabaseId)
2579  continue;
2580 
2581  /*
2582  * Likewise, let's just make real sure its xmin does cover us.
2583  */
2584  xid = UINT32_ACCESS_ONCE(proc->xmin);
2585  if (!TransactionIdIsNormal(xid) ||
2586  !TransactionIdPrecedesOrEquals(xid, xmin))
2587  continue;
2588 
2589  /*
2590  * We're good. Install the new xmin. As in GetSnapshotData, set
2591  * TransactionXmin too. (Note that because snapmgr.c called
2592  * GetSnapshotData first, we'll be overwriting a valid xmin here, so
2593  * we don't check that.)
2594  */
2595  MyProc->xmin = TransactionXmin = xmin;
2596 
2597  result = true;
2598  break;
2599  }
2600 
2601  LWLockRelease(ProcArrayLock);
2602 
2603  return result;
2604 }
ProcNumber procNumber
Definition: proc.h:190

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

Referenced by GetSerializableTransactionSnapshotInt(), and SetTransactionSnapshot().

◆ ProcArrayInstallRestoredXmin()

bool ProcArrayInstallRestoredXmin ( TransactionId  xmin,
PGPROC proc 
)

Definition at line 2620 of file procarray.c.

2621 {
2622  bool result = false;
2623  TransactionId xid;
2624 
2626  Assert(proc != NULL);
2627 
2628  /*
2629  * Get an exclusive lock so that we can copy statusFlags from source proc.
2630  */
2631  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
2632 
2633  /*
2634  * Be certain that the referenced PGPROC has an advertised xmin which is
2635  * no later than the one we're installing, so that the system-wide xmin
2636  * can't go backwards. Also, make sure it's running in the same database,
2637  * so that the per-database xmin cannot go backwards.
2638  */
2639  xid = UINT32_ACCESS_ONCE(proc->xmin);
2640  if (proc->databaseId == MyDatabaseId &&
2641  TransactionIdIsNormal(xid) &&
2642  TransactionIdPrecedesOrEquals(xid, xmin))
2643  {
2644  /*
2645  * Install xmin and propagate the statusFlags that affect how the
2646  * value is interpreted by vacuum.
2647  */
2648  MyProc->xmin = TransactionXmin = xmin;
2650  (proc->statusFlags & PROC_XMIN_FLAGS);
2652 
2653  result = true;
2654  }
2655 
2656  LWLockRelease(ProcArrayLock);
2657 
2658  return result;
2659 }
#define PROC_XMIN_FLAGS
Definition: proc.h:72

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

Referenced by SetTransactionSnapshot().

◆ ProcArrayRemove()

void ProcArrayRemove ( PGPROC proc,
TransactionId  latestXid 
)

Definition at line 565 of file procarray.c.

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

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

Referenced by FinishPreparedTransaction(), and RemoveProcFromArray().

◆ ProcArraySetReplicationSlotXmin()

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

Definition at line 3947 of file procarray.c.

3949 {
3950  Assert(!already_locked || LWLockHeldByMe(ProcArrayLock));
3951 
3952  if (!already_locked)
3953  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3954 
3956  procArray->replication_slot_catalog_xmin = catalog_xmin;
3957 
3958  if (!already_locked)
3959  LWLockRelease(ProcArrayLock);
3960 
3961  elog(DEBUG1, "xmin required by slots: data %u, catalog %u",
3962  xmin, catalog_xmin);
3963 }

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

Referenced by ReplicationSlotsComputeRequiredXmin().

◆ ProcArrayShmemSize()

Size ProcArrayShmemSize ( void  )

Definition at line 376 of file procarray.c.

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

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

Referenced by CalculateShmemSize().

◆ ProcNumberGetProc()

PGPROC* ProcNumberGetProc ( int  procNumber)

Definition at line 3142 of file procarray.c.

3143 {
3144  PGPROC *result;
3145 
3146  if (procNumber < 0 || procNumber >= ProcGlobal->allProcCount)
3147  return NULL;
3148  result = GetPGProcByNumber(procNumber);
3149 
3150  if (result->pid == 0)
3151  return NULL;
3152 
3153  return result;
3154 }
#define GetPGProcByNumber(n)
Definition: proc.h:427
uint32 allProcCount
Definition: proc.h:397

References PROC_HDR::allProcCount, GetPGProcByNumber, PGPROC::pid, and ProcGlobal.

Referenced by checkTempNamespaceStatus(), LogRecoveryConflict(), VirtualXactLock(), WaitForLockersMultiple(), and WaitForOlderSnapshots().

◆ ProcNumberGetTransactionIds()

void ProcNumberGetTransactionIds ( int  procNumber,
TransactionId xid,
TransactionId xmin,
int *  nsubxid,
bool overflowed 
)

Definition at line 3164 of file procarray.c.

3166 {
3167  PGPROC *proc;
3168 
3169  *xid = InvalidTransactionId;
3170  *xmin = InvalidTransactionId;
3171  *nsubxid = 0;
3172  *overflowed = false;
3173 
3174  if (procNumber < 0 || procNumber >= ProcGlobal->allProcCount)
3175  return;
3176  proc = GetPGProcByNumber(procNumber);
3177 
3178  /* Need to lock out additions/removals of backends */
3179  LWLockAcquire(ProcArrayLock, LW_SHARED);
3180 
3181  if (proc->pid != 0)
3182  {
3183  *xid = proc->xid;
3184  *xmin = proc->xmin;
3185  *nsubxid = proc->subxidStatus.count;
3186  *overflowed = proc->subxidStatus.overflowed;
3187  }
3188 
3189  LWLockRelease(ProcArrayLock);
3190 }

References PROC_HDR::allProcCount, XidCacheStatus::count, GetPGProcByNumber, InvalidTransactionId, LW_SHARED, LWLockAcquire(), LWLockRelease(), XidCacheStatus::overflowed, PGPROC::pid, ProcGlobal, PGPROC::subxidStatus, PGPROC::xid, and PGPROC::xmin.

Referenced by pgstat_read_current_status().

◆ RecordKnownAssignedTransactionIds()

void RecordKnownAssignedTransactionIds ( TransactionId  xid)

Definition at line 4407 of file procarray.c.

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

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

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

◆ SignalVirtualTransaction()

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

Definition at line 3501 of file procarray.c.

3503 {
3504  ProcArrayStruct *arrayP = procArray;
3505  int index;
3506  pid_t pid = 0;
3507 
3508  LWLockAcquire(ProcArrayLock, LW_SHARED);
3509 
3510  for (index = 0; index < arrayP->numProcs; index++)
3511  {
3512  int pgprocno = arrayP->pgprocnos[index];
3513  PGPROC *proc = &allProcs[pgprocno];
3514  VirtualTransactionId procvxid;
3515 
3516  GET_VXID_FROM_PGPROC(procvxid, *proc);
3517 
3518  if (procvxid.procNumber == vxid.procNumber &&
3519  procvxid.localTransactionId == vxid.localTransactionId)
3520  {
3521  proc->recoveryConflictPending = conflictPending;
3522  pid = proc->pid;
3523  if (pid != 0)
3524  {
3525  /*
3526  * Kill the pid if it's still here. If not, that's what we
3527  * wanted so ignore any errors.
3528  */
3529  (void) SendProcSignal(pid, sigmode, vxid.procNumber);
3530  }
3531  break;
3532  }
3533  }
3534 
3535  LWLockRelease(ProcArrayLock);
3536 
3537  return pid;
3538 }

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

Referenced by CancelVirtualTransaction(), and ResolveRecoveryConflictWithLock().

◆ TerminateOtherDBBackends()

void TerminateOtherDBBackends ( Oid  databaseId)

Definition at line 3832 of file procarray.c.

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

References allProcs, BackendPidGetProc(), PGPROC::databaseId, ereport, errcode(), errdetail(), errdetail_plural(), errmsg(), ERROR, get_database_name(), GetUserId(), has_privs_of_role(), i, kill, lappend_int(), lfirst_int, LW_SHARED, LWLockAcquire(), LWLockRelease(), MyProc, NIL, ProcArrayStruct::numProcs, ProcArrayStruct::pgprocnos, PGPROC::pid, procArray, PGPROC::roleId, superuser(), and superuser_arg().

Referenced by dropdb().

◆ TransactionIdIsActive()

bool TransactionIdIsActive ( TransactionId  xid)

Definition at line 1634 of file procarray.c.

1635 {
1636  bool result = false;
1637  ProcArrayStruct *arrayP = procArray;
1638  TransactionId *other_xids = ProcGlobal->xids;
1639  int i;
1640 
1641  /*
1642  * Don't bother checking a transaction older than RecentXmin; it could not
1643  * possibly still be running.
1644  */
1646  return false;
1647 
1648  LWLockAcquire(ProcArrayLock, LW_SHARED);
1649 
1650  for (i = 0; i < arrayP->numProcs; i++)
1651  {
1652  int pgprocno = arrayP->pgprocnos[i];
1653  PGPROC *proc = &allProcs[pgprocno];
1654  TransactionId pxid;
1655 
1656  /* Fetch xid just once - see GetNewTransactionId */
1657  pxid = UINT32_ACCESS_ONCE(other_xids[i]);
1658 
1659  if (!TransactionIdIsValid(pxid))
1660  continue;
1661 
1662  if (proc->pid == 0)
1663  continue; /* ignore prepared transactions */
1664 
1665  if (TransactionIdEquals(pxid, xid))
1666  {
1667  result = true;
1668  break;
1669  }
1670  }
1671 
1672  LWLockRelease(ProcArrayLock);
1673 
1674  return result;
1675 }

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

◆ TransactionIdIsInProgress()

bool TransactionIdIsInProgress ( TransactionId  xid)

Definition at line 1402 of file procarray.c.

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

References allProcs, Assert, cachedXidIsNotInProgress, XidCacheStatus::count, ereport, errcode(), errmsg(), ERROR, j, KnownAssignedXidExists(), KnownAssignedXidsGet(), ProcArrayStruct::lastOverflowedXid, TransamVariablesData::latestCompletedXid, LW_SHARED, LWLockAcquire(), LWLockRelease(), malloc, ProcArrayStruct::maxProcs, MyProc, ProcArrayStruct::numProcs, pg_lfind32(), pg_read_barrier, ProcArrayStruct::pgprocnos, PGPROC::pgxactoff, procArray, ProcGlobal, RecentXmin, RecoveryInProgress(), SubTransGetTopmostTransaction(), PGPROC::subxids, PROC_HDR::subxidStates, TOTAL_MAX_CACHED_SUBXIDS, TransactionIdDidAbort(), TransactionIdEquals, TransactionIdIsCurrentTransactionId(), TransactionIdIsValid, TransactionIdPrecedes(), TransactionIdPrecedesOrEquals(), TransamVariables, UINT32_ACCESS_ONCE, xc_by_child_xid_inc, xc_by_known_assigned_inc, xc_by_known_xact_inc, xc_by_latest_xid_inc, xc_by_main_xid_inc, xc_by_my_xact_inc, xc_by_recent_xmin_inc, xc_no_overflow_inc, xc_slow_answer_inc, XidFromFullTransactionId, XidCache::xids, and PROC_HDR::xids.

Referenced by check_safe_enum_use(), compute_new_xmax_infomask(), ConditionalXactLockTableWait(), Do_MultiXactIdWait(), DoesMultiXactIdConflict(), FreezeMultiXactId(), HandleConcurrentAbort(), HeapTupleHeaderIsOnlyLocked(), HeapTupleSatisfiesDirty(), HeapTupleSatisfiesSelf(), HeapTupleSatisfiesToast(), HeapTupleSatisfiesUpdate(), HeapTupleSatisfiesVacuumHorizon(), MultiXactIdExpand(), MultiXactIdIsRunning(), pg_xact_status(), test_lockmode_for_conflict(), verify_heapam(), and XactLockTableWait().

◆ XidCacheRemoveRunningXids()

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

Definition at line 3995 of file procarray.c.

3998 {
3999  int i,
4000  j;
4001  XidCacheStatus *mysubxidstat;
4002 
4004 
4005  /*
4006  * We must hold ProcArrayLock exclusively in order to remove transactions
4007  * from the PGPROC array. (See src/backend/access/transam/README.) It's
4008  * possible this could be relaxed since we know this routine is only used
4009  * to abort subtransactions, but pending closer analysis we'd best be
4010  * conservative.
4011  *
4012  * Note that we do not have to be careful about memory ordering of our own
4013  * reads wrt. GetNewTransactionId() here - only this process can modify
4014  * relevant fields of MyProc/ProcGlobal->xids[]. But we do have to be
4015  * careful about our own writes being well ordered.
4016  */
4017  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
4018 
4019  mysubxidstat = &ProcGlobal->subxidStates[MyProc->pgxactoff];
4020 
4021  /*
4022  * Under normal circumstances xid and xids[] will be in increasing order,
4023  * as will be the entries in subxids. Scan backwards to avoid O(N^2)
4024  * behavior when removing a lot of xids.
4025  */
4026  for (i = nxids - 1; i >= 0; i--)
4027  {
4028  TransactionId anxid = xids[i];
4029 
4030  for (j = MyProc->subxidStatus.count - 1; j >= 0; j--)
4031  {
4032  if (TransactionIdEquals(MyProc->subxids.xids[j], anxid))
4033  {
4035  pg_write_barrier();
4036  mysubxidstat->count--;
4038  break;
4039  }
4040  }
4041 
4042  /*
4043  * Ordinarily we should have found it, unless the cache has
4044  * overflowed. However it's also possible for this routine to be
4045  * invoked multiple times for the same subtransaction, in case of an
4046  * error during AbortSubTransaction. So instead of Assert, emit a
4047  * debug warning.
4048  */
4049  if (j < 0 && !MyProc->subxidStatus.overflowed)
4050  elog(WARNING, "did not find subXID %u in MyProc", anxid);
4051  }
4052 
4053  for (j = MyProc->subxidStatus.count - 1; j >= 0; j--)
4054  {
4055  if (TransactionIdEquals(MyProc->subxids.xids[j], xid))
4056  {
4058  pg_write_barrier();
4059  mysubxidstat->count--;
4061  break;
4062  }
4063  }
4064  /* Ordinarily we should have found it, unless the cache has overflowed */
4065  if (j < 0 && !MyProc->subxidStatus.overflowed)
4066  elog(WARNING, "did not find subXID %u in MyProc", xid);
4067 
4068  /* Also advance global latestCompletedXid while holding the lock */
4069  MaintainLatestCompletedXid(latestXid);
4070 
4071  /* ... and xactCompletionCount */
4073 
4074  LWLockRelease(ProcArrayLock);
4075 }
#define pg_write_barrier()
Definition: atomics.h:150
#define WARNING
Definition: elog.h:36

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

Referenced by RecordTransactionAbort().