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 GlobalVisState GlobalVisTempRels
 
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 316 of file procarray.c.

Referenced by TransactionIdIsInProgress().

◆ xc_by_known_assigned_inc

#define xc_by_known_assigned_inc ( )    ((void) 0)

Definition at line 317 of file procarray.c.

Referenced by TransactionIdIsInProgress().

◆ xc_by_known_xact_inc

#define xc_by_known_xact_inc ( )    ((void) 0)

Definition at line 312 of file procarray.c.

Referenced by TransactionIdIsInProgress().

◆ xc_by_latest_xid_inc

#define xc_by_latest_xid_inc ( )    ((void) 0)

Definition at line 314 of file procarray.c.

Referenced by TransactionIdIsInProgress().

◆ xc_by_main_xid_inc

#define xc_by_main_xid_inc ( )    ((void) 0)

Definition at line 315 of file procarray.c.

Referenced by TransactionIdIsInProgress().

◆ xc_by_my_xact_inc

#define xc_by_my_xact_inc ( )    ((void) 0)

Definition at line 313 of file procarray.c.

Referenced by TransactionIdIsInProgress().

◆ xc_by_recent_xmin_inc

#define xc_by_recent_xmin_inc ( )    ((void) 0)

Definition at line 311 of file procarray.c.

Referenced by TransactionIdIsInProgress().

◆ xc_no_overflow_inc

#define xc_no_overflow_inc ( )    ((void) 0)

Definition at line 318 of file procarray.c.

Referenced by TransactionIdIsInProgress().

◆ xc_slow_answer_inc

#define xc_slow_answer_inc ( )    ((void) 0)

Definition at line 319 of file procarray.c.

Referenced by TransactionIdIsInProgress().

Typedef Documentation

◆ ComputeXidHorizonsResult

◆ ProcArrayStruct

Function Documentation

◆ BackendPidGetProc()

PGPROC* BackendPidGetProc ( int  pid)

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

3039 {
3040  PGPROC *result;
3041 
3042  if (pid == 0) /* never match dummy PGPROCs */
3043  return NULL;
3044 
3045  LWLockAcquire(ProcArrayLock, LW_SHARED);
3046 
3047  result = BackendPidGetProcWithLock(pid);
3048 
3049  LWLockRelease(ProcArrayLock);
3050 
3051  return result;
3052 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1811
PGPROC * BackendPidGetProcWithLock(int pid)
Definition: procarray.c:3061
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1207
Definition: proc.h:117

◆ BackendPidGetProcWithLock()

PGPROC* BackendPidGetProcWithLock ( int  pid)

Definition at line 3061 of file procarray.c.

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

Referenced by BackendPidGetProc(), and GetBlockerStatusData().

3062 {
3063  PGPROC *result = NULL;
3064  ProcArrayStruct *arrayP = procArray;
3065  int index;
3066 
3067  if (pid == 0) /* never match dummy PGPROCs */
3068  return NULL;
3069 
3070  for (index = 0; index < arrayP->numProcs; index++)
3071  {
3072  PGPROC *proc = &allProcs[arrayP->pgprocnos[index]];
3073 
3074  if (proc->pid == pid)
3075  {
3076  result = proc;
3077  break;
3078  }
3079  }
3080 
3081  return result;
3082 }
Definition: type.h:89
static PGPROC * allProcs
Definition: procarray.c:252
static ProcArrayStruct * procArray
Definition: procarray.c:250
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
Definition: proc.h:117
int pid
Definition: proc.h:142

◆ BackendXidGetPid()

int BackendXidGetPid ( TransactionId  xid)

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

3099 {
3100  int result = 0;
3101  ProcArrayStruct *arrayP = procArray;
3102  TransactionId *other_xids = ProcGlobal->xids;
3103  int index;
3104 
3105  if (xid == InvalidTransactionId) /* never match invalid xid */
3106  return 0;
3107 
3108  LWLockAcquire(ProcArrayLock, LW_SHARED);
3109 
3110  for (index = 0; index < arrayP->numProcs; index++)
3111  {
3112  int pgprocno = arrayP->pgprocnos[index];
3113  PGPROC *proc = &allProcs[pgprocno];
3114 
3115  if (other_xids[index] == xid)
3116  {
3117  result = proc->pid;
3118  break;
3119  }
3120  }
3121 
3122  LWLockRelease(ProcArrayLock);
3123 
3124  return result;
3125 }
uint32 TransactionId
Definition: c.h:575
PROC_HDR * ProcGlobal
Definition: proc.c:79
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1811
#define InvalidTransactionId
Definition: transam.h:31
TransactionId * xids
Definition: proc.h:315
static PGPROC * allProcs
Definition: procarray.c:252
static ProcArrayStruct * procArray
Definition: procarray.c:250
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1207
Definition: proc.h:117
int pid
Definition: proc.h:142

◆ CancelDBBackends()

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

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

3491 {
3492  ProcArrayStruct *arrayP = procArray;
3493  int index;
3494 
3495  /* tell all backends to die */
3496  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3497 
3498  for (index = 0; index < arrayP->numProcs; index++)
3499  {
3500  int pgprocno = arrayP->pgprocnos[index];
3501  PGPROC *proc = &allProcs[pgprocno];
3502 
3503  if (databaseid == InvalidOid || proc->databaseId == databaseid)
3504  {
3505  VirtualTransactionId procvxid;
3506  pid_t pid;
3507 
3508  GET_VXID_FROM_PGPROC(procvxid, *proc);
3509 
3510  proc->recoveryConflictPending = conflictPending;
3511  pid = proc->pid;
3512  if (pid != 0)
3513  {
3514  /*
3515  * Kill the pid if it's still here. If not, that's what we
3516  * wanted so ignore any errors.
3517  */
3518  (void) SendProcSignal(pid, sigmode, procvxid.backendId);
3519  }
3520  }
3521  }
3522 
3523  LWLockRelease(ProcArrayLock);
3524 }
#define GET_VXID_FROM_PGPROC(vxid, proc)
Definition: lock.h:79
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1811
int SendProcSignal(pid_t pid, ProcSignalReason reason, BackendId backendId)
Definition: procsignal.c:250
bool recoveryConflictPending
Definition: proc.h:163
static PGPROC * allProcs
Definition: procarray.c:252
Oid databaseId
Definition: proc.h:150
static ProcArrayStruct * procArray
Definition: procarray.c:250
#define InvalidOid
Definition: postgres_ext.h:36
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
BackendId backendId
Definition: lock.h:64
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1207
Definition: proc.h:117
int pid
Definition: proc.h:142

◆ CancelVirtualTransaction()

pid_t CancelVirtualTransaction ( VirtualTransactionId  vxid,
ProcSignalReason  sigmode 
)

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

3329 {
3330  ProcArrayStruct *arrayP = procArray;
3331  int index;
3332  pid_t pid = 0;
3333 
3334  LWLockAcquire(ProcArrayLock, LW_SHARED);
3335 
3336  for (index = 0; index < arrayP->numProcs; index++)
3337  {
3338  int pgprocno = arrayP->pgprocnos[index];
3339  PGPROC *proc = &allProcs[pgprocno];
3340  VirtualTransactionId procvxid;
3341 
3342  GET_VXID_FROM_PGPROC(procvxid, *proc);
3343 
3344  if (procvxid.backendId == vxid.backendId &&
3345  procvxid.localTransactionId == vxid.localTransactionId)
3346  {
3347  proc->recoveryConflictPending = true;
3348  pid = proc->pid;
3349  if (pid != 0)
3350  {
3351  /*
3352  * Kill the pid if it's still here. If not, that's what we
3353  * wanted so ignore any errors.
3354  */
3355  (void) SendProcSignal(pid, sigmode, vxid.backendId);
3356  }
3357  break;
3358  }
3359  }
3360 
3361  LWLockRelease(ProcArrayLock);
3362 
3363  return pid;
3364 }
#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:1811
int SendProcSignal(pid_t pid, ProcSignalReason reason, BackendId backendId)
Definition: procsignal.c:250
bool recoveryConflictPending
Definition: proc.h:163
static PGPROC * allProcs
Definition: procarray.c:252
static ProcArrayStruct * procArray
Definition: procarray.c:250
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
BackendId backendId
Definition: lock.h:64
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1207
Definition: proc.h:117
int pid
Definition: proc.h:142

◆ ComputeXidHorizons()

static void ComputeXidHorizons ( ComputeXidHorizonsResult h)
static

Definition at line 1658 of file procarray.c.

References Assert, ComputeXidHorizonsResult::catalog_oldest_nonremovable, ComputeXidHorizonsResult::data_oldest_nonremovable, PGPROC::databaseId, GlobalVisUpdateApply(), InvalidOid, InvalidTransactionId, KnownAssignedXidsGetOldestXmin(), ComputeXidHorizonsResult::latest_completed, VariableCacheData::latestCompletedXid, LW_SHARED, LWLockAcquire(), LWLockRelease(), MyDatabaseId, MyProc, 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, PROC_HDR::statusFlags, ComputeXidHorizonsResult::temp_oldest_nonremovable, TransactionIdAdvance, TransactionIdIsValid, TransactionIdOlder(), TransactionIdPrecedesOrEquals(), TransactionIdRetreatedBy(), UINT32_ACCESS_ONCE, vacuum_defer_cleanup_age, PGPROC::xid, XidFromFullTransactionId, PROC_HDR::xids, and PGPROC::xmin.

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

1659 {
1660  ProcArrayStruct *arrayP = procArray;
1661  TransactionId kaxmin;
1662  bool in_recovery = RecoveryInProgress();
1663  TransactionId *other_xids = ProcGlobal->xids;
1664 
1665  /* inferred after ProcArrayLock is released */
1667 
1668  LWLockAcquire(ProcArrayLock, LW_SHARED);
1669 
1671 
1672  /*
1673  * We initialize the MIN() calculation with latestCompletedXid + 1. This
1674  * is a lower bound for the XIDs that might appear in the ProcArray later,
1675  * and so protects us against overestimating the result due to future
1676  * additions.
1677  */
1678  {
1679  TransactionId initial;
1680 
1682  Assert(TransactionIdIsValid(initial));
1683  TransactionIdAdvance(initial);
1684 
1685  h->oldest_considered_running = initial;
1686  h->shared_oldest_nonremovable = initial;
1687  h->data_oldest_nonremovable = initial;
1688 
1689  /*
1690  * Only modifications made by this backend affect the horizon for
1691  * temporary relations. Instead of a check in each iteration of the
1692  * loop over all PGPROCs it is cheaper to just initialize to the
1693  * current top-level xid any.
1694  *
1695  * Without an assigned xid we could use a horizon as aggressive as
1696  * ReadNewTransactionid(), but we can get away with the much cheaper
1697  * latestCompletedXid + 1: If this backend has no xid there, by
1698  * definition, can't be any newer changes in the temp table than
1699  * latestCompletedXid.
1700  */
1703  else
1704  h->temp_oldest_nonremovable = initial;
1705  }
1706 
1707  /*
1708  * Fetch slot horizons while ProcArrayLock is held - the
1709  * LWLockAcquire/LWLockRelease are a barrier, ensuring this happens inside
1710  * the lock.
1711  */
1714 
1715  for (int index = 0; index < arrayP->numProcs; index++)
1716  {
1717  int pgprocno = arrayP->pgprocnos[index];
1718  PGPROC *proc = &allProcs[pgprocno];
1719  int8 statusFlags = ProcGlobal->statusFlags[index];
1720  TransactionId xid;
1721  TransactionId xmin;
1722 
1723  /* Fetch xid just once - see GetNewTransactionId */
1724  xid = UINT32_ACCESS_ONCE(other_xids[index]);
1725  xmin = UINT32_ACCESS_ONCE(proc->xmin);
1726 
1727  /*
1728  * Consider both the transaction's Xmin, and its Xid.
1729  *
1730  * We must check both because a transaction might have an Xmin but not
1731  * (yet) an Xid; conversely, if it has an Xid, that could determine
1732  * some not-yet-set Xmin.
1733  */
1734  xmin = TransactionIdOlder(xmin, xid);
1735 
1736  /* if neither is set, this proc doesn't influence the horizon */
1737  if (!TransactionIdIsValid(xmin))
1738  continue;
1739 
1740  /*
1741  * Don't ignore any procs when determining which transactions might be
1742  * considered running. While slots should ensure logical decoding
1743  * backends are protected even without this check, it can't hurt to
1744  * include them here as well..
1745  */
1748 
1749  /*
1750  * Skip over backends either vacuuming (which is ok with rows being
1751  * removed, as long as pg_subtrans is not truncated) or doing logical
1752  * decoding (which manages xmin separately, check below).
1753  */
1754  if (statusFlags & (PROC_IN_VACUUM | PROC_IN_LOGICAL_DECODING))
1755  continue;
1756 
1757  /* shared tables need to take backends in all database into account */
1760 
1761  /*
1762  * Normally queries in other databases are ignored for anything but
1763  * the shared horizon. But in recovery we cannot compute an accurate
1764  * per-database horizon as all xids are managed via the
1765  * KnownAssignedXids machinery.
1766  *
1767  * Be careful to compute a pessimistic value when MyDatabaseId is not
1768  * set. If this is a backend in the process of starting up, we may not
1769  * use a "too aggressive" horizon (otherwise we could end up using it
1770  * to prune still needed data away). If the current backend never
1771  * connects to a database that is harmless, because
1772  * data_oldest_nonremovable will never be utilized.
1773  */
1774  if (in_recovery ||
1776  proc->databaseId == 0) /* always include WalSender */
1777  {
1780  }
1781  }
1782 
1783  /*
1784  * If in recovery fetch oldest xid in KnownAssignedXids, will be applied
1785  * after lock is released.
1786  */
1787  if (in_recovery)
1788  kaxmin = KnownAssignedXidsGetOldestXmin();
1789 
1790  /*
1791  * No other information from shared state is needed, release the lock
1792  * immediately. The rest of the computations can be done without a lock.
1793  */
1794  LWLockRelease(ProcArrayLock);
1795 
1796  if (in_recovery)
1797  {
1804  /* temp relations cannot be accessed in recovery */
1805  }
1806  else
1807  {
1808  /*
1809  * Compute the cutoff XID by subtracting vacuum_defer_cleanup_age.
1810  *
1811  * vacuum_defer_cleanup_age provides some additional "slop" for the
1812  * benefit of hot standby queries on standby servers. This is quick
1813  * and dirty, and perhaps not all that useful unless the primary has a
1814  * predictable transaction rate, but it offers some protection when
1815  * there's no walsender connection. Note that we are assuming
1816  * vacuum_defer_cleanup_age isn't large enough to cause wraparound ---
1817  * so guc.c should limit it to no more than the xidStopLimit threshold
1818  * in varsup.c. Also note that we intentionally don't apply
1819  * vacuum_defer_cleanup_age on standby servers.
1820  */
1830  /* defer doesn't apply to temp relations */
1831  }
1832 
1833  /*
1834  * Check whether there are replication slots requiring an older xmin.
1835  */
1840 
1841  /*
1842  * The only difference between catalog / data horizons is that the slot's
1843  * catalog xmin is applied to the catalog one (so catalogs can be accessed
1844  * for logical decoding). Initialize with data horizon, and then back up
1845  * further if necessary. Have to back up the shared horizon as well, since
1846  * that also can contain catalogs.
1847  */
1851  h->slot_catalog_xmin);
1855  h->slot_catalog_xmin);
1856 
1857  /*
1858  * It's possible that slots / vacuum_defer_cleanup_age backed up the
1859  * horizons further than oldest_considered_running. Fix.
1860  */
1870 
1871  /*
1872  * shared horizons have to be at least as old as the oldest visible in
1873  * current db
1874  */
1879 
1880  /*
1881  * Horizons need to ensure that pg_subtrans access is still possible for
1882  * the relevant backends.
1883  */
1894  h->slot_xmin));
1897  h->slot_catalog_xmin));
1898 
1899  /* update approximate horizons with the computed horizons */
1901 }
#define TransactionIdAdvance(dest)
Definition: transam.h:91
TransactionId oldest_considered_running
Definition: procarray.c:207
FullTransactionId latest_completed
Definition: procarray.c:187
TransactionId shared_oldest_nonremovable_raw
Definition: procarray.c:227
#define PROC_IN_LOGICAL_DECODING
Definition: proc.h:57
uint32 TransactionId
Definition: c.h:575
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
PROC_HDR * ProcGlobal
Definition: proc.c:79
FullTransactionId latestCompletedXid
Definition: transam.h:231
bool RecoveryInProgress(void)
Definition: xlog.c:8070
TransactionId catalog_oldest_nonremovable
Definition: procarray.c:233
#define XidFromFullTransactionId(x)
Definition: transam.h:48
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1811
#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:194
TransactionId xmin
Definition: proc.h:134
VariableCache ShmemVariableCache
Definition: varsup.c:34
#define InvalidTransactionId
Definition: transam.h:31
TransactionId * xids
Definition: proc.h:315
static PGPROC * allProcs
Definition: procarray.c:252
Oid databaseId
Definition: proc.h:150
TransactionId shared_oldest_nonremovable
Definition: procarray.c:216
static ProcArrayStruct * procArray
Definition: procarray.c:250
signed char int8
Definition: c.h:415
TransactionId replication_slot_xmin
Definition: procarray.c:96
Oid MyDatabaseId
Definition: globals.c:85
static TransactionId KnownAssignedXidsGetOldestXmin(void)
Definition: procarray.c:4957
#define InvalidOid
Definition: postgres_ext.h:36
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
TransactionId temp_oldest_nonremovable
Definition: procarray.c:245
static TransactionId TransactionIdOlder(TransactionId a, TransactionId b)
Definition: transam.h:327
#define Assert(condition)
Definition: c.h:800
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1207
static void GlobalVisUpdateApply(ComputeXidHorizonsResult *horizons)
Definition: procarray.c:3994
static TransactionId TransactionIdRetreatedBy(TransactionId xid, uint32 amount)
Definition: transam.h:315
TransactionId xid
Definition: proc.h:129
TransactionId data_oldest_nonremovable
Definition: procarray.c:239
uint8 * statusFlags
Definition: proc.h:327
#define TransactionIdIsValid(xid)
Definition: transam.h:41
TransactionId slot_xmin
Definition: procarray.c:193
Definition: proc.h:117

◆ CountDBBackends()

int CountDBBackends ( Oid  databaseid)

Definition at line 3429 of file procarray.c.

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

Referenced by ResolveRecoveryConflictWithDatabase().

3430 {
3431  ProcArrayStruct *arrayP = procArray;
3432  int count = 0;
3433  int index;
3434 
3435  LWLockAcquire(ProcArrayLock, LW_SHARED);
3436 
3437  for (index = 0; index < arrayP->numProcs; index++)
3438  {
3439  int pgprocno = arrayP->pgprocnos[index];
3440  PGPROC *proc = &allProcs[pgprocno];
3441 
3442  if (proc->pid == 0)
3443  continue; /* do not count prepared xacts */
3444  if (!OidIsValid(databaseid) ||
3445  proc->databaseId == databaseid)
3446  count++;
3447  }
3448 
3449  LWLockRelease(ProcArrayLock);
3450 
3451  return count;
3452 }
#define OidIsValid(objectId)
Definition: c.h:706
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1811
static PGPROC * allProcs
Definition: procarray.c:252
Oid databaseId
Definition: proc.h:150
static ProcArrayStruct * procArray
Definition: procarray.c:250
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1207
Definition: proc.h:117
int pid
Definition: proc.h:142

◆ CountDBConnections()

int CountDBConnections ( Oid  databaseid)

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

3460 {
3461  ProcArrayStruct *arrayP = procArray;
3462  int count = 0;
3463  int index;
3464 
3465  LWLockAcquire(ProcArrayLock, LW_SHARED);
3466 
3467  for (index = 0; index < arrayP->numProcs; index++)
3468  {
3469  int pgprocno = arrayP->pgprocnos[index];
3470  PGPROC *proc = &allProcs[pgprocno];
3471 
3472  if (proc->pid == 0)
3473  continue; /* do not count prepared xacts */
3474  if (proc->isBackgroundWorker)
3475  continue; /* do not count background workers */
3476  if (!OidIsValid(databaseid) ||
3477  proc->databaseId == databaseid)
3478  count++;
3479  }
3480 
3481  LWLockRelease(ProcArrayLock);
3482 
3483  return count;
3484 }
#define OidIsValid(objectId)
Definition: c.h:706
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1811
bool isBackgroundWorker
Definition: proc.h:156
static PGPROC * allProcs
Definition: procarray.c:252
Oid databaseId
Definition: proc.h:150
static ProcArrayStruct * procArray
Definition: procarray.c:250
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1207
Definition: proc.h:117
int pid
Definition: proc.h:142

◆ CountOtherDBBackends()

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

Definition at line 3580 of file procarray.c.

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

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

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

◆ CountUserBackends()

int CountUserBackends ( Oid  roleid)

Definition at line 3530 of file procarray.c.

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

Referenced by InitializeSessionUserId().

3531 {
3532  ProcArrayStruct *arrayP = procArray;
3533  int count = 0;
3534  int index;
3535 
3536  LWLockAcquire(ProcArrayLock, LW_SHARED);
3537 
3538  for (index = 0; index < arrayP->numProcs; index++)
3539  {
3540  int pgprocno = arrayP->pgprocnos[index];
3541  PGPROC *proc = &allProcs[pgprocno];
3542 
3543  if (proc->pid == 0)
3544  continue; /* do not count prepared xacts */
3545  if (proc->isBackgroundWorker)
3546  continue; /* do not count background workers */
3547  if (proc->roleId == roleid)
3548  count++;
3549  }
3550 
3551  LWLockRelease(ProcArrayLock);
3552 
3553  return count;
3554 }
Oid roleId
Definition: proc.h:151
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1811
bool isBackgroundWorker
Definition: proc.h:156
static PGPROC * allProcs
Definition: procarray.c:252
static ProcArrayStruct * procArray
Definition: procarray.c:250
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1207
Definition: proc.h:117
int pid
Definition: proc.h:142

◆ CreateSharedProcArray()

void CreateSharedProcArray ( void  )

Definition at line 394 of file procarray.c.

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

Referenced by CreateSharedMemoryAndSemaphores().

395 {
396  bool found;
397 
398  /* Create or attach to the ProcArray shared structure */
400  ShmemInitStruct("Proc Array",
401  add_size(offsetof(ProcArrayStruct, pgprocnos),
402  mul_size(sizeof(int),
404  &found);
405 
406  if (!found)
407  {
408  /*
409  * We're the first - initialize.
410  */
411  procArray->numProcs = 0;
422  }
423 
425 
426  /* Create or attach to the KnownAssignedXids arrays too, if needed */
427  if (EnableHotStandby)
428  {
430  ShmemInitStruct("KnownAssignedXids",
431  mul_size(sizeof(TransactionId),
433  &found);
434  KnownAssignedXidsValid = (bool *)
435  ShmemInitStruct("KnownAssignedXidsValid",
436  mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS),
437  &found);
438  }
439 }
#define PROCARRAY_MAXPROCS
uint32 TransactionId
Definition: c.h:575
#define SpinLockInit(lock)
Definition: spin.h:60
TransactionId replication_slot_catalog_xmin
Definition: procarray.c:98
uint64 xactCompletionCount
Definition: transam.h:241
slock_t known_assigned_xids_lck
Definition: procarray.c:84
PROC_HDR * ProcGlobal
Definition: proc.c:79
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition: shmem.c:392
VariableCache ShmemVariableCache
Definition: varsup.c:34
int maxKnownAssignedXids
Definition: procarray.c:80
#define InvalidTransactionId
Definition: transam.h:31
static PGPROC * allProcs
Definition: procarray.c:252
int numKnownAssignedXids
Definition: procarray.c:81
static bool * KnownAssignedXidsValid
Definition: procarray.c:258
TransactionId lastOverflowedXid
Definition: procarray.c:93
static ProcArrayStruct * procArray
Definition: procarray.c:250
TransactionId replication_slot_xmin
Definition: procarray.c:96
Size mul_size(Size s1, Size s2)
Definition: shmem.c:515
Size add_size(Size s1, Size s2)
Definition: shmem.c:498
#define TOTAL_MAX_CACHED_SUBXIDS
static TransactionId * KnownAssignedXids
Definition: procarray.c:257
bool EnableHotStandby
Definition: xlog.c:97
PGPROC * allProcs
Definition: proc.h:312
int tailKnownAssignedXids
Definition: procarray.c:82
#define offsetof(type, field)
Definition: c.h:723
int headKnownAssignedXids
Definition: procarray.c:83

◆ ExpireAllKnownAssignedTransactionIds()

void ExpireAllKnownAssignedTransactionIds ( void  )

Definition at line 4358 of file procarray.c.

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

Referenced by ShutdownRecoveryTransactionEnvironment().

4359 {
4360  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
4362  LWLockRelease(ProcArrayLock);
4363 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1811
static void KnownAssignedXidsRemovePreceding(TransactionId xid)
Definition: procarray.c:4807
#define InvalidTransactionId
Definition: transam.h:31
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1207

◆ ExpireOldKnownAssignedTransactionIds()

void ExpireOldKnownAssignedTransactionIds ( TransactionId  xid)

Definition at line 4370 of file procarray.c.

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

Referenced by ProcArrayApplyRecoveryInfo().

4371 {
4372  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
4374  LWLockRelease(ProcArrayLock);
4375 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1811
static void KnownAssignedXidsRemovePreceding(TransactionId xid)
Definition: procarray.c:4807
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1207

◆ ExpireTreeKnownAssignedTransactionIds()

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

Definition at line 4332 of file procarray.c.

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

Referenced by xact_redo_abort(), and xact_redo_commit().

4334 {
4336 
4337  /*
4338  * Uses same locking as transaction commit
4339  */
4340  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
4341 
4342  KnownAssignedXidsRemoveTree(xid, nsubxids, subxids);
4343 
4344  /* As in ProcArrayEndTransaction, advance latestCompletedXid */
4346 
4347  /* ... and xactCompletionCount */
4349 
4350  LWLockRelease(ProcArrayLock);
4351 }
static void MaintainLatestCompletedXidRecovery(TransactionId latestXid)
Definition: procarray.c:937
uint64 xactCompletionCount
Definition: transam.h:241
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1811
VariableCache ShmemVariableCache
Definition: varsup.c:34
static void KnownAssignedXidsRemoveTree(TransactionId xid, int nsubxids, TransactionId *subxids)
Definition: procarray.c:4785
#define Assert(condition)
Definition: c.h:800
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1207
HotStandbyState standbyState
Definition: xlog.c:208

◆ FullXidRelativeTo()

static FullTransactionId FullXidRelativeTo ( FullTransactionId  rel,
TransactionId  xid 
)
inlinestatic

Definition at line 4179 of file procarray.c.

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

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

4180 {
4181  TransactionId rel_xid = XidFromFullTransactionId(rel);
4182 
4184  Assert(TransactionIdIsValid(rel_xid));
4185 
4186  /* not guaranteed to find issues, but likely to catch mistakes */
4188 
4190  + (int32) (xid - rel_xid));
4191 }
uint32 TransactionId
Definition: c.h:575
static FullTransactionId FullTransactionIdFromU64(uint64 value)
Definition: transam.h:81
signed int int32
Definition: c.h:417
#define XidFromFullTransactionId(x)
Definition: transam.h:48
#define AssertTransactionIdInAllowableRange(xid)
Definition: transam.h:294
#define Assert(condition)
Definition: c.h:800
#define U64FromFullTransactionId(x)
Definition: transam.h:49
#define TransactionIdIsValid(xid)
Definition: transam.h:41

◆ GetConflictingVirtualXIDs()

VirtualTransactionId* GetConflictingVirtualXIDs ( TransactionId  limitXmin,
Oid  dbOid 
)

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

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

◆ GetCurrentVirtualXIDs()

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

Definition at line 3166 of file procarray.c.

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

Referenced by WaitForOlderSnapshots().

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

◆ GetMaxSnapshotSubxidCount()

int GetMaxSnapshotSubxidCount ( void  )

Definition at line 1985 of file procarray.c.

References TOTAL_MAX_CACHED_SUBXIDS.

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

1986 {
1987  return TOTAL_MAX_CACHED_SUBXIDS;
1988 }
#define TOTAL_MAX_CACHED_SUBXIDS

◆ GetMaxSnapshotXidCount()

int GetMaxSnapshotXidCount ( void  )

Definition at line 1974 of file procarray.c.

References ProcArrayStruct::maxProcs.

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

1975 {
1976  return procArray->maxProcs;
1977 }
static ProcArrayStruct * procArray
Definition: procarray.c:250

◆ GetOldestActiveTransactionId()

TransactionId GetOldestActiveTransactionId ( void  )

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

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

◆ GetOldestNonRemovableTransactionId()

TransactionId GetOldestNonRemovableTransactionId ( Relation  rel)

Definition at line 1915 of file procarray.c.

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

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

1916 {
1917  ComputeXidHorizonsResult horizons;
1918 
1919  ComputeXidHorizons(&horizons);
1920 
1921  /* select horizon appropriate for relation */
1922  if (rel == NULL || rel->rd_rel->relisshared)
1923  return horizons.shared_oldest_nonremovable;
1925  return horizons.catalog_oldest_nonremovable;
1926  else if (RELATION_IS_LOCAL(rel))
1927  return horizons.temp_oldest_nonremovable;
1928  else
1929  return horizons.data_oldest_nonremovable;
1930 }
static void ComputeXidHorizons(ComputeXidHorizonsResult *h)
Definition: procarray.c:1658
#define RELATION_IS_LOCAL(relation)
Definition: rel.h:584
Form_pg_class rd_rel
Definition: rel.h:110
TransactionId catalog_oldest_nonremovable
Definition: procarray.c:233
TransactionId shared_oldest_nonremovable
Definition: procarray.c:216
#define RelationIsAccessibleInLogicalDecoding(relation)
Definition: rel.h:620
TransactionId temp_oldest_nonremovable
Definition: procarray.c:245
TransactionId data_oldest_nonremovable
Definition: procarray.c:239

◆ GetOldestSafeDecodingTransactionId()

TransactionId GetOldestSafeDecodingTransactionId ( bool  catalogOnly)

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

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

◆ GetOldestTransactionIdConsideredRunning()

TransactionId GetOldestTransactionIdConsideredRunning ( void  )

Definition at line 1939 of file procarray.c.

References ComputeXidHorizons(), and ComputeXidHorizonsResult::oldest_considered_running.

Referenced by CreateCheckPoint(), and CreateRestartPoint().

1940 {
1941  ComputeXidHorizonsResult horizons;
1942 
1943  ComputeXidHorizons(&horizons);
1944 
1945  return horizons.oldest_considered_running;
1946 }
TransactionId oldest_considered_running
Definition: procarray.c:207
static void ComputeXidHorizons(ComputeXidHorizonsResult *h)
Definition: procarray.c:1658

◆ GetReplicationHorizons()

void GetReplicationHorizons ( TransactionId xmin,
TransactionId catalog_xmin 
)

Definition at line 1952 of file procarray.c.

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

Referenced by XLogWalRcvSendHSFeedback().

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

◆ GetRunningTransactionData()

RunningTransactions GetRunningTransactionData ( void  )

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

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

◆ GetSnapshotData()

Snapshot GetSnapshotData ( Snapshot  snapshot)

Definition at line 2111 of file procarray.c.

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

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

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

◆ GetSnapshotDataInitOldSnapshot()

static void GetSnapshotDataInitOldSnapshot ( Snapshot  snapshot)
static

Definition at line 1994 of file procarray.c.

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

Referenced by GetSnapshotData(), and GetSnapshotDataReuse().

1995 {
1997  {
1998  /*
1999  * If not using "snapshot too old" feature, fill related fields with
2000  * dummy values that don't require any locking.
2001  */
2002  snapshot->lsn = InvalidXLogRecPtr;
2003  snapshot->whenTaken = 0;
2004  }
2005  else
2006  {
2007  /*
2008  * Capture the current time and WAL stream location in case this
2009  * snapshot becomes old enough to need to fall back on the special
2010  * "old snapshot" logic.
2011  */
2012  snapshot->lsn = GetXLogInsertRecPtr();
2013  snapshot->whenTaken = GetSnapshotCurrentTimestamp();
2014  MaintainOldSnapshotTimeMapping(snapshot->whenTaken, snapshot->xmin);
2015  }
2016 }
#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:1635
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:1854

◆ GetSnapshotDataReuse()

static bool GetSnapshotDataReuse ( Snapshot  snapshot)
static

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

2029 {
2030  uint64 curXactCompletionCount;
2031 
2032  Assert(LWLockHeldByMe(ProcArrayLock));
2033 
2034  if (unlikely(snapshot->snapXactCompletionCount == 0))
2035  return false;
2036 
2037  curXactCompletionCount = ShmemVariableCache->xactCompletionCount;
2038  if (curXactCompletionCount != snapshot->snapXactCompletionCount)
2039  return false;
2040 
2041  /*
2042  * If the current xactCompletionCount is still the same as it was at the
2043  * time the snapshot was built, we can be sure that rebuilding the
2044  * contents of the snapshot the hard way would result in the same snapshot
2045  * contents:
2046  *
2047  * As explained in transam/README, the set of xids considered running by
2048  * GetSnapshotData() cannot change while ProcArrayLock is held. Snapshot
2049  * contents only depend on transactions with xids and xactCompletionCount
2050  * is incremented whenever a transaction with an xid finishes (while
2051  * holding ProcArrayLock) exclusively). Thus the xactCompletionCount check
2052  * ensures we would detect if the snapshot would have changed.
2053  *
2054  * As the snapshot contents are the same as it was before, it is is safe
2055  * to re-enter the snapshot's xmin into the PGPROC array. None of the rows
2056  * visible under the snapshot could already have been removed (that'd
2057  * require the set of running transactions to change) and it fulfills the
2058  * requirement that concurrent GetSnapshotData() calls yield the same
2059  * xmin.
2060  */
2062  MyProc->xmin = TransactionXmin = snapshot->xmin;
2063 
2064  RecentXmin = snapshot->xmin;
2066 
2067  snapshot->curcid = GetCurrentCommandId(false);
2068  snapshot->active_count = 0;
2069  snapshot->regd_count = 0;
2070  snapshot->copied = false;
2071 
2073 
2074  return true;
2075 }
uint64 snapXactCompletionCount
Definition: snapshot.h:216
bool copied
Definition: snapshot.h:185
bool LWLockHeldByMe(LWLock *l)
Definition: lwlock.c:1927
PGPROC * MyProc
Definition: proc.c:67
TransactionId RecentXmin
Definition: snapmgr.c:113
uint64 xactCompletionCount
Definition: transam.h:241
uint32 regd_count
Definition: snapshot.h:205
TransactionId TransactionXmin
Definition: snapmgr.c:112
static void GetSnapshotDataInitOldSnapshot(Snapshot snapshot)
Definition: procarray.c:1994
bool TransactionIdPrecedesOrEquals(TransactionId id1, TransactionId id2)
Definition: transam.c:319
TransactionId xmin
Definition: proc.h:134
VariableCache ShmemVariableCache
Definition: varsup.c:34
TransactionId xmin
Definition: snapshot.h:157
CommandId curcid
Definition: snapshot.h:187
#define Assert(condition)
Definition: c.h:800
#define unlikely(x)
Definition: c.h:261
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 2948 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().

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

◆ GlobalVisCheckRemovableXid()

bool GlobalVisCheckRemovableXid ( Relation  rel,
TransactionId  xid 
)

Definition at line 4158 of file procarray.c.

References GlobalVisTestFor(), and GlobalVisTestIsRemovableXid().

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

4159 {
4161 
4162  state = GlobalVisTestFor(rel);
4163 
4164  return GlobalVisTestIsRemovableXid(state, xid);
4165 }
bool GlobalVisTestIsRemovableXid(GlobalVisState *state, TransactionId xid)
Definition: procarray.c:4092
GlobalVisState * GlobalVisTestFor(Relation rel)
Definition: procarray.c:3924
Definition: regguts.h:298

◆ GlobalVisIsRemovableFullXid()

bool GlobalVisIsRemovableFullXid ( Relation  rel,
FullTransactionId  fxid 
)

Definition at line 4144 of file procarray.c.

References GlobalVisTestFor(), and GlobalVisTestIsRemovableFullXid().

Referenced by gistPageRecyclable().

4145 {
4147 
4148  state = GlobalVisTestFor(rel);
4149 
4150  return GlobalVisTestIsRemovableFullXid(state, fxid);
4151 }
bool GlobalVisTestIsRemovableFullXid(GlobalVisState *state, FullTransactionId fxid)
Definition: procarray.c:4050
GlobalVisState * GlobalVisTestFor(Relation rel)
Definition: procarray.c:3924
Definition: regguts.h:298

◆ GlobalVisTestFor()

GlobalVisState* GlobalVisTestFor ( Relation  rel)

Definition at line 3924 of file procarray.c.

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

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

3925 {
3926  bool need_shared;
3927  bool need_catalog;
3929 
3930  /* XXX: we should assert that a snapshot is pushed or registered */
3931  Assert(RecentXmin);
3932 
3933  if (!rel)
3934  need_shared = need_catalog = true;
3935  else
3936  {
3937  /*
3938  * Other kinds currently don't contain xids, nor always the necessary
3939  * logical decoding markers.
3940  */
3941  Assert(rel->rd_rel->relkind == RELKIND_RELATION ||
3942  rel->rd_rel->relkind == RELKIND_MATVIEW ||
3943  rel->rd_rel->relkind == RELKIND_TOASTVALUE);
3944 
3945  need_shared = rel->rd_rel->relisshared || RecoveryInProgress();
3946  need_catalog = IsCatalogRelation(rel) || RelationIsAccessibleInLogicalDecoding(rel);
3947  }
3948 
3949  if (need_shared)
3950  state = &GlobalVisSharedRels;
3951  else if (need_catalog)
3952  state = &GlobalVisCatalogRels;
3953  else if (RELATION_IS_LOCAL(rel))
3954  state = &GlobalVisTempRels;
3955  else
3956  state = &GlobalVisDataRels;
3957 
3960 
3961  return state;
3962 }
bool IsCatalogRelation(Relation relation)
Definition: catalog.c:96
#define FullTransactionIdIsValid(x)
Definition: transam.h:55
#define RELATION_IS_LOCAL(relation)
Definition: rel.h:584
TransactionId RecentXmin
Definition: snapmgr.c:113
Form_pg_class rd_rel
Definition: rel.h:110
bool RecoveryInProgress(void)
Definition: xlog.c:8070
FullTransactionId definitely_needed
Definition: procarray.c:172
static GlobalVisState GlobalVisSharedRels
Definition: procarray.c:273
#define RelationIsAccessibleInLogicalDecoding(relation)
Definition: rel.h:620
#define Assert(condition)
Definition: c.h:800
Definition: regguts.h:298
FullTransactionId maybe_needed
Definition: procarray.c:175
static GlobalVisState GlobalVisTempRels
Definition: procarray.c:276
static GlobalVisState GlobalVisCatalogRels
Definition: procarray.c:274
static GlobalVisState GlobalVisDataRels
Definition: procarray.c:275

◆ GlobalVisTestIsRemovableFullXid()

bool GlobalVisTestIsRemovableFullXid ( GlobalVisState state,
FullTransactionId  fxid 
)

Definition at line 4050 of file procarray.c.

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

Referenced by GlobalVisIsRemovableFullXid(), and GlobalVisTestIsRemovableXid().

4052 {
4053  /*
4054  * If fxid is older than maybe_needed bound, it definitely is visible to
4055  * everyone.
4056  */
4057  if (FullTransactionIdPrecedes(fxid, state->maybe_needed))
4058  return true;
4059 
4060  /*
4061  * If fxid is >= definitely_needed bound, it is very likely to still be
4062  * considered running.
4063  */
4065  return false;
4066 
4067  /*
4068  * fxid is between maybe_needed and definitely_needed, i.e. there might or
4069  * might not exist a snapshot considering fxid running. If it makes sense,
4070  * update boundaries and recheck.
4071  */
4072  if (GlobalVisTestShouldUpdate(state))
4073  {
4074  GlobalVisUpdate();
4075 
4077 
4078  return FullTransactionIdPrecedes(fxid, state->maybe_needed);
4079  }
4080  else
4081  return false;
4082 }
FullTransactionId definitely_needed
Definition: procarray.c:172
static bool GlobalVisTestShouldUpdate(GlobalVisState *state)
Definition: procarray.c:3975
#define Assert(condition)
Definition: c.h:800
#define FullTransactionIdFollowsOrEquals(a, b)
Definition: transam.h:54
FullTransactionId maybe_needed
Definition: procarray.c:175
#define FullTransactionIdPrecedes(a, b)
Definition: transam.h:51
static void GlobalVisUpdate(void)
Definition: procarray.c:4033

◆ GlobalVisTestIsRemovableXid()

bool GlobalVisTestIsRemovableXid ( GlobalVisState state,
TransactionId  xid 
)

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

4093 {
4094  FullTransactionId fxid;
4095 
4096  /*
4097  * Convert 32 bit argument to FullTransactionId. We can do so safely
4098  * because we know the xid has to, at the very least, be between
4099  * [oldestXid, nextFullXid), i.e. within 2 billion of xid. To avoid taking
4100  * a lock to determine either, we can just compare with
4101  * state->definitely_needed, which was based on those value at the time
4102  * the current snapshot was built.
4103  */
4104  fxid = FullXidRelativeTo(state->definitely_needed, xid);
4105 
4106  return GlobalVisTestIsRemovableFullXid(state, fxid);
4107 }
static FullTransactionId FullXidRelativeTo(FullTransactionId rel, TransactionId xid)
Definition: procarray.c:4179
bool GlobalVisTestIsRemovableFullXid(GlobalVisState *state, FullTransactionId fxid)
Definition: procarray.c:4050
FullTransactionId definitely_needed
Definition: procarray.c:172

◆ GlobalVisTestNonRemovableFullHorizon()

FullTransactionId GlobalVisTestNonRemovableFullHorizon ( GlobalVisState state)

Definition at line 4119 of file procarray.c.

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

Referenced by GlobalVisTestNonRemovableHorizon().

4120 {
4121  /* acquire accurate horizon if not already done */
4122  if (GlobalVisTestShouldUpdate(state))
4123  GlobalVisUpdate();
4124 
4125  return state->maybe_needed;
4126 }
static bool GlobalVisTestShouldUpdate(GlobalVisState *state)
Definition: procarray.c:3975
FullTransactionId maybe_needed
Definition: procarray.c:175
static void GlobalVisUpdate(void)
Definition: procarray.c:4033

◆ GlobalVisTestNonRemovableHorizon()

TransactionId GlobalVisTestNonRemovableHorizon ( GlobalVisState state)

Definition at line 4130 of file procarray.c.

References GlobalVisTestNonRemovableFullHorizon(), and XidFromFullTransactionId.

Referenced by heap_page_prune_opt(), and heap_prune_satisfies_vacuum().

4131 {
4132  FullTransactionId cutoff;
4133 
4134  cutoff = GlobalVisTestNonRemovableFullHorizon(state);
4135 
4136  return XidFromFullTransactionId(cutoff);
4137 }
#define XidFromFullTransactionId(x)
Definition: transam.h:48
FullTransactionId GlobalVisTestNonRemovableFullHorizon(GlobalVisState *state)
Definition: procarray.c:4119

◆ GlobalVisTestShouldUpdate()

static bool GlobalVisTestShouldUpdate ( GlobalVisState state)
static

Definition at line 3975 of file procarray.c.

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

Referenced by GlobalVisTestIsRemovableFullXid(), and GlobalVisTestNonRemovableFullHorizon().

3976 {
3977  /* hasn't been updated yet */
3979  return true;
3980 
3981  /*
3982  * If the maybe_needed/definitely_needed boundaries are the same, it's
3983  * unlikely to be beneficial to refresh boundaries.
3984  */
3986  state->definitely_needed))
3987  return false;
3988 
3989  /* does the last snapshot built have a different xmin? */
3991 }
TransactionId RecentXmin
Definition: snapmgr.c:113
FullTransactionId definitely_needed
Definition: procarray.c:172
static TransactionId ComputeXidHorizonsResultLastXmin
Definition: procarray.c:283
#define FullTransactionIdFollowsOrEquals(a, b)
Definition: transam.h:54
FullTransactionId maybe_needed
Definition: procarray.c:175
#define TransactionIdIsValid(xid)
Definition: transam.h:41

◆ GlobalVisUpdate()

static void GlobalVisUpdate ( void  )
static

Definition at line 4033 of file procarray.c.

References ComputeXidHorizons().

Referenced by GlobalVisTestIsRemovableFullXid(), and GlobalVisTestNonRemovableFullHorizon().

4034 {
4035  ComputeXidHorizonsResult horizons;
4036 
4037  /* updates the horizons as a side-effect */
4038  ComputeXidHorizons(&horizons);
4039 }
static void ComputeXidHorizons(ComputeXidHorizonsResult *h)
Definition: procarray.c:1658

◆ GlobalVisUpdateApply()

static void GlobalVisUpdateApply ( ComputeXidHorizonsResult horizons)
static

Definition at line 3994 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, ComputeXidHorizonsResult::shared_oldest_nonremovable, and ComputeXidHorizonsResult::temp_oldest_nonremovable.

Referenced by ComputeXidHorizons().

3995 {
3998  horizons->shared_oldest_nonremovable);
4001  horizons->catalog_oldest_nonremovable);
4004  horizons->data_oldest_nonremovable);
4007  horizons->temp_oldest_nonremovable);
4008 
4009  /*
4010  * In longer running transactions it's possible that transactions we
4011  * previously needed to treat as running aren't around anymore. So update
4012  * definitely_needed to not be earlier than maybe_needed.
4013  */
4024 
4026 }
FullTransactionId latest_completed
Definition: procarray.c:187
static FullTransactionId FullXidRelativeTo(FullTransactionId rel, TransactionId xid)
Definition: procarray.c:4179
TransactionId RecentXmin
Definition: snapmgr.c:113
TransactionId catalog_oldest_nonremovable
Definition: procarray.c:233
FullTransactionId definitely_needed
Definition: procarray.c:172
static GlobalVisState GlobalVisSharedRels
Definition: procarray.c:273
TransactionId shared_oldest_nonremovable
Definition: procarray.c:216
static TransactionId ComputeXidHorizonsResultLastXmin
Definition: procarray.c:283
TransactionId temp_oldest_nonremovable
Definition: procarray.c:245
FullTransactionId maybe_needed
Definition: procarray.c:175
static FullTransactionId FullTransactionIdNewer(FullTransactionId a, FullTransactionId b)
Definition: transam.h:353
static GlobalVisState GlobalVisTempRels
Definition: procarray.c:276
TransactionId data_oldest_nonremovable
Definition: procarray.c:239
static GlobalVisState GlobalVisCatalogRels
Definition: procarray.c:274
static GlobalVisState GlobalVisDataRels
Definition: procarray.c:275

◆ HaveVirtualXIDsDelayingChkpt()

bool HaveVirtualXIDsDelayingChkpt ( VirtualTransactionId vxids,
int  nvxids 
)

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

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

◆ IsBackendPid()

bool IsBackendPid ( int  pid)

Definition at line 3133 of file procarray.c.

References BackendPidGetProc().

Referenced by pg_stat_get_subscription().

3134 {
3135  return (BackendPidGetProc(pid) != NULL);
3136 }
PGPROC * BackendPidGetProc(int pid)
Definition: procarray.c:3038

◆ KnownAssignedXidExists()

static bool KnownAssignedXidExists ( TransactionId  xid)
static

Definition at line 4746 of file procarray.c.

References Assert, KnownAssignedXidsSearch(), and TransactionIdIsValid.

Referenced by TransactionIdIsInProgress().

4747 {
4749 
4750  return KnownAssignedXidsSearch(xid, false);
4751 }
#define Assert(condition)
Definition: c.h:800
static bool KnownAssignedXidsSearch(TransactionId xid, bool remove)
Definition: procarray.c:4653
#define TransactionIdIsValid(xid)
Definition: transam.h:41

◆ KnownAssignedXidsAdd()

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

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

4537 {
4538  ProcArrayStruct *pArray = procArray;
4539  TransactionId next_xid;
4540  int head,
4541  tail;
4542  int nxids;
4543  int i;
4544 
4545  Assert(TransactionIdPrecedesOrEquals(from_xid, to_xid));
4546 
4547  /*
4548  * Calculate how many array slots we'll need. Normally this is cheap; in
4549  * the unusual case where the XIDs cross the wrap point, we do it the hard
4550  * way.
4551  */
4552  if (to_xid >= from_xid)
4553  nxids = to_xid - from_xid + 1;
4554  else
4555  {
4556  nxids = 1;
4557  next_xid = from_xid;
4558  while (TransactionIdPrecedes(next_xid, to_xid))
4559  {
4560  nxids++;
4561  TransactionIdAdvance(next_xid);
4562  }
4563  }
4564 
4565  /*
4566  * Since only the startup process modifies the head/tail pointers, we
4567  * don't need a lock to read them here.
4568  */
4569  head = pArray->headKnownAssignedXids;
4570  tail = pArray->tailKnownAssignedXids;
4571 
4572  Assert(head >= 0 && head <= pArray->maxKnownAssignedXids);
4573  Assert(tail >= 0 && tail < pArray->maxKnownAssignedXids);
4574 
4575  /*
4576  * Verify that insertions occur in TransactionId sequence. Note that even
4577  * if the last existing element is marked invalid, it must still have a
4578  * correctly sequenced XID value.
4579  */
4580  if (head > tail &&
4581  TransactionIdFollowsOrEquals(KnownAssignedXids[head - 1], from_xid))
4582  {
4584  elog(ERROR, "out-of-order XID insertion in KnownAssignedXids");
4585  }
4586 
4587  /*
4588  * If our xids won't fit in the remaining space, compress out free space
4589  */
4590  if (head + nxids > pArray->maxKnownAssignedXids)
4591  {
4592  /* must hold lock to compress */
4593  if (!exclusive_lock)
4594  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
4595 
4597 
4598  head = pArray->headKnownAssignedXids;
4599  /* note: we no longer care about the tail pointer */
4600 
4601  if (!exclusive_lock)
4602  LWLockRelease(ProcArrayLock);
4603 
4604  /*
4605  * If it still won't fit then we're out of memory
4606  */
4607  if (head + nxids > pArray->maxKnownAssignedXids)
4608  elog(ERROR, "too many KnownAssignedXids");
4609  }
4610 
4611  /* Now we can insert the xids into the space starting at head */
4612  next_xid = from_xid;
4613  for (i = 0; i < nxids; i++)
4614  {
4615  KnownAssignedXids[head] = next_xid;
4616  KnownAssignedXidsValid[head] = true;
4617  TransactionIdAdvance(next_xid);
4618  head++;
4619  }
4620 
4621  /* Adjust count of number of valid entries */
4622  pArray->numKnownAssignedXids += nxids;
4623 
4624  /*
4625  * Now update the head pointer. We use a spinlock to protect this
4626  * pointer, not because the update is likely to be non-atomic, but to
4627  * ensure that other processors see the above array updates before they
4628  * see the head pointer change.
4629  *
4630  * If we're holding ProcArrayLock exclusively, there's no need to take the
4631  * spinlock.
4632  */
4633  if (exclusive_lock)
4634  pArray->headKnownAssignedXids = head;
4635  else
4636  {
4638  pArray->headKnownAssignedXids = head;
4640  }
4641 }
#define TransactionIdAdvance(dest)
Definition: transam.h:91
static void KnownAssignedXidsDisplay(int trace_level)
Definition: procarray.c:4992
uint32 TransactionId
Definition: c.h:575
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:1811
#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:258
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
static ProcArrayStruct * procArray
Definition: procarray.c:250
#define SpinLockRelease(lock)
Definition: spin.h:64
#define Assert(condition)
Definition: c.h:800
static TransactionId * KnownAssignedXids
Definition: procarray.c:257
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1207
static void KnownAssignedXidsCompress(bool force)
Definition: procarray.c:4473
#define elog(elevel,...)
Definition: elog.h:228
int i
int tailKnownAssignedXids
Definition: procarray.c:82
int headKnownAssignedXids
Definition: procarray.c:83

◆ KnownAssignedXidsCompress()

static void KnownAssignedXidsCompress ( bool  force)
static

Definition at line 4473 of file procarray.c.

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

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

4474 {
4475  ProcArrayStruct *pArray = procArray;
4476  int head,
4477  tail;
4478  int compress_index;
4479  int i;
4480 
4481  /* no spinlock required since we hold ProcArrayLock exclusively */
4482  head = pArray->headKnownAssignedXids;
4483  tail = pArray->tailKnownAssignedXids;
4484 
4485  if (!force)
4486  {
4487  /*
4488  * If we can choose how much to compress, use a heuristic to avoid
4489  * compressing too often or not often enough.
4490  *
4491  * Heuristic is if we have a large enough current spread and less than
4492  * 50% of the elements are currently in use, then compress. This
4493  * should ensure we compress fairly infrequently. We could compress
4494  * less often though the virtual array would spread out more and
4495  * snapshots would become more expensive.
4496  */
4497  int nelements = head - tail;
4498 
4499  if (nelements < 4 * PROCARRAY_MAXPROCS ||
4500  nelements < 2 * pArray->numKnownAssignedXids)
4501  return;
4502  }
4503 
4504  /*
4505  * We compress the array by reading the valid values from tail to head,
4506  * re-aligning data to 0th element.
4507  */
4508  compress_index = 0;
4509  for (i = tail; i < head; i++)
4510  {
4511  if (KnownAssignedXidsValid[i])
4512  {
4513  KnownAssignedXids[compress_index] = KnownAssignedXids[i];
4514  KnownAssignedXidsValid[compress_index] = true;
4515  compress_index++;
4516  }
4517  }
4518 
4519  pArray->tailKnownAssignedXids = 0;
4520  pArray->headKnownAssignedXids = compress_index;
4521 }
#define PROCARRAY_MAXPROCS
static bool * KnownAssignedXidsValid
Definition: procarray.c:258
static ProcArrayStruct * procArray
Definition: procarray.c:250
static TransactionId * KnownAssignedXids
Definition: procarray.c:257
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 4992 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().

4993 {
4994  ProcArrayStruct *pArray = procArray;
4996  int head,
4997  tail,
4998  i;
4999  int nxids = 0;
5000 
5001  tail = pArray->tailKnownAssignedXids;
5002  head = pArray->headKnownAssignedXids;
5003 
5004  initStringInfo(&buf);
5005 
5006  for (i = tail; i < head; i++)
5007  {
5008  if (KnownAssignedXidsValid[i])
5009  {
5010  nxids++;
5011  appendStringInfo(&buf, "[%d]=%u ", i, KnownAssignedXids[i]);
5012  }
5013  }
5014 
5015  elog(trace_level, "%d KnownAssignedXids (num=%d tail=%d head=%d) %s",
5016  nxids,
5017  pArray->numKnownAssignedXids,
5018  pArray->tailKnownAssignedXids,
5019  pArray->headKnownAssignedXids,
5020  buf.data);
5021 
5022  pfree(buf.data);
5023 }
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:68
int numKnownAssignedXids
Definition: procarray.c:81
static bool * KnownAssignedXidsValid
Definition: procarray.c:258
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
static ProcArrayStruct * procArray
Definition: procarray.c:250
static TransactionId * KnownAssignedXids
Definition: procarray.c:257
#define elog(elevel,...)
Definition: elog.h:228
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 4885 of file procarray.c.

References InvalidTransactionId, and KnownAssignedXidsGetAndSetXmin().

Referenced by TransactionIdIsInProgress().

4886 {
4888 
4889  return KnownAssignedXidsGetAndSetXmin(xarray, &xtmp, xmax);
4890 }
uint32 TransactionId
Definition: c.h:575
#define InvalidTransactionId
Definition: transam.h:31
static int KnownAssignedXidsGetAndSetXmin(TransactionId *xarray, TransactionId *xmin, TransactionId xmax)
Definition: procarray.c:4899

◆ KnownAssignedXidsGetAndSetXmin()

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

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

4901 {
4902  int count = 0;
4903  int head,
4904  tail;
4905  int i;
4906 
4907  /*
4908  * Fetch head just once, since it may change while we loop. We can stop
4909  * once we reach the initially seen head, since we are certain that an xid
4910  * cannot enter and then leave the array while we hold ProcArrayLock. We
4911  * might miss newly-added xids, but they should be >= xmax so irrelevant
4912  * anyway.
4913  *
4914  * Must take spinlock to ensure we see up-to-date array contents.
4915  */
4920 
4921  for (i = tail; i < head; i++)
4922  {
4923  /* Skip any gaps in the array */
4924  if (KnownAssignedXidsValid[i])
4925  {
4926  TransactionId knownXid = KnownAssignedXids[i];
4927 
4928  /*
4929  * Update xmin if required. Only the first XID need be checked,
4930  * since the array is sorted.
4931  */
4932  if (count == 0 &&
4933  TransactionIdPrecedes(knownXid, *xmin))
4934  *xmin = knownXid;
4935 
4936  /*
4937  * Filter out anything >= xmax, again relying on sorted property
4938  * of array.
4939  */
4940  if (TransactionIdIsValid(xmax) &&
4941  TransactionIdFollowsOrEquals(knownXid, xmax))
4942  break;
4943 
4944  /* Add knownXid into output array */
4945  xarray[count++] = knownXid;
4946  }
4947  }
4948 
4949  return count;
4950 }
uint32 TransactionId
Definition: c.h:575
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:258
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
static ProcArrayStruct * procArray
Definition: procarray.c:250
#define SpinLockRelease(lock)
Definition: spin.h:64
static TransactionId * KnownAssignedXids
Definition: procarray.c:257
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 4957 of file procarray.c.

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

Referenced by ComputeXidHorizons().

4958 {
4959  int head,
4960  tail;
4961  int i;
4962 
4963  /*
4964  * Fetch head just once, since it may change while we loop.
4965  */
4970 
4971  for (i = tail; i < head; i++)
4972  {
4973  /* Skip any gaps in the array */
4974  if (KnownAssignedXidsValid[i])
4975  return KnownAssignedXids[i];
4976  }
4977 
4978  return InvalidTransactionId;
4979 }
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:258
static ProcArrayStruct * procArray
Definition: procarray.c:250
#define SpinLockRelease(lock)
Definition: spin.h:64
static TransactionId * KnownAssignedXids
Definition: procarray.c:257
int i
int tailKnownAssignedXids
Definition: procarray.c:82
int headKnownAssignedXids
Definition: procarray.c:83

◆ KnownAssignedXidsRemove()

static void KnownAssignedXidsRemove ( TransactionId  xid)
static

Definition at line 4759 of file procarray.c.

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

Referenced by KnownAssignedXidsRemoveTree().

4760 {
4762 
4763  elog(trace_recovery(DEBUG4), "remove KnownAssignedXid %u", xid);
4764 
4765  /*
4766  * Note: we cannot consider it an error to remove an XID that's not
4767  * present. We intentionally remove subxact IDs while processing
4768  * XLOG_XACT_ASSIGNMENT, to avoid array overflow. Then those XIDs will be
4769  * removed again when the top-level xact commits or aborts.
4770  *
4771  * It might be possible to track such XIDs to distinguish this case from
4772  * actual errors, but it would be complicated and probably not worth it.
4773  * So, just ignore the search result.
4774  */
4775  (void) KnownAssignedXidsSearch(xid, true);
4776 }
#define DEBUG4
Definition: elog.h:22
int trace_recovery(int trace_level)
Definition: elog.c:3586
#define Assert(condition)
Definition: c.h:800
static bool KnownAssignedXidsSearch(TransactionId xid, bool remove)
Definition: procarray.c:4653
#define elog(elevel,...)
Definition: elog.h:228
#define TransactionIdIsValid(xid)
Definition: transam.h:41

◆ KnownAssignedXidsRemovePreceding()

static void KnownAssignedXidsRemovePreceding ( TransactionId  xid)
static

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

4808 {
4809  ProcArrayStruct *pArray = procArray;
4810  int count = 0;
4811  int head,
4812  tail,
4813  i;
4814 
4815  if (!TransactionIdIsValid(removeXid))
4816  {
4817  elog(trace_recovery(DEBUG4), "removing all KnownAssignedXids");
4818  pArray->numKnownAssignedXids = 0;
4819  pArray->headKnownAssignedXids = pArray->tailKnownAssignedXids = 0;
4820  return;
4821  }
4822 
4823  elog(trace_recovery(DEBUG4), "prune KnownAssignedXids to %u", removeXid);
4824 
4825  /*
4826  * Mark entries invalid starting at the tail. Since array is sorted, we
4827  * can stop as soon as we reach an entry >= removeXid.
4828  */
4829  tail = pArray->tailKnownAssignedXids;
4830  head = pArray->headKnownAssignedXids;
4831 
4832  for (i = tail; i < head; i++)
4833  {
4834  if (KnownAssignedXidsValid[i])
4835  {
4836  TransactionId knownXid = KnownAssignedXids[i];
4837 
4838  if (TransactionIdFollowsOrEquals(knownXid, removeXid))
4839  break;
4840 
4841  if (!StandbyTransactionIdIsPrepared(knownXid))
4842  {
4843  KnownAssignedXidsValid[i] = false;
4844  count++;
4845  }
4846  }
4847  }
4848 
4849  pArray->numKnownAssignedXids -= count;
4850  Assert(pArray->numKnownAssignedXids >= 0);
4851 
4852  /*
4853  * Advance the tail pointer if we've marked the tail item invalid.
4854  */
4855  for (i = tail; i < head; i++)
4856  {
4857  if (KnownAssignedXidsValid[i])
4858  break;
4859  }
4860  if (i >= head)
4861  {
4862  /* Array is empty, so we can reset both pointers */
4863  pArray->headKnownAssignedXids = 0;
4864  pArray->tailKnownAssignedXids = 0;
4865  }
4866  else
4867  {
4868  pArray->tailKnownAssignedXids = i;
4869  }
4870 
4871  /* Opportunistically compress the array */
4873 }
uint32 TransactionId
Definition: c.h:575
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:3586
bool StandbyTransactionIdIsPrepared(TransactionId xid)
Definition: twophase.c:1369
int numKnownAssignedXids
Definition: procarray.c:81
static bool * KnownAssignedXidsValid
Definition: procarray.c:258
static ProcArrayStruct * procArray
Definition: procarray.c:250
#define Assert(condition)
Definition: c.h:800
static TransactionId * KnownAssignedXids
Definition: procarray.c:257
static void KnownAssignedXidsCompress(bool force)
Definition: procarray.c:4473
#define elog(elevel,...)
Definition: elog.h:228
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 4785 of file procarray.c.

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

Referenced by ExpireTreeKnownAssignedTransactionIds(), and ProcArrayApplyXidAssignment().

4787 {
4788  int i;
4789 
4790  if (TransactionIdIsValid(xid))
4792 
4793  for (i = 0; i < nsubxids; i++)
4794  KnownAssignedXidsRemove(subxids[i]);
4795 
4796  /* Opportunistically compress the array */
4798 }
static void KnownAssignedXidsCompress(bool force)
Definition: procarray.c:4473
static void KnownAssignedXidsRemove(TransactionId xid)
Definition: procarray.c:4759
int i
#define TransactionIdIsValid(xid)
Definition: transam.h:41

◆ KnownAssignedXidsReset()

static void KnownAssignedXidsReset ( void  )
static

Definition at line 5030 of file procarray.c.

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

Referenced by ProcArrayApplyRecoveryInfo().

5031 {
5032  ProcArrayStruct *pArray = procArray;
5033 
5034  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
5035 
5036  pArray->numKnownAssignedXids = 0;
5037  pArray->tailKnownAssignedXids = 0;
5038  pArray->headKnownAssignedXids = 0;
5039 
5040  LWLockRelease(ProcArrayLock);
5041 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1811
int numKnownAssignedXids
Definition: procarray.c:81
static ProcArrayStruct * procArray
Definition: procarray.c:250
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1207
int tailKnownAssignedXids
Definition: procarray.c:82
int headKnownAssignedXids
Definition: procarray.c:83

◆ KnownAssignedXidsSearch()

static bool KnownAssignedXidsSearch ( TransactionId  xid,
bool  remove 
)
static

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

4654 {
4655  ProcArrayStruct *pArray = procArray;
4656  int first,
4657  last;
4658  int head;
4659  int tail;
4660  int result_index = -1;
4661 
4662  if (remove)
4663  {
4664  /* we hold ProcArrayLock exclusively, so no need for spinlock */
4665  tail = pArray->tailKnownAssignedXids;
4666  head = pArray->headKnownAssignedXids;
4667  }
4668  else
4669  {
4670  /* take spinlock to ensure we see up-to-date array contents */
4672  tail = pArray->tailKnownAssignedXids;
4673  head = pArray->headKnownAssignedXids;
4675  }
4676 
4677  /*
4678  * Standard binary search. Note we can ignore the KnownAssignedXidsValid
4679  * array here, since even invalid entries will contain sorted XIDs.
4680  */
4681  first = tail;
4682  last = head - 1;
4683  while (first <= last)
4684  {
4685  int mid_index;
4686  TransactionId mid_xid;
4687 
4688  mid_index = (first + last) / 2;
4689  mid_xid = KnownAssignedXids[mid_index];
4690 
4691  if (xid == mid_xid)
4692  {
4693  result_index = mid_index;
4694  break;
4695  }
4696  else if (TransactionIdPrecedes(xid, mid_xid))
4697  last = mid_index - 1;
4698  else
4699  first = mid_index + 1;
4700  }
4701 
4702  if (result_index < 0)
4703  return false; /* not in array */
4704 
4705  if (!KnownAssignedXidsValid[result_index])
4706  return false; /* in array, but invalid */
4707 
4708  if (remove)
4709  {
4710  KnownAssignedXidsValid[result_index] = false;
4711 
4712  pArray->numKnownAssignedXids--;
4713  Assert(pArray->numKnownAssignedXids >= 0);
4714 
4715  /*
4716  * If we're removing the tail element then advance tail pointer over
4717  * any invalid elements. This will speed future searches.
4718  */
4719  if (result_index == tail)
4720  {
4721  tail++;
4722  while (tail < head && !KnownAssignedXidsValid[tail])
4723  tail++;
4724  if (tail >= head)
4725  {
4726  /* Array is empty, so we can reset both pointers */
4727  pArray->headKnownAssignedXids = 0;
4728  pArray->tailKnownAssignedXids = 0;
4729  }
4730  else
4731  {
4732  pArray->tailKnownAssignedXids = tail;
4733  }
4734  }
4735  }
4736 
4737  return true;
4738 }
uint32 TransactionId
Definition: c.h:575
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:258
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
static ProcArrayStruct * procArray
Definition: procarray.c:250
#define SpinLockRelease(lock)
Definition: spin.h:64
#define Assert(condition)
Definition: c.h:800
static TransactionId * KnownAssignedXids
Definition: procarray.c:257
int tailKnownAssignedXids
Definition: procarray.c:82
int headKnownAssignedXids
Definition: procarray.c:83

◆ MaintainLatestCompletedXid()

static void MaintainLatestCompletedXid ( TransactionId  latestXid)
static

Definition at line 915 of file procarray.c.

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

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

916 {
918 
919  Assert(FullTransactionIdIsValid(cur_latest));
921  Assert(LWLockHeldByMe(ProcArrayLock));
922 
923  if (TransactionIdPrecedes(XidFromFullTransactionId(cur_latest), latestXid))
924  {
926  FullXidRelativeTo(cur_latest, latestXid);
927  }
928 
931 }
bool LWLockHeldByMe(LWLock *l)
Definition: lwlock.c:1927
#define FullTransactionIdIsValid(x)
Definition: transam.h:55
static FullTransactionId FullXidRelativeTo(FullTransactionId rel, TransactionId xid)
Definition: procarray.c:4179
FullTransactionId latestCompletedXid
Definition: transam.h:231
bool RecoveryInProgress(void)
Definition: xlog.c:8070
#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:800
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:393

◆ MaintainLatestCompletedXidRecovery()

static void MaintainLatestCompletedXidRecovery ( TransactionId  latestXid)
static

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

938 {
940  FullTransactionId rel;
941 
943  Assert(LWLockHeldByMe(ProcArrayLock));
944 
945  /*
946  * Need a FullTransactionId to compare latestXid with. Can't rely on
947  * latestCompletedXid to be initialized in recovery. But in recovery it's
948  * safe to access nextXid without a lock for the startup process.
949  */
952 
953  if (!FullTransactionIdIsValid(cur_latest) ||
954  TransactionIdPrecedes(XidFromFullTransactionId(cur_latest), latestXid))
955  {
957  FullXidRelativeTo(rel, latestXid);
958  }
959 
961 }
#define AmStartupProcess()
Definition: miscadmin.h:431
bool LWLockHeldByMe(LWLock *l)
Definition: lwlock.c:1927
#define FullTransactionIdIsValid(x)
Definition: transam.h:55
static FullTransactionId FullXidRelativeTo(FullTransactionId rel, TransactionId xid)
Definition: procarray.c:4179
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:800

◆ MinimumActiveBackends()

bool MinimumActiveBackends ( int  min)

Definition at line 3376 of file procarray.c.

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

Referenced by XLogFlush().

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

◆ ProcArrayAdd()

void ProcArrayAdd ( PGPROC proc)

Definition at line 445 of file procarray.c.

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

Referenced by InitProcessPhase2(), and MarkAsPrepared().

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

◆ ProcArrayApplyRecoveryInfo()

void ProcArrayApplyRecoveryInfo ( RunningTransactions  running)

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

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

◆ ProcArrayApplyXidAssignment()

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

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

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

◆ ProcArrayClearTransaction()

void ProcArrayClearTransaction ( PGPROC proc)

Definition at line 855 of file procarray.c.

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

Referenced by PrepareTransaction().

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

◆ ProcArrayEndTransaction()

void ProcArrayEndTransaction ( PGPROC proc,
TransactionId  latestXid 
)

Definition at line 620 of file procarray.c.

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

Referenced by AbortTransaction(), and CommitTransaction().

621 {
622  if (TransactionIdIsValid(latestXid))
623  {
624  /*
625  * We must lock ProcArrayLock while clearing our advertised XID, so
626  * that we do not exit the set of "running" transactions while someone
627  * else is taking a snapshot. See discussion in
628  * src/backend/access/transam/README.
629  */
631 
632  /*
633  * If we can immediately acquire ProcArrayLock, we clear our own XID
634  * and release the lock. If not, use group XID clearing to improve
635  * efficiency.
636  */
637  if (LWLockConditionalAcquire(ProcArrayLock, LW_EXCLUSIVE))
638  {
639  ProcArrayEndTransactionInternal(proc, latestXid);
640  LWLockRelease(ProcArrayLock);
641  }
642  else
643  ProcArrayGroupClearXid(proc, latestXid);
644  }
645  else
646  {
647  /*
648  * If we have no XID, we don't need to lock, since we won't affect
649  * anyone else's calculation of a snapshot. We might change their
650  * estimate of global xmin, but that's OK.
651  */
653  Assert(proc->subxidStatus.count == 0);
655 
657  proc->xmin = InvalidTransactionId;
658  proc->delayChkpt = false; /* be sure this is cleared in abort */
659  proc->recoveryConflictPending = false;
660 
661  /* must be cleared with xid/xmin: */
662  /* avoid unnecessarily dirtying shared cachelines */
664  {
665  /* Only safe to change my own flags with just share lock */
666  Assert(proc == MyProc);
667  Assert(!LWLockHeldByMe(ProcArrayLock));
668  LWLockAcquire(ProcArrayLock, LW_SHARED);
672  LWLockRelease(ProcArrayLock);
673  }
674  }
675 }
bool LWLockHeldByMe(LWLock *l)
Definition: lwlock.c:1927
static void ProcArrayEndTransactionInternal(PGPROC *proc, TransactionId latestXid)
Definition: procarray.c:683
PGPROC * MyProc
Definition: proc.c:67
static void ProcArrayGroupClearXid(PGPROC *proc, TransactionId latestXid)
Definition: procarray.c:741
PROC_HDR * ProcGlobal
Definition: proc.c:79
uint8 statusFlags
Definition: proc.h:183
XidCacheStatus subxidStatus
Definition: proc.h:204
#define PROC_VACUUM_STATE_MASK
Definition: proc.h:61
bool overflowed
Definition: proc.h:43
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1811
bool delayChkpt
Definition: proc.h:181
TransactionId xmin
Definition: proc.h:134
bool LWLockConditionalAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1379
bool recoveryConflictPending
Definition: proc.h:163
#define InvalidTransactionId
Definition: transam.h:31
#define Assert(condition)
Definition: c.h:800
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1207
uint8 count
Definition: proc.h:41
TransactionId xid
Definition: proc.h:129
#define InvalidLocalTransactionId
Definition: lock.h:68
int pgxactoff
Definition: proc.h:144
uint8 * statusFlags
Definition: proc.h:327
#define TransactionIdIsValid(xid)
Definition: transam.h:41
LocalTransactionId lxid
Definition: proc.h:139

◆ ProcArrayEndTransactionInternal()

static void ProcArrayEndTransactionInternal ( PGPROC proc,
TransactionId  latestXid 
)
inlinestatic

Definition at line 683 of file procarray.c.

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

Referenced by ProcArrayEndTransaction(), and ProcArrayGroupClearXid().

684 {
685  size_t pgxactoff = proc->pgxactoff;
686 
687  /*
688  * Note: we need exclusive lock here because we're going to
689  * change other processes' PGPROC entries.
690  */
691  Assert(LWLockHeldByMeInMode(ProcArrayLock, LW_EXCLUSIVE));
693  Assert(ProcGlobal->xids[pgxactoff] == proc->xid);
694 
695  ProcGlobal->xids[pgxactoff] = InvalidTransactionId;
696  proc->xid = InvalidTransactionId;
698  proc->xmin = InvalidTransactionId;
699  proc->delayChkpt = false; /* be sure this is cleared in abort */
700  proc->recoveryConflictPending = false;
701 
702  /* must be cleared with xid/xmin: */
703  /* avoid unnecessarily dirtying shared cachelines */
705  {
708  }
709 
710  /* Clear the subtransaction-XID cache too while holding the lock */
711  Assert(ProcGlobal->subxidStates[pgxactoff].count == proc->subxidStatus.count &&
713  if (proc->subxidStatus.count > 0 || proc->subxidStatus.overflowed)
714  {
715  ProcGlobal->subxidStates[pgxactoff].count = 0;
716  ProcGlobal->subxidStates[pgxactoff].overflowed = false;
717  proc->subxidStatus.count = 0;
718  proc->subxidStatus.overflowed = false;
719  }
720 
721  /* Also advance global latestCompletedXid while holding the lock */
722  MaintainLatestCompletedXid(latestXid);
723 
724  /* Same with xactCompletionCount */
726 }
bool LWLockHeldByMeInMode(LWLock *l, LWLockMode mode)
Definition: lwlock.c:1945
XidCacheStatus * subxidStates
Definition: proc.h:321
uint64 xactCompletionCount
Definition: transam.h:241
PROC_HDR * ProcGlobal
Definition: proc.c:79
uint8 statusFlags
Definition: proc.h:183
XidCacheStatus subxidStatus
Definition: proc.h:204
#define PROC_VACUUM_STATE_MASK
Definition: proc.h:61
bool overflowed
Definition: proc.h:43
bool delayChkpt
Definition: proc.h:181
TransactionId xmin
Definition: proc.h:134
bool recoveryConflictPending
Definition: proc.h:163
VariableCache ShmemVariableCache
Definition: varsup.c:34
#define InvalidTransactionId
Definition: transam.h:31
TransactionId * xids
Definition: proc.h:315
static void MaintainLatestCompletedXid(TransactionId latestXid)
Definition: procarray.c:915
#define Assert(condition)
Definition: c.h:800
uint8 count
Definition: proc.h:41
TransactionId xid
Definition: proc.h:129
#define InvalidLocalTransactionId
Definition: lock.h:68
int pgxactoff
Definition: proc.h:144
uint8 * statusFlags
Definition: proc.h:327
#define TransactionIdIsValid(xid)
Definition: transam.h:41
LocalTransactionId lxid
Definition: proc.h:139

◆ ProcArrayGetReplicationSlotXmin()

void ProcArrayGetReplicationSlotXmin ( TransactionId xmin,
TransactionId catalog_xmin 
)

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

3790 {
3791  LWLockAcquire(ProcArrayLock, LW_SHARED);
3792 
3793  if (xmin != NULL)
3795 
3796  if (catalog_xmin != NULL)
3797  *catalog_xmin = procArray->replication_slot_catalog_xmin;
3798 
3799  LWLockRelease(ProcArrayLock);
3800 }
TransactionId replication_slot_catalog_xmin
Definition: procarray.c:98
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1811
static ProcArrayStruct * procArray
Definition: procarray.c:250
TransactionId replication_slot_xmin
Definition: procarray.c:96
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1207

◆ ProcArrayGroupClearXid()

static void ProcArrayGroupClearXid ( PGPROC proc,
TransactionId  latestXid 
)
static

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

742 {
743  PROC_HDR *procglobal = ProcGlobal;
744  uint32 nextidx;
745  uint32 wakeidx;
746 
747  /* We should definitely have an XID to clear. */
749 
750  /* Add ourselves to the list of processes needing a group XID clear. */
751  proc->procArrayGroupMember = true;
752  proc->procArrayGroupMemberXid = latestXid;
753  nextidx = pg_atomic_read_u32(&procglobal->procArrayGroupFirst);
754  while (true)
755  {
756  pg_atomic_write_u32(&proc->procArrayGroupNext, nextidx);
757 
759  &nextidx,
760  (uint32) proc->pgprocno))
761  break;
762  }
763 
764  /*
765  * If the list was not empty, the leader will clear our XID. It is
766  * impossible to have followers without a leader because the first process
767  * that has added itself to the list will always have nextidx as
768  * INVALID_PGPROCNO.
769  */
770  if (nextidx != INVALID_PGPROCNO)
771  {
772  int extraWaits = 0;
773 
774  /* Sleep until the leader clears our XID. */
776  for (;;)
777  {
778  /* acts as a read barrier */
779  PGSemaphoreLock(proc->sem);
780  if (!proc->procArrayGroupMember)
781  break;
782  extraWaits++;
783  }
785 
787 
788  /* Fix semaphore count for any absorbed wakeups */
789  while (extraWaits-- > 0)
790  PGSemaphoreUnlock(proc->sem);
791  return;
792  }
793 
794  /* We are the leader. Acquire the lock on behalf of everyone. */
795  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
796 
797  /*
798  * Now that we've got the lock, clear the list of processes waiting for
799  * group XID clearing, saving a pointer to the head of the list. Trying
800  * to pop elements one at a time could lead to an ABA problem.
801  */