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 ProcArrayShmemInit (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 3196 of file procarray.c.

3197 {
3198  PGPROC *result;
3199 
3200  if (pid == 0) /* never match dummy PGPROCs */
3201  return NULL;
3202 
3203  LWLockAcquire(ProcArrayLock, LW_SHARED);
3204 
3205  result = BackendPidGetProcWithLock(pid);
3206 
3207  LWLockRelease(ProcArrayLock);
3208 
3209  return result;
3210 }
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:3219
Definition: proc.h:162

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

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

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

Referenced by BackendPidGetProc(), and GetBlockerStatusData().

◆ BackendXidGetPid()

int BackendXidGetPid ( TransactionId  xid)

Definition at line 3256 of file procarray.c.

3257 {
3258  int result = 0;
3259  ProcArrayStruct *arrayP = procArray;
3260  TransactionId *other_xids = ProcGlobal->xids;
3261  int index;
3262 
3263  if (xid == InvalidTransactionId) /* never match invalid xid */
3264  return 0;
3265 
3266  LWLockAcquire(ProcArrayLock, LW_SHARED);
3267 
3268  for (index = 0; index < arrayP->numProcs; index++)
3269  {
3270  if (other_xids[index] == xid)
3271  {
3272  int pgprocno = arrayP->pgprocnos[index];
3273  PGPROC *proc = &allProcs[pgprocno];
3274 
3275  result = proc->pid;
3276  break;
3277  }
3278  }
3279 
3280  LWLockRelease(ProcArrayLock);
3281 
3282  return result;
3283 }
uint32 TransactionId
Definition: c.h:606
PROC_HDR * ProcGlobal
Definition: proc.c:78
TransactionId * xids
Definition: proc.h:387
#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 3660 of file procarray.c.

3661 {
3662  ProcArrayStruct *arrayP = procArray;
3663  int index;
3664 
3665  /* tell all backends to die */
3666  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3667 
3668  for (index = 0; index < arrayP->numProcs; index++)
3669  {
3670  int pgprocno = arrayP->pgprocnos[index];
3671  PGPROC *proc = &allProcs[pgprocno];
3672 
3673  if (databaseid == InvalidOid || proc->databaseId == databaseid)
3674  {
3675  VirtualTransactionId procvxid;
3676  pid_t pid;
3677 
3678  GET_VXID_FROM_PGPROC(procvxid, *proc);
3679 
3680  proc->recoveryConflictPending = conflictPending;
3681  pid = proc->pid;
3682  if (pid != 0)
3683  {
3684  /*
3685  * Kill the pid if it's still here. If not, that's what we
3686  * wanted so ignore any errors.
3687  */
3688  (void) SendProcSignal(pid, sigmode, procvxid.procNumber);
3689  }
3690  }
3691  }
3692 
3693  LWLockRelease(ProcArrayLock);
3694 }
#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:281
bool recoveryConflictPending
Definition: proc.h:220
Oid databaseId
Definition: proc.h:207
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 3491 of file procarray.c.

3492 {
3493  return SignalVirtualTransaction(vxid, sigmode, true);
3494 }
pid_t SignalVirtualTransaction(VirtualTransactionId vxid, ProcSignalReason sigmode, bool conflictPending)
Definition: procarray.c:3497

References SignalVirtualTransaction().

Referenced by ResolveRecoveryConflictWithVirtualXIDs().

◆ CountDBBackends()

int CountDBBackends ( Oid  databaseid)

Definition at line 3599 of file procarray.c.

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

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

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

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

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

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

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

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

Referenced by InitializeSessionUserId().

◆ ExpireAllKnownAssignedTransactionIds()

void ExpireAllKnownAssignedTransactionIds ( void  )

Definition at line 4498 of file procarray.c.

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

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

Referenced by ShutdownRecoveryTransactionEnvironment().

◆ ExpireOldKnownAssignedTransactionIds()

void ExpireOldKnownAssignedTransactionIds ( TransactionId  xid)

Definition at line 4518 of file procarray.c.

4519 {
4520  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
4521 
4522  /*
4523  * Reset lastOverflowedXid if we know all transactions that have been
4524  * possibly running are being gone. Not doing so could cause an incorrect
4525  * lastOverflowedXid value, which makes extra snapshots be marked as
4526  * suboverflowed.
4527  */
4531  LWLockRelease(ProcArrayLock);
4532 }
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 4472 of file procarray.c.

4474 {
4476 
4477  /*
4478  * Uses same locking as transaction commit
4479  */
4480  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
4481 
4482  KnownAssignedXidsRemoveTree(xid, nsubxids, subxids);
4483 
4484  /* As in ProcArrayEndTransaction, advance latestCompletedXid */
4486 
4487  /* ... and xactCompletionCount */
4489 
4490  LWLockRelease(ProcArrayLock);
4491 }
#define Assert(condition)
Definition: c.h:812
static void KnownAssignedXidsRemoveTree(TransactionId xid, int nsubxids, TransactionId *subxids)
Definition: procarray.c:4989
static void MaintainLatestCompletedXidRecovery(TransactionId latestXid)
Definition: procarray.c:989
uint64 xactCompletionCount
Definition: transam.h:248
TransamVariablesData * TransamVariables
Definition: varsup.c:34
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 3417 of file procarray.c.

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

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

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

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

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

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

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

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

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

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, KnownAssignedXidsGetAndSetXmin(), ProcArrayStruct::lastOverflowedXid, TransamVariablesData::latestCompletedXid, likely, 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, 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 3043 of file procarray.c.

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

3090 {
3091  bool result = false;
3092  ProcArrayStruct *arrayP = procArray;
3093  int index;
3094 
3095  Assert(type != 0);
3096 
3097  LWLockAcquire(ProcArrayLock, LW_SHARED);
3098 
3099  for (index = 0; index < arrayP->numProcs; index++)
3100  {
3101  int pgprocno = arrayP->pgprocnos[index];
3102  PGPROC *proc = &allProcs[pgprocno];
3103  VirtualTransactionId vxid;
3104 
3105  GET_VXID_FROM_PGPROC(vxid, *proc);
3106 
3107  if ((proc->delayChkptFlags & type) != 0 &&
3109  {
3110  int i;
3111 
3112  for (i = 0; i < nvxids; i++)
3113  {
3114  if (VirtualTransactionIdEquals(vxid, vxids[i]))
3115  {
3116  result = true;
3117  break;
3118  }
3119  }
3120  if (result)
3121  break;
3122  }
3123  }
3124 
3125  LWLockRelease(ProcArrayLock);
3126 
3127  return result;
3128 }
int i
Definition: isn.c:72
#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 3291 of file procarray.c.

3292 {
3293  return (BackendPidGetProc(pid) != NULL);
3294 }
PGPROC * BackendPidGetProc(int pid)
Definition: procarray.c:3196

References BackendPidGetProc().

Referenced by pg_stat_get_subscription().

◆ KnownAssignedTransactionIdsIdleMaintenance()

void KnownAssignedTransactionIdsIdleMaintenance ( void  )

Definition at line 4540 of file procarray.c.

4541 {
4543 }
@ KAX_STARTUP_PROCESS_IDLE
Definition: procarray.c:265
static void KnownAssignedXidsCompress(KAXCompressReason reason, bool haveLock)
Definition: procarray.c:4641

References KAX_STARTUP_PROCESS_IDLE, and KnownAssignedXidsCompress().

Referenced by WaitForWALToBecomeAvailable().

◆ MinimumActiveBackends()

bool MinimumActiveBackends ( int  min)

Definition at line 3546 of file procarray.c.

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

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:448
#define GetNumberFromPGProc(proc)
Definition: proc.h:437
uint8 statusFlags
Definition: proc.h:242
XidCacheStatus subxidStatus
Definition: proc.h:263

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:225
void pfree(void *pointer)
Definition: mcxt.c:1521
#define qsort(a, b, c, d)
Definition: port.h:447
static TransactionId standbySnapshotPendingXmin
Definition: procarray.c:290
static TransactionId latestObservedXid
Definition: procarray.c:283
static void KnownAssignedXidsDisplay(int trace_level)
Definition: procarray.c:5194
static void KnownAssignedXidsReset(void)
Definition: procarray.c:5232
static void KnownAssignedXidsAdd(TransactionId from_xid, TransactionId to_xid, bool exclusive_lock)
Definition: procarray.c:4758
void ExpireOldKnownAssignedTransactionIds(TransactionId xid)
Definition: procarray.c:4518
void StandbyReleaseOldLocks(TransactionId oldxid)
Definition: standby.c:1129
@ SUBXIDS_MISSING
Definition: standby.h:81
int numKnownAssignedXids
Definition: procarray.c:80
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:169
@ 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:4403
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:200
struct PGPROC::@122 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 3968 of file procarray.c.

3970 {
3971  LWLockAcquire(ProcArrayLock, LW_SHARED);
3972 
3973  if (xmin != NULL)
3975 
3976  if (catalog_xmin != NULL)
3977  *catalog_xmin = procArray->replication_slot_catalog_xmin;
3978 
3979  LWLockRelease(ProcArrayLock);
3980 }

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

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

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

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

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

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

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

Referenced by ReplicationSlotsComputeRequiredXmin().

◆ ProcArrayShmemInit()

void ProcArrayShmemInit ( 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 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:488
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition: shmem.c:382
Size mul_size(Size s1, Size s2)
Definition: shmem.c:505
int maxKnownAssignedXids
Definition: procarray.c:79
int tailKnownAssignedXids
Definition: procarray.c:81
int headKnownAssignedXids
Definition: procarray.c:82
bool EnableHotStandby
Definition: xlog.c:121

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

◆ 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:559
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 3138 of file procarray.c.

3139 {
3140  PGPROC *result;
3141 
3142  if (procNumber < 0 || procNumber >= ProcGlobal->allProcCount)
3143  return NULL;
3144  result = GetPGProcByNumber(procNumber);
3145 
3146  if (result->pid == 0)
3147  return NULL;
3148 
3149  return result;
3150 }
#define GetPGProcByNumber(n)
Definition: proc.h:436
uint32 allProcCount
Definition: proc.h:402

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

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

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

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

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

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

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

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

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