PostgreSQL Source Code  git master
procarray.c File Reference
#include "postgres.h"
#include <signal.h>
#include "access/subtrans.h"
#include "access/transam.h"
#include "access/twophase.h"
#include "access/xact.h"
#include "access/xlogutils.h"
#include "catalog/catalog.h"
#include "catalog/pg_authid.h"
#include "commands/dbcommands.h"
#include "miscadmin.h"
#include "pgstat.h"
#include "port/pg_lfind.h"
#include "storage/proc.h"
#include "storage/procarray.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 */
 
#define KAX_COMPRESS_FREQUENCY   128 /* in transactions */
 
#define KAX_COMPRESS_IDLE_INTERVAL   1000 /* in ms */
 

Typedefs

typedef struct ProcArrayStruct ProcArrayStruct
 
typedef struct ComputeXidHorizonsResult ComputeXidHorizonsResult
 
typedef enum GlobalVisHorizonKind GlobalVisHorizonKind
 
typedef enum KAXCompressReason KAXCompressReason
 

Enumerations

enum  GlobalVisHorizonKind { VISHORIZON_SHARED , VISHORIZON_CATALOG , VISHORIZON_DATA , VISHORIZON_TEMP }
 
enum  KAXCompressReason { KAX_NO_SPACE , KAX_PRUNE , KAX_TRANSACTION_END , KAX_STARTUP_PROCESS_IDLE }
 

Functions

static void KnownAssignedXidsCompress (KAXCompressReason reason, bool haveLock)
 
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 removeXid)
 
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)
 
static GlobalVisHorizonKind GlobalVisHorizonKindForRel (Relation rel)
 
TransactionId GetOldestNonRemovableTransactionId (Relation rel)
 
TransactionId GetOldestTransactionIdConsideredRunning (void)
 
void GetReplicationHorizons (TransactionId *xmin, TransactionId *catalog_xmin)
 
int GetMaxSnapshotXidCount (void)
 
int GetMaxSnapshotSubxidCount (void)
 
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, int type)
 
bool HaveVirtualXIDsDelayingChkpt (VirtualTransactionId *vxids, int nvxids, int type)
 
PGPROCProcNumberGetProc (ProcNumber procNumber)
 
void ProcNumberGetTransactionIds (ProcNumber procNumber, TransactionId *xid, TransactionId *xmin, int *nsubxid, bool *overflowed)
 
PGPROCBackendPidGetProc (int pid)
 
PGPROCBackendPidGetProcWithLock (int pid)
 
int BackendXidGetPid (TransactionId xid)
 
bool IsBackendPid (int pid)
 
VirtualTransactionIdGetCurrentVirtualXIDs (TransactionId limitXmin, bool excludeXmin0, bool allDbs, int excludeVacuum, int *nvxids)
 
VirtualTransactionIdGetConflictingVirtualXIDs (TransactionId limitXmin, Oid dbOid)
 
pid_t CancelVirtualTransaction (VirtualTransactionId vxid, ProcSignalReason sigmode)
 
pid_t SignalVirtualTransaction (VirtualTransactionId vxid, ProcSignalReason sigmode, bool conflictPending)
 
bool MinimumActiveBackends (int min)
 
int CountDBBackends (Oid databaseid)
 
int CountDBConnections (Oid databaseid)
 
void CancelDBBackends (Oid databaseid, ProcSignalReason sigmode, bool conflictPending)
 
int CountUserBackends (Oid roleid)
 
bool CountOtherDBBackends (Oid databaseId, int *nbackends, int *nprepared)
 
void TerminateOtherDBBackends (Oid databaseId)
 
void 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 GlobalVisCheckRemovableFullXid (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)
 
void KnownAssignedTransactionIdsIdleMaintenance (void)
 

Variables

static ProcArrayStructprocArray
 
static PGPROCallProcs
 
static TransactionId cachedXidIsNotInProgress = InvalidTransactionId
 
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

◆ KAX_COMPRESS_FREQUENCY

#define KAX_COMPRESS_FREQUENCY   128 /* in transactions */

◆ KAX_COMPRESS_IDLE_INTERVAL

#define KAX_COMPRESS_IDLE_INTERVAL   1000 /* in ms */

◆ MAXAUTOVACPIDS

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

◆ PROCARRAY_MAXPROCS

#define PROCARRAY_MAXPROCS   (MaxBackends + max_prepared_xacts)

◆ TOTAL_MAX_CACHED_SUBXIDS

#define TOTAL_MAX_CACHED_SUBXIDS    ((PGPROC_MAX_CACHED_SUBXIDS + 1) * PROCARRAY_MAXPROCS)

◆ UINT32_ACCESS_ONCE

#define UINT32_ACCESS_ONCE (   var)    ((uint32)(*((volatile uint32 *)&(var))))

Definition at line 68 of file procarray.c.

◆ xc_by_child_xid_inc

#define xc_by_child_xid_inc ( )    ((void) 0)

Definition at line 340 of file procarray.c.

◆ xc_by_known_assigned_inc

#define xc_by_known_assigned_inc ( )    ((void) 0)

Definition at line 341 of file procarray.c.

◆ xc_by_known_xact_inc

#define xc_by_known_xact_inc ( )    ((void) 0)

Definition at line 336 of file procarray.c.

◆ xc_by_latest_xid_inc

#define xc_by_latest_xid_inc ( )    ((void) 0)

Definition at line 338 of file procarray.c.

◆ xc_by_main_xid_inc

#define xc_by_main_xid_inc ( )    ((void) 0)

Definition at line 339 of file procarray.c.

◆ xc_by_my_xact_inc

#define xc_by_my_xact_inc ( )    ((void) 0)

Definition at line 337 of file procarray.c.

◆ xc_by_recent_xmin_inc

#define xc_by_recent_xmin_inc ( )    ((void) 0)

Definition at line 335 of file procarray.c.

◆ xc_no_overflow_inc

#define xc_no_overflow_inc ( )    ((void) 0)

Definition at line 342 of file procarray.c.

◆ xc_slow_answer_inc

#define xc_slow_answer_inc ( )    ((void) 0)

Definition at line 343 of file procarray.c.

Typedef Documentation

◆ ComputeXidHorizonsResult

◆ GlobalVisHorizonKind

◆ KAXCompressReason

◆ ProcArrayStruct

Enumeration Type Documentation

◆ GlobalVisHorizonKind

Enumerator
VISHORIZON_SHARED 
VISHORIZON_CATALOG 
VISHORIZON_DATA 
VISHORIZON_TEMP 

Definition at line 249 of file procarray.c.

250 {
GlobalVisHorizonKind
Definition: procarray.c:250
@ VISHORIZON_SHARED
Definition: procarray.c:251
@ VISHORIZON_DATA
Definition: procarray.c:253
@ VISHORIZON_CATALOG
Definition: procarray.c:252
@ VISHORIZON_TEMP
Definition: procarray.c:254

◆ KAXCompressReason

Enumerator
KAX_NO_SPACE 
KAX_PRUNE 
KAX_TRANSACTION_END 
KAX_STARTUP_PROCESS_IDLE 

Definition at line 260 of file procarray.c.

261 {
262  KAX_NO_SPACE, /* need to free up space at array end */
263  KAX_PRUNE, /* we just pruned old entries */
264  KAX_TRANSACTION_END, /* we just committed/removed some XIDs */
265  KAX_STARTUP_PROCESS_IDLE, /* startup process is about to sleep */
KAXCompressReason
Definition: procarray.c:261
@ KAX_PRUNE
Definition: procarray.c:263
@ KAX_NO_SPACE
Definition: procarray.c:262
@ KAX_TRANSACTION_END
Definition: procarray.c:264
@ KAX_STARTUP_PROCESS_IDLE
Definition: procarray.c:265

Function Documentation

◆ BackendPidGetProc()

PGPROC* BackendPidGetProc ( int  pid)

Definition at line 3183 of file procarray.c.

3184 {
3185  PGPROC *result;
3186 
3187  if (pid == 0) /* never match dummy PGPROCs */
3188  return NULL;
3189 
3190  LWLockAcquire(ProcArrayLock, LW_SHARED);
3191 
3192  result = BackendPidGetProcWithLock(pid);
3193 
3194  LWLockRelease(ProcArrayLock);
3195 
3196  return result;
3197 }
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1172
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1785
@ LW_SHARED
Definition: lwlock.h:117
PGPROC * BackendPidGetProcWithLock(int pid)
Definition: procarray.c:3206
Definition: proc.h:157

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

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

◆ BackendPidGetProcWithLock()

PGPROC* BackendPidGetProcWithLock ( int  pid)

Definition at line 3206 of file procarray.c.

3207 {
3208  PGPROC *result = NULL;
3209  ProcArrayStruct *arrayP = procArray;
3210  int index;
3211 
3212  if (pid == 0) /* never match dummy PGPROCs */
3213  return NULL;
3214 
3215  for (index = 0; index < arrayP->numProcs; index++)
3216  {
3217  PGPROC *proc = &allProcs[arrayP->pgprocnos[index]];
3218 
3219  if (proc->pid == pid)
3220  {
3221  result = proc;
3222  break;
3223  }
3224  }
3225 
3226  return result;
3227 }
static PGPROC * allProcs
Definition: procarray.c:271
static ProcArrayStruct * procArray
Definition: procarray.c:269
int pid
Definition: proc.h:178
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:99
Definition: type.h:95

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

Referenced by BackendPidGetProc(), and GetBlockerStatusData().

◆ BackendXidGetPid()

int BackendXidGetPid ( TransactionId  xid)

Definition at line 3243 of file procarray.c.

3244 {
3245  int result = 0;
3246  ProcArrayStruct *arrayP = procArray;
3247  TransactionId *other_xids = ProcGlobal->xids;
3248  int index;
3249 
3250  if (xid == InvalidTransactionId) /* never match invalid xid */
3251  return 0;
3252 
3253  LWLockAcquire(ProcArrayLock, LW_SHARED);
3254 
3255  for (index = 0; index < arrayP->numProcs; index++)
3256  {
3257  if (other_xids[index] == xid)
3258  {
3259  int pgprocno = arrayP->pgprocnos[index];
3260  PGPROC *proc = &allProcs[pgprocno];
3261 
3262  result = proc->pid;
3263  break;
3264  }
3265  }
3266 
3267  LWLockRelease(ProcArrayLock);
3268 
3269  return result;
3270 }
uint32 TransactionId
Definition: c.h:639
PROC_HDR * ProcGlobal
Definition: proc.c:78
TransactionId * xids
Definition: proc.h:383
#define InvalidTransactionId
Definition: transam.h:31

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

Referenced by pgrowlocks().

◆ CancelDBBackends()

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

Definition at line 3647 of file procarray.c.

3648 {
3649  ProcArrayStruct *arrayP = procArray;
3650  int index;
3651 
3652  /* tell all backends to die */
3653  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3654 
3655  for (index = 0; index < arrayP->numProcs; index++)
3656  {
3657  int pgprocno = arrayP->pgprocnos[index];
3658  PGPROC *proc = &allProcs[pgprocno];
3659 
3660  if (databaseid == InvalidOid || proc->databaseId == databaseid)
3661  {
3662  VirtualTransactionId procvxid;
3663  pid_t pid;
3664 
3665  GET_VXID_FROM_PGPROC(procvxid, *proc);
3666 
3667  proc->recoveryConflictPending = conflictPending;
3668  pid = proc->pid;
3669  if (pid != 0)
3670  {
3671  /*
3672  * Kill the pid if it's still here. If not, that's what we
3673  * wanted so ignore any errors.
3674  */
3675  (void) SendProcSignal(pid, sigmode, procvxid.procNumber);
3676  }
3677  }
3678  }
3679 
3680  LWLockRelease(ProcArrayLock);
3681 }
#define GET_VXID_FROM_PGPROC(vxid_dst, proc)
Definition: lock.h:77
@ LW_EXCLUSIVE
Definition: lwlock.h:116
#define InvalidOid
Definition: postgres_ext.h:36
int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber)
Definition: procsignal.c:257
bool recoveryConflictPending
Definition: proc.h:216
Oid databaseId
Definition: proc.h:203
ProcNumber procNumber
Definition: lock.h:61

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

Referenced by ResolveRecoveryConflictWithDatabase(), and SendRecoveryConflictWithBufferPin().

◆ CancelVirtualTransaction()

pid_t CancelVirtualTransaction ( VirtualTransactionId  vxid,
ProcSignalReason  sigmode 
)

Definition at line 3478 of file procarray.c.

3479 {
3480  return SignalVirtualTransaction(vxid, sigmode, true);
3481 }
pid_t SignalVirtualTransaction(VirtualTransactionId vxid, ProcSignalReason sigmode, bool conflictPending)
Definition: procarray.c:3484

References SignalVirtualTransaction().

Referenced by ResolveRecoveryConflictWithVirtualXIDs().

◆ ComputeXidHorizons()

static void ComputeXidHorizons ( ComputeXidHorizonsResult h)
static

Definition at line 1723 of file procarray.c.

1724 {
1725  ProcArrayStruct *arrayP = procArray;
1726  TransactionId kaxmin;
1727  bool in_recovery = RecoveryInProgress();
1728  TransactionId *other_xids = ProcGlobal->xids;
1729 
1730  /* inferred after ProcArrayLock is released */
1732 
1733  LWLockAcquire(ProcArrayLock, LW_SHARED);
1734 
1736 
1737  /*
1738  * We initialize the MIN() calculation with latestCompletedXid + 1. This
1739  * is a lower bound for the XIDs that might appear in the ProcArray later,
1740  * and so protects us against overestimating the result due to future
1741  * additions.
1742  */
1743  {
1744  TransactionId initial;
1745 
1747  Assert(TransactionIdIsValid(initial));
1748  TransactionIdAdvance(initial);
1749 
1750  h->oldest_considered_running = initial;
1751  h->shared_oldest_nonremovable = initial;
1752  h->data_oldest_nonremovable = initial;
1753 
1754  /*
1755  * Only modifications made by this backend affect the horizon for
1756  * temporary relations. Instead of a check in each iteration of the
1757  * loop over all PGPROCs it is cheaper to just initialize to the
1758  * current top-level xid any.
1759  *
1760  * Without an assigned xid we could use a horizon as aggressive as
1761  * GetNewTransactionId(), but we can get away with the much cheaper
1762  * latestCompletedXid + 1: If this backend has no xid there, by
1763  * definition, can't be any newer changes in the temp table than
1764  * latestCompletedXid.
1765  */
1768  else
1769  h->temp_oldest_nonremovable = initial;
1770  }
1771 
1772  /*
1773  * Fetch slot horizons while ProcArrayLock is held - the
1774  * LWLockAcquire/LWLockRelease are a barrier, ensuring this happens inside
1775  * the lock.
1776  */
1779 
1780  for (int index = 0; index < arrayP->numProcs; index++)
1781  {
1782  int pgprocno = arrayP->pgprocnos[index];
1783  PGPROC *proc = &allProcs[pgprocno];
1784  int8 statusFlags = ProcGlobal->statusFlags[index];
1785  TransactionId xid;
1786  TransactionId xmin;
1787 
1788  /* Fetch xid just once - see GetNewTransactionId */
1789  xid = UINT32_ACCESS_ONCE(other_xids[index]);
1790  xmin = UINT32_ACCESS_ONCE(proc->xmin);
1791 
1792  /*
1793  * Consider both the transaction's Xmin, and its Xid.
1794  *
1795  * We must check both because a transaction might have an Xmin but not
1796  * (yet) an Xid; conversely, if it has an Xid, that could determine
1797  * some not-yet-set Xmin.
1798  */
1799  xmin = TransactionIdOlder(xmin, xid);
1800 
1801  /* if neither is set, this proc doesn't influence the horizon */
1802  if (!TransactionIdIsValid(xmin))
1803  continue;
1804 
1805  /*
1806  * Don't ignore any procs when determining which transactions might be
1807  * considered running. While slots should ensure logical decoding
1808  * backends are protected even without this check, it can't hurt to
1809  * include them here as well..
1810  */
1813 
1814  /*
1815  * Skip over backends either vacuuming (which is ok with rows being
1816  * removed, as long as pg_subtrans is not truncated) or doing logical
1817  * decoding (which manages xmin separately, check below).
1818  */
1819  if (statusFlags & (PROC_IN_VACUUM | PROC_IN_LOGICAL_DECODING))
1820  continue;
1821 
1822  /* shared tables need to take backends in all databases into account */
1825 
1826  /*
1827  * Normally sessions in other databases are ignored for anything but
1828  * the shared horizon.
1829  *
1830  * However, include them when MyDatabaseId is not (yet) set. A
1831  * backend in the process of starting up must not compute a "too
1832  * aggressive" horizon, otherwise we could end up using it to prune
1833  * still-needed data away. If the current backend never connects to a
1834  * database this is harmless, because data_oldest_nonremovable will
1835  * never be utilized.
1836  *
1837  * Also, sessions marked with PROC_AFFECTS_ALL_HORIZONS should always
1838  * be included. (This flag is used for hot standby feedback, which
1839  * can't be tied to a specific database.)
1840  *
1841  * Also, while in recovery we cannot compute an accurate per-database
1842  * horizon, as all xids are managed via the KnownAssignedXids
1843  * machinery.
1844  */
1845  if (proc->databaseId == MyDatabaseId ||
1846  MyDatabaseId == InvalidOid ||
1847  (statusFlags & PROC_AFFECTS_ALL_HORIZONS) ||
1848  in_recovery)
1849  {
1852  }
1853  }
1854 
1855  /*
1856  * If in recovery fetch oldest xid in KnownAssignedXids, will be applied
1857  * after lock is released.
1858  */
1859  if (in_recovery)
1860  kaxmin = KnownAssignedXidsGetOldestXmin();
1861 
1862  /*
1863  * No other information from shared state is needed, release the lock
1864  * immediately. The rest of the computations can be done without a lock.
1865  */
1866  LWLockRelease(ProcArrayLock);
1867 
1868  if (in_recovery)
1869  {
1876  /* temp relations cannot be accessed in recovery */
1877  }
1878 
1883 
1884  /*
1885  * Check whether there are replication slots requiring an older xmin.
1886  */
1891 
1892  /*
1893  * The only difference between catalog / data horizons is that the slot's
1894  * catalog xmin is applied to the catalog one (so catalogs can be accessed
1895  * for logical decoding). Initialize with data horizon, and then back up
1896  * further if necessary. Have to back up the shared horizon as well, since
1897  * that also can contain catalogs.
1898  */
1902  h->slot_catalog_xmin);
1906  h->slot_catalog_xmin);
1907 
1908  /*
1909  * It's possible that slots backed up the horizons further than
1910  * oldest_considered_running. Fix.
1911  */
1921 
1922  /*
1923  * shared horizons have to be at least as old as the oldest visible in
1924  * current db
1925  */
1930 
1931  /*
1932  * Horizons need to ensure that pg_subtrans access is still possible for
1933  * the relevant backends.
1934  */
1945  h->slot_xmin));
1948  h->slot_catalog_xmin));
1949 
1950  /* update approximate horizons with the computed horizons */
1952 }
signed char int8
Definition: c.h:479
Oid MyDatabaseId
Definition: globals.c:91
Assert(fmt[strlen(fmt) - 1] !='\n')
#define PROC_IN_LOGICAL_DECODING
Definition: proc.h:61
#define PROC_AFFECTS_ALL_HORIZONS
Definition: proc.h:62
#define PROC_IN_VACUUM
Definition: proc.h:58
#define UINT32_ACCESS_ONCE(var)
Definition: procarray.c:68
static void GlobalVisUpdateApply(ComputeXidHorizonsResult *horizons)
Definition: procarray.c:4150
static TransactionId KnownAssignedXidsGetOldestXmin(void)
Definition: procarray.c:5173
PGPROC * MyProc
Definition: proc.c:66
TransactionId slot_catalog_xmin
Definition: procarray.c:192
TransactionId data_oldest_nonremovable
Definition: procarray.c:237
TransactionId temp_oldest_nonremovable
Definition: procarray.c:243
TransactionId shared_oldest_nonremovable
Definition: procarray.c:214
TransactionId oldest_considered_running
Definition: procarray.c:205
TransactionId slot_xmin
Definition: procarray.c:191
FullTransactionId latest_completed
Definition: procarray.c:185
TransactionId catalog_oldest_nonremovable
Definition: procarray.c:231
TransactionId shared_oldest_nonremovable_raw
Definition: procarray.c:225
TransactionId xmin
Definition: proc.h:173
TransactionId xid
Definition: proc.h:168
uint8 * statusFlags
Definition: proc.h:395
TransactionId replication_slot_xmin
Definition: procarray.c:94
TransactionId replication_slot_catalog_xmin
Definition: procarray.c:96
FullTransactionId latestCompletedXid
Definition: transam.h:238
bool TransactionIdPrecedesOrEquals(TransactionId id1, TransactionId id2)
Definition: transam.c:299
#define XidFromFullTransactionId(x)
Definition: transam.h:48
#define TransactionIdIsValid(xid)
Definition: transam.h:41
#define TransactionIdAdvance(dest)
Definition: transam.h:91
static TransactionId TransactionIdOlder(TransactionId a, TransactionId b)
Definition: transam.h:334
TransamVariablesData * TransamVariables
Definition: varsup.c:34
bool RecoveryInProgress(void)
Definition: xlog.c:6201

References allProcs, Assert(), ComputeXidHorizonsResult::catalog_oldest_nonremovable, ComputeXidHorizonsResult::data_oldest_nonremovable, PGPROC::databaseId, GlobalVisUpdateApply(), InvalidOid, InvalidTransactionId, KnownAssignedXidsGetOldestXmin(), ComputeXidHorizonsResult::latest_completed, TransamVariablesData::latestCompletedXid, LW_SHARED, LWLockAcquire(), LWLockRelease(), MyDatabaseId, MyProc, ProcArrayStruct::numProcs, ComputeXidHorizonsResult::oldest_considered_running, ProcArrayStruct::pgprocnos, PROC_AFFECTS_ALL_HORIZONS, 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, ComputeXidHorizonsResult::slot_catalog_xmin, ComputeXidHorizonsResult::slot_xmin, PROC_HDR::statusFlags, ComputeXidHorizonsResult::temp_oldest_nonremovable, TransactionIdAdvance, TransactionIdIsValid, TransactionIdOlder(), TransactionIdPrecedesOrEquals(), TransamVariables, UINT32_ACCESS_ONCE, PGPROC::xid, XidFromFullTransactionId, PROC_HDR::xids, and PGPROC::xmin.

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

◆ CountDBBackends()

int CountDBBackends ( Oid  databaseid)

Definition at line 3586 of file procarray.c.

3587 {
3588  ProcArrayStruct *arrayP = procArray;
3589  int count = 0;
3590  int index;
3591 
3592  LWLockAcquire(ProcArrayLock, LW_SHARED);
3593 
3594  for (index = 0; index < arrayP->numProcs; index++)
3595  {
3596  int pgprocno = arrayP->pgprocnos[index];
3597  PGPROC *proc = &allProcs[pgprocno];
3598 
3599  if (proc->pid == 0)
3600  continue; /* do not count prepared xacts */
3601  if (!OidIsValid(databaseid) ||
3602  proc->databaseId == databaseid)
3603  count++;
3604  }
3605 
3606  LWLockRelease(ProcArrayLock);
3607 
3608  return count;
3609 }
#define OidIsValid(objectId)
Definition: c.h:762

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

Referenced by ResolveRecoveryConflictWithDatabase().

◆ CountDBConnections()

int CountDBConnections ( Oid  databaseid)

Definition at line 3616 of file procarray.c.

3617 {
3618  ProcArrayStruct *arrayP = procArray;
3619  int count = 0;
3620  int index;
3621 
3622  LWLockAcquire(ProcArrayLock, LW_SHARED);
3623 
3624  for (index = 0; index < arrayP->numProcs; index++)
3625  {
3626  int pgprocno = arrayP->pgprocnos[index];
3627  PGPROC *proc = &allProcs[pgprocno];
3628 
3629  if (proc->pid == 0)
3630  continue; /* do not count prepared xacts */
3631  if (proc->isBackgroundWorker)
3632  continue; /* do not count background workers */
3633  if (!OidIsValid(databaseid) ||
3634  proc->databaseId == databaseid)
3635  count++;
3636  }
3637 
3638  LWLockRelease(ProcArrayLock);
3639 
3640  return count;
3641 }
bool isBackgroundWorker
Definition: proc.h:209

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

Referenced by CheckMyDatabase().

◆ CountOtherDBBackends()

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

Definition at line 3737 of file procarray.c.

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

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

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

◆ CountUserBackends()

int CountUserBackends ( Oid  roleid)

Definition at line 3687 of file procarray.c.

3688 {
3689  ProcArrayStruct *arrayP = procArray;
3690  int count = 0;
3691  int index;
3692 
3693  LWLockAcquire(ProcArrayLock, LW_SHARED);
3694 
3695  for (index = 0; index < arrayP->numProcs; index++)
3696  {
3697  int pgprocno = arrayP->pgprocnos[index];
3698  PGPROC *proc = &allProcs[pgprocno];
3699 
3700  if (proc->pid == 0)
3701  continue; /* do not count prepared xacts */
3702  if (proc->isBackgroundWorker)
3703  continue; /* do not count background workers */
3704  if (proc->roleId == roleid)
3705  count++;
3706  }
3707 
3708  LWLockRelease(ProcArrayLock);
3709 
3710  return count;
3711 }
Oid roleId
Definition: proc.h:204

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

Referenced by InitializeSessionUserId().

◆ CreateSharedProcArray()

void CreateSharedProcArray ( void  )

Definition at line 418 of file procarray.c.

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

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

Referenced by CreateOrAttachShmemStructs().

◆ ExpireAllKnownAssignedTransactionIds()

void ExpireAllKnownAssignedTransactionIds ( void  )

Definition at line 4512 of file procarray.c.

4513 {
4514  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
4516 
4517  /*
4518  * Reset lastOverflowedXid. Currently, lastOverflowedXid has no use after
4519  * the call of this function. But do this for unification with what
4520  * ExpireOldKnownAssignedTransactionIds() do.
4521  */
4523  LWLockRelease(ProcArrayLock);
4524 }
static void KnownAssignedXidsRemovePreceding(TransactionId removeXid)
Definition: procarray.c:5025

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

Referenced by ShutdownRecoveryTransactionEnvironment().

◆ ExpireOldKnownAssignedTransactionIds()

void ExpireOldKnownAssignedTransactionIds ( TransactionId  xid)

Definition at line 4532 of file procarray.c.

4533 {
4534  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
4535 
4536  /*
4537  * Reset lastOverflowedXid if we know all transactions that have been
4538  * possibly running are being gone. Not doing so could cause an incorrect
4539  * lastOverflowedXid value, which makes extra snapshots be marked as
4540  * suboverflowed.
4541  */
4545  LWLockRelease(ProcArrayLock);
4546 }
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:280

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

Referenced by ProcArrayApplyRecoveryInfo().

◆ ExpireTreeKnownAssignedTransactionIds()

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

Definition at line 4486 of file procarray.c.

4488 {
4490 
4491  /*
4492  * Uses same locking as transaction commit
4493  */
4494  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
4495 
4496  KnownAssignedXidsRemoveTree(xid, nsubxids, subxids);
4497 
4498  /* As in ProcArrayEndTransaction, advance latestCompletedXid */
4500 
4501  /* ... and xactCompletionCount */
4503 
4504  LWLockRelease(ProcArrayLock);
4505 }
static void KnownAssignedXidsRemoveTree(TransactionId xid, int nsubxids, TransactionId *subxids)
Definition: procarray.c:5003
static void MaintainLatestCompletedXidRecovery(TransactionId latestXid)
Definition: procarray.c:989
HotStandbyState standbyState
Definition: xlogutils.c:53
@ STANDBY_INITIALIZED
Definition: xlogutils.h:50

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

Referenced by xact_redo_abort(), and xact_redo_commit().

◆ FullXidRelativeTo()

static FullTransactionId FullXidRelativeTo ( FullTransactionId  rel,
TransactionId  xid 
)
inlinestatic

Definition at line 4335 of file procarray.c.

4336 {
4337  TransactionId rel_xid = XidFromFullTransactionId(rel);
4338 
4340  Assert(TransactionIdIsValid(rel_xid));
4341 
4342  /* not guaranteed to find issues, but likely to catch mistakes */
4344 
4346  + (int32) (xid - rel_xid));
4347 }
signed int int32
Definition: c.h:481
#define U64FromFullTransactionId(x)
Definition: transam.h:49
static FullTransactionId FullTransactionIdFromU64(uint64 value)
Definition: transam.h:81
#define AssertTransactionIdInAllowableRange(xid)
Definition: transam.h:301

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

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

◆ GetConflictingVirtualXIDs()

VirtualTransactionId* GetConflictingVirtualXIDs ( TransactionId  limitXmin,
Oid  dbOid 
)

Definition at line 3404 of file procarray.c.

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

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

Referenced by ResolveRecoveryConflictWithSnapshot(), and ResolveRecoveryConflictWithTablespace().

◆ GetCurrentVirtualXIDs()

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

Definition at line 3311 of file procarray.c.

3314 {
3315  VirtualTransactionId *vxids;
3316  ProcArrayStruct *arrayP = procArray;
3317  int count = 0;
3318  int index;
3319 
3320  /* allocate what's certainly enough result space */
3321  vxids = (VirtualTransactionId *)
3322  palloc(sizeof(VirtualTransactionId) * arrayP->maxProcs);
3323 
3324  LWLockAcquire(ProcArrayLock, LW_SHARED);
3325 
3326  for (index = 0; index < arrayP->numProcs; index++)
3327  {
3328  int pgprocno = arrayP->pgprocnos[index];
3329  PGPROC *proc = &allProcs[pgprocno];
3330  uint8 statusFlags = ProcGlobal->statusFlags[index];
3331 
3332  if (proc == MyProc)
3333  continue;
3334 
3335  if (excludeVacuum & statusFlags)
3336  continue;
3337 
3338  if (allDbs || proc->databaseId == MyDatabaseId)
3339  {
3340  /* Fetch xmin just once - might change on us */
3341  TransactionId pxmin = UINT32_ACCESS_ONCE(proc->xmin);
3342 
3343  if (excludeXmin0 && !TransactionIdIsValid(pxmin))
3344  continue;
3345 
3346  /*
3347  * InvalidTransactionId precedes all other XIDs, so a proc that
3348  * hasn't set xmin yet will not be rejected by this test.
3349  */
3350  if (!TransactionIdIsValid(limitXmin) ||
3351  TransactionIdPrecedesOrEquals(pxmin, limitXmin))
3352  {
3353  VirtualTransactionId vxid;
3354 
3355  GET_VXID_FROM_PGPROC(vxid, *proc);
3356  if (VirtualTransactionIdIsValid(vxid))
3357  vxids[count++] = vxid;
3358  }
3359  }
3360  }
3361 
3362  LWLockRelease(ProcArrayLock);
3363 
3364  *nvxids = count;
3365  return vxids;
3366 }
void * palloc(Size size)
Definition: mcxt.c:1304

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

Referenced by WaitForOlderSnapshots().

◆ GetMaxSnapshotSubxidCount()

int GetMaxSnapshotSubxidCount ( void  )

Definition at line 2068 of file procarray.c.

2069 {
2070  return TOTAL_MAX_CACHED_SUBXIDS;
2071 }

References TOTAL_MAX_CACHED_SUBXIDS.

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

◆ GetMaxSnapshotXidCount()

int GetMaxSnapshotXidCount ( void  )

Definition at line 2057 of file procarray.c.

2058 {
2059  return procArray->maxProcs;
2060 }

References ProcArrayStruct::maxProcs, and procArray.

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

◆ GetOldestActiveTransactionId()

TransactionId GetOldestActiveTransactionId ( void  )

Definition at line 2867 of file procarray.c.

2868 {
2869  ProcArrayStruct *arrayP = procArray;
2870  TransactionId *other_xids = ProcGlobal->xids;
2871  TransactionId oldestRunningXid;
2872  int index;
2873 
2875 
2876  /*
2877  * Read nextXid, as the upper bound of what's still active.
2878  *
2879  * Reading a TransactionId is atomic, but we must grab the lock to make
2880  * sure that all XIDs < nextXid are already present in the proc array (or
2881  * have already completed), when we spin over it.
2882  */
2883  LWLockAcquire(XidGenLock, LW_SHARED);
2884  oldestRunningXid = XidFromFullTransactionId(TransamVariables->nextXid);
2885  LWLockRelease(XidGenLock);
2886 
2887  /*
2888  * Spin over procArray collecting all xids and subxids.
2889  */
2890  LWLockAcquire(ProcArrayLock, LW_SHARED);
2891  for (index = 0; index < arrayP->numProcs; index++)
2892  {
2893  TransactionId xid;
2894 
2895  /* Fetch xid just once - see GetNewTransactionId */
2896  xid = UINT32_ACCESS_ONCE(other_xids[index]);
2897 
2898  if (!TransactionIdIsNormal(xid))
2899  continue;
2900 
2901  if (TransactionIdPrecedes(xid, oldestRunningXid))
2902  oldestRunningXid = xid;
2903 
2904  /*
2905  * Top-level XID of a transaction is always less than any of its
2906  * subxids, so we don't need to check if any of the subxids are
2907  * smaller than oldestRunningXid
2908  */
2909  }
2910  LWLockRelease(ProcArrayLock);
2911 
2912  return oldestRunningXid;
2913 }
FullTransactionId nextXid
Definition: transam.h:220
#define TransactionIdIsNormal(xid)
Definition: transam.h:42

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

Referenced by CreateCheckPoint().

◆ GetOldestNonRemovableTransactionId()

TransactionId GetOldestNonRemovableTransactionId ( Relation  rel)

Definition at line 1993 of file procarray.c.

1994 {
1995  ComputeXidHorizonsResult horizons;
1996 
1997  ComputeXidHorizons(&horizons);
1998 
1999  switch (GlobalVisHorizonKindForRel(rel))
2000  {
2001  case VISHORIZON_SHARED:
2002  return horizons.shared_oldest_nonremovable;
2003  case VISHORIZON_CATALOG:
2004  return horizons.catalog_oldest_nonremovable;
2005  case VISHORIZON_DATA:
2006  return horizons.data_oldest_nonremovable;
2007  case VISHORIZON_TEMP:
2008  return horizons.temp_oldest_nonremovable;
2009  }
2010 
2011  /* just to prevent compiler warnings */
2012  return InvalidTransactionId;
2013 }
static void ComputeXidHorizons(ComputeXidHorizonsResult *h)
Definition: procarray.c:1723
static GlobalVisHorizonKind GlobalVisHorizonKindForRel(Relation rel)
Definition: procarray.c:1959

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

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

◆ GetOldestSafeDecodingTransactionId()

TransactionId GetOldestSafeDecodingTransactionId ( bool  catalogOnly)

Definition at line 2932 of file procarray.c.

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

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

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

◆ GetOldestTransactionIdConsideredRunning()

TransactionId GetOldestTransactionIdConsideredRunning ( void  )

Definition at line 2022 of file procarray.c.

2023 {
2024  ComputeXidHorizonsResult horizons;
2025 
2026  ComputeXidHorizons(&horizons);
2027 
2028  return horizons.oldest_considered_running;
2029 }

References ComputeXidHorizons(), and ComputeXidHorizonsResult::oldest_considered_running.

Referenced by CreateCheckPoint(), and CreateRestartPoint().

◆ GetReplicationHorizons()

void GetReplicationHorizons ( TransactionId xmin,
TransactionId catalog_xmin 
)

Definition at line 2035 of file procarray.c.

2036 {
2037  ComputeXidHorizonsResult horizons;
2038 
2039  ComputeXidHorizons(&horizons);
2040 
2041  /*
2042  * Don't want to use shared_oldest_nonremovable here, as that contains the
2043  * effect of replication slot's catalog_xmin. We want to send a separate
2044  * feedback for the catalog horizon, so the primary can remove data table
2045  * contents more aggressively.
2046  */
2047  *xmin = horizons.shared_oldest_nonremovable_raw;
2048  *catalog_xmin = horizons.slot_catalog_xmin;
2049 }

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

Referenced by XLogWalRcvSendHSFeedback().

◆ GetRunningTransactionData()

RunningTransactions GetRunningTransactionData ( void  )

Definition at line 2681 of file procarray.c.

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

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

Referenced by GetStrictOldestNonRemovableTransactionId(), and LogStandbySnapshot().

◆ GetSnapshotData()

Snapshot GetSnapshotData ( Snapshot  snapshot)

Definition at line 2165 of file procarray.c.

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

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

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

◆ GetSnapshotDataReuse()

static bool GetSnapshotDataReuse ( Snapshot  snapshot)
static

Definition at line 2083 of file procarray.c.

2084 {
2085  uint64 curXactCompletionCount;
2086 
2087  Assert(LWLockHeldByMe(ProcArrayLock));
2088 
2089  if (unlikely(snapshot->snapXactCompletionCount == 0))
2090  return false;
2091 
2092  curXactCompletionCount = TransamVariables->xactCompletionCount;
2093  if (curXactCompletionCount != snapshot->snapXactCompletionCount)
2094  return false;
2095 
2096  /*
2097  * If the current xactCompletionCount is still the same as it was at the
2098  * time the snapshot was built, we can be sure that rebuilding the
2099  * contents of the snapshot the hard way would result in the same snapshot
2100  * contents:
2101  *
2102  * As explained in transam/README, the set of xids considered running by
2103  * GetSnapshotData() cannot change while ProcArrayLock is held. Snapshot
2104  * contents only depend on transactions with xids and xactCompletionCount
2105  * is incremented whenever a transaction with an xid finishes (while
2106  * holding ProcArrayLock exclusively). Thus the xactCompletionCount check
2107  * ensures we would detect if the snapshot would have changed.
2108  *
2109  * As the snapshot contents are the same as it was before, it is safe to
2110  * re-enter the snapshot's xmin into the PGPROC array. None of the rows
2111  * visible under the snapshot could already have been removed (that'd
2112  * require the set of running transactions to change) and it fulfills the
2113  * requirement that concurrent GetSnapshotData() calls yield the same
2114  * xmin.
2115  */
2117  MyProc->xmin = TransactionXmin = snapshot->xmin;
2118 
2119  RecentXmin = snapshot->xmin;
2121 
2122  snapshot->curcid = GetCurrentCommandId(false);
2123  snapshot->active_count = 0;
2124  snapshot->regd_count = 0;
2125  snapshot->copied = false;
2126  snapshot->lsn = InvalidXLogRecPtr;
2127  snapshot->whenTaken = 0;
2128 
2129  return true;
2130 }
#define unlikely(x)
Definition: c.h:298

References SnapshotData::active_count, Assert(), SnapshotData::copied, SnapshotData::curcid, GetCurrentCommandId(), InvalidXLogRecPtr, SnapshotData::lsn, LWLockHeldByMe(), MyProc, RecentXmin, SnapshotData::regd_count, SnapshotData::snapXactCompletionCount, TransactionIdIsValid, TransactionIdPrecedesOrEquals(), TransactionXmin, TransamVariables, unlikely, SnapshotData::whenTaken, TransamVariablesData::xactCompletionCount, PGPROC::xmin, and SnapshotData::xmin.

Referenced by GetSnapshotData().

◆ GetVirtualXIDsDelayingChkpt()

VirtualTransactionId* GetVirtualXIDsDelayingChkpt ( int *  nvxids,
int  type 
)

Definition at line 3030 of file procarray.c.

3031 {
3032  VirtualTransactionId *vxids;
3033  ProcArrayStruct *arrayP = procArray;
3034  int count = 0;
3035  int index;
3036 
3037  Assert(type != 0);
3038 
3039  /* allocate what's certainly enough result space */
3040  vxids = (VirtualTransactionId *)
3041  palloc(sizeof(VirtualTransactionId) * arrayP->maxProcs);
3042 
3043  LWLockAcquire(ProcArrayLock, LW_SHARED);
3044 
3045  for (index = 0; index < arrayP->numProcs; index++)
3046  {
3047  int pgprocno = arrayP->pgprocnos[index];
3048  PGPROC *proc = &allProcs[pgprocno];
3049 
3050  if ((proc->delayChkptFlags & type) != 0)
3051  {
3052  VirtualTransactionId vxid;
3053 
3054  GET_VXID_FROM_PGPROC(vxid, *proc);
3055  if (VirtualTransactionIdIsValid(vxid))
3056  vxids[count++] = vxid;
3057  }
3058  }
3059 
3060  LWLockRelease(ProcArrayLock);
3061 
3062  *nvxids = count;
3063  return vxids;
3064 }
int delayChkptFlags
Definition: proc.h:236
const char * type

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

Referenced by CreateCheckPoint().

◆ GlobalVisCheckRemovableFullXid()

bool GlobalVisCheckRemovableFullXid ( Relation  rel,
FullTransactionId  fxid 
)

Definition at line 4300 of file procarray.c.

4301 {
4303 
4304  state = GlobalVisTestFor(rel);
4305 
4306  return GlobalVisTestIsRemovableFullXid(state, fxid);
4307 }
bool GlobalVisTestIsRemovableFullXid(GlobalVisState *state, FullTransactionId fxid)
Definition: procarray.c:4206
GlobalVisState * GlobalVisTestFor(Relation rel)
Definition: procarray.c:4091
Definition: regguts.h:323

References GlobalVisTestFor(), and GlobalVisTestIsRemovableFullXid().

Referenced by _bt_pendingfsm_finalize(), BTPageIsRecyclable(), and gistPageRecyclable().

◆ GlobalVisCheckRemovableXid()

bool GlobalVisCheckRemovableXid ( Relation  rel,
TransactionId  xid 
)

Definition at line 4314 of file procarray.c.

4315 {
4317 
4318  state = GlobalVisTestFor(rel);
4319 
4320  return GlobalVisTestIsRemovableXid(state, xid);
4321 }
bool GlobalVisTestIsRemovableXid(GlobalVisState *state, TransactionId xid)
Definition: procarray.c:4248

References GlobalVisTestFor(), and GlobalVisTestIsRemovableXid().

Referenced by GinPageIsRecyclable().

◆ GlobalVisHorizonKindForRel()

static GlobalVisHorizonKind GlobalVisHorizonKindForRel ( Relation  rel)
inlinestatic

Definition at line 1959 of file procarray.c.

1960 {
1961  /*
1962  * Other relkinds currently don't contain xids, nor always the necessary
1963  * logical decoding markers.
1964  */
1965  Assert(!rel ||
1966  rel->rd_rel->relkind == RELKIND_RELATION ||
1967  rel->rd_rel->relkind == RELKIND_MATVIEW ||
1968  rel->rd_rel->relkind == RELKIND_TOASTVALUE);
1969 
1970  if (rel == NULL || rel->rd_rel->relisshared || RecoveryInProgress())
1971  return VISHORIZON_SHARED;
1972  else if (IsCatalogRelation(rel) ||
1974  return VISHORIZON_CATALOG;
1975  else if (!RELATION_IS_LOCAL(rel))
1976  return VISHORIZON_DATA;
1977  else
1978  return VISHORIZON_TEMP;
1979 }
bool IsCatalogRelation(Relation relation)
Definition: catalog.c:103
#define RELATION_IS_LOCAL(relation)
Definition: rel.h:648
#define RelationIsAccessibleInLogicalDecoding(relation)
Definition: rel.h:684
Form_pg_class rd_rel
Definition: rel.h:111

References Assert(), IsCatalogRelation(), RelationData::rd_rel, RecoveryInProgress(), RELATION_IS_LOCAL, RelationIsAccessibleInLogicalDecoding, VISHORIZON_CATALOG, VISHORIZON_DATA, VISHORIZON_SHARED, and VISHORIZON_TEMP.

Referenced by GetOldestNonRemovableTransactionId(), and GlobalVisTestFor().

◆ GlobalVisTestFor()

GlobalVisState* GlobalVisTestFor ( Relation  rel)

Definition at line 4091 of file procarray.c.

4092 {
4093  GlobalVisState *state = NULL;
4094 
4095  /* XXX: we should assert that a snapshot is pushed or registered */
4096  Assert(RecentXmin);
4097 
4098  switch (GlobalVisHorizonKindForRel(rel))
4099  {
4100  case VISHORIZON_SHARED:
4102  break;
4103  case VISHORIZON_CATALOG:
4105  break;
4106  case VISHORIZON_DATA:
4108  break;
4109  case VISHORIZON_TEMP:
4111  break;
4112  }
4113 
4114  Assert(FullTransactionIdIsValid(state->definitely_needed) &&
4115  FullTransactionIdIsValid(state->maybe_needed));
4116 
4117  return state;
4118 }
#define FullTransactionIdIsValid(x)
Definition: transam.h:55

References Assert(), FullTransactionIdIsValid, GlobalVisCatalogRels, GlobalVisDataRels, GlobalVisHorizonKindForRel(), GlobalVisSharedRels, GlobalVisTempRels, RecentXmin, VISHORIZON_CATALOG, VISHORIZON_DATA, VISHORIZON_SHARED, and VISHORIZON_TEMP.

Referenced by get_actual_variable_endpoint(), GlobalVisCheckRemovableFullXid(), GlobalVisCheckRemovableXid(), heap_hot_search_buffer(), heap_index_delete_tuples(), heap_page_prune_opt(), heap_vacuum_rel(), and vacuumRedirectAndPlaceholder().

◆ GlobalVisTestIsRemovableFullXid()

bool GlobalVisTestIsRemovableFullXid ( GlobalVisState state,
FullTransactionId  fxid 
)

Definition at line 4206 of file procarray.c.

4208 {
4209  /*
4210  * If fxid is older than maybe_needed bound, it definitely is visible to
4211  * everyone.
4212  */
4213  if (FullTransactionIdPrecedes(fxid, state->maybe_needed))
4214  return true;
4215 
4216  /*
4217  * If fxid is >= definitely_needed bound, it is very likely to still be
4218  * considered running.
4219  */
4220  if (FullTransactionIdFollowsOrEquals(fxid, state->definitely_needed))
4221  return false;
4222 
4223  /*
4224  * fxid is between maybe_needed and definitely_needed, i.e. there might or
4225  * might not exist a snapshot considering fxid running. If it makes sense,
4226  * update boundaries and recheck.
4227  */
4229  {
4230  GlobalVisUpdate();
4231 
4232  Assert(FullTransactionIdPrecedes(fxid, state->definitely_needed));
4233 
4234  return FullTransactionIdPrecedes(fxid, state->maybe_needed);
4235  }
4236  else
4237  return false;
4238 }
static bool GlobalVisTestShouldUpdate(GlobalVisState *state)
Definition: procarray.c:4131
static void GlobalVisUpdate(void)
Definition: procarray.c:4189
#define FullTransactionIdFollowsOrEquals(a, b)
Definition: transam.h:54
#define FullTransactionIdPrecedes(a, b)
Definition: transam.h:51

References Assert(), FullTransactionIdFollowsOrEquals, FullTransactionIdPrecedes, GlobalVisTestShouldUpdate(), and GlobalVisUpdate().

Referenced by GlobalVisCheckRemovableFullXid(), and GlobalVisTestIsRemovableXid().

◆ GlobalVisTestIsRemovableXid()

bool GlobalVisTestIsRemovableXid ( GlobalVisState state,
TransactionId  xid 
)

Definition at line 4248 of file procarray.c.

4249 {
4250  FullTransactionId fxid;
4251 
4252  /*
4253  * Convert 32 bit argument to FullTransactionId. We can do so safely
4254  * because we know the xid has to, at the very least, be between
4255  * [oldestXid, nextXid), i.e. within 2 billion of xid. To avoid taking a
4256  * lock to determine either, we can just compare with
4257  * state->definitely_needed, which was based on those value at the time
4258  * the current snapshot was built.
4259  */
4260  fxid = FullXidRelativeTo(state->definitely_needed, xid);
4261 
4262  return GlobalVisTestIsRemovableFullXid(state, fxid);
4263 }

References FullXidRelativeTo(), and GlobalVisTestIsRemovableFullXid().

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

◆ GlobalVisTestNonRemovableFullHorizon()

FullTransactionId GlobalVisTestNonRemovableFullHorizon ( GlobalVisState state)

Definition at line 4275 of file procarray.c.

4276 {
4277  /* acquire accurate horizon if not already done */
4279  GlobalVisUpdate();
4280 
4281  return state->maybe_needed;
4282 }

References GlobalVisTestShouldUpdate(), and GlobalVisUpdate().

Referenced by GlobalVisTestNonRemovableHorizon().

◆ GlobalVisTestNonRemovableHorizon()

TransactionId GlobalVisTestNonRemovableHorizon ( GlobalVisState state)

Definition at line 4286 of file procarray.c.

4287 {
4288  FullTransactionId cutoff;
4289 
4291 
4292  return XidFromFullTransactionId(cutoff);
4293 }
FullTransactionId GlobalVisTestNonRemovableFullHorizon(GlobalVisState *state)
Definition: procarray.c:4275

References GlobalVisTestNonRemovableFullHorizon(), and XidFromFullTransactionId.

◆ GlobalVisTestShouldUpdate()

static bool GlobalVisTestShouldUpdate ( GlobalVisState state)
static

Definition at line 4131 of file procarray.c.

4132 {
4133  /* hasn't been updated yet */
4135  return true;
4136 
4137  /*
4138  * If the maybe_needed/definitely_needed boundaries are the same, it's
4139  * unlikely to be beneficial to refresh boundaries.
4140  */
4141  if (FullTransactionIdFollowsOrEquals(state->maybe_needed,
4142  state->definitely_needed))
4143  return false;
4144 
4145  /* does the last snapshot built have a different xmin? */
4147 }
static TransactionId ComputeXidHorizonsResultLastXmin
Definition: procarray.c:307

References ComputeXidHorizonsResultLastXmin, FullTransactionIdFollowsOrEquals, RecentXmin, and TransactionIdIsValid.

Referenced by GlobalVisTestIsRemovableFullXid(), and GlobalVisTestNonRemovableFullHorizon().

◆ GlobalVisUpdate()

static void GlobalVisUpdate ( void  )
static

Definition at line 4189 of file procarray.c.

4190 {
4191  ComputeXidHorizonsResult horizons;
4192 
4193  /* updates the horizons as a side-effect */
4194  ComputeXidHorizons(&horizons);
4195 }

References ComputeXidHorizons().

Referenced by GlobalVisTestIsRemovableFullXid(), and GlobalVisTestNonRemovableFullHorizon().

◆ GlobalVisUpdateApply()

static void GlobalVisUpdateApply ( ComputeXidHorizonsResult horizons)
static

Definition at line 4150 of file procarray.c.

4151 {
4154  horizons->shared_oldest_nonremovable);
4157  horizons->catalog_oldest_nonremovable);
4160  horizons->data_oldest_nonremovable);
4163  horizons->temp_oldest_nonremovable);
4164 
4165  /*
4166  * In longer running transactions it's possible that transactions we
4167  * previously needed to treat as running aren't around anymore. So update
4168  * definitely_needed to not be earlier than maybe_needed.
4169  */
4180 
4182 }

References ComputeXidHorizonsResult::catalog_oldest_nonremovable, ComputeXidHorizonsResultLastXmin, ComputeXidHorizonsResult::data_oldest_nonremovable, GlobalVisState::definitely_needed, FullTransactionIdNewer(), FullXidRelativeTo(), GlobalVisCatalogRels, GlobalVisDataRels, GlobalVisSharedRels, GlobalVisTempRels, ComputeXidHorizonsResult::latest_completed, GlobalVisState::maybe_needed, RecentXmin, ComputeXidHorizonsResult::shared_oldest_nonremovable, and ComputeXidHorizonsResult::temp_oldest_nonremovable.

Referenced by ComputeXidHorizons().

◆ HaveVirtualXIDsDelayingChkpt()

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

Definition at line 3076 of file procarray.c.

3077 {
3078  bool result = false;
3079  ProcArrayStruct *arrayP = procArray;
3080  int index;
3081 
3082  Assert(type != 0);
3083 
3084  LWLockAcquire(ProcArrayLock, LW_SHARED);
3085 
3086  for (index = 0; index < arrayP->numProcs; index++)
3087  {
3088  int pgprocno = arrayP->pgprocnos[index];
3089  PGPROC *proc = &allProcs[pgprocno];
3090  VirtualTransactionId vxid;
3091 
3092  GET_VXID_FROM_PGPROC(vxid, *proc);
3093 
3094  if ((proc->delayChkptFlags & type) != 0 &&
3096  {
3097  int i;
3098 
3099  for (i = 0; i < nvxids; i++)
3100  {
3101  if (VirtualTransactionIdEquals(vxid, vxids[i]))
3102  {
3103  result = true;
3104  break;
3105  }
3106  }
3107  if (result)
3108  break;
3109  }
3110  }
3111 
3112  LWLockRelease(ProcArrayLock);
3113 
3114  return result;
3115 }
int i
Definition: isn.c:73
#define VirtualTransactionIdEquals(vxid1, vxid2)
Definition: lock.h:71

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

Referenced by CreateCheckPoint().

◆ IsBackendPid()

bool IsBackendPid ( int  pid)

Definition at line 3278 of file procarray.c.

3279 {
3280  return (BackendPidGetProc(pid) != NULL);
3281 }
PGPROC * BackendPidGetProc(int pid)
Definition: procarray.c:3183

References BackendPidGetProc().

Referenced by pg_stat_get_subscription().

◆ KnownAssignedTransactionIdsIdleMaintenance()

void KnownAssignedTransactionIdsIdleMaintenance ( void  )

Definition at line 4554 of file procarray.c.

4555 {
4557 }
static void KnownAssignedXidsCompress(KAXCompressReason reason, bool haveLock)
Definition: procarray.c:4655

References KAX_STARTUP_PROCESS_IDLE, and KnownAssignedXidsCompress().

Referenced by WaitForWALToBecomeAvailable().

◆ KnownAssignedXidExists()

static bool KnownAssignedXidExists ( TransactionId  xid)
static

Definition at line 4964 of file procarray.c.

4965 {
4967 
4968  return KnownAssignedXidsSearch(xid, false);
4969 }
static bool KnownAssignedXidsSearch(TransactionId xid, bool remove)
Definition: procarray.c:4876

References Assert(), KnownAssignedXidsSearch(), and TransactionIdIsValid.

Referenced by TransactionIdIsInProgress().

◆ KnownAssignedXidsAdd()

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

Definition at line 4772 of file procarray.c.

4774 {
4775  ProcArrayStruct *pArray = procArray;
4776  TransactionId next_xid;
4777  int head,
4778  tail;
4779  int nxids;
4780  int i;
4781 
4782  Assert(TransactionIdPrecedesOrEquals(from_xid, to_xid));
4783 
4784  /*
4785  * Calculate how many array slots we'll need. Normally this is cheap; in
4786  * the unusual case where the XIDs cross the wrap point, we do it the hard
4787  * way.
4788  */
4789  if (to_xid >= from_xid)
4790  nxids = to_xid - from_xid + 1;
4791  else
4792  {
4793  nxids = 1;
4794  next_xid = from_xid;
4795  while (TransactionIdPrecedes(next_xid, to_xid))
4796  {
4797  nxids++;
4798  TransactionIdAdvance(next_xid);
4799  }
4800  }
4801 
4802  /*
4803  * Since only the startup process modifies the head/tail pointers, we
4804  * don't need a lock to read them here.
4805  */
4806  head = pArray->headKnownAssignedXids;
4807  tail = pArray->tailKnownAssignedXids;
4808 
4809  Assert(head >= 0 && head <= pArray->maxKnownAssignedXids);
4810  Assert(tail >= 0 && tail < pArray->maxKnownAssignedXids);
4811 
4812  /*
4813  * Verify that insertions occur in TransactionId sequence. Note that even
4814  * if the last existing element is marked invalid, it must still have a
4815  * correctly sequenced XID value.
4816  */
4817  if (head > tail &&
4818  TransactionIdFollowsOrEquals(KnownAssignedXids[head - 1], from_xid))
4819  {
4821  elog(ERROR, "out-of-order XID insertion in KnownAssignedXids");
4822  }
4823 
4824  /*
4825  * If our xids won't fit in the remaining space, compress out free space
4826  */
4827  if (head + nxids > pArray->maxKnownAssignedXids)
4828  {
4829  KnownAssignedXidsCompress(KAX_NO_SPACE, exclusive_lock);
4830 
4831  head = pArray->headKnownAssignedXids;
4832  /* note: we no longer care about the tail pointer */
4833 
4834  /*
4835  * If it still won't fit then we're out of memory
4836  */
4837  if (head + nxids > pArray->maxKnownAssignedXids)
4838  elog(ERROR, "too many KnownAssignedXids");
4839  }
4840 
4841  /* Now we can insert the xids into the space starting at head */
4842  next_xid = from_xid;
4843  for (i = 0; i < nxids; i++)
4844  {
4845  KnownAssignedXids[head] = next_xid;
4846  KnownAssignedXidsValid[head] = true;
4847  TransactionIdAdvance(next_xid);
4848  head++;
4849  }
4850 
4851  /* Adjust count of number of valid entries */
4852  pArray->numKnownAssignedXids += nxids;
4853 
4854  /*
4855  * Now update the head pointer. We use a write barrier to ensure that
4856  * other processors see the above array updates before they see the head
4857  * pointer change. The barrier isn't required if we're holding
4858  * ProcArrayLock exclusively.
4859  */
4860  if (!exclusive_lock)
4861  pg_write_barrier();
4862 
4863  pArray->headKnownAssignedXids = head;
4864 }
#define pg_write_barrier()
Definition: atomics.h:152
#define LOG
Definition: elog.h:31
#define elog(elevel,...)
Definition: elog.h:224
static void KnownAssignedXidsDisplay(int trace_level)
Definition: procarray.c:5208
bool TransactionIdFollowsOrEquals(TransactionId id1, TransactionId id2)
Definition: transam.c:329

References Assert(), elog, ERROR, ProcArrayStruct::headKnownAssignedXids, i, KAX_NO_SPACE, KnownAssignedXids, KnownAssignedXidsCompress(), KnownAssignedXidsDisplay(), KnownAssignedXidsValid, LOG, ProcArrayStruct::maxKnownAssignedXids, ProcArrayStruct::numKnownAssignedXids, pg_write_barrier, procArray, ProcArrayStruct::tailKnownAssignedXids, TransactionIdAdvance, TransactionIdFollowsOrEquals(), TransactionIdPrecedes(), and TransactionIdPrecedesOrEquals().

Referenced by ProcArrayApplyRecoveryInfo(), and RecordKnownAssignedTransactionIds().

◆ KnownAssignedXidsCompress()

static void KnownAssignedXidsCompress ( KAXCompressReason  reason,
bool  haveLock 
)
static

Definition at line 4655 of file procarray.c.

4656 {
4657  ProcArrayStruct *pArray = procArray;
4658  int head,
4659  tail,
4660  nelements;
4661  int compress_index;
4662  int i;
4663 
4664  /* Counters for compression heuristics */
4665  static unsigned int transactionEndsCounter;
4666  static TimestampTz lastCompressTs;
4667 
4668  /* Tuning constants */
4669 #define KAX_COMPRESS_FREQUENCY 128 /* in transactions */
4670 #define KAX_COMPRESS_IDLE_INTERVAL 1000 /* in ms */
4671 
4672  /*
4673  * Since only the startup process modifies the head/tail pointers, we
4674  * don't need a lock to read them here.
4675  */
4676  head = pArray->headKnownAssignedXids;
4677  tail = pArray->tailKnownAssignedXids;
4678  nelements = head - tail;
4679 
4680  /*
4681  * If we can choose whether to compress, use a heuristic to avoid
4682  * compressing too often or not often enough. "Compress" here simply
4683  * means moving the values to the beginning of the array, so it is not as
4684  * complex or costly as typical data compression algorithms.
4685  */
4686  if (nelements == pArray->numKnownAssignedXids)
4687  {
4688  /*
4689  * When there are no gaps between head and tail, don't bother to
4690  * compress, except in the KAX_NO_SPACE case where we must compress to
4691  * create some space after the head.
4692  */
4693  if (reason != KAX_NO_SPACE)
4694  return;
4695  }
4696  else if (reason == KAX_TRANSACTION_END)
4697  {
4698  /*
4699  * Consider compressing only once every so many commits. Frequency
4700  * determined by benchmarks.
4701  */
4702  if ((transactionEndsCounter++) % KAX_COMPRESS_FREQUENCY != 0)
4703  return;
4704 
4705  /*
4706  * Furthermore, compress only if the used part of the array is less
4707  * than 50% full (see comments above).
4708  */
4709  if (nelements < 2 * pArray->numKnownAssignedXids)
4710  return;
4711  }
4712  else if (reason == KAX_STARTUP_PROCESS_IDLE)
4713  {
4714  /*
4715  * We're about to go idle for lack of new WAL, so we might as well
4716  * compress. But not too often, to avoid ProcArray lock contention
4717  * with readers.
4718  */
4719  if (lastCompressTs != 0)
4720  {
4721  TimestampTz compress_after;
4722 
4723  compress_after = TimestampTzPlusMilliseconds(lastCompressTs,
4725  if (GetCurrentTimestamp() < compress_after)
4726  return;
4727  }
4728  }
4729 
4730  /* Need to compress, so get the lock if we don't have it. */
4731  if (!haveLock)
4732  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
4733 
4734  /*
4735  * We compress the array by reading the valid values from tail to head,
4736  * re-aligning data to 0th element.
4737  */
4738  compress_index = 0;
4739  for (i = tail; i < head; i++)
4740  {
4742  {
4743  KnownAssignedXids[compress_index] = KnownAssignedXids[i];
4744  KnownAssignedXidsValid[compress_index] = true;
4745  compress_index++;
4746  }
4747  }
4748  Assert(compress_index == pArray->numKnownAssignedXids);
4749 
4750  pArray->tailKnownAssignedXids = 0;
4751  pArray->headKnownAssignedXids = compress_index;
4752 
4753  if (!haveLock)
4754  LWLockRelease(ProcArrayLock);
4755 
4756  /* Update timestamp for maintenance. No need to hold lock for this. */
4757  lastCompressTs = GetCurrentTimestamp();
4758 }
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1654
int64 TimestampTz
Definition: timestamp.h:39
#define KAX_COMPRESS_FREQUENCY
#define KAX_COMPRESS_IDLE_INTERVAL
#define TimestampTzPlusMilliseconds(tz, ms)
Definition: timestamp.h:85

References Assert(), GetCurrentTimestamp(), ProcArrayStruct::headKnownAssignedXids, i, KAX_COMPRESS_FREQUENCY, KAX_COMPRESS_IDLE_INTERVAL, KAX_NO_SPACE, KAX_STARTUP_PROCESS_IDLE, KAX_TRANSACTION_END, KnownAssignedXids, KnownAssignedXidsValid, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), ProcArrayStruct::numKnownAssignedXids, procArray, ProcArrayStruct::tailKnownAssignedXids, and TimestampTzPlusMilliseconds.

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

◆ KnownAssignedXidsDisplay()

static void KnownAssignedXidsDisplay ( int  trace_level)
static

Definition at line 5208 of file procarray.c.

5209 {
5210  ProcArrayStruct *pArray = procArray;
5212  int head,
5213  tail,
5214  i;
5215  int nxids = 0;
5216 
5217  tail = pArray->tailKnownAssignedXids;
5218  head = pArray->headKnownAssignedXids;
5219 
5220  initStringInfo(&buf);
5221 
5222  for (i = tail; i < head; i++)
5223  {
5225  {
5226  nxids++;
5227  appendStringInfo(&buf, "[%d]=%u ", i, KnownAssignedXids[i]);
5228  }
5229  }
5230 
5231  elog(trace_level, "%d KnownAssignedXids (num=%d tail=%d head=%d) %s",
5232  nxids,
5233  pArray->numKnownAssignedXids,
5234  pArray->tailKnownAssignedXids,
5235  pArray->headKnownAssignedXids,
5236  buf.data);
5237 
5238  pfree(buf.data);
5239 }
void pfree(void *pointer)
Definition: mcxt.c:1508
static char * buf
Definition: pg_test_fsync.c:73
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:97
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59

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

Referenced by KnownAssignedXidsAdd(), and ProcArrayApplyRecoveryInfo().

◆ KnownAssignedXidsGet()

static int KnownAssignedXidsGet ( TransactionId xarray,
TransactionId  xmax 
)
static

Definition at line 5103 of file procarray.c.

5104 {
5106 
5107  return KnownAssignedXidsGetAndSetXmin(xarray, &xtmp, xmax);
5108 }

References InvalidTransactionId, and KnownAssignedXidsGetAndSetXmin().

Referenced by TransactionIdIsInProgress().

◆ KnownAssignedXidsGetAndSetXmin()

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

Definition at line 5117 of file procarray.c.

5119 {
5120  int count = 0;
5121  int head,
5122  tail;
5123  int i;
5124 
5125  /*
5126  * Fetch head just once, since it may change while we loop. We can stop
5127  * once we reach the initially seen head, since we are certain that an xid
5128  * cannot enter and then leave the array while we hold ProcArrayLock. We
5129  * might miss newly-added xids, but they should be >= xmax so irrelevant
5130  * anyway.
5131  */
5134 
5135  pg_read_barrier(); /* pairs with KnownAssignedXidsAdd */
5136 
5137  for (i = tail; i < head; i++)
5138  {
5139  /* Skip any gaps in the array */
5141  {
5142  TransactionId knownXid = KnownAssignedXids[i];
5143 
5144  /*
5145  * Update xmin if required. Only the first XID need be checked,
5146  * since the array is sorted.
5147  */
5148  if (count == 0 &&
5149  TransactionIdPrecedes(knownXid, *xmin))
5150  *xmin = knownXid;
5151 
5152  /*
5153  * Filter out anything >= xmax, again relying on sorted property
5154  * of array.
5155  */
5156  if (TransactionIdIsValid(xmax) &&
5157  TransactionIdFollowsOrEquals(knownXid, xmax))
5158  break;
5159 
5160  /* Add knownXid into output array */
5161  xarray[count++] = knownXid;
5162  }
5163  }
5164 
5165  return count;
5166 }

References ProcArrayStruct::headKnownAssignedXids, i, KnownAssignedXids, KnownAssignedXidsValid, pg_read_barrier, procArray, ProcArrayStruct::tailKnownAssignedXids, TransactionIdFollowsOrEquals(), TransactionIdIsValid, and TransactionIdPrecedes().

Referenced by GetSnapshotData(), and KnownAssignedXidsGet().

◆ KnownAssignedXidsGetOldestXmin()

static TransactionId KnownAssignedXidsGetOldestXmin ( void  )
static

Definition at line 5173 of file procarray.c.

5174 {
5175  int head,
5176  tail;
5177  int i;
5178 
5179  /*
5180  * Fetch head just once, since it may change while we loop.
5181  */
5184 
5185  pg_read_barrier(); /* pairs with KnownAssignedXidsAdd */
5186 
5187  for (i = tail; i < head; i++)
5188  {
5189  /* Skip any gaps in the array */
5191  return KnownAssignedXids[i];
5192  }
5193 
5194  return InvalidTransactionId;
5195 }

References ProcArrayStruct::headKnownAssignedXids, i, InvalidTransactionId, KnownAssignedXids, KnownAssignedXidsValid, pg_read_barrier, procArray, and ProcArrayStruct::tailKnownAssignedXids.

Referenced by ComputeXidHorizons().

◆ KnownAssignedXidsRemove()

static void KnownAssignedXidsRemove ( TransactionId  xid)
static

Definition at line 4977 of file procarray.c.

4978 {
4980 
4981  elog(DEBUG4, "remove KnownAssignedXid %u", xid);
4982 
4983  /*
4984  * Note: we cannot consider it an error to remove an XID that's not
4985  * present. We intentionally remove subxact IDs while processing
4986  * XLOG_XACT_ASSIGNMENT, to avoid array overflow. Then those XIDs will be
4987  * removed again when the top-level xact commits or aborts.
4988  *
4989  * It might be possible to track such XIDs to distinguish this case from
4990  * actual errors, but it would be complicated and probably not worth it.
4991  * So, just ignore the search result.
4992  */
4993  (void) KnownAssignedXidsSearch(xid, true);
4994 }
#define DEBUG4
Definition: elog.h:27

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

Referenced by KnownAssignedXidsRemoveTree().

◆ KnownAssignedXidsRemovePreceding()

static void KnownAssignedXidsRemovePreceding ( TransactionId  removeXid)
static

Definition at line 5025 of file procarray.c.

5026 {
5027  ProcArrayStruct *pArray = procArray;
5028  int count = 0;
5029  int head,
5030  tail,
5031  i;
5032 
5033  if (!TransactionIdIsValid(removeXid))
5034  {
5035  elog(DEBUG4, "removing all KnownAssignedXids");
5036  pArray->numKnownAssignedXids = 0;
5037  pArray->headKnownAssignedXids = pArray->tailKnownAssignedXids = 0;
5038  return;
5039  }
5040 
5041  elog(DEBUG4, "prune KnownAssignedXids to %u", removeXid);
5042 
5043  /*
5044  * Mark entries invalid starting at the tail. Since array is sorted, we
5045  * can stop as soon as we reach an entry >= removeXid.
5046  */
5047  tail = pArray->tailKnownAssignedXids;
5048  head = pArray->headKnownAssignedXids;
5049 
5050  for (i = tail; i < head; i++)
5051  {
5053  {
5054  TransactionId knownXid = KnownAssignedXids[i];
5055 
5056  if (TransactionIdFollowsOrEquals(knownXid, removeXid))
5057  break;
5058 
5059  if (!StandbyTransactionIdIsPrepared(knownXid))
5060  {
5061  KnownAssignedXidsValid[i] = false;
5062  count++;
5063  }
5064  }
5065  }
5066 
5067  pArray->numKnownAssignedXids -= count;
5068  Assert(pArray->numKnownAssignedXids >= 0);
5069 
5070  /*
5071  * Advance the tail pointer if we've marked the tail item invalid.
5072  */
5073  for (i = tail; i < head; i++)
5074  {
5076  break;
5077  }
5078  if (i >= head)
5079  {
5080  /* Array is empty, so we can reset both pointers */
5081  pArray->headKnownAssignedXids = 0;
5082  pArray->tailKnownAssignedXids = 0;
5083  }
5084  else
5085  {
5086  pArray->tailKnownAssignedXids = i;
5087  }
5088 
5089  /* Opportunistically compress the array */
5091 }
bool StandbyTransactionIdIsPrepared(TransactionId xid)
Definition: twophase.c:1475

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

Referenced by ExpireAllKnownAssignedTransactionIds(), and ExpireOldKnownAssignedTransactionIds().

◆ KnownAssignedXidsRemoveTree()

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

Definition at line 5003 of file procarray.c.

5005 {
5006  int i;
5007 
5008  if (TransactionIdIsValid(xid))
5010 
5011  for (i = 0; i < nsubxids; i++)
5012  KnownAssignedXidsRemove(subxids[i]);
5013 
5014  /* Opportunistically compress the array */
5016 }
static void KnownAssignedXidsRemove(TransactionId xid)
Definition: procarray.c:4977

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

Referenced by ExpireTreeKnownAssignedTransactionIds(), and ProcArrayApplyXidAssignment().

◆ KnownAssignedXidsReset()

static void KnownAssignedXidsReset ( void  )
static

Definition at line 5246 of file procarray.c.

5247 {
5248  ProcArrayStruct *pArray = procArray;
5249 
5250  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
5251 
5252  pArray->numKnownAssignedXids = 0;
5253  pArray->tailKnownAssignedXids = 0;
5254  pArray->headKnownAssignedXids = 0;
5255 
5256  LWLockRelease(ProcArrayLock);
5257 }

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

Referenced by ProcArrayApplyRecoveryInfo().

◆ KnownAssignedXidsSearch()

static bool KnownAssignedXidsSearch ( TransactionId  xid,
bool  remove 
)
static

Definition at line 4876 of file procarray.c.

4877 {
4878  ProcArrayStruct *pArray = procArray;
4879  int first,
4880  last;
4881  int head;
4882  int tail;
4883  int result_index = -1;
4884 
4885  tail = pArray->tailKnownAssignedXids;
4886  head = pArray->headKnownAssignedXids;
4887 
4888  /*
4889  * Only the startup process removes entries, so we don't need the read
4890  * barrier in that case.
4891  */
4892  if (!remove)
4893  pg_read_barrier(); /* pairs with KnownAssignedXidsAdd */
4894 
4895  /*
4896  * Standard binary search. Note we can ignore the KnownAssignedXidsValid
4897  * array here, since even invalid entries will contain sorted XIDs.
4898  */
4899  first = tail;
4900  last = head - 1;
4901  while (first <= last)
4902  {
4903  int mid_index;
4904  TransactionId mid_xid;
4905 
4906  mid_index = (first + last) / 2;
4907  mid_xid = KnownAssignedXids[mid_index];
4908 
4909  if (xid == mid_xid)
4910  {
4911  result_index = mid_index;
4912  break;
4913  }
4914  else if (TransactionIdPrecedes(xid, mid_xid))
4915  last = mid_index - 1;
4916  else
4917  first = mid_index + 1;
4918  }
4919 
4920  if (result_index < 0)
4921  return false; /* not in array */
4922 
4923  if (!KnownAssignedXidsValid[result_index])
4924  return false; /* in array, but invalid */
4925 
4926  if (remove)
4927  {
4928  KnownAssignedXidsValid[result_index] = false;
4929 
4930  pArray->numKnownAssignedXids--;
4931  Assert(pArray->numKnownAssignedXids >= 0);
4932 
4933  /*
4934  * If we're removing the tail element then advance tail pointer over
4935  * any invalid elements. This will speed future searches.
4936  */
4937  if (result_index == tail)
4938  {
4939  tail++;
4940  while (tail < head && !KnownAssignedXidsValid[tail])
4941  tail++;
4942  if (tail >= head)
4943  {
4944  /* Array is empty, so we can reset both pointers */
4945  pArray->headKnownAssignedXids = 0;
4946  pArray->tailKnownAssignedXids = 0;
4947  }
4948  else
4949  {
4950  pArray->tailKnownAssignedXids = tail;
4951  }
4952  }
4953  }
4954 
4955  return true;
4956 }

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

Referenced by KnownAssignedXidExists(), and KnownAssignedXidsRemove().

◆ MaintainLatestCompletedXid()

static void MaintainLatestCompletedXid ( TransactionId  latestXid)
static

◆ MaintainLatestCompletedXidRecovery()

static void MaintainLatestCompletedXidRecovery ( TransactionId  latestXid)
static

Definition at line 989 of file procarray.c.

990 {
992  FullTransactionId rel;
993 
995  Assert(LWLockHeldByMe(ProcArrayLock));
996 
997  /*
998  * Need a FullTransactionId to compare latestXid with. Can't rely on
999  * latestCompletedXid to be initialized in recovery. But in recovery it's
1000  * safe to access nextXid without a lock for the startup process.
1001  */
1002  rel = TransamVariables->nextXid;
1004 
1005  if (!FullTransactionIdIsValid(cur_latest) ||
1006  TransactionIdPrecedes(XidFromFullTransactionId(cur_latest), latestXid))
1007  {
1009  FullXidRelativeTo(rel, latestXid);
1010  }
1011 
1013 }
bool IsUnderPostmaster
Definition: globals.c:117
#define AmStartupProcess()
Definition: miscadmin.h:379

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

Referenced by ExpireTreeKnownAssignedTransactionIds(), and ProcArrayApplyRecoveryInfo().

◆ MinimumActiveBackends()

bool MinimumActiveBackends ( int  min)

Definition at line 3533 of file procarray.c.

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

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

Referenced by XLogFlush().

◆ ProcArrayAdd()

void ProcArrayAdd ( PGPROC proc)

Definition at line 468 of file procarray.c.

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

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

Referenced by InitProcessPhase2(), and MarkAsPrepared().

◆ ProcArrayApplyRecoveryInfo()

void ProcArrayApplyRecoveryInfo ( RunningTransactions  running)

Definition at line 1054 of file procarray.c.

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

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

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

◆ ProcArrayApplyXidAssignment()

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

Definition at line 1306 of file procarray.c.

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

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

Referenced by xact_redo().

◆ ProcArrayClearTransaction()

void ProcArrayClearTransaction ( PGPROC proc)

Definition at line 907 of file procarray.c.

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

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

Referenced by PrepareTransaction().

◆ ProcArrayEndTransaction()

void ProcArrayEndTransaction ( PGPROC proc,
TransactionId  latestXid 
)

Definition at line 667 of file procarray.c.

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

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

Referenced by AbortTransaction(), and CommitTransaction().

◆ ProcArrayEndTransactionInternal()

static void ProcArrayEndTransactionInternal ( PGPROC proc,
TransactionId  latestXid 
)
inlinestatic

Definition at line 731 of file procarray.c.

732 {
733  int pgxactoff = proc->pgxactoff;
734 
735  /*
736  * Note: we need exclusive lock here because we're going to change other
737  * processes' PGPROC entries.
738  */
739  Assert(LWLockHeldByMeInMode(ProcArrayLock, LW_EXCLUSIVE));
741  Assert(ProcGlobal->xids[pgxactoff] == proc->xid);
742 
743  ProcGlobal->xids[pgxactoff] = InvalidTransactionId;
744  proc->xid = InvalidTransactionId;
746  proc->xmin = InvalidTransactionId;
747 
748  /* be sure this is cleared in abort */
749  proc->delayChkptFlags = 0;
750 
751  proc->recoveryConflictPending = false;
752 
753  /* must be cleared with xid/xmin: */
754  /* avoid unnecessarily dirtying shared cachelines */
756  {
759  }
760 
761  /* Clear the subtransaction-XID cache too while holding the lock */
762  Assert(ProcGlobal->subxidStates[pgxactoff].count == proc->subxidStatus.count &&
764  if (proc->subxidStatus.count > 0 || proc->subxidStatus.overflowed)
765  {
766  ProcGlobal->subxidStates[pgxactoff].count = 0;
767  ProcGlobal->subxidStates[pgxactoff].overflowed = false;
768  proc->subxidStatus.count = 0;
769  proc->subxidStatus.overflowed = false;
770  }
771 
772  /* Also advance global latestCompletedXid while holding the lock */
773  MaintainLatestCompletedXid(latestXid);
774 
775  /* Same with xactCompletionCount */
777 }
bool LWLockHeldByMeInMode(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1941
static void MaintainLatestCompletedXid(TransactionId latestXid)
Definition: procarray.c:967

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

Referenced by ProcArrayEndTransaction(), and ProcArrayGroupClearXid().

◆ ProcArrayGetReplicationSlotXmin()

void ProcArrayGetReplicationSlotXmin ( TransactionId xmin,
TransactionId catalog_xmin 
)

Definition at line 3952 of file procarray.c.

3954 {
3955  LWLockAcquire(ProcArrayLock, LW_SHARED);
3956 
3957  if (xmin != NULL)
3959 
3960  if (catalog_xmin != NULL)
3961  *catalog_xmin = procArray->replication_slot_catalog_xmin;
3962 
3963  LWLockRelease(ProcArrayLock);
3964 }

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

Referenced by logical_begin_heap_rewrite().

◆ ProcArrayGroupClearXid()

static void ProcArrayGroupClearXid ( PGPROC proc,
TransactionId  latestXid 
)
static

Definition at line 792 of file procarray.c.

793 {
794  int pgprocno = GetNumberFromPGProc(proc);
795  PROC_HDR *procglobal = ProcGlobal;
796  uint32 nextidx;
797  uint32 wakeidx;
798 
799  /* We should definitely have an XID to clear. */
801 
802  /* Add ourselves to the list of processes needing a group XID clear. */
803  proc->procArrayGroupMember = true;
804  proc->procArrayGroupMemberXid = latestXid;
805  nextidx = pg_atomic_read_u32(&procglobal->procArrayGroupFirst);
806  while (true)
807  {
808  pg_atomic_write_u32(&proc->procArrayGroupNext, nextidx);
809 
811  &nextidx,
812  (uint32) pgprocno))
813  break;
814  }
815 
816  /*
817  * If the list was not empty, the leader will clear our XID. It is
818  * impossible to have followers without a leader because the first process
819  * that has added itself to the list will always have nextidx as
820  * INVALID_PROC_NUMBER.
821  */
822  if (nextidx != INVALID_PROC_NUMBER)
823  {
824  int extraWaits = 0;
825 
826  /* Sleep until the leader clears our XID. */
827  pgstat_report_wait_start(WAIT_EVENT_PROCARRAY_GROUP_UPDATE);
828  for (;;)
829  {
830  /* acts as a read barrier */
831  PGSemaphoreLock(proc->sem);
832  if (!proc->procArrayGroupMember)
833  break;
834  extraWaits++;
835  }
837 
839 
840  /* Fix semaphore count for any absorbed wakeups */
841  while (extraWaits-- > 0)
842  PGSemaphoreUnlock(proc->sem);
843  return;
844  }
845 
846  /* We are the leader. Acquire the lock on behalf of everyone. */
847  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
848 
849  /*
850  * Now that we've got the lock, clear the list of processes waiting for
851  * group XID clearing, saving a pointer to the head of the list. Trying
852  * to pop elements one at a time could lead to an ABA problem.
853  */
854  nextidx = pg_atomic_exchange_u32(&procglobal->procArrayGroupFirst,
856 
857  /* Remember head of list so we can perform wakeups after dropping lock. */
858  wakeidx = nextidx;
859 
860  /* Walk the list and clear all XIDs. */
861  while (nextidx != INVALID_PROC_NUMBER)
862  {
863  PGPROC *nextproc = &allProcs[nextidx];
864 
866 
867  /* Move to next proc in list. */
868  nextidx = pg_atomic_read_u32(&nextproc->procArrayGroupNext);
869  }
870 
871  /* We're done with the lock now. */
872  LWLockRelease(ProcArrayLock);
873 
874  /*
875  * Now that we've released the lock, go back and wake everybody up. We
876  * don't do this under the lock so as to keep lock hold times to a
877  * minimum. The system calls we need to perform to wake other processes
878  * up are probably much slower than the simple memory writes we did while
879  * holding the lock.
880  */
881  while (wakeidx != INVALID_PROC_NUMBER)
882  {
883  PGPROC *nextproc = &allProcs[wakeidx];
884 
885  wakeidx = pg_atomic_read_u32(&nextproc->procArrayGroupNext);
887 
888  /* ensure all previous writes are visible before follower continues. */
890 
891  nextproc->procArrayGroupMember = false;
892 
893  if (nextproc != MyProc)
894  PGSemaphoreUnlock(nextproc->sem);
895  }
896 }
static bool pg_atomic_compare_exchange_u32(volatile pg_atomic_uint32 *ptr, uint32 *expected, uint32 newval)
Definition: atomics.h:344
static void pg_atomic_write_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
Definition: atomics.h:271
static uint32 pg_atomic_read_u32(volatile pg_atomic_uint32 *ptr)
Definition: atomics.h:234
static uint32 pg_atomic_exchange_u32(volatile pg_atomic_uint32 *ptr, uint32 newval)
Definition: atomics.h:325
unsigned int uint32
Definition: c.h:493
void PGSemaphoreUnlock(PGSemaphore sema)
Definition: posix_sema.c:340
void PGSemaphoreLock(PGSemaphore sema)
Definition: posix_sema.c:320
bool procArrayGroupMember
Definition: proc.h:265
pg_atomic_uint32 procArrayGroupNext
Definition: proc.h:267
TransactionId procArrayGroupMemberXid
Definition: proc.h:273
PGSemaphore sem
Definition: proc.h:162
Definition: proc.h:378
pg_atomic_uint32 procArrayGroupFirst
Definition: proc.h:408
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition: wait_event.h:88
static void pgstat_report_wait_end(void)
Definition: wait_event.h:104

References allProcs, Assert(), GetNumberFromPGProc, INVALID_PROC_NUMBER, 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, PGSemaphoreLock(), PGSemaphoreUnlock(), pgstat_report_wait_end(), pgstat_report_wait_start(), ProcArrayEndTransactionInternal(), PROC_HDR::procArrayGroupFirst, PGPROC::procArrayGroupMember, PGPROC::procArrayGroupMemberXid, PGPROC::procArrayGroupNext, ProcGlobal, PGPROC::sem, TransactionIdIsValid, and PGPROC::xid.

Referenced by ProcArrayEndTransaction().

◆ ProcArrayInitRecovery()

void ProcArrayInitRecovery ( TransactionId  initializedUptoXID)

Definition at line 1023 of file procarray.c.

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

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

Referenced by StartupXLOG().

◆ ProcArrayInstallImportedXmin()

bool ProcArrayInstallImportedXmin ( TransactionId  xmin,
VirtualTransactionId sourcevxid 
)

Definition at line 2524 of file procarray.c.

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

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

Referenced by GetSerializableTransactionSnapshotInt(), and SetTransactionSnapshot().

◆ ProcArrayInstallRestoredXmin()

bool ProcArrayInstallRestoredXmin ( TransactionId  xmin,
PGPROC proc 
)

Definition at line 2608 of file procarray.c.

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

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

Referenced by SetTransactionSnapshot().

◆ ProcArrayRemove()

void ProcArrayRemove ( PGPROC proc,
TransactionId  latestXid 
)

Definition at line 565 of file procarray.c.

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

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

Referenced by FinishPreparedTransaction(), and RemoveProcFromArray().

◆ ProcArraySetReplicationSlotXmin()

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

Definition at line 3927 of file procarray.c.

3929 {
3930  Assert(!already_locked || LWLockHeldByMe(ProcArrayLock));
3931 
3932  if (!already_locked)
3933  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3934 
3936  procArray->replication_slot_catalog_xmin = catalog_xmin;
3937 
3938  if (!already_locked)
3939  LWLockRelease(ProcArrayLock);
3940 
3941  elog(DEBUG1, "xmin required by slots: data %u, catalog %u",
3942  xmin, catalog_xmin);
3943 }

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

Referenced by ReplicationSlotsComputeRequiredXmin().

◆ ProcArrayShmemSize()

Size ProcArrayShmemSize ( void  )

Definition at line 376 of file procarray.c.

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

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

Referenced by CalculateShmemSize().

◆ ProcNumberGetProc()

PGPROC* ProcNumberGetProc ( ProcNumber  procNumber)

Definition at line 3125 of file procarray.c.

3126 {
3127  PGPROC *result;
3128 
3129  if (procNumber < 0 || procNumber >= ProcGlobal->allProcCount)
3130  return NULL;
3131  result = GetPGProcByNumber(procNumber);
3132 
3133  if (result->pid == 0)
3134  return NULL;
3135 
3136  return result;
3137 }
#define GetPGProcByNumber(n)
Definition: proc.h:428
uint32 allProcCount
Definition: proc.h:398

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

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

◆ ProcNumberGetTransactionIds()

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

Definition at line 3147 of file procarray.c.

3149 {
3150  PGPROC *proc;
3151 
3152  *xid = InvalidTransactionId;
3153  *xmin = InvalidTransactionId;
3154  *nsubxid = 0;
3155  *overflowed = false;
3156 
3157  if (procNumber < 0 || procNumber >= ProcGlobal->allProcCount)
3158  return;
3159  proc = GetPGProcByNumber(procNumber);
3160 
3161  /* Need to lock out additions/removals of backends */
3162  LWLockAcquire(ProcArrayLock, LW_SHARED);
3163 
3164  if (proc->pid != 0)
3165  {
3166  *xid = proc->xid;
3167  *xmin = proc->xmin;
3168  *nsubxid = proc->subxidStatus.count;
3169  *overflowed = proc->subxidStatus.overflowed;
3170  }
3171 
3172  LWLockRelease(ProcArrayLock);
3173 }

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

Referenced by pgstat_read_current_status().

◆ RecordKnownAssignedTransactionIds()

void RecordKnownAssignedTransactionIds ( TransactionId  xid)

Definition at line 4417 of file procarray.c.

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

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

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

◆ SignalVirtualTransaction()

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

Definition at line 3484 of file procarray.c.

3486 {
3487  ProcArrayStruct *arrayP = procArray;
3488  int index;
3489  pid_t pid = 0;
3490 
3491  LWLockAcquire(ProcArrayLock, LW_SHARED);
3492 
3493  for (index = 0; index < arrayP->numProcs; index++)
3494  {
3495  int pgprocno = arrayP->pgprocnos[index];
3496  PGPROC *proc = &allProcs[pgprocno];
3497  VirtualTransactionId procvxid;
3498 
3499  GET_VXID_FROM_PGPROC(procvxid, *proc);
3500 
3501  if (procvxid.procNumber == vxid.procNumber &&
3502  procvxid.localTransactionId == vxid.localTransactionId)
3503  {
3504  proc->recoveryConflictPending = conflictPending;
3505  pid = proc->pid;
3506  if (pid != 0)
3507  {
3508  /*
3509  * Kill the pid if it's still here. If not, that's what we
3510  * wanted so ignore any errors.
3511  */
3512  (void) SendProcSignal(pid, sigmode, vxid.procNumber);
3513  }
3514  break;
3515  }
3516  }
3517 
3518  LWLockRelease(ProcArrayLock);
3519 
3520  return pid;
3521 }

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

Referenced by CancelVirtualTransaction(), and ResolveRecoveryConflictWithLock().

◆ TerminateOtherDBBackends()

void TerminateOtherDBBackends ( Oid  databaseId)

Definition at line 3815 of file procarray.c.

3816 {
3817  ProcArrayStruct *arrayP = procArray;
3818  List *pids = NIL;
3819  int nprepared = 0;
3820  int i;
3821 
3822  LWLockAcquire(ProcArrayLock, LW_SHARED);
3823 
3824  for (i = 0; i < procArray->numProcs; i++)
3825  {
3826  int pgprocno = arrayP->pgprocnos[i];
3827  PGPROC *proc = &allProcs[pgprocno];
3828 
3829  if (proc->databaseId != databaseId)
3830  continue;
3831  if (proc == MyProc)
3832  continue;
3833 
3834  if (proc->pid != 0)
3835  pids = lappend_int(pids, proc->pid);
3836  else
3837  nprepared++;
3838  }
3839 
3840  LWLockRelease(ProcArrayLock);
3841 
3842  if (nprepared > 0)
3843  ereport(ERROR,
3844  (errcode(ERRCODE_OBJECT_IN_USE),
3845  errmsg("database \"%s\" is being used by prepared transactions",
3846  get_database_name(databaseId)),
3847  errdetail_plural("There is %d prepared transaction using the database.",
3848  "There are %d prepared transactions using the database.",
3849  nprepared,
3850  nprepared)));
3851 
3852  if (pids)
3853  {
3854  ListCell *lc;
3855 
3856  /*
3857  * Check whether we have the necessary rights to terminate other
3858  * sessions. We don't terminate any session until we ensure that we
3859  * have rights on all the sessions to be terminated. These checks are
3860  * the same as we do in pg_terminate_backend.
3861  *
3862  * In this case we don't raise some warnings - like "PID %d is not a
3863  * PostgreSQL server process", because for us already finished session
3864  * is not a problem.
3865  */
3866  foreach(lc, pids)
3867  {
3868  int pid = lfirst_int(lc);
3869  PGPROC *proc = BackendPidGetProc(pid);
3870 
3871  if (proc != NULL)
3872  {
3873  /* Only allow superusers to signal superuser-owned backends. */
3874  if (superuser_arg(proc->roleId) && !superuser())
3875  ereport(ERROR,
3876  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
3877  errmsg("permission denied to terminate process"),
3878  errdetail("Only roles with the %s attribute may terminate processes of roles with the %s attribute.",
3879  "SUPERUSER", "SUPERUSER")));
3880 
3881  /* Users can signal backends they have role membership in. */
3882  if (!has_privs_of_role(GetUserId(), proc->roleId) &&
3883  !has_privs_of_role(GetUserId(), ROLE_PG_SIGNAL_BACKEND))
3884  ereport(ERROR,
3885  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
3886  errmsg("permission denied to terminate process"),
3887  errdetail("Only roles with privileges of the role whose process is being terminated or with privileges of the \"%s\" role may terminate this process.",
3888  "pg_signal_backend")));
3889  }
3890  }
3891 
3892  /*
3893  * There's a race condition here: once we release the ProcArrayLock,
3894  * it's possible for the session to exit before we issue kill. That
3895  * race condition possibility seems too unlikely to worry about. See
3896  * pg_signal_backend.
3897  */
3898  foreach(lc, pids)
3899  {
3900  int pid = lfirst_int(lc);
3901  PGPROC *proc = BackendPidGetProc(pid);
3902 
3903  if (proc != NULL)
3904  {
3905  /*
3906  * If we have setsid(), signal the backend's whole process
3907  * group
3908  */
3909 #ifdef HAVE_SETSID
3910  (void) kill(-pid, SIGTERM);
3911 #else
3912  (void) kill(pid, SIGTERM);
3913 #endif
3914  }
3915  }
3916  }
3917 }
bool has_privs_of_role(Oid member, Oid role)
Definition: acl.c:5066
char * get_database_name(Oid dbid)
Definition: dbcommands.c:3153
int errdetail(const char *fmt,...)
Definition: elog.c:1205
int errdetail_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n,...)
Definition: elog.c:1297
List * lappend_int(List *list, int datum)
Definition: list.c:357
Oid GetUserId(void)
Definition: miscinit.c:514
#define NIL
Definition: pg_list.h:68
#define lfirst_int(lc)
Definition: pg_list.h:173
Definition: pg_list.h:54
bool superuser_arg(Oid roleid)
Definition: superuser.c:56
bool superuser(void)
Definition: superuser.c:46

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

Referenced by dropdb().

◆ TransactionIdIsActive()

bool TransactionIdIsActive ( TransactionId  xid)

Definition at line 1622 of file procarray.c.

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

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

◆ TransactionIdIsInProgress()

bool TransactionIdIsInProgress ( TransactionId  xid)

Definition at line 1390 of file procarray.c.

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

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

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

◆ XidCacheRemoveRunningXids()

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

Definition at line 3975 of file procarray.c.

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

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

Referenced by RecordTransactionAbort().

Variable Documentation

◆ allProcs

◆ cachedXidIsNotInProgress

TransactionId cachedXidIsNotInProgress = InvalidTransactionId
static

Definition at line 276 of file procarray.c.

Referenced by TransactionIdIsInProgress().

◆ ComputeXidHorizonsResultLastXmin

TransactionId ComputeXidHorizonsResultLastXmin
static

Definition at line 307 of file procarray.c.

Referenced by GlobalVisTestShouldUpdate(), and GlobalVisUpdateApply().

◆ GlobalVisCatalogRels

GlobalVisState GlobalVisCatalogRels
static

Definition at line 298 of file procarray.c.

Referenced by GetSnapshotData(), GlobalVisTestFor(), and GlobalVisUpdateApply().

◆ GlobalVisDataRels

GlobalVisState GlobalVisDataRels
static

Definition at line 299 of file procarray.c.

Referenced by GetSnapshotData(), GlobalVisTestFor(), and GlobalVisUpdateApply().

◆ GlobalVisSharedRels

GlobalVisState GlobalVisSharedRels
static

Definition at line 297 of file procarray.c.

Referenced by GetSnapshotData(), GlobalVisTestFor(), and GlobalVisUpdateApply().

◆ GlobalVisTempRels

GlobalVisState GlobalVisTempRels
static

Definition at line 300 of file procarray.c.

Referenced by GetSnapshotData(), GlobalVisTestFor(), and GlobalVisUpdateApply().

◆ KnownAssignedXids

◆ KnownAssignedXidsValid

◆ latestObservedXid

◆ procArray

◆ standbySnapshotPendingXmin

TransactionId standbySnapshotPendingXmin
static

Definition at line 290 of file procarray.c.

Referenced by ProcArrayApplyRecoveryInfo().