PostgreSQL Source Code  git master
procarray.c File Reference
#include "postgres.h"
#include <signal.h>
#include "access/clog.h"
#include "access/subtrans.h"
#include "access/transam.h"
#include "access/twophase.h"
#include "access/xact.h"
#include "access/xlog.h"
#include "catalog/catalog.h"
#include "catalog/pg_authid.h"
#include "commands/dbcommands.h"
#include "miscadmin.h"
#include "pgstat.h"
#include "storage/proc.h"
#include "storage/procarray.h"
#include "storage/spin.h"
#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/rel.h"
#include "utils/snapmgr.h"
Include dependency graph for procarray.c:

Go to the source code of this file.

Data Structures

struct  ProcArrayStruct
 
struct  GlobalVisState
 
struct  ComputeXidHorizonsResult
 

Macros

#define UINT32_ACCESS_ONCE(var)   ((uint32)(*((volatile uint32 *)&(var))))
 
#define xc_by_recent_xmin_inc()   ((void) 0)
 
#define xc_by_known_xact_inc()   ((void) 0)
 
#define xc_by_my_xact_inc()   ((void) 0)
 
#define xc_by_latest_xid_inc()   ((void) 0)
 
#define xc_by_main_xid_inc()   ((void) 0)
 
#define xc_by_child_xid_inc()   ((void) 0)
 
#define xc_by_known_assigned_inc()   ((void) 0)
 
#define xc_no_overflow_inc()   ((void) 0)
 
#define xc_slow_answer_inc()   ((void) 0)
 
#define PROCARRAY_MAXPROCS   (MaxBackends + max_prepared_xacts)
 
#define TOTAL_MAX_CACHED_SUBXIDS   ((PGPROC_MAX_CACHED_SUBXIDS + 1) * PROCARRAY_MAXPROCS)
 
#define MAXAUTOVACPIDS   10 /* max autovacs to SIGTERM per iteration */
 

Typedefs

typedef struct ProcArrayStruct ProcArrayStruct
 
typedef struct ComputeXidHorizonsResult ComputeXidHorizonsResult
 

Functions

static void KnownAssignedXidsCompress (bool force)
 
static void KnownAssignedXidsAdd (TransactionId from_xid, TransactionId to_xid, bool exclusive_lock)
 
static bool KnownAssignedXidsSearch (TransactionId xid, bool remove)
 
static bool KnownAssignedXidExists (TransactionId xid)
 
static void KnownAssignedXidsRemove (TransactionId xid)
 
static void KnownAssignedXidsRemoveTree (TransactionId xid, int nsubxids, TransactionId *subxids)
 
static void KnownAssignedXidsRemovePreceding (TransactionId xid)
 
static int KnownAssignedXidsGet (TransactionId *xarray, TransactionId xmax)
 
static int KnownAssignedXidsGetAndSetXmin (TransactionId *xarray, TransactionId *xmin, TransactionId xmax)
 
static TransactionId KnownAssignedXidsGetOldestXmin (void)
 
static void KnownAssignedXidsDisplay (int trace_level)
 
static void KnownAssignedXidsReset (void)
 
static void ProcArrayEndTransactionInternal (PGPROC *proc, TransactionId latestXid)
 
static void ProcArrayGroupClearXid (PGPROC *proc, TransactionId latestXid)
 
static void MaintainLatestCompletedXid (TransactionId latestXid)
 
static void MaintainLatestCompletedXidRecovery (TransactionId latestXid)
 
static FullTransactionId FullXidRelativeTo (FullTransactionId rel, TransactionId xid)
 
static void GlobalVisUpdateApply (ComputeXidHorizonsResult *horizons)
 
Size ProcArrayShmemSize (void)
 
void CreateSharedProcArray (void)
 
void ProcArrayAdd (PGPROC *proc)
 
void ProcArrayRemove (PGPROC *proc, TransactionId latestXid)
 
void ProcArrayEndTransaction (PGPROC *proc, TransactionId latestXid)
 
void ProcArrayClearTransaction (PGPROC *proc)
 
void ProcArrayInitRecovery (TransactionId initializedUptoXID)
 
void ProcArrayApplyRecoveryInfo (RunningTransactions running)
 
void ProcArrayApplyXidAssignment (TransactionId topxid, int nsubxids, TransactionId *subxids)
 
bool TransactionIdIsInProgress (TransactionId xid)
 
bool TransactionIdIsActive (TransactionId xid)
 
static void ComputeXidHorizons (ComputeXidHorizonsResult *h)
 
TransactionId GetOldestNonRemovableTransactionId (Relation rel)
 
TransactionId GetOldestTransactionIdConsideredRunning (void)
 
void GetReplicationHorizons (TransactionId *xmin, TransactionId *catalog_xmin)
 
int GetMaxSnapshotXidCount (void)
 
int GetMaxSnapshotSubxidCount (void)
 
static void GetSnapshotDataInitOldSnapshot (Snapshot snapshot)
 
static bool GetSnapshotDataReuse (Snapshot snapshot)
 
Snapshot GetSnapshotData (Snapshot snapshot)
 
bool ProcArrayInstallImportedXmin (TransactionId xmin, VirtualTransactionId *sourcevxid)
 
bool ProcArrayInstallRestoredXmin (TransactionId xmin, PGPROC *proc)
 
RunningTransactions GetRunningTransactionData (void)
 
TransactionId GetOldestActiveTransactionId (void)
 
TransactionId GetOldestSafeDecodingTransactionId (bool catalogOnly)
 
VirtualTransactionIdGetVirtualXIDsDelayingChkpt (int *nvxids)
 
bool HaveVirtualXIDsDelayingChkpt (VirtualTransactionId *vxids, int nvxids)
 
PGPROCBackendPidGetProc (int pid)
 
PGPROCBackendPidGetProcWithLock (int pid)
 
int BackendXidGetPid (TransactionId xid)
 
bool IsBackendPid (int pid)
 
VirtualTransactionIdGetCurrentVirtualXIDs (TransactionId limitXmin, bool excludeXmin0, bool allDbs, int excludeVacuum, int *nvxids)
 
VirtualTransactionIdGetConflictingVirtualXIDs (TransactionId limitXmin, Oid dbOid)
 
pid_t CancelVirtualTransaction (VirtualTransactionId vxid, ProcSignalReason sigmode)
 
bool MinimumActiveBackends (int min)
 
int CountDBBackends (Oid databaseid)
 
int CountDBConnections (Oid databaseid)
 
void CancelDBBackends (Oid databaseid, ProcSignalReason sigmode, bool conflictPending)
 
int CountUserBackends (Oid roleid)
 
bool CountOtherDBBackends (Oid databaseId, int *nbackends, int *nprepared)
 
void TerminateOtherDBBackends (Oid databaseId)
 
void ProcArraySetReplicationSlotXmin (TransactionId xmin, TransactionId catalog_xmin, bool already_locked)
 
void ProcArrayGetReplicationSlotXmin (TransactionId *xmin, TransactionId *catalog_xmin)
 
void XidCacheRemoveRunningXids (TransactionId xid, int nxids, const TransactionId *xids, TransactionId latestXid)
 
GlobalVisStateGlobalVisTestFor (Relation rel)
 
static bool GlobalVisTestShouldUpdate (GlobalVisState *state)
 
static void GlobalVisUpdate (void)
 
bool GlobalVisTestIsRemovableFullXid (GlobalVisState *state, FullTransactionId fxid)
 
bool GlobalVisTestIsRemovableXid (GlobalVisState *state, TransactionId xid)
 
FullTransactionId GlobalVisTestNonRemovableFullHorizon (GlobalVisState *state)
 
TransactionId GlobalVisTestNonRemovableHorizon (GlobalVisState *state)
 
bool GlobalVisIsRemovableFullXid (Relation rel, FullTransactionId fxid)
 
bool GlobalVisCheckRemovableXid (Relation rel, TransactionId xid)
 
void RecordKnownAssignedTransactionIds (TransactionId xid)
 
void ExpireTreeKnownAssignedTransactionIds (TransactionId xid, int nsubxids, TransactionId *subxids, TransactionId max_xid)
 
void ExpireAllKnownAssignedTransactionIds (void)
 
void ExpireOldKnownAssignedTransactionIds (TransactionId xid)
 

Variables

static ProcArrayStructprocArray
 
static PGPROCallProcs
 
static TransactionIdKnownAssignedXids
 
static boolKnownAssignedXidsValid
 
static TransactionId latestObservedXid = InvalidTransactionId
 
static TransactionId standbySnapshotPendingXmin
 
static GlobalVisState GlobalVisSharedRels
 
static GlobalVisState GlobalVisCatalogRels
 
static GlobalVisState GlobalVisDataRels
 
static TransactionId ComputeXidHorizonsResultLastXmin
 

Macro Definition Documentation

◆ MAXAUTOVACPIDS

#define MAXAUTOVACPIDS   10 /* max autovacs to SIGTERM per iteration */

Referenced by CountOtherDBBackends().

◆ PROCARRAY_MAXPROCS

◆ TOTAL_MAX_CACHED_SUBXIDS

◆ UINT32_ACCESS_ONCE

◆ xc_by_child_xid_inc

#define xc_by_child_xid_inc ( )    ((void) 0)

Definition at line 305 of file procarray.c.

Referenced by TransactionIdIsInProgress().

◆ xc_by_known_assigned_inc

#define xc_by_known_assigned_inc ( )    ((void) 0)

Definition at line 306 of file procarray.c.

Referenced by TransactionIdIsInProgress().

◆ xc_by_known_xact_inc

#define xc_by_known_xact_inc ( )    ((void) 0)

Definition at line 301 of file procarray.c.

Referenced by TransactionIdIsInProgress().

◆ xc_by_latest_xid_inc

#define xc_by_latest_xid_inc ( )    ((void) 0)

Definition at line 303 of file procarray.c.

Referenced by TransactionIdIsInProgress().

◆ xc_by_main_xid_inc

#define xc_by_main_xid_inc ( )    ((void) 0)

Definition at line 304 of file procarray.c.

Referenced by TransactionIdIsInProgress().

◆ xc_by_my_xact_inc

#define xc_by_my_xact_inc ( )    ((void) 0)

Definition at line 302 of file procarray.c.

Referenced by TransactionIdIsInProgress().

◆ xc_by_recent_xmin_inc

#define xc_by_recent_xmin_inc ( )    ((void) 0)

Definition at line 300 of file procarray.c.

Referenced by TransactionIdIsInProgress().

◆ xc_no_overflow_inc

#define xc_no_overflow_inc ( )    ((void) 0)

Definition at line 307 of file procarray.c.

Referenced by TransactionIdIsInProgress().

◆ xc_slow_answer_inc

#define xc_slow_answer_inc ( )    ((void) 0)

Definition at line 308 of file procarray.c.

Referenced by TransactionIdIsInProgress().

Typedef Documentation

◆ ComputeXidHorizonsResult

◆ ProcArrayStruct

Function Documentation

◆ BackendPidGetProc()

PGPROC* BackendPidGetProc ( int  pid)

Definition at line 2980 of file procarray.c.

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

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

2981 {
2982  PGPROC *result;
2983 
2984  if (pid == 0) /* never match dummy PGPROCs */
2985  return NULL;
2986 
2987  LWLockAcquire(ProcArrayLock, LW_SHARED);
2988 
2989  result = BackendPidGetProcWithLock(pid);
2990 
2991  LWLockRelease(ProcArrayLock);
2992 
2993  return result;
2994 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
PGPROC * BackendPidGetProcWithLock(int pid)
Definition: procarray.c:3003
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
Definition: proc.h:112

◆ BackendPidGetProcWithLock()

PGPROC* BackendPidGetProcWithLock ( int  pid)

Definition at line 3003 of file procarray.c.

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

Referenced by BackendPidGetProc(), and GetBlockerStatusData().

3004 {
3005  PGPROC *result = NULL;
3006  ProcArrayStruct *arrayP = procArray;
3007  int index;
3008 
3009  if (pid == 0) /* never match dummy PGPROCs */
3010  return NULL;
3011 
3012  for (index = 0; index < arrayP->numProcs; index++)
3013  {
3014  PGPROC *proc = &allProcs[arrayP->pgprocnos[index]];
3015 
3016  if (proc->pid == pid)
3017  {
3018  result = proc;
3019  break;
3020  }
3021  }
3022 
3023  return result;
3024 }
Definition: type.h:89
static PGPROC * allProcs
Definition: procarray.c:242
static ProcArrayStruct * procArray
Definition: procarray.c:240
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
Definition: proc.h:112
int pid
Definition: proc.h:137

◆ BackendXidGetPid()

int BackendXidGetPid ( TransactionId  xid)

Definition at line 3040 of file procarray.c.

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

Referenced by pgrowlocks().

3041 {
3042  int result = 0;
3043  ProcArrayStruct *arrayP = procArray;
3044  TransactionId *other_xids = ProcGlobal->xids;
3045  int index;
3046 
3047  if (xid == InvalidTransactionId) /* never match invalid xid */
3048  return 0;
3049 
3050  LWLockAcquire(ProcArrayLock, LW_SHARED);
3051 
3052  for (index = 0; index < arrayP->numProcs; index++)
3053  {
3054  int pgprocno = arrayP->pgprocnos[index];
3055  PGPROC *proc = &allProcs[pgprocno];
3056 
3057  if (other_xids[index] == xid)
3058  {
3059  result = proc->pid;
3060  break;
3061  }
3062  }
3063 
3064  LWLockRelease(ProcArrayLock);
3065 
3066  return result;
3067 }
uint32 TransactionId
Definition: c.h:520
PROC_HDR * ProcGlobal
Definition: proc.c:79
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
#define InvalidTransactionId
Definition: transam.h:31
TransactionId * xids
Definition: proc.h:309
static PGPROC * allProcs
Definition: procarray.c:242
static ProcArrayStruct * procArray
Definition: procarray.c:240
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
Definition: proc.h:112
int pid
Definition: proc.h:137

◆ CancelDBBackends()

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

Definition at line 3432 of file procarray.c.

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

Referenced by ResolveRecoveryConflictWithDatabase(), and SendRecoveryConflictWithBufferPin().

3433 {
3434  ProcArrayStruct *arrayP = procArray;
3435  int index;
3436 
3437  /* tell all backends to die */
3438  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3439 
3440  for (index = 0; index < arrayP->numProcs; index++)
3441  {
3442  int pgprocno = arrayP->pgprocnos[index];
3443  PGPROC *proc = &allProcs[pgprocno];
3444 
3445  if (databaseid == InvalidOid || proc->databaseId == databaseid)
3446  {
3447  VirtualTransactionId procvxid;
3448  pid_t pid;
3449 
3450  GET_VXID_FROM_PGPROC(procvxid, *proc);
3451 
3452  proc->recoveryConflictPending = conflictPending;
3453  pid = proc->pid;
3454  if (pid != 0)
3455  {
3456  /*
3457  * Kill the pid if it's still here. If not, that's what we
3458  * wanted so ignore any errors.
3459  */
3460  (void) SendProcSignal(pid, sigmode, procvxid.backendId);
3461  }
3462  }
3463  }
3464 
3465  LWLockRelease(ProcArrayLock);
3466 }
#define GET_VXID_FROM_PGPROC(vxid, proc)
Definition: lock.h:79
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
int SendProcSignal(pid_t pid, ProcSignalReason reason, BackendId backendId)
Definition: procsignal.c:250
bool recoveryConflictPending
Definition: proc.h:158
static PGPROC * allProcs
Definition: procarray.c:242
Oid databaseId
Definition: proc.h:145
static ProcArrayStruct * procArray
Definition: procarray.c:240
#define InvalidOid
Definition: postgres_ext.h:36
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
BackendId backendId
Definition: lock.h:64
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
Definition: proc.h:112
int pid
Definition: proc.h:137

◆ CancelVirtualTransaction()

pid_t CancelVirtualTransaction ( VirtualTransactionId  vxid,
ProcSignalReason  sigmode 
)

Definition at line 3270 of file procarray.c.

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

Referenced by ResolveRecoveryConflictWithVirtualXIDs().

3271 {
3272  ProcArrayStruct *arrayP = procArray;
3273  int index;
3274  pid_t pid = 0;
3275 
3276  LWLockAcquire(ProcArrayLock, LW_SHARED);
3277 
3278  for (index = 0; index < arrayP->numProcs; index++)
3279  {
3280  int pgprocno = arrayP->pgprocnos[index];
3281  PGPROC *proc = &allProcs[pgprocno];
3282  VirtualTransactionId procvxid;
3283 
3284  GET_VXID_FROM_PGPROC(procvxid, *proc);
3285 
3286  if (procvxid.backendId == vxid.backendId &&
3287  procvxid.localTransactionId == vxid.localTransactionId)
3288  {
3289  proc->recoveryConflictPending = true;
3290  pid = proc->pid;
3291  if (pid != 0)
3292  {
3293  /*
3294  * Kill the pid if it's still here. If not, that's what we
3295  * wanted so ignore any errors.
3296  */
3297  (void) SendProcSignal(pid, sigmode, vxid.backendId);
3298  }
3299  break;
3300  }
3301  }
3302 
3303  LWLockRelease(ProcArrayLock);
3304 
3305  return pid;
3306 }
#define GET_VXID_FROM_PGPROC(vxid, proc)
Definition: lock.h:79
LocalTransactionId localTransactionId
Definition: lock.h:65
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
int SendProcSignal(pid_t pid, ProcSignalReason reason, BackendId backendId)
Definition: procsignal.c:250
bool recoveryConflictPending
Definition: proc.h:158
static PGPROC * allProcs
Definition: procarray.c:242
static ProcArrayStruct * procArray
Definition: procarray.c:240
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
BackendId backendId
Definition: lock.h:64
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
Definition: proc.h:112
int pid
Definition: proc.h:137

◆ ComputeXidHorizons()

static void ComputeXidHorizons ( ComputeXidHorizonsResult h)
static

Definition at line 1641 of file procarray.c.

References Assert, ComputeXidHorizonsResult::catalog_oldest_nonremovable, ComputeXidHorizonsResult::data_oldest_nonremovable, PGPROC::databaseId, GlobalVisUpdateApply(), InvalidTransactionId, KnownAssignedXidsGetOldestXmin(), ComputeXidHorizonsResult::latest_completed, VariableCacheData::latestCompletedXid, LW_SHARED, LWLockAcquire(), LWLockRelease(), MyDatabaseId, ProcArrayStruct::numProcs, ComputeXidHorizonsResult::oldest_considered_running, ProcArrayStruct::pgprocnos, PROC_IN_LOGICAL_DECODING, PROC_IN_VACUUM, procArray, ProcGlobal, RecoveryInProgress(), ProcArrayStruct::replication_slot_catalog_xmin, ProcArrayStruct::replication_slot_xmin, ComputeXidHorizonsResult::shared_oldest_nonremovable, ComputeXidHorizonsResult::shared_oldest_nonremovable_raw, ShmemVariableCache, ComputeXidHorizonsResult::slot_catalog_xmin, ComputeXidHorizonsResult::slot_xmin, TransactionIdAdvance, TransactionIdIsValid, TransactionIdOlder(), TransactionIdPrecedesOrEquals(), TransactionIdRetreatedBy(), UINT32_ACCESS_ONCE, vacuum_defer_cleanup_age, PROC_HDR::vacuumFlags, XidFromFullTransactionId, PROC_HDR::xids, and PGPROC::xmin.

Referenced by GetOldestNonRemovableTransactionId(), GetOldestTransactionIdConsideredRunning(), GetReplicationHorizons(), and GlobalVisUpdate().

1642 {
1643  ProcArrayStruct *arrayP = procArray;
1644  TransactionId kaxmin;
1645  bool in_recovery = RecoveryInProgress();
1646  TransactionId *other_xids = ProcGlobal->xids;
1647 
1648  /* inferred after ProcArrayLock is released */
1650 
1651  LWLockAcquire(ProcArrayLock, LW_SHARED);
1652 
1654 
1655  /*
1656  * We initialize the MIN() calculation with latestCompletedXid + 1. This
1657  * is a lower bound for the XIDs that might appear in the ProcArray later,
1658  * and so protects us against overestimating the result due to future
1659  * additions.
1660  */
1661  {
1662  TransactionId initial;
1663 
1665  Assert(TransactionIdIsValid(initial));
1666  TransactionIdAdvance(initial);
1667 
1668  h->oldest_considered_running = initial;
1669  h->shared_oldest_nonremovable = initial;
1670  h->data_oldest_nonremovable = initial;
1671  }
1672 
1673  /*
1674  * Fetch slot horizons while ProcArrayLock is held - the
1675  * LWLockAcquire/LWLockRelease are a barrier, ensuring this happens inside
1676  * the lock.
1677  */
1680 
1681  for (int index = 0; index < arrayP->numProcs; index++)
1682  {
1683  int pgprocno = arrayP->pgprocnos[index];
1684  PGPROC *proc = &allProcs[pgprocno];
1685  int8 vacuumFlags = ProcGlobal->vacuumFlags[index];
1686  TransactionId xid;
1687  TransactionId xmin;
1688 
1689  /* Fetch xid just once - see GetNewTransactionId */
1690  xid = UINT32_ACCESS_ONCE(other_xids[index]);
1691  xmin = UINT32_ACCESS_ONCE(proc->xmin);
1692 
1693  /*
1694  * Consider both the transaction's Xmin, and its Xid.
1695  *
1696  * We must check both because a transaction might have an Xmin but not
1697  * (yet) an Xid; conversely, if it has an Xid, that could determine
1698  * some not-yet-set Xmin.
1699  */
1700  xmin = TransactionIdOlder(xmin, xid);
1701 
1702  /* if neither is set, this proc doesn't influence the horizon */
1703  if (!TransactionIdIsValid(xmin))
1704  continue;
1705 
1706  /*
1707  * Don't ignore any procs when determining which transactions might be
1708  * considered running. While slots should ensure logical decoding
1709  * backends are protected even without this check, it can't hurt to
1710  * include them here as well..
1711  */
1714 
1715  /*
1716  * Skip over backends either vacuuming (which is ok with rows being
1717  * removed, as long as pg_subtrans is not truncated) or doing logical
1718  * decoding (which manages xmin separately, check below).
1719  */
1720  if (vacuumFlags & (PROC_IN_VACUUM | PROC_IN_LOGICAL_DECODING))
1721  continue;
1722 
1723  /* shared tables need to take backends in all database into account */
1726 
1727  /*
1728  * Normally queries in other databases are ignored for anything but
1729  * the shared horizon. But in recovery we cannot compute an accurate
1730  * per-database horizon as all xids are managed via the
1731  * KnownAssignedXids machinery.
1732  */
1733  if (in_recovery ||
1734  proc->databaseId == MyDatabaseId ||
1735  proc->databaseId == 0) /* always include WalSender */
1736  {
1739  }
1740  }
1741 
1742  /*
1743  * If in recovery fetch oldest xid in KnownAssignedXids, will be applied
1744  * after lock is released.
1745  */
1746  if (in_recovery)
1747  kaxmin = KnownAssignedXidsGetOldestXmin();
1748 
1749  /*
1750  * No other information from shared state is needed, release the lock
1751  * immediately. The rest of the computations can be done without a lock.
1752  */
1753  LWLockRelease(ProcArrayLock);
1754 
1755  if (in_recovery)
1756  {
1763  }
1764  else
1765  {
1766  /*
1767  * Compute the cutoff XID by subtracting vacuum_defer_cleanup_age.
1768  *
1769  * vacuum_defer_cleanup_age provides some additional "slop" for the
1770  * benefit of hot standby queries on standby servers. This is quick
1771  * and dirty, and perhaps not all that useful unless the primary has a
1772  * predictable transaction rate, but it offers some protection when
1773  * there's no walsender connection. Note that we are assuming
1774  * vacuum_defer_cleanup_age isn't large enough to cause wraparound ---
1775  * so guc.c should limit it to no more than the xidStopLimit threshold
1776  * in varsup.c. Also note that we intentionally don't apply
1777  * vacuum_defer_cleanup_age on standby servers.
1778  */
1788  }
1789 
1790  /*
1791  * Check whether there are replication slots requiring an older xmin.
1792  */
1797 
1798  /*
1799  * The only difference between catalog / data horizons is that the slot's
1800  * catalog xmin is applied to the catalog one (so catalogs can be accessed
1801  * for logical decoding). Initialize with data horizon, and then back up
1802  * further if necessary. Have to back up the shared horizon as well, since
1803  * that also can contain catalogs.
1804  */
1808  h->slot_catalog_xmin);
1812  h->slot_catalog_xmin);
1813 
1814  /*
1815  * It's possible that slots / vacuum_defer_cleanup_age backed up the
1816  * horizons further than oldest_considered_running. Fix.
1817  */
1827 
1828  /*
1829  * shared horizons have to be at least as old as the oldest visible in
1830  * current db
1831  */
1836 
1837  /*
1838  * Horizons need to ensure that pg_subtrans access is still possible for
1839  * the relevant backends.
1840  */
1849  h->slot_xmin));
1852  h->slot_catalog_xmin));
1853 
1854  /* update approximate horizons with the computed horizons */
1856 }
#define TransactionIdAdvance(dest)
Definition: transam.h:91
TransactionId oldest_considered_running
Definition: procarray.c:204
FullTransactionId latest_completed
Definition: procarray.c:184
TransactionId shared_oldest_nonremovable_raw
Definition: procarray.c:224
#define PROC_IN_LOGICAL_DECODING
Definition: proc.h:57
uint32 TransactionId
Definition: c.h:520
int vacuum_defer_cleanup_age
Definition: standby.c:39
#define UINT32_ACCESS_ONCE(var)
Definition: procarray.c:69
TransactionId replication_slot_catalog_xmin
Definition: procarray.c:98
PROC_HDR * ProcGlobal
Definition: proc.c:79
FullTransactionId latestCompletedXid
Definition: transam.h:231
bool RecoveryInProgress(void)
Definition: xlog.c:8074
TransactionId catalog_oldest_nonremovable
Definition: procarray.c:230
#define XidFromFullTransactionId(x)
Definition: transam.h:48
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
#define PROC_IN_VACUUM
Definition: proc.h:55
bool TransactionIdPrecedesOrEquals(TransactionId id1, TransactionId id2)
Definition: transam.c:319
TransactionId slot_catalog_xmin
Definition: procarray.c:191
TransactionId xmin
Definition: proc.h:129
VariableCache ShmemVariableCache
Definition: varsup.c:34
#define InvalidTransactionId
Definition: transam.h:31
TransactionId * xids
Definition: proc.h:309
static PGPROC * allProcs
Definition: procarray.c:242
Oid databaseId
Definition: proc.h:145
TransactionId shared_oldest_nonremovable
Definition: procarray.c:213
static ProcArrayStruct * procArray
Definition: procarray.c:240
signed char int8
Definition: c.h:360
TransactionId replication_slot_xmin
Definition: procarray.c:96
Oid MyDatabaseId
Definition: globals.c:85
static TransactionId KnownAssignedXidsGetOldestXmin(void)
Definition: procarray.c:4890
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
static TransactionId TransactionIdOlder(TransactionId a, TransactionId b)
Definition: transam.h:327
#define Assert(condition)
Definition: c.h:745
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
static void GlobalVisUpdateApply(ComputeXidHorizonsResult *horizons)
Definition: procarray.c:3934
static TransactionId TransactionIdRetreatedBy(TransactionId xid, uint32 amount)
Definition: transam.h:315
TransactionId data_oldest_nonremovable
Definition: procarray.c:236
uint8 * vacuumFlags
Definition: proc.h:321
#define TransactionIdIsValid(xid)
Definition: transam.h:41
TransactionId slot_xmin
Definition: procarray.c:190
Definition: proc.h:112

◆ CountDBBackends()

int CountDBBackends ( Oid  databaseid)

Definition at line 3371 of file procarray.c.

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

Referenced by ResolveRecoveryConflictWithDatabase().

3372 {
3373  ProcArrayStruct *arrayP = procArray;
3374  int count = 0;
3375  int index;
3376 
3377  LWLockAcquire(ProcArrayLock, LW_SHARED);
3378 
3379  for (index = 0; index < arrayP->numProcs; index++)
3380  {
3381  int pgprocno = arrayP->pgprocnos[index];
3382  PGPROC *proc = &allProcs[pgprocno];
3383 
3384  if (proc->pid == 0)
3385  continue; /* do not count prepared xacts */
3386  if (!OidIsValid(databaseid) ||
3387  proc->databaseId == databaseid)
3388  count++;
3389  }
3390 
3391  LWLockRelease(ProcArrayLock);
3392 
3393  return count;
3394 }
#define OidIsValid(objectId)
Definition: c.h:651
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
static PGPROC * allProcs
Definition: procarray.c:242
Oid databaseId
Definition: proc.h:145
static ProcArrayStruct * procArray
Definition: procarray.c:240
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
Definition: proc.h:112
int pid
Definition: proc.h:137

◆ CountDBConnections()

int CountDBConnections ( Oid  databaseid)

Definition at line 3401 of file procarray.c.

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

Referenced by CheckMyDatabase().

3402 {
3403  ProcArrayStruct *arrayP = procArray;
3404  int count = 0;
3405  int index;
3406 
3407  LWLockAcquire(ProcArrayLock, LW_SHARED);
3408 
3409  for (index = 0; index < arrayP->numProcs; index++)
3410  {
3411  int pgprocno = arrayP->pgprocnos[index];
3412  PGPROC *proc = &allProcs[pgprocno];
3413 
3414  if (proc->pid == 0)
3415  continue; /* do not count prepared xacts */
3416  if (proc->isBackgroundWorker)
3417  continue; /* do not count background workers */
3418  if (!OidIsValid(databaseid) ||
3419  proc->databaseId == databaseid)
3420  count++;
3421  }
3422 
3423  LWLockRelease(ProcArrayLock);
3424 
3425  return count;
3426 }
#define OidIsValid(objectId)
Definition: c.h:651
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
bool isBackgroundWorker
Definition: proc.h:151
static PGPROC * allProcs
Definition: procarray.c:242
Oid databaseId
Definition: proc.h:145
static ProcArrayStruct * procArray
Definition: procarray.c:240
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
Definition: proc.h:112
int pid
Definition: proc.h:137

◆ CountOtherDBBackends()

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

Definition at line 3522 of file procarray.c.

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

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

3523 {
3524  ProcArrayStruct *arrayP = procArray;
3525 
3526 #define MAXAUTOVACPIDS 10 /* max autovacs to SIGTERM per iteration */
3527  int autovac_pids[MAXAUTOVACPIDS];
3528  int tries;
3529 
3530  /* 50 tries with 100ms sleep between tries makes 5 sec total wait */
3531  for (tries = 0; tries < 50; tries++)
3532  {
3533  int nautovacs = 0;
3534  bool found = false;
3535  int index;
3536 
3538 
3539  *nbackends = *nprepared = 0;
3540 
3541  LWLockAcquire(ProcArrayLock, LW_SHARED);
3542 
3543  for (index = 0; index < arrayP->numProcs; index++)
3544  {
3545  int pgprocno = arrayP->pgprocnos[index];
3546  PGPROC *proc = &allProcs[pgprocno];
3547  uint8 vacuumFlags = ProcGlobal->vacuumFlags[index];
3548 
3549  if (proc->databaseId != databaseId)
3550  continue;
3551  if (proc == MyProc)
3552  continue;
3553 
3554  found = true;
3555 
3556  if (proc->pid == 0)
3557  (*nprepared)++;
3558  else
3559  {
3560  (*nbackends)++;
3561  if ((vacuumFlags & PROC_IS_AUTOVACUUM) &&
3562  nautovacs < MAXAUTOVACPIDS)
3563  autovac_pids[nautovacs++] = proc->pid;
3564  }
3565  }
3566 
3567  LWLockRelease(ProcArrayLock);
3568 
3569  if (!found)
3570  return false; /* no conflicting backends, so done */
3571 
3572  /*
3573  * Send SIGTERM to any conflicting autovacuums before sleeping. We
3574  * postpone this step until after the loop because we don't want to
3575  * hold ProcArrayLock while issuing kill(). We have no idea what might
3576  * block kill() inside the kernel...
3577  */
3578  for (index = 0; index < nautovacs; index++)
3579  (void) kill(autovac_pids[index], SIGTERM); /* ignore any error */
3580 
3581  /* sleep, then try again */
3582  pg_usleep(100 * 1000L); /* 100ms */
3583  }
3584 
3585  return true; /* timed out, still conflicts */
3586 }
PGPROC * MyProc
Definition: proc.c:67
unsigned char uint8
Definition: c.h:372
PROC_HDR * ProcGlobal
Definition: proc.c:79
#define kill(pid, sig)
Definition: win32_port.h:426
#define MAXAUTOVACPIDS
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
void pg_usleep(long microsec)
Definition: signal.c:53
static PGPROC * allProcs
Definition: procarray.c:242
Oid databaseId
Definition: proc.h:145
static ProcArrayStruct * procArray
Definition: procarray.c:240
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
uint8 * vacuumFlags
Definition: proc.h:321
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:99
Definition: proc.h:112
int pid
Definition: proc.h:137
#define PROC_IS_AUTOVACUUM
Definition: proc.h:54

◆ CountUserBackends()

int CountUserBackends ( Oid  roleid)

Definition at line 3472 of file procarray.c.

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

Referenced by InitializeSessionUserId().

3473 {
3474  ProcArrayStruct *arrayP = procArray;
3475  int count = 0;
3476  int index;
3477 
3478  LWLockAcquire(ProcArrayLock, LW_SHARED);
3479 
3480  for (index = 0; index < arrayP->numProcs; index++)
3481  {
3482  int pgprocno = arrayP->pgprocnos[index];
3483  PGPROC *proc = &allProcs[pgprocno];
3484 
3485  if (proc->pid == 0)
3486  continue; /* do not count prepared xacts */
3487  if (proc->isBackgroundWorker)
3488  continue; /* do not count background workers */
3489  if (proc->roleId == roleid)
3490  count++;
3491  }
3492 
3493  LWLockRelease(ProcArrayLock);
3494 
3495  return count;
3496 }
Oid roleId
Definition: proc.h:146
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
bool isBackgroundWorker
Definition: proc.h:151
static PGPROC * allProcs
Definition: procarray.c:242
static ProcArrayStruct * procArray
Definition: procarray.c:240
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
Definition: proc.h:112
int pid
Definition: proc.h:137

◆ CreateSharedProcArray()

void CreateSharedProcArray ( void  )

Definition at line 383 of file procarray.c.

References add_size(), PROC_HDR::allProcs, EnableHotStandby, ProcArrayStruct::headKnownAssignedXids, InvalidTransactionId, ProcArrayStruct::known_assigned_xids_lck, KnownAssignedXids, KnownAssignedXidsValid, ProcArrayStruct::lastOverflowedXid, ProcArrayStruct::maxKnownAssignedXids, ProcArrayStruct::maxProcs, mul_size(), ProcArrayStruct::numKnownAssignedXids, ProcArrayStruct::numProcs, offsetof, ProcArrayStruct::pgprocnos, PROCARRAY_MAXPROCS, ProcGlobal, ProcArrayStruct::replication_slot_catalog_xmin, ProcArrayStruct::replication_slot_xmin, ShmemInitStruct(), ShmemVariableCache, SpinLockInit, ProcArrayStruct::tailKnownAssignedXids, TOTAL_MAX_CACHED_SUBXIDS, and VariableCacheData::xactCompletionCount.

Referenced by CreateSharedMemoryAndSemaphores().

384 {
385  bool found;
386 
387  /* Create or attach to the ProcArray shared structure */
389  ShmemInitStruct("Proc Array",
390  add_size(offsetof(ProcArrayStruct, pgprocnos),
391  mul_size(sizeof(int),
393  &found);
394 
395  if (!found)
396  {
397  /*
398  * We're the first - initialize.
399  */
400  procArray->numProcs = 0;
411  }
412 
414 
415  /* Create or attach to the KnownAssignedXids arrays too, if needed */
416  if (EnableHotStandby)
417  {
419  ShmemInitStruct("KnownAssignedXids",
420  mul_size(sizeof(TransactionId),
422  &found);
423  KnownAssignedXidsValid = (bool *)
424  ShmemInitStruct("KnownAssignedXidsValid",
425  mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS),
426  &found);
427  }
428 }
#define PROCARRAY_MAXPROCS
uint32 TransactionId
Definition: c.h:520
#define SpinLockInit(lock)
Definition: spin.h:60
TransactionId replication_slot_catalog_xmin
Definition: procarray.c:98
uint64 xactCompletionCount
Definition: transam.h:241
slock_t known_assigned_xids_lck
Definition: procarray.c:84
PROC_HDR * ProcGlobal
Definition: proc.c:79
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition: shmem.c:392
VariableCache ShmemVariableCache
Definition: varsup.c:34
int maxKnownAssignedXids
Definition: procarray.c:80
#define InvalidTransactionId
Definition: transam.h:31
static PGPROC * allProcs
Definition: procarray.c:242
int numKnownAssignedXids
Definition: procarray.c:81
static bool * KnownAssignedXidsValid
Definition: procarray.c:248
TransactionId lastOverflowedXid
Definition: procarray.c:93
static ProcArrayStruct * procArray
Definition: procarray.c:240
TransactionId replication_slot_xmin
Definition: procarray.c:96
Size mul_size(Size s1, Size s2)
Definition: shmem.c:515
Size add_size(Size s1, Size s2)
Definition: shmem.c:498
#define TOTAL_MAX_CACHED_SUBXIDS
static TransactionId * KnownAssignedXids
Definition: procarray.c:247
bool EnableHotStandby
Definition: xlog.c:97
PGPROC * allProcs
Definition: proc.h:306
int tailKnownAssignedXids
Definition: procarray.c:82
#define offsetof(type, field)
Definition: c.h:668
int headKnownAssignedXids
Definition: procarray.c:83

◆ ExpireAllKnownAssignedTransactionIds()

void ExpireAllKnownAssignedTransactionIds ( void  )

Definition at line 4291 of file procarray.c.

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

Referenced by ShutdownRecoveryTransactionEnvironment().

4292 {
4293  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
4295  LWLockRelease(ProcArrayLock);
4296 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
static void KnownAssignedXidsRemovePreceding(TransactionId xid)
Definition: procarray.c:4740
#define InvalidTransactionId
Definition: transam.h:31
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208

◆ ExpireOldKnownAssignedTransactionIds()

void ExpireOldKnownAssignedTransactionIds ( TransactionId  xid)

Definition at line 4303 of file procarray.c.

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

Referenced by ProcArrayApplyRecoveryInfo().

4304 {
4305  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
4307  LWLockRelease(ProcArrayLock);
4308 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
static void KnownAssignedXidsRemovePreceding(TransactionId xid)
Definition: procarray.c:4740
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208

◆ ExpireTreeKnownAssignedTransactionIds()

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

Definition at line 4268 of file procarray.c.

References Assert, KnownAssignedXidsRemoveTree(), LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MaintainLatestCompletedXidRecovery(), STANDBY_INITIALIZED, and standbyState.

Referenced by xact_redo_abort(), and xact_redo_commit().

4270 {
4272 
4273  /*
4274  * Uses same locking as transaction commit
4275  */
4276  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
4277 
4278  KnownAssignedXidsRemoveTree(xid, nsubxids, subxids);
4279 
4280  /* As in ProcArrayEndTransaction, advance latestCompletedXid */
4282 
4283  LWLockRelease(ProcArrayLock);
4284 }
static void MaintainLatestCompletedXidRecovery(TransactionId latestXid)
Definition: procarray.c:920
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
static void KnownAssignedXidsRemoveTree(TransactionId xid, int nsubxids, TransactionId *subxids)
Definition: procarray.c:4718
#define Assert(condition)
Definition: c.h:745
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
HotStandbyState standbyState
Definition: xlog.c:208

◆ FullXidRelativeTo()

static FullTransactionId FullXidRelativeTo ( FullTransactionId  rel,
TransactionId  xid 
)
inlinestatic

Definition at line 4115 of file procarray.c.

References Assert, AssertTransactionIdInAllowableRange, FullTransactionIdFromU64(), TransactionIdIsValid, U64FromFullTransactionId, and XidFromFullTransactionId.

Referenced by GetSnapshotData(), GlobalVisTestIsRemovableXid(), GlobalVisUpdateApply(), MaintainLatestCompletedXid(), and MaintainLatestCompletedXidRecovery().

4116 {
4117  TransactionId rel_xid = XidFromFullTransactionId(rel);
4118 
4120  Assert(TransactionIdIsValid(rel_xid));
4121 
4122  /* not guaranteed to find issues, but likely to catch mistakes */
4124 
4126  + (int32) (xid - rel_xid));
4127 }
uint32 TransactionId
Definition: c.h:520
static FullTransactionId FullTransactionIdFromU64(uint64 value)
Definition: transam.h:81
signed int int32
Definition: c.h:362
#define XidFromFullTransactionId(x)
Definition: transam.h:48
#define AssertTransactionIdInAllowableRange(xid)
Definition: transam.h:294
#define Assert(condition)
Definition: c.h:745
#define U64FromFullTransactionId(x)
Definition: transam.h:49
#define TransactionIdIsValid(xid)
Definition: transam.h:41

◆ GetConflictingVirtualXIDs()

VirtualTransactionId* GetConflictingVirtualXIDs ( TransactionId  limitXmin,
Oid  dbOid 
)

Definition at line 3196 of file procarray.c.

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

Referenced by ResolveRecoveryConflictWithSnapshot(), and ResolveRecoveryConflictWithTablespace().

3197 {
3198  static VirtualTransactionId *vxids;
3199  ProcArrayStruct *arrayP = procArray;
3200  int count = 0;
3201  int index;
3202 
3203  /*
3204  * If first time through, get workspace to remember main XIDs in. We
3205  * malloc it permanently to avoid repeated palloc/pfree overhead. Allow
3206  * result space, remembering room for a terminator.
3207  */
3208  if (vxids == NULL)
3209  {
3210  vxids = (VirtualTransactionId *)
3211  malloc(sizeof(VirtualTransactionId) * (arrayP->maxProcs + 1));
3212  if (vxids == NULL)
3213  ereport(ERROR,
3214  (errcode(ERRCODE_OUT_OF_MEMORY),
3215  errmsg("out of memory")));
3216  }
3217 
3218  LWLockAcquire(ProcArrayLock, LW_SHARED);
3219 
3220  for (index = 0; index < arrayP->numProcs; index++)
3221  {
3222  int pgprocno = arrayP->pgprocnos[index];
3223  PGPROC *proc = &allProcs[pgprocno];
3224 
3225  /* Exclude prepared transactions */
3226  if (proc->pid == 0)
3227  continue;
3228 
3229  if (!OidIsValid(dbOid) ||
3230  proc->databaseId == dbOid)
3231  {
3232  /* Fetch xmin just once - can't change on us, but good coding */
3233  TransactionId pxmin = UINT32_ACCESS_ONCE(proc->xmin);
3234 
3235  /*
3236  * We ignore an invalid pxmin because this means that backend has
3237  * no snapshot currently. We hold a Share lock to avoid contention
3238  * with users taking snapshots. That is not a problem because the
3239  * current xmin is always at least one higher than the latest
3240  * removed xid, so any new snapshot would never conflict with the
3241  * test here.
3242  */
3243  if (!TransactionIdIsValid(limitXmin) ||
3244  (TransactionIdIsValid(pxmin) && !TransactionIdFollows(pxmin, limitXmin)))
3245  {
3246  VirtualTransactionId vxid;
3247 
3248  GET_VXID_FROM_PGPROC(vxid, *proc);
3249  if (VirtualTransactionIdIsValid(vxid))
3250  vxids[count++] = vxid;
3251  }
3252  }
3253  }
3254 
3255  LWLockRelease(ProcArrayLock);
3256 
3257  /* add the terminator */
3258  vxids[count].backendId = InvalidBackendId;
3260 
3261  return vxids;
3262 }
#define GET_VXID_FROM_PGPROC(vxid, proc)
Definition: lock.h:79
bool TransactionIdFollows(TransactionId id1, TransactionId id2)
Definition: transam.c:334
uint32 TransactionId
Definition: c.h:520
#define UINT32_ACCESS_ONCE(var)
Definition: procarray.c:69
int errcode(int sqlerrcode)
Definition: elog.c:610
LocalTransactionId localTransactionId
Definition: lock.h:65
#define OidIsValid(objectId)
Definition: c.h:651
Definition: type.h:89
#define malloc(a)
Definition: header.h:50
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
#define ERROR
Definition: elog.h:43
TransactionId xmin
Definition: proc.h:129
static PGPROC * allProcs
Definition: procarray.c:242
Oid databaseId
Definition: proc.h:145
static ProcArrayStruct * procArray
Definition: procarray.c:240
#define VirtualTransactionIdIsValid(vxid)
Definition: lock.h:70
#define InvalidBackendId
Definition: backendid.h:23
#define ereport(elevel,...)
Definition: elog.h:144
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
BackendId backendId
Definition: lock.h:64
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
int errmsg(const char *fmt,...)
Definition: elog.c:824
#define InvalidLocalTransactionId
Definition: lock.h:68
#define TransactionIdIsValid(xid)
Definition: transam.h:41
Definition: proc.h:112
int pid
Definition: proc.h:137

◆ GetCurrentVirtualXIDs()

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

Definition at line 3108 of file procarray.c.

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

Referenced by WaitForOlderSnapshots().

3111 {
3112  VirtualTransactionId *vxids;
3113  ProcArrayStruct *arrayP = procArray;
3114  int count = 0;
3115  int index;
3116 
3117  /* allocate what's certainly enough result space */
3118  vxids = (VirtualTransactionId *)
3119  palloc(sizeof(VirtualTransactionId) * arrayP->maxProcs);
3120 
3121  LWLockAcquire(ProcArrayLock, LW_SHARED);
3122 
3123  for (index = 0; index < arrayP->numProcs; index++)
3124  {
3125  int pgprocno = arrayP->pgprocnos[index];
3126  PGPROC *proc = &allProcs[pgprocno];
3127  uint8 vacuumFlags = ProcGlobal->vacuumFlags[index];
3128 
3129  if (proc == MyProc)
3130  continue;
3131 
3132  if (excludeVacuum & vacuumFlags)
3133  continue;
3134 
3135  if (allDbs || proc->databaseId == MyDatabaseId)
3136  {
3137  /* Fetch xmin just once - might change on us */
3138  TransactionId pxmin = UINT32_ACCESS_ONCE(proc->xmin);
3139 
3140  if (excludeXmin0 && !TransactionIdIsValid(pxmin))
3141  continue;
3142 
3143  /*
3144  * InvalidTransactionId precedes all other XIDs, so a proc that
3145  * hasn't set xmin yet will not be rejected by this test.
3146  */
3147  if (!TransactionIdIsValid(limitXmin) ||
3148  TransactionIdPrecedesOrEquals(pxmin, limitXmin))
3149  {
3150  VirtualTransactionId vxid;
3151 
3152  GET_VXID_FROM_PGPROC(vxid, *proc);
3153  if (VirtualTransactionIdIsValid(vxid))
3154  vxids[count++] = vxid;
3155  }
3156  }
3157  }
3158 
3159  LWLockRelease(ProcArrayLock);
3160 
3161  *nvxids = count;
3162  return vxids;
3163 }
#define GET_VXID_FROM_PGPROC(vxid, proc)
Definition: lock.h:79
uint32 TransactionId
Definition: c.h:520
PGPROC * MyProc
Definition: proc.c:67
#define UINT32_ACCESS_ONCE(var)
Definition: procarray.c:69
unsigned char uint8
Definition: c.h:372
PROC_HDR * ProcGlobal
Definition: proc.c:79
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
bool TransactionIdPrecedesOrEquals(TransactionId id1, TransactionId id2)
Definition: transam.c:319
TransactionId xmin
Definition: proc.h:129
static PGPROC * allProcs
Definition: procarray.c:242
Oid databaseId
Definition: proc.h:145
static ProcArrayStruct * procArray
Definition: procarray.c:240
#define VirtualTransactionIdIsValid(vxid)
Definition: lock.h:70
Oid MyDatabaseId
Definition: globals.c:85
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
void * palloc(Size size)
Definition: mcxt.c:950
uint8 * vacuumFlags
Definition: proc.h:321
#define TransactionIdIsValid(xid)
Definition: transam.h:41
Definition: proc.h:112

◆ GetMaxSnapshotSubxidCount()

int GetMaxSnapshotSubxidCount ( void  )

Definition at line 1938 of file procarray.c.

References TOTAL_MAX_CACHED_SUBXIDS.

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

1939 {
1940  return TOTAL_MAX_CACHED_SUBXIDS;
1941 }
#define TOTAL_MAX_CACHED_SUBXIDS

◆ GetMaxSnapshotXidCount()

int GetMaxSnapshotXidCount ( void  )

Definition at line 1927 of file procarray.c.

References ProcArrayStruct::maxProcs.

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

1928 {
1929  return procArray->maxProcs;
1930 }
static ProcArrayStruct * procArray
Definition: procarray.c:240

◆ GetOldestActiveTransactionId()

TransactionId GetOldestActiveTransactionId ( void  )

Definition at line 2729 of file procarray.c.

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

Referenced by CreateCheckPoint().

2730 {
2731  ProcArrayStruct *arrayP = procArray;
2732  TransactionId *other_xids = ProcGlobal->xids;
2733  TransactionId oldestRunningXid;
2734  int index;
2735 
2737 
2738  /*
2739  * Read nextXid, as the upper bound of what's still active.
2740  *
2741  * Reading a TransactionId is atomic, but we must grab the lock to make
2742  * sure that all XIDs < nextXid are already present in the proc array (or
2743  * have already completed), when we spin over it.
2744  */
2745  LWLockAcquire(XidGenLock, LW_SHARED);
2747  LWLockRelease(XidGenLock);
2748 
2749  /*
2750  * Spin over procArray collecting all xids and subxids.
2751  */
2752  LWLockAcquire(ProcArrayLock, LW_SHARED);
2753  for (index = 0; index < arrayP->numProcs; index++)
2754  {
2755  TransactionId xid;
2756 
2757  /* Fetch xid just once - see GetNewTransactionId */
2758  xid = UINT32_ACCESS_ONCE(other_xids[index]);
2759 
2760  if (!TransactionIdIsNormal(xid))
2761  continue;
2762 
2763  if (TransactionIdPrecedes(xid, oldestRunningXid))
2764  oldestRunningXid = xid;
2765 
2766  /*
2767  * Top-level XID of a transaction is always less than any of its
2768  * subxids, so we don't need to check if any of the subxids are
2769  * smaller than oldestRunningXid
2770  */
2771  }
2772  LWLockRelease(ProcArrayLock);
2773 
2774  return oldestRunningXid;
2775 }
uint32 TransactionId
Definition: c.h:520
#define UINT32_ACCESS_ONCE(var)
Definition: procarray.c:69
PROC_HDR * ProcGlobal
Definition: proc.c:79
bool RecoveryInProgress(void)
Definition: xlog.c:8074
FullTransactionId nextXid
Definition: transam.h:213
#define XidFromFullTransactionId(x)
Definition: transam.h:48
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
VariableCache ShmemVariableCache
Definition: varsup.c:34
TransactionId * xids
Definition: proc.h:309
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
static ProcArrayStruct * procArray
Definition: procarray.c:240
#define Assert(condition)
Definition: c.h:745
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
#define TransactionIdIsNormal(xid)
Definition: transam.h:42

◆ GetOldestNonRemovableTransactionId()

TransactionId GetOldestNonRemovableTransactionId ( Relation  rel)

Definition at line 1870 of file procarray.c.

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

Referenced by acquire_sample_rows(), collect_corrupt_items(), heapam_index_build_range_scan(), statapprox_heap(), vac_update_datfrozenxid(), and vacuum_set_xid_limits().

1871 {
1872  ComputeXidHorizonsResult horizons;
1873 
1874  ComputeXidHorizons(&horizons);
1875 
1876  /* select horizon appropriate for relation */
1877  if (rel == NULL || rel->rd_rel->relisshared)
1878  return horizons.shared_oldest_nonremovable;
1880  return horizons.catalog_oldest_nonremovable;
1881  else
1882  return horizons.data_oldest_nonremovable;
1883 }
static void ComputeXidHorizons(ComputeXidHorizonsResult *h)
Definition: procarray.c:1641
Form_pg_class rd_rel
Definition: rel.h:109
TransactionId catalog_oldest_nonremovable
Definition: procarray.c:230
TransactionId shared_oldest_nonremovable
Definition: procarray.c:213
#define RelationIsAccessibleInLogicalDecoding(relation)
Definition: rel.h:619
TransactionId data_oldest_nonremovable
Definition: procarray.c:236

◆ GetOldestSafeDecodingTransactionId()

TransactionId GetOldestSafeDecodingTransactionId ( bool  catalogOnly)

Definition at line 2794 of file procarray.c.

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

Referenced by CreateInitDecodingContext(), and SnapBuildInitialSnapshot().

2795 {
2796  ProcArrayStruct *arrayP = procArray;
2797  TransactionId oldestSafeXid;
2798  int index;
2799  bool recovery_in_progress = RecoveryInProgress();
2800 
2801  Assert(LWLockHeldByMe(ProcArrayLock));
2802 
2803  /*
2804  * Acquire XidGenLock, so no transactions can acquire an xid while we're
2805  * running. If no transaction with xid were running concurrently a new xid
2806  * could influence the RecentXmin et al.
2807  *
2808  * We initialize the computation to nextXid since that's guaranteed to be
2809  * a safe, albeit pessimal, value.
2810  */
2811  LWLockAcquire(XidGenLock, LW_SHARED);
2813 
2814  /*
2815  * If there's already a slot pegging the xmin horizon, we can start with
2816  * that value, it's guaranteed to be safe since it's computed by this
2817  * routine initially and has been enforced since. We can always use the
2818  * slot's general xmin horizon, but the catalog horizon is only usable
2819  * when only catalog data is going to be looked at.
2820  */
2823  oldestSafeXid))
2824  oldestSafeXid = procArray->replication_slot_xmin;
2825 
2826  if (catalogOnly &&
2829  oldestSafeXid))
2830  oldestSafeXid = procArray->replication_slot_catalog_xmin;
2831 
2832  /*
2833  * If we're not in recovery, we walk over the procarray and collect the
2834  * lowest xid. Since we're called with ProcArrayLock held and have
2835  * acquired XidGenLock, no entries can vanish concurrently, since
2836  * ProcGlobal->xids[i] is only set with XidGenLock held and only cleared
2837  * with ProcArrayLock held.
2838  *
2839  * In recovery we can't lower the safe value besides what we've computed
2840  * above, so we'll have to wait a bit longer there. We unfortunately can
2841  * *not* use KnownAssignedXidsGetOldestXmin() since the KnownAssignedXids
2842  * machinery can miss values and return an older value than is safe.
2843  */
2844  if (!recovery_in_progress)
2845  {
2846  TransactionId *other_xids = ProcGlobal->xids;
2847 
2848  /*
2849  * Spin over procArray collecting min(ProcGlobal->xids[i])
2850  */
2851  for (index = 0; index < arrayP->numProcs; index++)
2852  {
2853  TransactionId xid;
2854 
2855  /* Fetch xid just once - see GetNewTransactionId */
2856  xid = UINT32_ACCESS_ONCE(other_xids[index]);
2857 
2858  if (!TransactionIdIsNormal(xid))
2859  continue;
2860 
2861  if (TransactionIdPrecedes(xid, oldestSafeXid))
2862  oldestSafeXid = xid;
2863  }
2864  }
2865 
2866  LWLockRelease(XidGenLock);
2867 
2868  return oldestSafeXid;
2869 }
uint32 TransactionId
Definition: c.h:520
bool LWLockHeldByMe(LWLock *l)
Definition: lwlock.c:1928
#define UINT32_ACCESS_ONCE(var)
Definition: procarray.c:69
TransactionId replication_slot_catalog_xmin
Definition: procarray.c:98
PROC_HDR * ProcGlobal
Definition: proc.c:79
bool RecoveryInProgress(void)
Definition: xlog.c:8074
FullTransactionId nextXid
Definition: transam.h:213
#define XidFromFullTransactionId(x)
Definition: transam.h:48
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
VariableCache ShmemVariableCache
Definition: varsup.c:34
TransactionId * xids
Definition: proc.h:309
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
static ProcArrayStruct * procArray
Definition: procarray.c:240
TransactionId replication_slot_xmin
Definition: procarray.c:96
#define Assert(condition)
Definition: c.h:745
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
#define TransactionIdIsValid(xid)
Definition: transam.h:41
#define TransactionIdIsNormal(xid)
Definition: transam.h:42

◆ GetOldestTransactionIdConsideredRunning()

TransactionId GetOldestTransactionIdConsideredRunning ( void  )

Definition at line 1892 of file procarray.c.

References ComputeXidHorizons(), and ComputeXidHorizonsResult::oldest_considered_running.

Referenced by CreateCheckPoint(), and CreateRestartPoint().

1893 {
1894  ComputeXidHorizonsResult horizons;
1895 
1896  ComputeXidHorizons(&horizons);
1897 
1898  return horizons.oldest_considered_running;
1899 }
TransactionId oldest_considered_running
Definition: procarray.c:204
static void ComputeXidHorizons(ComputeXidHorizonsResult *h)
Definition: procarray.c:1641

◆ GetReplicationHorizons()

void GetReplicationHorizons ( TransactionId xmin,
TransactionId catalog_xmin 
)

Definition at line 1905 of file procarray.c.

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

Referenced by XLogWalRcvSendHSFeedback().

1906 {
1907  ComputeXidHorizonsResult horizons;
1908 
1909  ComputeXidHorizons(&horizons);
1910 
1911  /*
1912  * Don't want to use shared_oldest_nonremovable here, as that contains the
1913  * effect of replication slot's catalog_xmin. We want to send a separate
1914  * feedback for the catalog horizon, so the primary can remove data table
1915  * contents more aggressively.
1916  */
1917  *xmin = horizons.shared_oldest_nonremovable_raw;
1918  *catalog_xmin = horizons.slot_catalog_xmin;
1919 }
static void ComputeXidHorizons(ComputeXidHorizonsResult *h)
Definition: procarray.c:1641
TransactionId shared_oldest_nonremovable_raw
Definition: procarray.c:224
TransactionId slot_catalog_xmin
Definition: procarray.c:191

◆ GetRunningTransactionData()

RunningTransactions GetRunningTransactionData ( void  )

Definition at line 2554 of file procarray.c.

References Assert, XidCacheStatus::count, ereport, errcode(), errmsg(), ERROR, RunningTransactionsData::latestCompletedXid, VariableCacheData::latestCompletedXid, LW_SHARED, LWLockAcquire(), malloc, RunningTransactionsData::nextXid, VariableCacheData::nextXid, ProcArrayStruct::numProcs, RunningTransactionsData::oldestRunningXid, XidCacheStatus::overflowed, pg_read_barrier, ProcArrayStruct::pgprocnos, procArray, ProcGlobal, RecoveryInProgress(), ShmemVariableCache, RunningTransactionsData::subxcnt, RunningTransactionsData::subxid_overflow, PGPROC::subxids, PROC_HDR::subxidStates, TOTAL_MAX_CACHED_SUBXIDS, TransactionIdIsNormal, TransactionIdIsValid, TransactionIdPrecedes(), UINT32_ACCESS_ONCE, RunningTransactionsData::xcnt, XidFromFullTransactionId, XidCache::xids, RunningTransactionsData::xids, and PROC_HDR::xids.

Referenced by LogStandbySnapshot().

2555 {
2556  /* result workspace */
2557  static RunningTransactionsData CurrentRunningXactsData;
2558 
2559  ProcArrayStruct *arrayP = procArray;
2560  TransactionId *other_xids = ProcGlobal->xids;
2561  RunningTransactions CurrentRunningXacts = &CurrentRunningXactsData;
2562  TransactionId latestCompletedXid;
2563  TransactionId oldestRunningXid;
2564  TransactionId *xids;
2565  int index;
2566  int count;
2567  int subcount;
2568  bool suboverflowed;
2569 
2571 
2572  /*
2573  * Allocating space for maxProcs xids is usually overkill; numProcs would
2574  * be sufficient. But it seems better to do the malloc while not holding
2575  * the lock, so we can't look at numProcs. Likewise, we allocate much
2576  * more subxip storage than is probably needed.
2577  *
2578  * Should only be allocated in bgwriter, since only ever executed during
2579  * checkpoints.
2580  */
2581  if (CurrentRunningXacts->xids == NULL)
2582  {
2583  /*
2584  * First call
2585  */
2586  CurrentRunningXacts->xids = (TransactionId *)
2588  if (CurrentRunningXacts->xids == NULL)
2589  ereport(ERROR,
2590  (errcode(ERRCODE_OUT_OF_MEMORY),
2591  errmsg("out of memory")));
2592  }
2593 
2594  xids = CurrentRunningXacts->xids;
2595 
2596  count = subcount = 0;
2597  suboverflowed = false;
2598 
2599  /*
2600  * Ensure that no xids enter or leave the procarray while we obtain
2601  * snapshot.
2602  */
2603  LWLockAcquire(ProcArrayLock, LW_SHARED);
2604  LWLockAcquire(XidGenLock, LW_SHARED);
2605 
2606  latestCompletedXid =
2608  oldestRunningXid =
2610 
2611  /*
2612  * Spin over procArray collecting all xids
2613  */
2614  for (index = 0; index < arrayP->numProcs; index++)
2615  {
2616  TransactionId xid;
2617 
2618  /* Fetch xid just once - see GetNewTransactionId */
2619  xid = UINT32_ACCESS_ONCE(other_xids[index]);
2620 
2621  /*
2622  * We don't need to store transactions that don't have a TransactionId
2623  * yet because they will not show as running on a standby server.
2624  */
2625  if (!TransactionIdIsValid(xid))
2626  continue;
2627 
2628  /*
2629  * Be careful not to exclude any xids before calculating the values of
2630  * oldestRunningXid and suboverflowed, since these are used to clean
2631  * up transaction information held on standbys.
2632  */
2633  if (TransactionIdPrecedes(xid, oldestRunningXid))
2634  oldestRunningXid = xid;
2635 
2636  if (ProcGlobal->subxidStates[index].overflowed)
2637  suboverflowed = true;
2638 
2639  /*
2640  * If we wished to exclude xids this would be the right place for it.
2641  * Procs with the PROC_IN_VACUUM flag set don't usually assign xids,
2642  * but they do during truncation at the end when they get the lock and
2643  * truncate, so it is not much of a problem to include them if they
2644  * are seen and it is cleaner to include them.
2645  */
2646 
2647  xids[count++] = xid;
2648  }
2649 
2650  /*
2651  * Spin over procArray collecting all subxids, but only if there hasn't
2652  * been a suboverflow.
2653  */
2654  if (!suboverflowed)
2655  {
2656  XidCacheStatus *other_subxidstates = ProcGlobal->subxidStates;
2657 
2658  for (index = 0; index < arrayP->numProcs; index++)
2659  {
2660  int pgprocno = arrayP->pgprocnos[index];
2661  PGPROC *proc = &allProcs[pgprocno];
2662  int nsubxids;
2663 
2664  /*
2665  * Save subtransaction XIDs. Other backends can't add or remove
2666  * entries while we're holding XidGenLock.
2667  */
2668  nsubxids = other_subxidstates[index].count;
2669  if (nsubxids > 0)
2670  {
2671  /* barrier not really required, as XidGenLock is held, but ... */
2672  pg_read_barrier(); /* pairs with GetNewTransactionId */
2673 
2674  memcpy(&xids[count], (void *) proc->subxids.xids,
2675  nsubxids * sizeof(TransactionId));
2676  count += nsubxids;
2677  subcount += nsubxids;
2678 
2679  /*
2680  * Top-level XID of a transaction is always less than any of
2681  * its subxids, so we don't need to check if any of the
2682  * subxids are smaller than oldestRunningXid
2683  */
2684  }
2685  }
2686  }
2687 
2688  /*
2689  * It's important *not* to include the limits set by slots here because
2690  * snapbuild.c uses oldestRunningXid to manage its xmin horizon. If those
2691  * were to be included here the initial value could never increase because
2692  * of a circular dependency where slots only increase their limits when
2693  * running xacts increases oldestRunningXid and running xacts only
2694  * increases if slots do.
2695  */
2696 
2697  CurrentRunningXacts->xcnt = count - subcount;
2698  CurrentRunningXacts->subxcnt = subcount;
2699  CurrentRunningXacts->subxid_overflow = suboverflowed;
2701  CurrentRunningXacts->oldestRunningXid = oldestRunningXid;
2702  CurrentRunningXacts->latestCompletedXid = latestCompletedXid;
2703 
2704  Assert(TransactionIdIsValid(CurrentRunningXacts->nextXid));
2705  Assert(TransactionIdIsValid(CurrentRunningXacts->oldestRunningXid));
2706  Assert(TransactionIdIsNormal(CurrentRunningXacts->latestCompletedXid));
2707 
2708  /* We don't release the locks here, the caller is responsible for that */
2709 
2710  return CurrentRunningXacts;
2711 }
TransactionId oldestRunningXid
Definition: standby.h:76
uint32 TransactionId
Definition: c.h:520
XidCacheStatus * subxidStates
Definition: proc.h:315
#define UINT32_ACCESS_ONCE(var)
Definition: procarray.c:69
int errcode(int sqlerrcode)
Definition: elog.c:610
PROC_HDR * ProcGlobal
Definition: proc.c:79
TransactionId * xids
Definition: standby.h:79
FullTransactionId latestCompletedXid
Definition: transam.h:231
bool RecoveryInProgress(void)
Definition: xlog.c:8074
FullTransactionId nextXid
Definition: transam.h:213
bool overflowed
Definition: proc.h:43
#define XidFromFullTransactionId(x)
Definition: transam.h:48
TransactionId latestCompletedXid
Definition: standby.h:77
Definition: type.h:89
#define malloc(a)
Definition: header.h:50
#define ERROR
Definition: elog.h:43
VariableCache ShmemVariableCache
Definition: varsup.c:34
TransactionId * xids
Definition: proc.h:309
static PGPROC * allProcs
Definition: procarray.c:242
struct XidCache subxids
Definition: proc.h:200
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
static ProcArrayStruct * procArray
Definition: procarray.c:240
#define ereport(elevel,...)
Definition: elog.h:144
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
TransactionId xids[PGPROC_MAX_CACHED_SUBXIDS]
Definition: proc.h:48
#define TOTAL_MAX_CACHED_SUBXIDS
#define Assert(condition)
Definition: c.h:745
#define pg_read_barrier()
Definition: atomics.h:158
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
uint8 count
Definition: proc.h:41
TransactionId nextXid
Definition: standby.h:75
int errmsg(const char *fmt,...)
Definition: elog.c:824
#define TransactionIdIsValid(xid)
Definition: transam.h:41
#define TransactionIdIsNormal(xid)
Definition: transam.h:42
Definition: proc.h:112

◆ GetSnapshotData()

Snapshot GetSnapshotData ( Snapshot  snapshot)

Definition at line 2064 of file procarray.c.

References SnapshotData::active_count, Assert, SnapshotData::copied, XidCacheStatus::count, SnapshotData::curcid, GlobalVisState::definitely_needed, ereport, errcode(), errmsg(), ERROR, FullTransactionIdNewer(), FullXidRelativeTo(), GetCurrentCommandId(), GetMaxSnapshotSubxidCount(), GetMaxSnapshotXidCount(), GetSnapshotDataInitOldSnapshot(), GetSnapshotDataReuse(), InvalidTransactionId, KnownAssignedXidsGetAndSetXmin(), ProcArrayStruct::lastOverflowedXid, VariableCacheData::latestCompletedXid, likely, LW_SHARED, LWLockAcquire(), LWLockRelease(), malloc, GlobalVisState::maybe_needed, MyProc, NormalTransactionIdPrecedes, ProcArrayStruct::numProcs, VariableCacheData::oldestXid, pg_read_barrier, ProcArrayStruct::pgprocnos, PGPROC::pgxactoff, PROC_IN_LOGICAL_DECODING, PROC_IN_VACUUM, procArray, ProcGlobal, RecentXmin, RecoveryInProgress(), SnapshotData::regd_count, ProcArrayStruct::replication_slot_catalog_xmin, ProcArrayStruct::replication_slot_xmin, ShmemVariableCache, SnapshotData::snapXactCompletionCount, SnapshotData::suboverflowed, SnapshotData::subxcnt, PGPROC::subxids, PROC_HDR::subxidStates, SnapshotData::subxip, SnapshotData::takenDuringRecovery, TransactionIdAdvance, TransactionIdIsNormal, TransactionIdIsValid, TransactionIdOlder(), TransactionIdPrecedesOrEquals(), TransactionIdRetreatedBy(), TransactionXmin, UINT32_ACCESS_ONCE, vacuum_defer_cleanup_age, PROC_HDR::vacuumFlags, VariableCacheData::xactCompletionCount, SnapshotData::xcnt, PGPROC::xid, XidFromFullTransactionId, XidCache::xids, PROC_HDR::xids, SnapshotData::xip, SnapshotData::xmax, PGPROC::xmin, and SnapshotData::xmin.

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

2065 {
2066  ProcArrayStruct *arrayP = procArray;
2067  TransactionId *other_xids = ProcGlobal->xids;
2068  TransactionId xmin;
2069  TransactionId xmax;
2070  size_t count = 0;
2071  int subcount = 0;
2072  bool suboverflowed = false;
2073  FullTransactionId latest_completed;
2074  TransactionId oldestxid;
2075  int mypgxactoff;
2076  TransactionId myxid;
2077  uint64 curXactCompletionCount;
2078 
2079  TransactionId replication_slot_xmin = InvalidTransactionId;
2080  TransactionId replication_slot_catalog_xmin = InvalidTransactionId;
2081 
2082  Assert(snapshot != NULL);
2083 
2084  /*
2085  * Allocating space for maxProcs xids is usually overkill; numProcs would
2086  * be sufficient. But it seems better to do the malloc while not holding
2087  * the lock, so we can't look at numProcs. Likewise, we allocate much
2088  * more subxip storage than is probably needed.
2089  *
2090  * This does open a possibility for avoiding repeated malloc/free: since
2091  * maxProcs does not change at runtime, we can simply reuse the previous
2092  * xip arrays if any. (This relies on the fact that all callers pass
2093  * static SnapshotData structs.)
2094  */
2095  if (snapshot->xip == NULL)
2096  {
2097  /*
2098  * First call for this snapshot. Snapshot is same size whether or not
2099  * we are in recovery, see later comments.
2100  */
2101  snapshot->xip = (TransactionId *)
2103  if (snapshot->xip == NULL)
2104  ereport(ERROR,
2105  (errcode(ERRCODE_OUT_OF_MEMORY),
2106  errmsg("out of memory")));
2107  Assert(snapshot->subxip == NULL);
2108  snapshot->subxip = (TransactionId *)
2110  if (snapshot->subxip == NULL)
2111  ereport(ERROR,
2112  (errcode(ERRCODE_OUT_OF_MEMORY),
2113  errmsg("out of memory")));
2114  }
2115 
2116  /*
2117  * It is sufficient to get shared lock on ProcArrayLock, even if we are
2118  * going to set MyProc->xmin.
2119  */
2120  LWLockAcquire(ProcArrayLock, LW_SHARED);
2121 
2122  if (GetSnapshotDataReuse(snapshot))
2123  {
2124  LWLockRelease(ProcArrayLock);
2125  return snapshot;
2126  }
2127 
2128  latest_completed = ShmemVariableCache->latestCompletedXid;
2129  mypgxactoff = MyProc->pgxactoff;
2130  myxid = other_xids[mypgxactoff];
2131  Assert(myxid == MyProc->xid);
2132 
2133  oldestxid = ShmemVariableCache->oldestXid;
2134  curXactCompletionCount = ShmemVariableCache->xactCompletionCount;
2135 
2136  /* xmax is always latestCompletedXid + 1 */
2137  xmax = XidFromFullTransactionId(latest_completed);
2138  TransactionIdAdvance(xmax);
2140 
2141  /* initialize xmin calculation with xmax */
2142  xmin = xmax;
2143 
2144  /* take own xid into account, saves a check inside the loop */
2145  if (TransactionIdIsNormal(myxid) && NormalTransactionIdPrecedes(myxid, xmin))
2146  xmin = myxid;
2147 
2149 
2150  if (!snapshot->takenDuringRecovery)
2151  {
2152  size_t numProcs = arrayP->numProcs;
2153  TransactionId *xip = snapshot->xip;
2154  int *pgprocnos = arrayP->pgprocnos;
2155  XidCacheStatus *subxidStates = ProcGlobal->subxidStates;
2156  uint8 *allVacuumFlags = ProcGlobal->vacuumFlags;
2157 
2158  /*
2159  * First collect set of pgxactoff/xids that need to be included in the
2160  * snapshot.
2161  */
2162  for (size_t pgxactoff = 0; pgxactoff < numProcs; pgxactoff++)
2163  {
2164  /* Fetch xid just once - see GetNewTransactionId */
2165  TransactionId xid = UINT32_ACCESS_ONCE(other_xids[pgxactoff]);
2166  uint8 vacuumFlags;
2167 
2168  Assert(allProcs[arrayP->pgprocnos[pgxactoff]].pgxactoff == pgxactoff);
2169 
2170  /*
2171  * If the transaction has no XID assigned, we can skip it; it
2172  * won't have sub-XIDs either.
2173  */
2174  if (likely(xid == InvalidTransactionId))
2175  continue;
2176 
2177  /*
2178  * We don't include our own XIDs (if any) in the snapshot. It
2179  * needs to be includeded in the xmin computation, but we did so
2180  * outside the loop.
2181  */
2182  if (pgxactoff == mypgxactoff)
2183  continue;
2184 
2185  /*
2186  * The only way we are able to get here with a non-normal xid
2187  * is during bootstrap - with this backend using
2188  * BootstrapTransactionId. But the above test should filter
2189  * that out.
2190  */
2192 
2193  /*
2194  * If the XID is >= xmax, we can skip it; such transactions will
2195  * be treated as running anyway (and any sub-XIDs will also be >=
2196  * xmax).
2197  */
2198  if (!NormalTransactionIdPrecedes(xid, xmax))
2199  continue;
2200 
2201  /*
2202  * Skip over backends doing logical decoding which manages xmin
2203  * separately (check below) and ones running LAZY VACUUM.
2204  */
2205  vacuumFlags = allVacuumFlags[pgxactoff];
2206  if (vacuumFlags & (PROC_IN_LOGICAL_DECODING | PROC_IN_VACUUM))
2207  continue;
2208 
2209  if (NormalTransactionIdPrecedes(xid, xmin))
2210  xmin = xid;
2211 
2212  /* Add XID to snapshot. */
2213  xip[count++] = xid;
2214 
2215  /*
2216  * Save subtransaction XIDs if possible (if we've already
2217  * overflowed, there's no point). Note that the subxact XIDs must
2218  * be later than their parent, so no need to check them against
2219  * xmin. We could filter against xmax, but it seems better not to
2220  * do that much work while holding the ProcArrayLock.
2221  *
2222  * The other backend can add more subxids concurrently, but cannot
2223  * remove any. Hence it's important to fetch nxids just once.
2224  * Should be safe to use memcpy, though. (We needn't worry about
2225  * missing any xids added concurrently, because they must postdate
2226  * xmax.)
2227  *
2228  * Again, our own XIDs are not included in the snapshot.
2229  */
2230  if (!suboverflowed)
2231  {
2232 
2233  if (subxidStates[pgxactoff].overflowed)
2234  suboverflowed = true;
2235  else
2236  {
2237  int nsubxids = subxidStates[pgxactoff].count;
2238 
2239  if (nsubxids > 0)
2240  {
2241  int pgprocno = pgprocnos[pgxactoff];
2242  PGPROC *proc = &allProcs[pgprocno];
2243 
2244  pg_read_barrier(); /* pairs with GetNewTransactionId */
2245 
2246  memcpy(snapshot->subxip + subcount,
2247  (void *) proc->subxids.xids,
2248  nsubxids * sizeof(TransactionId));
2249  subcount += nsubxids;
2250  }
2251  }
2252  }
2253  }
2254  }
2255  else
2256  {
2257  /*
2258  * We're in hot standby, so get XIDs from KnownAssignedXids.
2259  *
2260  * We store all xids directly into subxip[]. Here's why:
2261  *
2262  * In recovery we don't know which xids are top-level and which are
2263  * subxacts, a design choice that greatly simplifies xid processing.
2264  *
2265  * It seems like we would want to try to put xids into xip[] only, but
2266  * that is fairly small. We would either need to make that bigger or
2267  * to increase the rate at which we WAL-log xid assignment; neither is
2268  * an appealing choice.
2269  *
2270  * We could try to store xids into xip[] first and then into subxip[]
2271  * if there are too many xids. That only works if the snapshot doesn't
2272  * overflow because we do not search subxip[] in that case. A simpler
2273  * way is to just store all xids in the subxact array because this is
2274  * by far the bigger array. We just leave the xip array empty.
2275  *
2276  * Either way we need to change the way XidInMVCCSnapshot() works
2277  * depending upon when the snapshot was taken, or change normal
2278  * snapshot processing so it matches.
2279  *
2280  * Note: It is possible for recovery to end before we finish taking
2281  * the snapshot, and for newly assigned transaction ids to be added to
2282  * the ProcArray. xmax cannot change while we hold ProcArrayLock, so
2283  * those newly added transaction ids would be filtered away, so we
2284  * need not be concerned about them.
2285  */
2286  subcount = KnownAssignedXidsGetAndSetXmin(snapshot->subxip, &xmin,
2287  xmax);
2288 
2290  suboverflowed = true;
2291  }
2292 
2293 
2294  /*
2295  * Fetch into local variable while ProcArrayLock is held - the
2296  * LWLockRelease below is a barrier, ensuring this happens inside the
2297  * lock.
2298  */
2299  replication_slot_xmin = procArray->replication_slot_xmin;
2300  replication_slot_catalog_xmin = procArray->replication_slot_catalog_xmin;
2301 
2303  MyProc->xmin = TransactionXmin = xmin;
2304 
2305  LWLockRelease(ProcArrayLock);
2306 
2307  /* maintain state for GlobalVis* */
2308  {
2309  TransactionId def_vis_xid;
2310  TransactionId def_vis_xid_data;
2311  FullTransactionId def_vis_fxid;
2312  FullTransactionId def_vis_fxid_data;
2313  FullTransactionId oldestfxid;
2314 
2315  /*
2316  * Converting oldestXid is only safe when xid horizon cannot advance,
2317  * i.e. holding locks. While we don't hold the lock anymore, all the
2318  * necessary data has been gathered with lock held.
2319  */
2320  oldestfxid = FullXidRelativeTo(latest_completed, oldestxid);
2321 
2322  /* apply vacuum_defer_cleanup_age */
2323  def_vis_xid_data =
2325 
2326  /* Check whether there's a replication slot requiring an older xmin. */
2327  def_vis_xid_data =
2328  TransactionIdOlder(def_vis_xid_data, replication_slot_xmin);
2329 
2330  /*
2331  * Rows in non-shared, non-catalog tables possibly could be vacuumed
2332  * if older than this xid.
2333  */
2334  def_vis_xid = def_vis_xid_data;
2335 
2336  /*
2337  * Check whether there's a replication slot requiring an older catalog
2338  * xmin.
2339  */
2340  def_vis_xid =
2341  TransactionIdOlder(replication_slot_catalog_xmin, def_vis_xid);
2342 
2343  def_vis_fxid = FullXidRelativeTo(latest_completed, def_vis_xid);
2344  def_vis_fxid_data = FullXidRelativeTo(latest_completed, def_vis_xid_data);
2345 
2346  /*
2347  * Check if we can increase upper bound. As a previous
2348  * GlobalVisUpdate() might have computed more aggressive values, don't
2349  * overwrite them if so.
2350  */
2352  FullTransactionIdNewer(def_vis_fxid,
2355  FullTransactionIdNewer(def_vis_fxid,
2358  FullTransactionIdNewer(def_vis_fxid_data,
2360 
2361  /*
2362  * Check if we know that we can initialize or increase the lower
2363  * bound. Currently the only cheap way to do so is to use
2364  * ShmemVariableCache->oldestXid as input.
2365  *
2366  * We should definitely be able to do better. We could e.g. put a
2367  * global lower bound value into ShmemVariableCache.
2368  */
2371  oldestfxid);
2374  oldestfxid);
2377  oldestfxid);
2378  }
2379 
2380  RecentXmin = xmin;
2382 
2383  snapshot->xmin = xmin;
2384  snapshot->xmax = xmax;
2385  snapshot->xcnt = count;
2386  snapshot->subxcnt = subcount;
2387  snapshot->suboverflowed = suboverflowed;
2388  snapshot->snapXactCompletionCount = curXactCompletionCount;
2389 
2390  snapshot->curcid = GetCurrentCommandId(false);
2391 
2392  /*
2393  * This is a new snapshot, so set both refcounts are zero, and mark it as
2394  * not copied in persistent memory.
2395  */
2396  snapshot->active_count = 0;
2397  snapshot->regd_count = 0;
2398  snapshot->copied = false;
2399 
2401 
2402  return snapshot;
2403 }
#define TransactionIdAdvance(dest)
Definition: transam.h:91
uint64 snapXactCompletionCount
Definition: snapshot.h:216
#define likely(x)
Definition: c.h:205
#define PROC_IN_LOGICAL_DECODING
Definition: proc.h:57
uint32 TransactionId
Definition: c.h:520
bool copied
Definition: snapshot.h:185
XidCacheStatus * subxidStates
Definition: proc.h:315
PGPROC * MyProc
Definition: proc.c:67
int vacuum_defer_cleanup_age
Definition: standby.c:39
#define UINT32_ACCESS_ONCE(var)
Definition: procarray.c:69
TransactionId replication_slot_catalog_xmin
Definition: procarray.c:98
unsigned char uint8
Definition: c.h:372
static FullTransactionId FullXidRelativeTo(FullTransactionId rel, TransactionId xid)
Definition: procarray.c:4115
TransactionId oldestXid
Definition: transam.h:215
int errcode(int sqlerrcode)
Definition: elog.c:610
TransactionId RecentXmin
Definition: snapmgr.c:164
uint64 xactCompletionCount
Definition: transam.h:241
PROC_HDR * ProcGlobal
Definition: proc.c:79
bool suboverflowed
Definition: snapshot.h:182
FullTransactionId latestCompletedXid
Definition: transam.h:231
bool RecoveryInProgress(void)
Definition: xlog.c:8074
uint32 regd_count
Definition: snapshot.h:205
#define XidFromFullTransactionId(x)
Definition: transam.h:48
TransactionId TransactionXmin
Definition: snapmgr.c:163
FullTransactionId definitely_needed
Definition: procarray.c:169
#define malloc(a)
Definition: header.h:50
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
static void GetSnapshotDataInitOldSnapshot(Snapshot snapshot)
Definition: procarray.c:1947
#define PROC_IN_VACUUM
Definition: proc.h:55
bool TransactionIdPrecedesOrEquals(TransactionId id1, TransactionId id2)
Definition: transam.c:319
#define ERROR
Definition: elog.h:43
TransactionId xmin
Definition: proc.h:129
static GlobalVisState GlobalVisSharedRels
Definition: procarray.c:263
VariableCache ShmemVariableCache
Definition: varsup.c:34
#define InvalidTransactionId
Definition: transam.h:31
TransactionId * xids
Definition: proc.h:309
static PGPROC * allProcs
Definition: procarray.c:242
TransactionId xmax
Definition: snapshot.h:158
TransactionId xmin
Definition: snapshot.h:157
struct XidCache subxids
Definition: proc.h:200
TransactionId lastOverflowedXid
Definition: procarray.c:93
TransactionId * xip
Definition: snapshot.h:168
static ProcArrayStruct * procArray
Definition: procarray.c:240
TransactionId replication_slot_xmin
Definition: procarray.c:96
CommandId curcid
Definition: snapshot.h:187
#define ereport(elevel,...)
Definition: elog.h:144
int GetMaxSnapshotXidCount(void)
Definition: procarray.c:1927
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
TransactionId xids[PGPROC_MAX_CACHED_SUBXIDS]
Definition: proc.h:48
static TransactionId TransactionIdOlder(TransactionId a, TransactionId b)
Definition: transam.h:327
#define Assert(condition)
Definition: c.h:745
#define pg_read_barrier()
Definition: atomics.h:158
bool takenDuringRecovery
Definition: snapshot.h:184
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
static TransactionId TransactionIdRetreatedBy(TransactionId xid, uint32 amount)
Definition: transam.h:315
static int KnownAssignedXidsGetAndSetXmin(TransactionId *xarray, TransactionId *xmin, TransactionId xmax)
Definition: procarray.c:4832
#define NormalTransactionIdPrecedes(id1, id2)
Definition: transam.h:147
FullTransactionId maybe_needed
Definition: procarray.c:172
uint8 count
Definition: proc.h:41
TransactionId xid
Definition: proc.h:124
static FullTransactionId FullTransactionIdNewer(FullTransactionId a, FullTransactionId b)
Definition: transam.h:353
uint32 xcnt
Definition: snapshot.h:169
int errmsg(const char *fmt,...)
Definition: elog.c:824
int pgxactoff
Definition: proc.h:139
uint8 * vacuumFlags
Definition: proc.h:321
static bool GetSnapshotDataReuse(Snapshot snapshot)
Definition: procarray.c:1981
int GetMaxSnapshotSubxidCount(void)
Definition: procarray.c:1938
CommandId GetCurrentCommandId(bool used)
Definition: xact.c:761
#define TransactionIdIsValid(xid)
Definition: transam.h:41
static GlobalVisState GlobalVisCatalogRels
Definition: procarray.c:264
#define TransactionIdIsNormal(xid)
Definition: transam.h:42
static GlobalVisState GlobalVisDataRels
Definition: procarray.c:265
Definition: proc.h:112
TransactionId * subxip
Definition: snapshot.h:180
uint32 active_count
Definition: snapshot.h:204
int32 subxcnt
Definition: snapshot.h:181

◆ GetSnapshotDataInitOldSnapshot()

static void GetSnapshotDataInitOldSnapshot ( Snapshot  snapshot)
static

Definition at line 1947 of file procarray.c.

References GetSnapshotCurrentTimestamp(), GetXLogInsertRecPtr(), InvalidXLogRecPtr, SnapshotData::lsn, MaintainOldSnapshotTimeMapping(), OldSnapshotThresholdActive(), SnapshotData::whenTaken, and SnapshotData::xmin.

Referenced by GetSnapshotData(), and GetSnapshotDataReuse().

1948 {
1950  {
1951  /*
1952  * If not using "snapshot too old" feature, fill related fields with
1953  * dummy values that don't require any locking.
1954  */
1955  snapshot->lsn = InvalidXLogRecPtr;
1956  snapshot->whenTaken = 0;
1957  }
1958  else
1959  {
1960  /*
1961  * Capture the current time and WAL stream location in case this
1962  * snapshot becomes old enough to need to fall back on the special
1963  * "old snapshot" logic.
1964  */
1965  snapshot->lsn = GetXLogInsertRecPtr();
1966  snapshot->whenTaken = GetSnapshotCurrentTimestamp();
1967  MaintainOldSnapshotTimeMapping(snapshot->whenTaken, snapshot->xmin);
1968  }
1969 }
#define InvalidXLogRecPtr
Definition: xlogdefs.h:28
static bool OldSnapshotThresholdActive(void)
Definition: snapmgr.h:102
XLogRecPtr lsn
Definition: snapshot.h:209
TimestampTz GetSnapshotCurrentTimestamp(void)
Definition: snapmgr.c:1686
XLogRecPtr GetXLogInsertRecPtr(void)
Definition: xlog.c:11499
TransactionId xmin
Definition: snapshot.h:157
TimestampTz whenTaken
Definition: snapshot.h:208
void MaintainOldSnapshotTimeMapping(TimestampTz whenTaken, TransactionId xmin)
Definition: snapmgr.c:1905

◆ GetSnapshotDataReuse()

static bool GetSnapshotDataReuse ( Snapshot  snapshot)
static

Definition at line 1981 of file procarray.c.

References SnapshotData::active_count, Assert, SnapshotData::copied, SnapshotData::curcid, GetCurrentCommandId(), GetSnapshotDataInitOldSnapshot(), LWLockHeldByMe(), MyProc, RecentXmin, SnapshotData::regd_count, ShmemVariableCache, SnapshotData::snapXactCompletionCount, TransactionIdIsValid, TransactionIdPrecedesOrEquals(), TransactionXmin, unlikely, VariableCacheData::xactCompletionCount, PGPROC::xmin, and SnapshotData::xmin.

Referenced by GetSnapshotData().

1982 {
1983  uint64 curXactCompletionCount;
1984 
1985  Assert(LWLockHeldByMe(ProcArrayLock));
1986 
1987  if (unlikely(snapshot->snapXactCompletionCount == 0))
1988  return false;
1989 
1990  curXactCompletionCount = ShmemVariableCache->xactCompletionCount;
1991  if (curXactCompletionCount != snapshot->snapXactCompletionCount)
1992  return false;
1993 
1994  /*
1995  * If the current xactCompletionCount is still the same as it was at the
1996  * time the snapshot was built, we can be sure that rebuilding the
1997  * contents of the snapshot the hard way would result in the same snapshot
1998  * contents:
1999  *
2000  * As explained in transam/README, the set of xids considered running by
2001  * GetSnapshotData() cannot change while ProcArrayLock is held. Snapshot
2002  * contents only depend on transactions with xids and xactCompletionCount
2003  * is incremented whenever a transaction with an xid finishes (while
2004  * holding ProcArrayLock) exclusively). Thus the xactCompletionCount check
2005  * ensures we would detect if the snapshot would have changed.
2006  *
2007  * As the snapshot contents are the same as it was before, it is is safe
2008  * to re-enter the snapshot's xmin into the PGPROC array. None of the rows
2009  * visible under the snapshot could already have been removed (that'd
2010  * require the set of running transactions to change) and it fulfills the
2011  * requirement that concurrent GetSnapshotData() calls yield the same
2012  * xmin.
2013  */
2015  MyProc->xmin = TransactionXmin = snapshot->xmin;
2016 
2017  RecentXmin = snapshot->xmin;
2019 
2020  snapshot->curcid = GetCurrentCommandId(false);
2021  snapshot->active_count = 0;
2022  snapshot->regd_count = 0;
2023  snapshot->copied = false;
2024 
2026 
2027  return true;
2028 }
uint64 snapXactCompletionCount
Definition: snapshot.h:216
bool copied
Definition: snapshot.h:185
bool LWLockHeldByMe(LWLock *l)
Definition: lwlock.c:1928
PGPROC * MyProc
Definition: proc.c:67
TransactionId RecentXmin
Definition: snapmgr.c:164
uint64 xactCompletionCount
Definition: transam.h:241
uint32 regd_count
Definition: snapshot.h:205
TransactionId TransactionXmin
Definition: snapmgr.c:163
static void GetSnapshotDataInitOldSnapshot(Snapshot snapshot)
Definition: procarray.c:1947
bool TransactionIdPrecedesOrEquals(TransactionId id1, TransactionId id2)
Definition: transam.c:319
TransactionId xmin
Definition: proc.h:129
VariableCache ShmemVariableCache
Definition: varsup.c:34
TransactionId xmin
Definition: snapshot.h:157
CommandId curcid
Definition: snapshot.h:187
#define Assert(condition)
Definition: c.h:745
#define unlikely(x)
Definition: c.h:206
CommandId GetCurrentCommandId(bool used)
Definition: xact.c:761
#define TransactionIdIsValid(xid)
Definition: transam.h:41
uint32 active_count
Definition: snapshot.h:204

◆ GetVirtualXIDsDelayingChkpt()

VirtualTransactionId* GetVirtualXIDsDelayingChkpt ( int *  nvxids)

Definition at line 2890 of file procarray.c.

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

Referenced by CreateCheckPoint().

2891 {
2892  VirtualTransactionId *vxids;
2893  ProcArrayStruct *arrayP = procArray;
2894  int count = 0;
2895  int index;
2896 
2897  /* allocate what's certainly enough result space */
2898  vxids = (VirtualTransactionId *)
2899  palloc(sizeof(VirtualTransactionId) * arrayP->maxProcs);
2900 
2901  LWLockAcquire(ProcArrayLock, LW_SHARED);
2902 
2903  for (index = 0; index < arrayP->numProcs; index++)
2904  {
2905  int pgprocno = arrayP->pgprocnos[index];
2906  PGPROC *proc = &allProcs[pgprocno];
2907 
2908  if (proc->delayChkpt)
2909  {
2910  VirtualTransactionId vxid;
2911 
2912  GET_VXID_FROM_PGPROC(vxid, *proc);
2913  if (VirtualTransactionIdIsValid(vxid))
2914  vxids[count++] = vxid;
2915  }
2916  }
2917 
2918  LWLockRelease(ProcArrayLock);
2919 
2920  *nvxids = count;
2921  return vxids;
2922 }
#define GET_VXID_FROM_PGPROC(vxid, proc)
Definition: lock.h:79
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
bool delayChkpt
Definition: proc.h:176
static PGPROC * allProcs
Definition: procarray.c:242
static ProcArrayStruct * procArray
Definition: procarray.c:240
#define VirtualTransactionIdIsValid(vxid)
Definition: lock.h:70
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
void * palloc(Size size)
Definition: mcxt.c:950
Definition: proc.h:112

◆ GlobalVisCheckRemovableXid()

bool GlobalVisCheckRemovableXid ( Relation  rel,
TransactionId  xid 
)

Definition at line 4094 of file procarray.c.

References GlobalVisTestFor(), and GlobalVisTestIsRemovableXid().

Referenced by _bt_page_recyclable(), _bt_vacuum_needs_cleanup(), and GinPageIsRecyclable().

4095 {
4097 
4098  state = GlobalVisTestFor(rel);
4099 
4100  return GlobalVisTestIsRemovableXid(state, xid);
4101 }
bool GlobalVisTestIsRemovableXid(GlobalVisState *state, TransactionId xid)
Definition: procarray.c:4028
GlobalVisState * GlobalVisTestFor(Relation rel)
Definition: procarray.c:3866
Definition: regguts.h:298

◆ GlobalVisIsRemovableFullXid()

bool GlobalVisIsRemovableFullXid ( Relation  rel,
FullTransactionId  fxid 
)

Definition at line 4080 of file procarray.c.

References GlobalVisTestFor(), and GlobalVisTestIsRemovableFullXid().

Referenced by gistPageRecyclable().

4081 {
4083 
4084  state = GlobalVisTestFor(rel);
4085 
4086  return GlobalVisTestIsRemovableFullXid(state, fxid);
4087 }
bool GlobalVisTestIsRemovableFullXid(GlobalVisState *state, FullTransactionId fxid)
Definition: procarray.c:3986
GlobalVisState * GlobalVisTestFor(Relation rel)
Definition: procarray.c:3866
Definition: regguts.h:298

◆ GlobalVisTestFor()

GlobalVisState* GlobalVisTestFor ( Relation  rel)

Definition at line 3866 of file procarray.c.

References Assert, GlobalVisState::definitely_needed, FullTransactionIdIsValid, GlobalVisCatalogRels, GlobalVisDataRels, GlobalVisSharedRels, IsCatalogRelation(), GlobalVisState::maybe_needed, RelationData::rd_rel, RecentXmin, RecoveryInProgress(), and RelationIsAccessibleInLogicalDecoding.

Referenced by get_actual_variable_endpoint(), GlobalVisCheckRemovableXid(), GlobalVisIsRemovableFullXid(), heap_hot_search_buffer(), heap_page_prune_opt(), lazy_scan_heap(), and vacuumRedirectAndPlaceholder().

3867 {
3868  bool need_shared;
3869  bool need_catalog;
3871 
3872  /* XXX: we should assert that a snapshot is pushed or registered */
3873  Assert(RecentXmin);
3874 
3875  if (!rel)
3876  need_shared = need_catalog = true;
3877  else
3878  {
3879  /*
3880  * Other kinds currently don't contain xids, nor always the necessary
3881  * logical decoding markers.
3882  */
3883  Assert(rel->rd_rel->relkind == RELKIND_RELATION ||
3884  rel->rd_rel->relkind == RELKIND_MATVIEW ||
3885  rel->rd_rel->relkind == RELKIND_TOASTVALUE);
3886 
3887  need_shared = rel->rd_rel->relisshared || RecoveryInProgress();
3888  need_catalog = IsCatalogRelation(rel) || RelationIsAccessibleInLogicalDecoding(rel);
3889  }
3890 
3891  if (need_shared)
3892  state = &GlobalVisSharedRels;
3893  else if (need_catalog)
3894  state = &GlobalVisCatalogRels;
3895  else
3896  state = &GlobalVisDataRels;
3897 
3900 
3901  return state;
3902 }
bool IsCatalogRelation(Relation relation)
Definition: catalog.c:98
#define FullTransactionIdIsValid(x)
Definition: transam.h:55
TransactionId RecentXmin
Definition: snapmgr.c:164
Form_pg_class rd_rel
Definition: rel.h:109
bool RecoveryInProgress(void)
Definition: xlog.c:8074
FullTransactionId definitely_needed
Definition: procarray.c:169
static GlobalVisState GlobalVisSharedRels
Definition: procarray.c:263
#define RelationIsAccessibleInLogicalDecoding(relation)
Definition: rel.h:619
#define Assert(condition)
Definition: c.h:745
Definition: regguts.h:298
FullTransactionId maybe_needed
Definition: procarray.c:172
static GlobalVisState GlobalVisCatalogRels
Definition: procarray.c:264
static GlobalVisState GlobalVisDataRels
Definition: procarray.c:265

◆ GlobalVisTestIsRemovableFullXid()

bool GlobalVisTestIsRemovableFullXid ( GlobalVisState state,
FullTransactionId  fxid 
)

Definition at line 3986 of file procarray.c.

References Assert, GlobalVisState::definitely_needed, FullTransactionIdFollowsOrEquals, FullTransactionIdPrecedes, GlobalVisTestShouldUpdate(), GlobalVisUpdate(), and GlobalVisState::maybe_needed.

Referenced by GlobalVisIsRemovableFullXid(), and GlobalVisTestIsRemovableXid().

3988 {
3989  /*
3990  * If fxid is older than maybe_needed bound, it definitely is visible to
3991  * everyone.
3992  */
3993  if (FullTransactionIdPrecedes(fxid, state->maybe_needed))
3994  return true;
3995 
3996  /*
3997  * If fxid is >= definitely_needed bound, it is very likely to still be
3998  * considered running.
3999  */
4001  return false;
4002 
4003  /*
4004  * fxid is between maybe_needed and definitely_needed, i.e. there might or
4005  * might not exist a snapshot considering fxid running. If it makes sense,
4006  * update boundaries and recheck.
4007  */
4008  if (GlobalVisTestShouldUpdate(state))
4009  {
4010  GlobalVisUpdate();
4011 
4013 
4014  return FullTransactionIdPrecedes(fxid, state->maybe_needed);
4015  }
4016  else
4017  return false;
4018 }
FullTransactionId definitely_needed
Definition: procarray.c:169
static bool GlobalVisTestShouldUpdate(GlobalVisState *state)
Definition: procarray.c:3915
#define Assert(condition)
Definition: c.h:745
#define FullTransactionIdFollowsOrEquals(a, b)
Definition: transam.h:54
FullTransactionId maybe_needed
Definition: procarray.c:172
#define FullTransactionIdPrecedes(a, b)
Definition: transam.h:51
static void GlobalVisUpdate(void)
Definition: procarray.c:3969

◆ GlobalVisTestIsRemovableXid()

bool GlobalVisTestIsRemovableXid ( GlobalVisState state,
TransactionId  xid 
)

Definition at line 4028 of file procarray.c.

References GlobalVisState::definitely_needed, FullXidRelativeTo(), and GlobalVisTestIsRemovableFullXid().

Referenced by GlobalVisCheckRemovableXid(), heap_page_prune_opt(), heap_prune_satisfies_vacuum(), HeapTupleIsSurelyDead(), HeapTupleSatisfiesNonVacuumable(), and vacuumRedirectAndPlaceholder().

4029 {
4030  FullTransactionId fxid;
4031 
4032  /*
4033  * Convert 32 bit argument to FullTransactionId. We can do so safely
4034  * because we know the xid has to, at the very least, be between
4035  * [oldestXid, nextFullXid), i.e. within 2 billion of xid. To avoid taking
4036  * a lock to determine either, we can just compare with
4037  * state->definitely_needed, which was based on those value at the time
4038  * the current snapshot was built.
4039  */
4040  fxid = FullXidRelativeTo(state->definitely_needed, xid);
4041 
4042  return GlobalVisTestIsRemovableFullXid(state, fxid);
4043 }
static FullTransactionId FullXidRelativeTo(FullTransactionId rel, TransactionId xid)
Definition: procarray.c:4115
bool GlobalVisTestIsRemovableFullXid(GlobalVisState *state, FullTransactionId fxid)
Definition: procarray.c:3986
FullTransactionId definitely_needed
Definition: procarray.c:169

◆ GlobalVisTestNonRemovableFullHorizon()

FullTransactionId GlobalVisTestNonRemovableFullHorizon ( GlobalVisState state)

Definition at line 4055 of file procarray.c.

References GlobalVisTestShouldUpdate(), GlobalVisUpdate(), and GlobalVisState::maybe_needed.

Referenced by GlobalVisTestNonRemovableHorizon().

4056 {
4057  /* acquire accurate horizon if not already done */
4058  if (GlobalVisTestShouldUpdate(state))
4059  GlobalVisUpdate();
4060 
4061  return state->maybe_needed;
4062 }
static bool GlobalVisTestShouldUpdate(GlobalVisState *state)
Definition: procarray.c:3915
FullTransactionId maybe_needed
Definition: procarray.c:172
static void GlobalVisUpdate(void)
Definition: procarray.c:3969

◆ GlobalVisTestNonRemovableHorizon()

TransactionId GlobalVisTestNonRemovableHorizon ( GlobalVisState state)

Definition at line 4066 of file procarray.c.

References GlobalVisTestNonRemovableFullHorizon(), and XidFromFullTransactionId.

Referenced by heap_page_prune_opt(), and heap_prune_satisfies_vacuum().

4067 {
4068  FullTransactionId cutoff;
4069 
4070  cutoff = GlobalVisTestNonRemovableFullHorizon(state);
4071 
4072  return XidFromFullTransactionId(cutoff);
4073 }
#define XidFromFullTransactionId(x)
Definition: transam.h:48
FullTransactionId GlobalVisTestNonRemovableFullHorizon(GlobalVisState *state)
Definition: procarray.c:4055

◆ GlobalVisTestShouldUpdate()

static bool GlobalVisTestShouldUpdate ( GlobalVisState state)
static

Definition at line 3915 of file procarray.c.

References ComputeXidHorizonsResultLastXmin, GlobalVisState::definitely_needed, FullTransactionIdFollowsOrEquals, GlobalVisState::maybe_needed, RecentXmin, and TransactionIdIsValid.

Referenced by GlobalVisTestIsRemovableFullXid(), and GlobalVisTestNonRemovableFullHorizon().

3916 {
3917  /* hasn't been updated yet */
3919  return true;
3920 
3921  /*
3922  * If the maybe_needed/definitely_needed boundaries are the same, it's
3923  * unlikely to be beneficial to refresh boundaries.
3924  */
3926  state->definitely_needed))
3927  return false;
3928 
3929  /* does the last snapshot built have a different xmin? */
3931 }
TransactionId RecentXmin
Definition: snapmgr.c:164
FullTransactionId definitely_needed
Definition: procarray.c:169
static TransactionId ComputeXidHorizonsResultLastXmin
Definition: procarray.c:272
#define FullTransactionIdFollowsOrEquals(a, b)
Definition: transam.h:54
FullTransactionId maybe_needed
Definition: procarray.c:172
#define TransactionIdIsValid(xid)
Definition: transam.h:41

◆ GlobalVisUpdate()

static void GlobalVisUpdate ( void  )
static

Definition at line 3969 of file procarray.c.

References ComputeXidHorizons().

Referenced by GlobalVisTestIsRemovableFullXid(), and GlobalVisTestNonRemovableFullHorizon().

3970 {
3971  ComputeXidHorizonsResult horizons;
3972 
3973  /* updates the horizons as a side-effect */
3974  ComputeXidHorizons(&horizons);
3975 }
static void ComputeXidHorizons(ComputeXidHorizonsResult *h)
Definition: procarray.c:1641

◆ GlobalVisUpdateApply()

static void GlobalVisUpdateApply ( ComputeXidHorizonsResult horizons)
static

Definition at line 3934 of file procarray.c.

References ComputeXidHorizonsResult::catalog_oldest_nonremovable, ComputeXidHorizonsResultLastXmin, ComputeXidHorizonsResult::data_oldest_nonremovable, GlobalVisState::definitely_needed, FullTransactionIdNewer(), FullXidRelativeTo(), ComputeXidHorizonsResult::latest_completed, GlobalVisState::maybe_needed, RecentXmin, and ComputeXidHorizonsResult::shared_oldest_nonremovable.

Referenced by ComputeXidHorizons().

3935 {
3938  horizons->shared_oldest_nonremovable);
3941  horizons->catalog_oldest_nonremovable);
3944  horizons->data_oldest_nonremovable);
3945 
3946  /*
3947  * In longer running transactions it's possible that transactions we
3948  * previously needed to treat as running aren't around anymore. So update
3949  * definitely_needed to not be earlier than maybe_needed.
3950  */
3960 
3962 }
FullTransactionId latest_completed
Definition: procarray.c:184
static FullTransactionId FullXidRelativeTo(FullTransactionId rel, TransactionId xid)
Definition: procarray.c:4115
TransactionId RecentXmin
Definition: snapmgr.c:164
TransactionId catalog_oldest_nonremovable
Definition: procarray.c:230
FullTransactionId definitely_needed
Definition: procarray.c:169
static GlobalVisState GlobalVisSharedRels
Definition: procarray.c:263
TransactionId shared_oldest_nonremovable
Definition: procarray.c:213
static TransactionId ComputeXidHorizonsResultLastXmin
Definition: procarray.c:272
FullTransactionId maybe_needed
Definition: procarray.c:172
static FullTransactionId FullTransactionIdNewer(FullTransactionId a, FullTransactionId b)
Definition: transam.h:353
TransactionId data_oldest_nonremovable
Definition: procarray.c:236
static GlobalVisState GlobalVisCatalogRels
Definition: procarray.c:264
static GlobalVisState GlobalVisDataRels
Definition: procarray.c:265

◆ HaveVirtualXIDsDelayingChkpt()

bool HaveVirtualXIDsDelayingChkpt ( VirtualTransactionId vxids,
int  nvxids 
)

Definition at line 2934 of file procarray.c.

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

Referenced by CreateCheckPoint().

2935 {
2936  bool result = false;
2937  ProcArrayStruct *arrayP = procArray;
2938  int index;
2939 
2940  LWLockAcquire(ProcArrayLock, LW_SHARED);
2941 
2942  for (index = 0; index < arrayP->numProcs; index++)
2943  {
2944  int pgprocno = arrayP->pgprocnos[index];
2945  PGPROC *proc = &allProcs[pgprocno];
2946  VirtualTransactionId vxid;
2947 
2948  GET_VXID_FROM_PGPROC(vxid, *proc);
2949 
2950  if (proc->delayChkpt && VirtualTransactionIdIsValid(vxid))
2951  {
2952  int i;
2953 
2954  for (i = 0; i < nvxids; i++)
2955  {
2956  if (VirtualTransactionIdEquals(vxid, vxids[i]))
2957  {
2958  result = true;
2959  break;
2960  }
2961  }
2962  if (result)
2963  break;
2964  }
2965  }
2966 
2967  LWLockRelease(ProcArrayLock);
2968 
2969  return result;
2970 }
#define GET_VXID_FROM_PGPROC(vxid, proc)
Definition: lock.h:79
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
#define VirtualTransactionIdEquals(vxid1, vxid2)
Definition: lock.h:73
bool delayChkpt
Definition: proc.h:176
static PGPROC * allProcs
Definition: procarray.c:242
static ProcArrayStruct * procArray
Definition: procarray.c:240
#define VirtualTransactionIdIsValid(vxid)
Definition: lock.h:70
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
int i
Definition: proc.h:112

◆ IsBackendPid()

bool IsBackendPid ( int  pid)

Definition at line 3075 of file procarray.c.

References BackendPidGetProc().

Referenced by pg_stat_get_subscription().

3076 {
3077  return (BackendPidGetProc(pid) != NULL);
3078 }
PGPROC * BackendPidGetProc(int pid)
Definition: procarray.c:2980

◆ KnownAssignedXidExists()

static bool KnownAssignedXidExists ( TransactionId  xid)
static

Definition at line 4679 of file procarray.c.

References Assert, KnownAssignedXidsSearch(), and TransactionIdIsValid.

Referenced by TransactionIdIsInProgress().

4680 {
4682 
4683  return KnownAssignedXidsSearch(xid, false);
4684 }
#define Assert(condition)
Definition: c.h:745
static bool KnownAssignedXidsSearch(TransactionId xid, bool remove)
Definition: procarray.c:4586
#define TransactionIdIsValid(xid)
Definition: transam.h:41

◆ KnownAssignedXidsAdd()

static void KnownAssignedXidsAdd ( TransactionId  from_xid,
TransactionId  to_xid,
bool  exclusive_lock 
)
static

Definition at line 4468 of file procarray.c.

References Assert, elog, ERROR, ProcArrayStruct::headKnownAssignedXids, i, ProcArrayStruct::known_assigned_xids_lck, KnownAssignedXids, KnownAssignedXidsCompress(), KnownAssignedXidsDisplay(), KnownAssignedXidsValid, LOG, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), ProcArrayStruct::maxKnownAssignedXids, ProcArrayStruct::numKnownAssignedXids, procArray, SpinLockAcquire, SpinLockRelease, ProcArrayStruct::tailKnownAssignedXids, TransactionIdAdvance, TransactionIdFollowsOrEquals(), TransactionIdPrecedes(), and TransactionIdPrecedesOrEquals().

Referenced by ProcArrayApplyRecoveryInfo(), and RecordKnownAssignedTransactionIds().

4470 {
4471  ProcArrayStruct *pArray = procArray;
4472  TransactionId next_xid;
4473  int head,
4474  tail;
4475  int nxids;
4476  int i;
4477 
4478  Assert(TransactionIdPrecedesOrEquals(from_xid, to_xid));
4479 
4480  /*
4481  * Calculate how many array slots we'll need. Normally this is cheap; in
4482  * the unusual case where the XIDs cross the wrap point, we do it the hard
4483  * way.
4484  */
4485  if (to_xid >= from_xid)
4486  nxids = to_xid - from_xid + 1;
4487  else
4488  {
4489  nxids = 1;
4490  next_xid = from_xid;
4491  while (TransactionIdPrecedes(next_xid, to_xid))
4492  {
4493  nxids++;
4494  TransactionIdAdvance(next_xid);
4495  }
4496  }
4497 
4498  /*
4499  * Since only the startup process modifies the head/tail pointers, we
4500  * don't need a lock to read them here.
4501  */
4502  head = pArray->headKnownAssignedXids;
4503  tail = pArray->tailKnownAssignedXids;
4504 
4505  Assert(head >= 0 && head <= pArray->maxKnownAssignedXids);
4506  Assert(tail >= 0 && tail < pArray->maxKnownAssignedXids);
4507 
4508  /*
4509  * Verify that insertions occur in TransactionId sequence. Note that even
4510  * if the last existing element is marked invalid, it must still have a
4511  * correctly sequenced XID value.
4512  */
4513  if (head > tail &&
4514  TransactionIdFollowsOrEquals(KnownAssignedXids[head - 1], from_xid))
4515  {
4517  elog(ERROR, "out-of-order XID insertion in KnownAssignedXids");
4518  }
4519 
4520  /*
4521  * If our xids won't fit in the remaining space, compress out free space
4522  */
4523  if (head + nxids > pArray->maxKnownAssignedXids)
4524  {
4525  /* must hold lock to compress */
4526  if (!exclusive_lock)
4527  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
4528 
4530 
4531  head = pArray->headKnownAssignedXids;
4532  /* note: we no longer care about the tail pointer */
4533 
4534  if (!exclusive_lock)
4535  LWLockRelease(ProcArrayLock);
4536 
4537  /*
4538  * If it still won't fit then we're out of memory
4539  */
4540  if (head + nxids > pArray->maxKnownAssignedXids)
4541  elog(ERROR, "too many KnownAssignedXids");
4542  }
4543 
4544  /* Now we can insert the xids into the space starting at head */
4545  next_xid = from_xid;
4546  for (i = 0; i < nxids; i++)
4547  {
4548  KnownAssignedXids[head] = next_xid;
4549  KnownAssignedXidsValid[head] = true;
4550  TransactionIdAdvance(next_xid);
4551  head++;
4552  }
4553 
4554  /* Adjust count of number of valid entries */
4555  pArray->numKnownAssignedXids += nxids;
4556 
4557  /*
4558  * Now update the head pointer. We use a spinlock to protect this
4559  * pointer, not because the update is likely to be non-atomic, but to
4560  * ensure that other processors see the above array updates before they
4561  * see the head pointer change.
4562  *
4563  * If we're holding ProcArrayLock exclusively, there's no need to take the
4564  * spinlock.
4565  */
4566  if (exclusive_lock)
4567  pArray->headKnownAssignedXids = head;
4568  else
4569  {
4571  pArray->headKnownAssignedXids = head;
4573  }
4574 }
#define TransactionIdAdvance(dest)
Definition: transam.h:91
static void KnownAssignedXidsDisplay(int trace_level)
Definition: procarray.c:4925
uint32 TransactionId
Definition: c.h:520
bool TransactionIdFollowsOrEquals(TransactionId id1, TransactionId id2)
Definition: transam.c:349
slock_t known_assigned_xids_lck
Definition: procarray.c:84
#define LOG
Definition: elog.h:26
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
#define SpinLockAcquire(lock)
Definition: spin.h:62
bool TransactionIdPrecedesOrEquals(TransactionId id1, TransactionId id2)
Definition: transam.c:319
#define ERROR
Definition: elog.h:43
int maxKnownAssignedXids
Definition: procarray.c:80
int numKnownAssignedXids
Definition: procarray.c:81
static bool * KnownAssignedXidsValid
Definition: procarray.c:248
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
static ProcArrayStruct * procArray
Definition: procarray.c:240
#define SpinLockRelease(lock)
Definition: spin.h:64
#define Assert(condition)
Definition: c.h:745
static TransactionId * KnownAssignedXids
Definition: procarray.c:247
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
static void KnownAssignedXidsCompress(bool force)
Definition: procarray.c:4406
#define elog(elevel,...)
Definition: elog.h:214
int i
int tailKnownAssignedXids
Definition: procarray.c:82
int headKnownAssignedXids
Definition: procarray.c:83

◆ KnownAssignedXidsCompress()

static void KnownAssignedXidsCompress ( bool  force)
static

Definition at line 4406 of file procarray.c.

References ProcArrayStruct::headKnownAssignedXids, i, KnownAssignedXids, KnownAssignedXidsValid, ProcArrayStruct::numKnownAssignedXids, procArray, PROCARRAY_MAXPROCS, and ProcArrayStruct::tailKnownAssignedXids.

Referenced by KnownAssignedXidsAdd(), KnownAssignedXidsRemovePreceding(), and KnownAssignedXidsRemoveTree().

4407 {
4408  ProcArrayStruct *pArray = procArray;
4409  int head,
4410  tail;
4411  int compress_index;
4412  int i;
4413 
4414  /* no spinlock required since we hold ProcArrayLock exclusively */
4415  head = pArray->headKnownAssignedXids;
4416  tail = pArray->tailKnownAssignedXids;
4417 
4418  if (!force)
4419  {
4420  /*
4421  * If we can choose how much to compress, use a heuristic to avoid
4422  * compressing too often or not often enough.
4423  *
4424  * Heuristic is if we have a large enough current spread and less than
4425  * 50% of the elements are currently in use, then compress. This
4426  * should ensure we compress fairly infrequently. We could compress
4427  * less often though the virtual array would spread out more and
4428  * snapshots would become more expensive.
4429  */
4430  int nelements = head - tail;
4431 
4432  if (nelements < 4 * PROCARRAY_MAXPROCS ||
4433  nelements < 2 * pArray->numKnownAssignedXids)
4434  return;
4435  }
4436 
4437  /*
4438  * We compress the array by reading the valid values from tail to head,
4439  * re-aligning data to 0th element.
4440  */
4441  compress_index = 0;
4442  for (i = tail; i < head; i++)
4443  {
4444  if (KnownAssignedXidsValid[i])
4445  {
4446  KnownAssignedXids[compress_index] = KnownAssignedXids[i];
4447  KnownAssignedXidsValid[compress_index] = true;
4448  compress_index++;
4449  }
4450  }
4451 
4452  pArray->tailKnownAssignedXids = 0;
4453  pArray->headKnownAssignedXids = compress_index;
4454 }
#define PROCARRAY_MAXPROCS
static bool * KnownAssignedXidsValid
Definition: procarray.c:248
static ProcArrayStruct * procArray
Definition: procarray.c:240
static TransactionId * KnownAssignedXids
Definition: procarray.c:247
int i
int tailKnownAssignedXids
Definition: procarray.c:82
int headKnownAssignedXids
Definition: procarray.c:83

◆ KnownAssignedXidsDisplay()

static void KnownAssignedXidsDisplay ( int  trace_level)
static

Definition at line 4925 of file procarray.c.

References appendStringInfo(), buf, StringInfoData::data, elog, ProcArrayStruct::headKnownAssignedXids, i, initStringInfo(), KnownAssignedXids, KnownAssignedXidsValid, ProcArrayStruct::numKnownAssignedXids, pfree(), procArray, and ProcArrayStruct::tailKnownAssignedXids.

Referenced by KnownAssignedXidsAdd(), and ProcArrayApplyRecoveryInfo().

4926 {
4927  ProcArrayStruct *pArray = procArray;
4929  int head,
4930  tail,
4931  i;
4932  int nxids = 0;
4933 
4934  tail = pArray->tailKnownAssignedXids;
4935  head = pArray->headKnownAssignedXids;
4936 
4937  initStringInfo(&buf);
4938 
4939  for (i = tail; i < head; i++)
4940  {
4941  if (KnownAssignedXidsValid[i])
4942  {
4943  nxids++;
4944  appendStringInfo(&buf, "[%d]=%u ", i, KnownAssignedXids[i]);
4945  }
4946  }
4947 
4948  elog(trace_level, "%d KnownAssignedXids (num=%d tail=%d head=%d) %s",
4949  nxids,
4950  pArray->numKnownAssignedXids,
4951  pArray->tailKnownAssignedXids,
4952  pArray->headKnownAssignedXids,
4953  buf.data);
4954 
4955  pfree(buf.data);
4956 }
void pfree(void *pointer)
Definition: mcxt.c:1057
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
static char * buf
Definition: pg_test_fsync.c:67
int numKnownAssignedXids
Definition: procarray.c:81
static bool * KnownAssignedXidsValid
Definition: procarray.c:248
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
static ProcArrayStruct * procArray
Definition: procarray.c:240
static TransactionId * KnownAssignedXids
Definition: procarray.c:247
#define elog(elevel,...)
Definition: elog.h:214
int i
int tailKnownAssignedXids
Definition: procarray.c:82
int headKnownAssignedXids
Definition: procarray.c:83

◆ KnownAssignedXidsGet()

static int KnownAssignedXidsGet ( TransactionId xarray,
TransactionId  xmax 
)
static

Definition at line 4818 of file procarray.c.

References InvalidTransactionId, and KnownAssignedXidsGetAndSetXmin().

Referenced by TransactionIdIsInProgress().

4819 {
4821 
4822  return KnownAssignedXidsGetAndSetXmin(xarray, &xtmp, xmax);
4823 }
uint32 TransactionId
Definition: c.h:520
#define InvalidTransactionId
Definition: transam.h:31
static int KnownAssignedXidsGetAndSetXmin(TransactionId *xarray, TransactionId *xmin, TransactionId xmax)
Definition: procarray.c:4832

◆ KnownAssignedXidsGetAndSetXmin()

static int KnownAssignedXidsGetAndSetXmin ( TransactionId xarray,
TransactionId xmin,
TransactionId  xmax 
)
static

Definition at line 4832 of file procarray.c.

References ProcArrayStruct::headKnownAssignedXids, i, ProcArrayStruct::known_assigned_xids_lck, KnownAssignedXids, KnownAssignedXidsValid, SpinLockAcquire, SpinLockRelease, ProcArrayStruct::tailKnownAssignedXids, TransactionIdFollowsOrEquals(), TransactionIdIsValid, and TransactionIdPrecedes().

Referenced by GetSnapshotData(), and KnownAssignedXidsGet().

4834 {
4835  int count = 0;
4836  int head,
4837  tail;
4838  int i;
4839 
4840  /*
4841  * Fetch head just once, since it may change while we loop. We can stop
4842  * once we reach the initially seen head, since we are certain that an xid
4843  * cannot enter and then leave the array while we hold ProcArrayLock. We
4844  * might miss newly-added xids, but they should be >= xmax so irrelevant
4845  * anyway.
4846  *
4847  * Must take spinlock to ensure we see up-to-date array contents.
4848  */
4853 
4854  for (i = tail; i < head; i++)
4855  {
4856  /* Skip any gaps in the array */
4857  if (KnownAssignedXidsValid[i])
4858  {
4859  TransactionId knownXid = KnownAssignedXids[i];
4860 
4861  /*
4862  * Update xmin if required. Only the first XID need be checked,
4863  * since the array is sorted.
4864  */
4865  if (count == 0 &&
4866  TransactionIdPrecedes(knownXid, *xmin))
4867  *xmin = knownXid;
4868 
4869  /*
4870  * Filter out anything >= xmax, again relying on sorted property
4871  * of array.
4872  */
4873  if (TransactionIdIsValid(xmax) &&
4874  TransactionIdFollowsOrEquals(knownXid, xmax))
4875  break;
4876 
4877  /* Add knownXid into output array */
4878  xarray[count++] = knownXid;
4879  }
4880  }
4881 
4882  return count;
4883 }
uint32 TransactionId
Definition: c.h:520
bool TransactionIdFollowsOrEquals(TransactionId id1, TransactionId id2)
Definition: transam.c:349
slock_t known_assigned_xids_lck
Definition: procarray.c:84
#define SpinLockAcquire(lock)
Definition: spin.h:62
static bool * KnownAssignedXidsValid
Definition: procarray.c:248
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
static ProcArrayStruct * procArray
Definition: procarray.c:240
#define SpinLockRelease(lock)
Definition: spin.h:64
static TransactionId * KnownAssignedXids
Definition: procarray.c:247
int i
#define TransactionIdIsValid(xid)
Definition: transam.h:41
int tailKnownAssignedXids
Definition: procarray.c:82
int headKnownAssignedXids
Definition: procarray.c:83

◆ KnownAssignedXidsGetOldestXmin()

static TransactionId KnownAssignedXidsGetOldestXmin ( void  )
static

Definition at line 4890 of file procarray.c.

References ProcArrayStruct::headKnownAssignedXids, i, InvalidTransactionId, ProcArrayStruct::known_assigned_xids_lck, KnownAssignedXids, KnownAssignedXidsValid, SpinLockAcquire, SpinLockRelease, and ProcArrayStruct::tailKnownAssignedXids.

Referenced by ComputeXidHorizons().

4891 {
4892  int head,
4893  tail;
4894  int i;
4895 
4896  /*
4897  * Fetch head just once, since it may change while we loop.
4898  */
4903 
4904  for (i = tail; i < head; i++)
4905  {
4906  /* Skip any gaps in the array */
4907  if (KnownAssignedXidsValid[i])
4908  return KnownAssignedXids[i];
4909  }
4910 
4911  return InvalidTransactionId;
4912 }
slock_t known_assigned_xids_lck
Definition: procarray.c:84
#define SpinLockAcquire(lock)
Definition: spin.h:62
#define InvalidTransactionId
Definition: transam.h:31
static bool * KnownAssignedXidsValid
Definition: procarray.c:248
static ProcArrayStruct * procArray
Definition: procarray.c:240
#define SpinLockRelease(lock)
Definition: spin.h:64
static TransactionId * KnownAssignedXids
Definition: procarray.c:247
int i
int tailKnownAssignedXids
Definition: procarray.c:82
int headKnownAssignedXids
Definition: procarray.c:83

◆ KnownAssignedXidsRemove()

static void KnownAssignedXidsRemove ( TransactionId  xid)
static

Definition at line 4692 of file procarray.c.

References Assert, DEBUG4, elog, KnownAssignedXidsSearch(), trace_recovery(), and TransactionIdIsValid.

Referenced by KnownAssignedXidsRemoveTree().

4693 {
4695 
4696  elog(trace_recovery(DEBUG4), "remove KnownAssignedXid %u", xid);
4697 
4698  /*
4699  * Note: we cannot consider it an error to remove an XID that's not
4700  * present. We intentionally remove subxact IDs while processing
4701  * XLOG_XACT_ASSIGNMENT, to avoid array overflow. Then those XIDs will be
4702  * removed again when the top-level xact commits or aborts.
4703  *
4704  * It might be possible to track such XIDs to distinguish this case from
4705  * actual errors, but it would be complicated and probably not worth it.
4706  * So, just ignore the search result.
4707  */
4708  (void) KnownAssignedXidsSearch(xid, true);
4709 }
#define DEBUG4
Definition: elog.h:22
int trace_recovery(int trace_level)
Definition: elog.c:3543
#define Assert(condition)
Definition: c.h:745
static bool KnownAssignedXidsSearch(TransactionId xid, bool remove)
Definition: procarray.c:4586
#define elog(elevel,...)
Definition: elog.h:214
#define TransactionIdIsValid(xid)
Definition: transam.h:41

◆ KnownAssignedXidsRemovePreceding()

static void KnownAssignedXidsRemovePreceding ( TransactionId  xid)
static

Definition at line 4740 of file procarray.c.

References Assert, DEBUG4, elog, ProcArrayStruct::headKnownAssignedXids, i, KnownAssignedXids, KnownAssignedXidsCompress(), KnownAssignedXidsValid, ProcArrayStruct::numKnownAssignedXids, procArray, StandbyTransactionIdIsPrepared(), ProcArrayStruct::tailKnownAssignedXids, trace_recovery(), TransactionIdFollowsOrEquals(), and TransactionIdIsValid.

Referenced by ExpireAllKnownAssignedTransactionIds(), and ExpireOldKnownAssignedTransactionIds().

4741 {
4742  ProcArrayStruct *pArray = procArray;
4743  int count = 0;
4744  int head,
4745  tail,
4746  i;
4747 
4748  if (!TransactionIdIsValid(removeXid))
4749  {
4750  elog(trace_recovery(DEBUG4), "removing all KnownAssignedXids");
4751  pArray->numKnownAssignedXids = 0;
4752  pArray->headKnownAssignedXids = pArray->tailKnownAssignedXids = 0;
4753  return;
4754  }
4755 
4756  elog(trace_recovery(DEBUG4), "prune KnownAssignedXids to %u", removeXid);
4757 
4758  /*
4759  * Mark entries invalid starting at the tail. Since array is sorted, we
4760  * can stop as soon as we reach an entry >= removeXid.
4761  */
4762  tail = pArray->tailKnownAssignedXids;
4763  head = pArray->headKnownAssignedXids;
4764 
4765  for (i = tail; i < head; i++)
4766  {
4767  if (KnownAssignedXidsValid[i])
4768  {
4769  TransactionId knownXid = KnownAssignedXids[i];
4770 
4771  if (TransactionIdFollowsOrEquals(knownXid, removeXid))
4772  break;
4773 
4774  if (!StandbyTransactionIdIsPrepared(knownXid))
4775  {
4776  KnownAssignedXidsValid[i] = false;
4777  count++;
4778  }
4779  }
4780  }
4781 
4782  pArray->numKnownAssignedXids -= count;
4783  Assert(pArray->numKnownAssignedXids >= 0);
4784 
4785  /*
4786  * Advance the tail pointer if we've marked the tail item invalid.
4787  */
4788  for (i = tail; i < head; i++)
4789  {
4790  if (KnownAssignedXidsValid[i])
4791  break;
4792  }
4793  if (i >= head)
4794  {
4795  /* Array is empty, so we can reset both pointers */
4796  pArray->headKnownAssignedXids = 0;
4797  pArray->tailKnownAssignedXids = 0;
4798  }
4799  else
4800  {
4801  pArray->tailKnownAssignedXids = i;
4802  }
4803 
4804  /* Opportunistically compress the array */
4806 }
uint32 TransactionId
Definition: c.h:520
bool TransactionIdFollowsOrEquals(TransactionId id1, TransactionId id2)
Definition: transam.c:349
#define DEBUG4
Definition: elog.h:22
int trace_recovery(int trace_level)
Definition: elog.c:3543
bool StandbyTransactionIdIsPrepared(TransactionId xid)
Definition: twophase.c:1369
int numKnownAssignedXids
Definition: procarray.c:81
static bool * KnownAssignedXidsValid
Definition: procarray.c:248
static ProcArrayStruct * procArray
Definition: procarray.c:240
#define Assert(condition)
Definition: c.h:745
static TransactionId * KnownAssignedXids
Definition: procarray.c:247
static void KnownAssignedXidsCompress(bool force)
Definition: procarray.c:4406
#define elog(elevel,...)
Definition: elog.h:214
int i
#define TransactionIdIsValid(xid)
Definition: transam.h:41
int tailKnownAssignedXids
Definition: procarray.c:82
int headKnownAssignedXids
Definition: procarray.c:83

◆ KnownAssignedXidsRemoveTree()

static void KnownAssignedXidsRemoveTree ( TransactionId  xid,
int  nsubxids,
TransactionId subxids 
)
static

Definition at line 4718 of file procarray.c.

References i, KnownAssignedXidsCompress(), KnownAssignedXidsRemove(), and TransactionIdIsValid.

Referenced by ExpireTreeKnownAssignedTransactionIds(), and ProcArrayApplyXidAssignment().

4720 {
4721  int i;
4722 
4723  if (TransactionIdIsValid(xid))
4725 
4726  for (i = 0; i < nsubxids; i++)
4727  KnownAssignedXidsRemove(subxids[i]);
4728 
4729  /* Opportunistically compress the array */
4731 }
static void KnownAssignedXidsCompress(bool force)
Definition: procarray.c:4406
static void KnownAssignedXidsRemove(TransactionId xid)
Definition: procarray.c:4692
int i
#define TransactionIdIsValid(xid)
Definition: transam.h:41

◆ KnownAssignedXidsReset()

static void KnownAssignedXidsReset ( void  )
static

Definition at line 4963 of file procarray.c.

References ProcArrayStruct::headKnownAssignedXids, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), ProcArrayStruct::numKnownAssignedXids, procArray, and ProcArrayStruct::tailKnownAssignedXids.

Referenced by ProcArrayApplyRecoveryInfo().

4964 {
4965  ProcArrayStruct *pArray = procArray;
4966 
4967  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
4968 
4969  pArray->numKnownAssignedXids = 0;
4970  pArray->tailKnownAssignedXids = 0;
4971  pArray->headKnownAssignedXids = 0;
4972 
4973  LWLockRelease(ProcArrayLock);
4974 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
int numKnownAssignedXids
Definition: procarray.c:81
static ProcArrayStruct * procArray
Definition: procarray.c:240
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
int tailKnownAssignedXids
Definition: procarray.c:82
int headKnownAssignedXids
Definition: procarray.c:83

◆ KnownAssignedXidsSearch()

static bool KnownAssignedXidsSearch ( TransactionId  xid,
bool  remove 
)
static

Definition at line 4586 of file procarray.c.

References Assert, ProcArrayStruct::headKnownAssignedXids, ProcArrayStruct::known_assigned_xids_lck, KnownAssignedXids, KnownAssignedXidsValid, ProcArrayStruct::numKnownAssignedXids, procArray, SpinLockAcquire, SpinLockRelease, ProcArrayStruct::tailKnownAssignedXids, and TransactionIdPrecedes().

Referenced by KnownAssignedXidExists(), and KnownAssignedXidsRemove().

4587 {
4588  ProcArrayStruct *pArray = procArray;
4589  int first,
4590  last;
4591  int head;
4592  int tail;
4593  int result_index = -1;
4594 
4595  if (remove)
4596  {
4597  /* we hold ProcArrayLock exclusively, so no need for spinlock */
4598  tail = pArray->tailKnownAssignedXids;
4599  head = pArray->headKnownAssignedXids;
4600  }
4601  else
4602  {
4603  /* take spinlock to ensure we see up-to-date array contents */
4605  tail = pArray->tailKnownAssignedXids;
4606  head = pArray->headKnownAssignedXids;
4608  }
4609 
4610  /*
4611  * Standard binary search. Note we can ignore the KnownAssignedXidsValid
4612  * array here, since even invalid entries will contain sorted XIDs.
4613  */
4614  first = tail;
4615  last = head - 1;
4616  while (first <= last)
4617  {
4618  int mid_index;
4619  TransactionId mid_xid;
4620 
4621  mid_index = (first + last) / 2;
4622  mid_xid = KnownAssignedXids[mid_index];
4623 
4624  if (xid == mid_xid)
4625  {
4626  result_index = mid_index;
4627  break;
4628  }
4629  else if (TransactionIdPrecedes(xid, mid_xid))
4630  last = mid_index - 1;
4631  else
4632  first = mid_index + 1;
4633  }
4634 
4635  if (result_index < 0)
4636  return false; /* not in array */
4637 
4638  if (!KnownAssignedXidsValid[result_index])
4639  return false; /* in array, but invalid */
4640 
4641  if (remove)
4642  {
4643  KnownAssignedXidsValid[result_index] = false;
4644 
4645  pArray->numKnownAssignedXids--;
4646  Assert(pArray->numKnownAssignedXids >= 0);
4647 
4648  /*
4649  * If we're removing the tail element then advance tail pointer over
4650  * any invalid elements. This will speed future searches.
4651  */
4652  if (result_index == tail)
4653  {
4654  tail++;
4655  while (tail < head && !KnownAssignedXidsValid[tail])
4656  tail++;
4657  if (tail >= head)
4658  {
4659  /* Array is empty, so we can reset both pointers */
4660  pArray->headKnownAssignedXids = 0;
4661  pArray->tailKnownAssignedXids = 0;
4662  }
4663  else
4664  {
4665  pArray->tailKnownAssignedXids = tail;
4666  }
4667  }
4668  }
4669 
4670  return true;
4671 }
uint32 TransactionId
Definition: c.h:520
slock_t known_assigned_xids_lck
Definition: procarray.c:84
#define SpinLockAcquire(lock)
Definition: spin.h:62
int numKnownAssignedXids
Definition: procarray.c:81
static bool * KnownAssignedXidsValid
Definition: procarray.c:248
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
static ProcArrayStruct * procArray
Definition: procarray.c:240
#define SpinLockRelease(lock)
Definition: spin.h:64
#define Assert(condition)
Definition: c.h:745
static TransactionId * KnownAssignedXids
Definition: procarray.c:247
int tailKnownAssignedXids
Definition: procarray.c:82
int headKnownAssignedXids
Definition: procarray.c:83

◆ MaintainLatestCompletedXid()

static void MaintainLatestCompletedXid ( TransactionId  latestXid)
static

Definition at line 898 of file procarray.c.

References Assert, FullTransactionIdIsNormal, FullTransactionIdIsValid, FullXidRelativeTo(), IsBootstrapProcessingMode, VariableCacheData::latestCompletedXid, LWLockHeldByMe(), RecoveryInProgress(), ShmemVariableCache, TransactionIdPrecedes(), and XidFromFullTransactionId.

Referenced by ProcArrayEndTransactionInternal(), ProcArrayRemove(), and XidCacheRemoveRunningXids().

899 {
901 
902  Assert(FullTransactionIdIsValid(cur_latest));
904  Assert(LWLockHeldByMe(ProcArrayLock));
905 
906  if (TransactionIdPrecedes(XidFromFullTransactionId(cur_latest), latestXid))
907  {
909  FullXidRelativeTo(cur_latest, latestXid);
910  }
911 
914 }
bool LWLockHeldByMe(LWLock *l)
Definition: lwlock.c:1928
#define FullTransactionIdIsValid(x)
Definition: transam.h:55
static FullTransactionId FullXidRelativeTo(FullTransactionId rel, TransactionId xid)
Definition: procarray.c:4115
FullTransactionId latestCompletedXid
Definition: transam.h:231
bool RecoveryInProgress(void)
Definition: xlog.c:8074
#define XidFromFullTransactionId(x)
Definition: transam.h:48
#define FullTransactionIdIsNormal(x)
Definition: transam.h:58
VariableCache ShmemVariableCache
Definition: varsup.c:34
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
#define Assert(condition)
Definition: c.h:745
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:393

◆ MaintainLatestCompletedXidRecovery()

static void MaintainLatestCompletedXidRecovery ( TransactionId  latestXid)
static

Definition at line 920 of file procarray.c.

References AmStartupProcess, Assert, FullTransactionIdIsNormal, FullTransactionIdIsValid, FullXidRelativeTo(), IsUnderPostmaster, VariableCacheData::latestCompletedXid, LWLockHeldByMe(), VariableCacheData::nextXid, ShmemVariableCache, TransactionIdPrecedes(), and XidFromFullTransactionId.

Referenced by ExpireTreeKnownAssignedTransactionIds(), and ProcArrayApplyRecoveryInfo().

921 {
923  FullTransactionId rel;
924 
926  Assert(LWLockHeldByMe(ProcArrayLock));
927 
928  /*
929  * Need a FullTransactionId to compare latestXid with. Can't rely on
930  * latestCompletedXid to be initialized in recovery. But in recovery it's
931  * safe to access nextXid without a lock for the startup process.
932  */
935 
936  if (!FullTransactionIdIsValid(cur_latest) ||
937  TransactionIdPrecedes(XidFromFullTransactionId(cur_latest), latestXid))
938  {
940  FullXidRelativeTo(rel, latestXid);
941  }
942 
944 }
#define AmStartupProcess()
Definition: miscadmin.h:431
bool LWLockHeldByMe(LWLock *l)
Definition: lwlock.c:1928
#define FullTransactionIdIsValid(x)
Definition: transam.h:55
static FullTransactionId FullXidRelativeTo(FullTransactionId rel, TransactionId xid)
Definition: procarray.c:4115
FullTransactionId latestCompletedXid
Definition: transam.h:231
FullTransactionId nextXid
Definition: transam.h:213
#define XidFromFullTransactionId(x)
Definition: transam.h:48
#define FullTransactionIdIsNormal(x)
Definition: transam.h:58
bool IsUnderPostmaster
Definition: globals.c:109
VariableCache ShmemVariableCache
Definition: varsup.c:34
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
#define Assert(condition)
Definition: c.h:745

◆ MinimumActiveBackends()

bool MinimumActiveBackends ( int  min)

Definition at line 3318 of file procarray.c.

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

Referenced by XLogFlush().

3319 {
3320  ProcArrayStruct *arrayP = procArray;
3321  int count = 0;
3322  int index;
3323 
3324  /* Quick short-circuit if no minimum is specified */
3325  if (min == 0)
3326  return true;
3327 
3328  /*
3329  * Note: for speed, we don't acquire ProcArrayLock. This is a little bit
3330  * bogus, but since we are only testing fields for zero or nonzero, it
3331  * should be OK. The result is only used for heuristic purposes anyway...
3332  */
3333  for (index = 0; index < arrayP->numProcs; index++)
3334  {
3335  int pgprocno = arrayP->pgprocnos[index];
3336  PGPROC *proc = &allProcs[pgprocno];
3337 
3338  /*
3339  * Since we're not holding a lock, need to be prepared to deal with
3340  * garbage, as someone could have incremented numProcs but not yet
3341  * filled the structure.
3342  *
3343  * If someone just decremented numProcs, 'proc' could also point to a
3344  * PGPROC entry that's no longer in the array. It still points to a
3345  * PGPROC struct, though, because freed PGPROC entries just go to the
3346  * free list and are recycled. Its contents are nonsense in that case,
3347  * but that's acceptable for this function.
3348  */
3349  if (pgprocno == -1)
3350  continue; /* do not count deleted entries */
3351  if (proc == MyProc)
3352  continue; /* do not count myself */
3353  if (proc->xid == InvalidTransactionId)
3354  continue; /* do not count if no XID assigned */
3355  if (proc->pid == 0)
3356  continue; /* do not count prepared xacts */
3357  if (proc->waitLock != NULL)
3358  continue; /* do not count if blocked on a lock */
3359  count++;
3360  if (count >= min)
3361  break;
3362  }
3363 
3364  return count >= min;
3365 }
PGPROC * MyProc
Definition: proc.c:67
Definition: type.h:89
#define InvalidTransactionId
Definition: transam.h:31
static PGPROC * allProcs
Definition: procarray.c:242
LOCK * waitLock
Definition: proc.h:170
static ProcArrayStruct * procArray
Definition: procarray.c:240
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
TransactionId xid
Definition: proc.h:124
Definition: proc.h:112
int pid
Definition: proc.h:137

◆ ProcArrayAdd()

void ProcArrayAdd ( PGPROC proc)

Definition at line 434 of file procarray.c.

References ereport, errcode(), errmsg(), FATAL, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), ProcArrayStruct::maxProcs, ProcArrayStruct::numProcs, PGPROC::pgprocno, ProcArrayStruct::pgprocnos, PGPROC::pgxactoff, procArray, ProcGlobal, PROC_HDR::subxidStates, PGPROC::subxidStatus, PGPROC::vacuumFlags, PROC_HDR::vacuumFlags, PGPROC::xid, and PROC_HDR::xids.

Referenced by InitProcessPhase2(), and MarkAsPrepared().

435 {
436  ProcArrayStruct *arrayP = procArray;
437  int index;
438 
439  /* See ProcGlobal comment explaining why both locks are held */
440  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
441  LWLockAcquire(XidGenLock, LW_EXCLUSIVE);
442 
443  if (arrayP->numProcs >= arrayP->maxProcs)
444  {
445  /*
446  * Oops, no room. (This really shouldn't happen, since there is a
447  * fixed supply of PGPROC structs too, and so we should have failed
448  * earlier.)
449  */
450  ereport(FATAL,
451  (errcode(ERRCODE_TOO_MANY_CONNECTIONS),
452  errmsg("sorry, too many clients already")));
453  }
454 
455  /*
456  * Keep the procs array sorted by (PGPROC *) so that we can utilize
457  * locality of references much better. This is useful while traversing the
458  * ProcArray because there is an increased likelihood of finding the next
459  * PGPROC structure in the cache.
460  *
461  * Since the occurrence of adding/removing a proc is much lower than the
462  * access to the ProcArray itself, the overhead should be marginal
463  */
464  for (index = 0; index < arrayP->numProcs; index++)
465  {
466  /*
467  * If we are the first PGPROC or if we have found our right position
468  * in the array, break
469  */
470  if ((arrayP->pgprocnos[index] == -1) || (arrayP->pgprocnos[index] > proc->pgprocno))
471  break;
472  }
473 
474  memmove(&arrayP->pgprocnos[index + 1], &arrayP->pgprocnos[index],
475  (arrayP->numProcs - index) * sizeof(*arrayP->pgprocnos));
476  memmove(&ProcGlobal->xids[index + 1], &ProcGlobal->xids[index],
477  (arrayP->numProcs - index) * sizeof(*ProcGlobal->xids));
478  memmove(&ProcGlobal->subxidStates[index + 1], &ProcGlobal->subxidStates[index],
479  (arrayP->numProcs - index) * sizeof(*ProcGlobal->subxidStates));
480  memmove(&ProcGlobal->vacuumFlags[index + 1], &ProcGlobal->vacuumFlags[index],
481  (arrayP->numProcs - index) * sizeof(*ProcGlobal->vacuumFlags));
482 
483  arrayP->pgprocnos[index] = proc->pgprocno;
484  ProcGlobal->xids[index] = proc->xid;
485  ProcGlobal->subxidStates[index] = proc->subxidStatus;
486  ProcGlobal->vacuumFlags[index] = proc->vacuumFlags;
487 
488  arrayP->numProcs++;
489 
490  for (; index < arrayP->numProcs; index++)
491  {
492  allProcs[arrayP->pgprocnos[index]].pgxactoff = index;
493  }
494 
495  /*
496  * Release in reversed acquisition order, to reduce frequency of having to
497  * wait for XidGenLock while holding ProcArrayLock.
498  */
499  LWLockRelease(XidGenLock);
500  LWLockRelease(ProcArrayLock);
501 }
XidCacheStatus * subxidStates
Definition: proc.h:315
int errcode(int sqlerrcode)
Definition: elog.c:610
PROC_HDR * ProcGlobal
Definition: proc.c:79
XidCacheStatus subxidStatus
Definition: proc.h:198
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
#define FATAL
Definition: elog.h:52
TransactionId * xids
Definition: proc.h:309
static PGPROC * allProcs
Definition: procarray.c:242
static ProcArrayStruct * procArray
Definition: procarray.c:240
#define ereport(elevel,...)
Definition: elog.h:144
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
TransactionId xid
Definition: proc.h:124
int pgprocno
Definition: proc.h:141
int errmsg(const char *fmt,...)
Definition: elog.c:824
int pgxactoff
Definition: proc.h:139
uint8 * vacuumFlags
Definition: proc.h:321
uint8 vacuumFlags
Definition: proc.h:178

◆ ProcArrayApplyRecoveryInfo()

void ProcArrayApplyRecoveryInfo ( RunningTransactions  running)

Definition at line 985 of file procarray.c.

References AdvanceNextFullTransactionIdPastXid(), Assert, DEBUG1, DEBUG3, elog, ERROR, ExpireOldKnownAssignedTransactionIds(), ExtendSUBTRANS(), FullTransactionIdIsValid, i, InvalidTransactionId, KnownAssignedXidsAdd(), KnownAssignedXidsDisplay(), KnownAssignedXidsReset(), ProcArrayStruct::lastOverflowedXid, RunningTransactionsData::latestCompletedXid, latestObservedXid, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MaintainLatestCompletedXidRecovery(), RunningTransactionsData::nextXid, VariableCacheData::nextXid, ProcArrayStruct::numKnownAssignedXids, RunningTransactionsData::oldestRunningXid, palloc(), pfree(), qsort, ShmemVariableCache, STANDBY_INITIALIZED, STANDBY_SNAPSHOT_PENDING, STANDBY_SNAPSHOT_READY, StandbyReleaseOldLocks(), standbySnapshotPendingXmin, standbyState, RunningTransactionsData::subxcnt, RunningTransactionsData::subxid_overflow, trace_recovery(), TransactionIdAdvance, TransactionIdDidAbort(), TransactionIdDidCommit(), TransactionIdEquals, TransactionIdIsNormal, TransactionIdIsValid, TransactionIdPrecedes(), TransactionIdRetreat, RunningTransactionsData::xcnt, xidComparator(), and RunningTransactionsData::xids.

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

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

◆ ProcArrayApplyXidAssignment()

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

Definition at line 1221 of file procarray.c.

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

Referenced by xact_redo().

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

◆ ProcArrayClearTransaction()

void ProcArrayClearTransaction ( PGPROC proc)

Definition at line 838 of file procarray.c.

References Assert, XidCacheStatus::count, PGPROC::delayChkpt, InvalidLocalTransactionId, InvalidTransactionId, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), PGPROC::lxid, XidCacheStatus::overflowed, PGPROC::pgxactoff, PROC_VACUUM_STATE_MASK, ProcGlobal, PGPROC::recoveryConflictPending, ShmemVariableCache, PROC_HDR::subxidStates, PGPROC::subxidStatus, PGPROC::vacuumFlags, VariableCacheData::xactCompletionCount, PGPROC::xid, PROC_HDR::xids, and PGPROC::xmin.

Referenced by PrepareTransaction().

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

◆ ProcArrayEndTransaction()

void ProcArrayEndTransaction ( PGPROC proc,
TransactionId  latestXid 
)

Definition at line 609 of file procarray.c.

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

Referenced by AbortTransaction(), and CommitTransaction().

610 {
611  if (TransactionIdIsValid(latestXid))
612  {
613  /*
614  * We must lock ProcArrayLock while clearing our advertised XID, so
615  * that we do not exit the set of "running" transactions while someone
616  * else is taking a snapshot. See discussion in
617  * src/backend/access/transam/README.
618  */
620 
621  /*
622  * If we can immediately acquire ProcArrayLock, we clear our own XID
623  * and release the lock. If not, use group XID clearing to improve
624  * efficiency.
625  */
626  if (LWLockConditionalAcquire(ProcArrayLock, LW_EXCLUSIVE))
627  {
628  ProcArrayEndTransactionInternal(proc, latestXid);
629  LWLockRelease(ProcArrayLock);
630  }
631  else
632  ProcArrayGroupClearXid(proc, latestXid);
633  }
634  else
635  {
636  /*
637  * If we have no XID, we don't need to lock, since we won't affect
638  * anyone else's calculation of a snapshot. We might change their
639  * estimate of global xmin, but that's OK.
640  */
642  Assert(proc->subxidStatus.count == 0);
644 
646  proc->xmin = InvalidTransactionId;
647  proc->delayChkpt = false; /* be sure this is cleared in abort */
648  proc->recoveryConflictPending = false;
649 
650  /* must be cleared with xid/xmin: */
651  /* avoid unnecessarily dirtying shared cachelines */
653  {
654  Assert(!LWLockHeldByMe(ProcArrayLock));
655  LWLockAcquire(ProcArrayLock, LW_SHARED);
659  LWLockRelease(ProcArrayLock);
660  }
661  }
662 }
bool LWLockHeldByMe(LWLock *l)
Definition: lwlock.c:1928
static void ProcArrayEndTransactionInternal(PGPROC *proc, TransactionId latestXid)
Definition: procarray.c:670
static void ProcArrayGroupClearXid(PGPROC *proc, TransactionId latestXid)
Definition: procarray.c:724
PROC_HDR * ProcGlobal
Definition: proc.c:79
XidCacheStatus subxidStatus
Definition: proc.h:198
#define PROC_VACUUM_STATE_MASK
Definition: proc.h:61
bool overflowed
Definition: proc.h:43
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
bool delayChkpt
Definition: proc.h:176
TransactionId xmin
Definition: proc.h:129
bool LWLockConditionalAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1380
bool recoveryConflictPending
Definition: proc.h:158
#define InvalidTransactionId
Definition: transam.h:31
#define Assert(condition)
Definition: c.h:745
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
uint8 count
Definition: proc.h:41
TransactionId xid
Definition: proc.h:124
#define InvalidLocalTransactionId
Definition: lock.h:68
int pgxactoff
Definition: proc.h:139
uint8 * vacuumFlags
Definition: proc.h:321
uint8 vacuumFlags
Definition: proc.h:178
#define TransactionIdIsValid(xid)
Definition: transam.h:41
LocalTransactionId lxid
Definition: proc.h:134

◆ ProcArrayEndTransactionInternal()

static void ProcArrayEndTransactionInternal ( PGPROC proc,
TransactionId  latestXid 
)
inlinestatic

Definition at line 670 of file procarray.c.

References Assert, XidCacheStatus::count, PGPROC::delayChkpt, InvalidLocalTransactionId, InvalidTransactionId, LWLockHeldByMe(), PGPROC::lxid, MaintainLatestCompletedXid(), XidCacheStatus::overflowed, PGPROC::pgxactoff, PROC_VACUUM_STATE_MASK, ProcGlobal, PGPROC::recoveryConflictPending, ShmemVariableCache, PROC_HDR::subxidStates, PGPROC::subxidStatus, TransactionIdIsValid, PGPROC::vacuumFlags, PROC_HDR::vacuumFlags, VariableCacheData::xactCompletionCount, PGPROC::xid, PROC_HDR::xids, and PGPROC::xmin.

Referenced by ProcArrayEndTransaction(), and ProcArrayGroupClearXid().

671 {
672  size_t pgxactoff = proc->pgxactoff;
673 
674  Assert(LWLockHeldByMe(ProcArrayLock));
676  Assert(ProcGlobal->xids[pgxactoff] == proc->xid);
677 
678  ProcGlobal->xids[pgxactoff] = InvalidTransactionId;
679  proc->xid = InvalidTransactionId;
681  proc->xmin = InvalidTransactionId;
682  proc->delayChkpt = false; /* be sure this is cleared in abort */
683  proc->recoveryConflictPending = false;
684 
685  /* must be cleared with xid/xmin: */
686  /* avoid unnecessarily dirtying shared cachelines */
688  {
691  }
692 
693  /* Clear the subtransaction-XID cache too while holding the lock */
694  Assert(ProcGlobal->subxidStates[pgxactoff].count == proc->subxidStatus.count &&
696  if (proc->subxidStatus.count > 0 || proc->subxidStatus.overflowed)
697  {
698  ProcGlobal->subxidStates[pgxactoff].count = 0;
699  ProcGlobal->subxidStates[pgxactoff].overflowed = false;
700  proc->subxidStatus.count = 0;
701  proc->subxidStatus.overflowed = false;
702  }
703 
704  /* Also advance global latestCompletedXid while holding the lock */
705  MaintainLatestCompletedXid(latestXid);
706 
707  /* Same with xactCompletionCount */
709 }
XidCacheStatus * subxidStates
Definition: proc.h:315
bool LWLockHeldByMe(LWLock *l)
Definition: lwlock.c:1928
uint64 xactCompletionCount
Definition: transam.h:241
PROC_HDR * ProcGlobal
Definition: proc.c:79
XidCacheStatus subxidStatus
Definition: proc.h:198
#define PROC_VACUUM_STATE_MASK
Definition: proc.h:61
bool overflowed
Definition: proc.h:43
bool delayChkpt
Definition: proc.h:176
TransactionId xmin
Definition: proc.h:129
bool recoveryConflictPending
Definition: proc.h:158
VariableCache ShmemVariableCache
Definition: varsup.c:34
#define InvalidTransactionId
Definition: transam.h:31
TransactionId * xids
Definition: proc.h:309
static void MaintainLatestCompletedXid(TransactionId latestXid)
Definition: procarray.c:898
#define Assert(condition)
Definition: c.h:745
uint8 count
Definition: proc.h:41
TransactionId xid
Definition: proc.h:124
#define InvalidLocalTransactionId
Definition: lock.h:68
int pgxactoff
Definition: proc.h:139
uint8 * vacuumFlags
Definition: proc.h:321
uint8 vacuumFlags
Definition: proc.h:178
#define TransactionIdIsValid(xid)
Definition: transam.h:41
LocalTransactionId lxid
Definition: proc.h:134

◆ ProcArrayGetReplicationSlotXmin()

void ProcArrayGetReplicationSlotXmin ( TransactionId xmin,
TransactionId catalog_xmin 
)

Definition at line 3730 of file procarray.c.

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

Referenced by logical_begin_heap_rewrite().

3732 {
3733  LWLockAcquire(ProcArrayLock, LW_SHARED);
3734 
3735  if (xmin != NULL)
3737 
3738  if (catalog_xmin != NULL)
3739  *catalog_xmin = procArray->replication_slot_catalog_xmin;
3740 
3741  LWLockRelease(ProcArrayLock);
3742 }
TransactionId replication_slot_catalog_xmin
Definition: procarray.c:98
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
static ProcArrayStruct * procArray
Definition: procarray.c:240
TransactionId replication_slot_xmin
Definition: procarray.c:96
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208

◆ ProcArrayGroupClearXid()

static void ProcArrayGroupClearXid ( PGPROC proc,
TransactionId  latestXid 
)
static

Definition at line 724 of file procarray.c.

References Assert, INVALID_PGPROCNO, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MyProc, pg_atomic_compare_exchange_u32(), pg_atomic_exchange_u32(), pg_atomic_read_u32(), pg_atomic_write_u32(), pg_write_barrier, PGPROC::pgprocno, PGSemaphoreLock(), PGSemaphoreUnlock(), pgstat_report_wait_end(), pgstat_report_wait_start(), ProcArrayEndTransactionInternal(), PROC_HDR::procArrayGroupFirst, PGPROC::procArrayGroupMember, PGPROC::procArrayGroupMemberXid, PGPROC::procArrayGroupNext, ProcGlobal, PGPROC::sem, TransactionIdIsValid, WAIT_EVENT_PROCARRAY_GROUP_UPDATE, and PGPROC::xid.

Referenced by ProcArrayEndTransaction().

725 {
726  PROC_HDR *procglobal = ProcGlobal;
727  uint32 nextidx;
728  uint32 wakeidx;
729 
730  /* We should definitely have an XID to clear. */
732 
733  /* Add ourselves to the list of processes needing a group XID clear. */
734  proc->procArrayGroupMember = true;
735  proc->procArrayGroupMemberXid = latestXid;
736  nextidx = pg_atomic_read_u32(&procglobal->procArrayGroupFirst);
737  while (true)
738  {
739  pg_atomic_write_u32(&proc->procArrayGroupNext, nextidx);
740 
742  &nextidx,
743  (uint32) proc->pgprocno))
744  break;
745  }
746 
747  /*
748  * If the list was not empty, the leader will clear our XID. It is
749  * impossible to have followers without a leader because the first process
750  * that has added itself to the list will always have nextidx as
751  * INVALID_PGPROCNO.
752  */
753  if (nextidx != INVALID_PGPROCNO)
754  {
755  int extraWaits = 0;
756 
757  /* Sleep until the leader clears our XID. */
759  for (;;)
760  {
761  /* acts as a read barrier */
762  PGSemaphoreLock(proc->sem);
763  if (!proc->procArrayGroupMember)
764  break;
765  extraWaits++;
766  }
768 
770 
771  /* Fix semaphore count for any absorbed wakeups */
772  while (extraWaits-- > 0)
773  PGSemaphoreUnlock(proc->sem);
774  return;
775  }
776 
777  /* We are the leader. Acquire the lock on behalf of everyone. */
778  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
779 
780  /*
781  * Now that we've got the lock, clear the list of processes waiting for
782  * group XID clearing, saving a pointer to the head of the list. Trying
783  * to pop elements one at a time could lead to an ABA problem.
784  */
785  nextidx = pg_atomic_exchange_u32(&procglobal->procArrayGroupFirst,
787 
788  /* Remember head of list so we can perform wakeups after dropping lock. */
789  wakeidx = nextidx;
790 
791  /* Walk the list and clear all XIDs. */
792  while (nextidx != INVALID_PGPROCNO)
793  {
794  PGPROC *proc = &allProcs[nextidx];
795 
797 
798  /* Move to next proc in list. */
799  nextidx = pg_atomic_read_u32(&proc->procArrayGroupNext);
800  }
801 
802  /* We're done with the lock now. */
803  LWLockRelease(ProcArrayLock);
804 
805  /*
806  * Now that we've released the lock, go back and wake everybody up. We
807  * don't do this under the lock so as to keep lock hold times to a
808  * minimum. The system calls we need to perform to wake other processes
809  * up are probably much slower than the simple memory writes we did while
810  * holding the lock.
811  */
812  while (wakeidx != INVALID_PGPROCNO)
813  {
814  PGPROC *proc = &allProcs[wakeidx];
815 
816  wakeidx = pg_atomic_read_u32(&proc->procArrayGroupNext);
818 
819  /* ensure all previous writes are visible before follower continues. */
821 
822  proc->procArrayGroupMember = false;
823 
824  if (proc != MyProc)
825  PGSemaphoreUnlock(proc->sem);
826  }
827 }
bool procArrayGroupMember
Definition: proc.h:204
void PGSemaphoreUnlock(PGSemaphore sema)
Definition: posix_sema.c:340
static bool pg_atomic_compare_exchange_u32(volatile pg_atomic_uint32 *ptr, uint32 *expected, uint32 newval)
Definition: atomics.h:311
static void ProcArrayEndTransactionInternal(PGPROC *proc, TransactionId latestXid)
Definition: procarray.c:670
PGPROC * MyProc
Definition: proc.c:67
PROC_HDR * ProcGlobal
Definition: proc.c:79
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
static uint32 pg_atomic_exchange_u32(volatile pg_atomic_uint32 *ptr, uint32 newval)
Definition: atomics.h:292
static PGPROC * allProcs
Definition: procarray.c:242
unsigned int uint32
Definition: c.h:374
static void pgstat_report_wait_end(void)
Definition: pgstat.h:1386
#define INVALID_PGPROCNO
Definition: proc.h:76
pg_atomic_uint32 procArrayGroupNext
Definition: proc.h:206
Definition: proc.h:303
#define Assert(condition)
Definition: c.h:745
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition: pgstat.h:1362
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
void PGSemaphoreLock(PGSemaphore sema)
Definition: posix_sema.c:320
TransactionId xid
Definition: proc.h:124
int pgprocno
Definition: proc.h:141
pg_atomic_uint32 procArrayGroupFirst
Definition: proc.h:334
#define pg_write_barrier()
Definition: atomics.h:159
#define TransactionIdIsValid(xid)
Definition: transam.h:41
static void pg_atomic_write_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
Definition: atomics.h:258
PGSemaphore sem
Definition: proc.h:118
Definition: proc.h:112
TransactionId procArrayGroupMemberXid
Definition: proc.h:212
static uint32 pg_atomic_read_u32(volatile pg_atomic_uint32 *ptr)
Definition: atomics.h:241

◆ ProcArrayInitRecovery()

void ProcArrayInitRecovery ( TransactionId  initializedUptoXID)

Definition at line 954 of file procarray.c.

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

Referenced by StartupXLOG().

955 {
957  Assert(TransactionIdIsNormal(initializedUptoXID));