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

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

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

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

◆ BackendPidGetProcWithLock()

PGPROC* BackendPidGetProcWithLock ( int  pid)

Definition at line 3223 of file procarray.c.

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

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

Referenced by BackendPidGetProc(), and GetBlockerStatusData().

◆ BackendXidGetPid()

int BackendXidGetPid ( TransactionId  xid)

Definition at line 3260 of file procarray.c.

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

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

Referenced by pgrowlocks().

◆ CancelDBBackends()

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

Definition at line 3664 of file procarray.c.

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

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

Referenced by ResolveRecoveryConflictWithDatabase(), and SendRecoveryConflictWithBufferPin().

◆ CancelVirtualTransaction()

pid_t CancelVirtualTransaction ( VirtualTransactionId  vxid,
ProcSignalReason  sigmode 
)

Definition at line 3495 of file procarray.c.

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

References SignalVirtualTransaction().

Referenced by ResolveRecoveryConflictWithVirtualXIDs().

◆ ComputeXidHorizons()

static void ComputeXidHorizons ( ComputeXidHorizonsResult h)
static

Definition at line 1735 of file procarray.c.

1736 {
1737  ProcArrayStruct *arrayP = procArray;
1738  TransactionId kaxmin;
1739  bool in_recovery = RecoveryInProgress();
1740  TransactionId *other_xids = ProcGlobal->xids;
1741 
1742  /* inferred after ProcArrayLock is released */
1744 
1745  LWLockAcquire(ProcArrayLock, LW_SHARED);
1746 
1748 
1749  /*
1750  * We initialize the MIN() calculation with latestCompletedXid + 1. This
1751  * is a lower bound for the XIDs that might appear in the ProcArray later,
1752  * and so protects us against overestimating the result due to future
1753  * additions.
1754  */
1755  {
1756  TransactionId initial;
1757 
1759  Assert(TransactionIdIsValid(initial));
1760  TransactionIdAdvance(initial);
1761 
1762  h->oldest_considered_running = initial;
1763  h->shared_oldest_nonremovable = initial;
1764  h->data_oldest_nonremovable = initial;
1765 
1766  /*
1767  * Only modifications made by this backend affect the horizon for
1768  * temporary relations. Instead of a check in each iteration of the
1769  * loop over all PGPROCs it is cheaper to just initialize to the
1770  * current top-level xid any.
1771  *
1772  * Without an assigned xid we could use a horizon as aggressive as
1773  * GetNewTransactionId(), but we can get away with the much cheaper
1774  * latestCompletedXid + 1: If this backend has no xid there, by
1775  * definition, can't be any newer changes in the temp table than
1776  * latestCompletedXid.
1777  */
1780  else
1781  h->temp_oldest_nonremovable = initial;
1782  }
1783 
1784  /*
1785  * Fetch slot horizons while ProcArrayLock is held - the
1786  * LWLockAcquire/LWLockRelease are a barrier, ensuring this happens inside
1787  * the lock.
1788  */
1791 
1792  for (int index = 0; index < arrayP->numProcs; index++)
1793  {
1794  int pgprocno = arrayP->pgprocnos[index];
1795  PGPROC *proc = &allProcs[pgprocno];
1796  int8 statusFlags = ProcGlobal->statusFlags[index];
1797  TransactionId xid;
1798  TransactionId xmin;
1799 
1800  /* Fetch xid just once - see GetNewTransactionId */
1801  xid = UINT32_ACCESS_ONCE(other_xids[index]);
1802  xmin = UINT32_ACCESS_ONCE(proc->xmin);
1803 
1804  /*
1805  * Consider both the transaction's Xmin, and its Xid.
1806  *
1807  * We must check both because a transaction might have an Xmin but not
1808  * (yet) an Xid; conversely, if it has an Xid, that could determine
1809  * some not-yet-set Xmin.
1810  */
1811  xmin = TransactionIdOlder(xmin, xid);
1812 
1813  /* if neither is set, this proc doesn't influence the horizon */
1814  if (!TransactionIdIsValid(xmin))
1815  continue;
1816 
1817  /*
1818  * Don't ignore any procs when determining which transactions might be
1819  * considered running. While slots should ensure logical decoding
1820  * backends are protected even without this check, it can't hurt to
1821  * include them here as well..
1822  */
1825 
1826  /*
1827  * Skip over backends either vacuuming (which is ok with rows being
1828  * removed, as long as pg_subtrans is not truncated) or doing logical
1829  * decoding (which manages xmin separately, check below).
1830  */
1831  if (statusFlags & (PROC_IN_VACUUM | PROC_IN_LOGICAL_DECODING))
1832  continue;
1833 
1834  /* shared tables need to take backends in all databases into account */
1837 
1838  /*
1839  * Normally sessions in other databases are ignored for anything but
1840  * the shared horizon.
1841  *
1842  * However, include them when MyDatabaseId is not (yet) set. A
1843  * backend in the process of starting up must not compute a "too
1844  * aggressive" horizon, otherwise we could end up using it to prune
1845  * still-needed data away. If the current backend never connects to a
1846  * database this is harmless, because data_oldest_nonremovable will
1847  * never be utilized.
1848  *
1849  * Also, sessions marked with PROC_AFFECTS_ALL_HORIZONS should always
1850  * be included. (This flag is used for hot standby feedback, which
1851  * can't be tied to a specific database.)
1852  *
1853  * Also, while in recovery we cannot compute an accurate per-database
1854  * horizon, as all xids are managed via the KnownAssignedXids
1855  * machinery.
1856  */
1857  if (proc->databaseId == MyDatabaseId ||
1858  MyDatabaseId == InvalidOid ||
1859  (statusFlags & PROC_AFFECTS_ALL_HORIZONS) ||
1860  in_recovery)
1861  {
1864  }
1865  }
1866 
1867  /*
1868  * If in recovery fetch oldest xid in KnownAssignedXids, will be applied
1869  * after lock is released.
1870  */
1871  if (in_recovery)
1872  kaxmin = KnownAssignedXidsGetOldestXmin();
1873 
1874  /*
1875  * No other information from shared state is needed, release the lock
1876  * immediately. The rest of the computations can be done without a lock.
1877  */
1878  LWLockRelease(ProcArrayLock);
1879 
1880  if (in_recovery)
1881  {
1888  /* temp relations cannot be accessed in recovery */
1889  }
1890 
1895 
1896  /*
1897  * Check whether there are replication slots requiring an older xmin.
1898  */
1903 
1904  /*
1905  * The only difference between catalog / data horizons is that the slot's
1906  * catalog xmin is applied to the catalog one (so catalogs can be accessed
1907  * for logical decoding). Initialize with data horizon, and then back up
1908  * further if necessary. Have to back up the shared horizon as well, since
1909  * that also can contain catalogs.
1910  */
1914  h->slot_catalog_xmin);
1918  h->slot_catalog_xmin);
1919 
1920  /*
1921  * It's possible that slots backed up the horizons further than
1922  * oldest_considered_running. Fix.
1923  */
1933 
1934  /*
1935  * shared horizons have to be at least as old as the oldest visible in
1936  * current db
1937  */
1942 
1943  /*
1944  * Horizons need to ensure that pg_subtrans access is still possible for
1945  * the relevant backends.
1946  */
1957  h->slot_xmin));
1960  h->slot_catalog_xmin));
1961 
1962  /* update approximate horizons with the computed horizons */
1964 }
signed char int8
Definition: c.h:492
#define Assert(condition)
Definition: c.h:858
Oid MyDatabaseId
Definition: globals.c:92
#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:4170
static TransactionId KnownAssignedXidsGetOldestXmin(void)
Definition: procarray.c:5163
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:172
TransactionId xid
Definition: proc.h:167
uint8 * statusFlags
Definition: proc.h:394
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:6304

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

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

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

Referenced by ResolveRecoveryConflictWithDatabase().

◆ CountDBConnections()

int CountDBConnections ( Oid  databaseid)

Definition at line 3633 of file procarray.c.

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

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

Referenced by CheckMyDatabase().

◆ CountOtherDBBackends()

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

Definition at line 3754 of file procarray.c.

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

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

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

◆ CountUserBackends()

int CountUserBackends ( Oid  roleid)

Definition at line 3704 of file procarray.c.

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

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

Referenced by InitializeSessionUserId().

◆ CreateSharedProcArray()

void CreateSharedProcArray ( void  )

Definition at line 418 of file procarray.c.

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

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

Referenced by CreateOrAttachShmemStructs().

◆ ExpireAllKnownAssignedTransactionIds()

void ExpireAllKnownAssignedTransactionIds ( void  )

Definition at line 4502 of file procarray.c.

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

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

Referenced by ShutdownRecoveryTransactionEnvironment().

◆ ExpireOldKnownAssignedTransactionIds()

void ExpireOldKnownAssignedTransactionIds ( TransactionId  xid)

Definition at line 4522 of file procarray.c.

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

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

Referenced by ProcArrayApplyRecoveryInfo().

◆ ExpireTreeKnownAssignedTransactionIds()

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

Definition at line 4476 of file procarray.c.

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

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

Referenced by xact_redo_abort(), and xact_redo_commit().

◆ FullXidRelativeTo()

static FullTransactionId FullXidRelativeTo ( FullTransactionId  rel,
TransactionId  xid 
)
inlinestatic

Definition at line 4325 of file procarray.c.

4326 {
4327  TransactionId rel_xid = XidFromFullTransactionId(rel);
4328 
4330  Assert(TransactionIdIsValid(rel_xid));
4331 
4332  /* not guaranteed to find issues, but likely to catch mistakes */
4334 
4336  + (int32) (xid - rel_xid));
4337 }
signed int int32
Definition: c.h:494
#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 3421 of file procarray.c.

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

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

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

Referenced by WaitForOlderSnapshots().

◆ GetMaxSnapshotSubxidCount()

int GetMaxSnapshotSubxidCount ( void  )

Definition at line 2080 of file procarray.c.

2081 {
2082  return TOTAL_MAX_CACHED_SUBXIDS;
2083 }

References TOTAL_MAX_CACHED_SUBXIDS.

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

◆ GetMaxSnapshotXidCount()

int GetMaxSnapshotXidCount ( void  )

Definition at line 2069 of file procarray.c.

2070 {
2071  return procArray->maxProcs;
2072 }

References ProcArrayStruct::maxProcs, and procArray.

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

◆ GetOldestActiveTransactionId()

TransactionId GetOldestActiveTransactionId ( void  )

Definition at line 2884 of file procarray.c.

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

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

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

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

◆ GetOldestSafeDecodingTransactionId()

TransactionId GetOldestSafeDecodingTransactionId ( bool  catalogOnly)

Definition at line 2949 of file procarray.c.

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

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

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

◆ GetOldestTransactionIdConsideredRunning()

TransactionId GetOldestTransactionIdConsideredRunning ( void  )

Definition at line 2034 of file procarray.c.

2035 {
2036  ComputeXidHorizonsResult horizons;
2037 
2038  ComputeXidHorizons(&horizons);
2039 
2040  return horizons.oldest_considered_running;
2041 }

References ComputeXidHorizons(), and ComputeXidHorizonsResult::oldest_considered_running.

Referenced by CreateCheckPoint(), and CreateRestartPoint().

◆ GetReplicationHorizons()

void GetReplicationHorizons ( TransactionId xmin,
TransactionId catalog_xmin 
)

Definition at line 2047 of file procarray.c.

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

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

Referenced by XLogWalRcvSendHSFeedback().

◆ GetRunningTransactionData()

RunningTransactions GetRunningTransactionData ( void  )

Definition at line 2693 of file procarray.c.

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

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

Referenced by GetStrictOldestNonRemovableTransactionId(), and LogStandbySnapshot().

◆ GetSnapshotData()

Snapshot GetSnapshotData ( Snapshot  snapshot)

Definition at line 2177 of file procarray.c.

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

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

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

◆ GetSnapshotDataReuse()

static bool GetSnapshotDataReuse ( Snapshot  snapshot)
static

Definition at line 2095 of file procarray.c.

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

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

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

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

Referenced by CreateCheckPoint().

◆ GlobalVisCheckRemovableFullXid()

bool GlobalVisCheckRemovableFullXid ( Relation  rel,
FullTransactionId  fxid 
)

Definition at line 4290 of file procarray.c.

4291 {
4293 
4294  state = GlobalVisTestFor(rel);
4295 
4296  return GlobalVisTestIsRemovableFullXid(state, fxid);
4297 }
bool GlobalVisTestIsRemovableFullXid(GlobalVisState *state, FullTransactionId fxid)
Definition: procarray.c:4226
GlobalVisState * GlobalVisTestFor(Relation rel)
Definition: procarray.c:4111
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 4304 of file procarray.c.

4305 {
4307 
4308  state = GlobalVisTestFor(rel);
4309 
4310  return GlobalVisTestIsRemovableXid(state, xid);
4311 }
bool GlobalVisTestIsRemovableXid(GlobalVisState *state, TransactionId xid)
Definition: procarray.c:4268

References GlobalVisTestFor(), and GlobalVisTestIsRemovableXid().

Referenced by GinPageIsRecyclable().

◆ GlobalVisHorizonKindForRel()

static GlobalVisHorizonKind GlobalVisHorizonKindForRel ( Relation  rel)
inlinestatic

Definition at line 1971 of file procarray.c.

1972 {
1973  /*
1974  * Other relkinds currently don't contain xids, nor always the necessary
1975  * logical decoding markers.
1976  */
1977  Assert(!rel ||
1978  rel->rd_rel->relkind == RELKIND_RELATION ||
1979  rel->rd_rel->relkind == RELKIND_MATVIEW ||
1980  rel->rd_rel->relkind == RELKIND_TOASTVALUE);
1981 
1982  if (rel == NULL || rel->rd_rel->relisshared || RecoveryInProgress())
1983  return VISHORIZON_SHARED;
1984  else if (IsCatalogRelation(rel) ||
1986  return VISHORIZON_CATALOG;
1987  else if (!RELATION_IS_LOCAL(rel))
1988  return VISHORIZON_DATA;
1989  else
1990  return VISHORIZON_TEMP;
1991 }
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 4111 of file procarray.c.

4112 {
4113  GlobalVisState *state = NULL;
4114 
4115  /* XXX: we should assert that a snapshot is pushed or registered */
4116  Assert(RecentXmin);
4117 
4118  switch (GlobalVisHorizonKindForRel(rel))
4119  {
4120  case VISHORIZON_SHARED:
4122  break;
4123  case VISHORIZON_CATALOG:
4125  break;
4126  case VISHORIZON_DATA:
4128  break;
4129  case VISHORIZON_TEMP:
4131  break;
4132  }
4133 
4134  Assert(FullTransactionIdIsValid(state->definitely_needed) &&
4135  FullTransactionIdIsValid(state->maybe_needed));
4136 
4137  return state;
4138 }
#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 4226 of file procarray.c.

4228 {
4229  /*
4230  * If fxid is older than maybe_needed bound, it definitely is visible to
4231  * everyone.
4232  */
4233  if (FullTransactionIdPrecedes(fxid, state->maybe_needed))
4234  return true;
4235 
4236  /*
4237  * If fxid is >= definitely_needed bound, it is very likely to still be
4238  * considered running.
4239  */
4240  if (FullTransactionIdFollowsOrEquals(fxid, state->definitely_needed))
4241  return false;
4242 
4243  /*
4244  * fxid is between maybe_needed and definitely_needed, i.e. there might or
4245  * might not exist a snapshot considering fxid running. If it makes sense,
4246  * update boundaries and recheck.
4247  */
4249  {
4250  GlobalVisUpdate();
4251 
4252  Assert(FullTransactionIdPrecedes(fxid, state->definitely_needed));
4253 
4254  return FullTransactionIdPrecedes(fxid, state->maybe_needed);
4255  }
4256  else
4257  return false;
4258 }
static bool GlobalVisTestShouldUpdate(GlobalVisState *state)
Definition: procarray.c:4151
static void GlobalVisUpdate(void)
Definition: procarray.c:4209
#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 4268 of file procarray.c.

4269 {
4270  FullTransactionId fxid;
4271 
4272  /*
4273  * Convert 32 bit argument to FullTransactionId. We can do so safely
4274  * because we know the xid has to, at the very least, be between
4275  * [oldestXid, nextXid), i.e. within 2 billion of xid. To avoid taking a
4276  * lock to determine either, we can just compare with
4277  * state->definitely_needed, which was based on those value at the time
4278  * the current snapshot was built.
4279  */
4280  fxid = FullXidRelativeTo(state->definitely_needed, xid);
4281 
4282  return GlobalVisTestIsRemovableFullXid(state, fxid);
4283 }

References FullXidRelativeTo(), and GlobalVisTestIsRemovableFullXid().

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

◆ GlobalVisTestShouldUpdate()

static bool GlobalVisTestShouldUpdate ( GlobalVisState state)
static

Definition at line 4151 of file procarray.c.

4152 {
4153  /* hasn't been updated yet */
4155  return true;
4156 
4157  /*
4158  * If the maybe_needed/definitely_needed boundaries are the same, it's
4159  * unlikely to be beneficial to refresh boundaries.
4160  */
4161  if (FullTransactionIdFollowsOrEquals(state->maybe_needed,
4162  state->definitely_needed))
4163  return false;
4164 
4165  /* does the last snapshot built have a different xmin? */
4167 }
static TransactionId ComputeXidHorizonsResultLastXmin
Definition: procarray.c:307

References ComputeXidHorizonsResultLastXmin, FullTransactionIdFollowsOrEquals, RecentXmin, and TransactionIdIsValid.

Referenced by GlobalVisTestIsRemovableFullXid().

◆ GlobalVisUpdate()

static void GlobalVisUpdate ( void  )
static

Definition at line 4209 of file procarray.c.

4210 {
4211  ComputeXidHorizonsResult horizons;
4212 
4213  /* updates the horizons as a side-effect */
4214  ComputeXidHorizons(&horizons);
4215 }

References ComputeXidHorizons().

Referenced by GlobalVisTestIsRemovableFullXid().

◆ GlobalVisUpdateApply()

static void GlobalVisUpdateApply ( ComputeXidHorizonsResult horizons)
static

Definition at line 4170 of file procarray.c.

4171 {
4174  horizons->shared_oldest_nonremovable);
4177  horizons->catalog_oldest_nonremovable);
4180  horizons->data_oldest_nonremovable);
4183  horizons->temp_oldest_nonremovable);
4184 
4185  /*
4186  * In longer running transactions it's possible that transactions we
4187  * previously needed to treat as running aren't around anymore. So update
4188  * definitely_needed to not be earlier than maybe_needed.
4189  */
4200 
4202 }

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

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

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

Referenced by CreateCheckPoint().

◆ IsBackendPid()

bool IsBackendPid ( int  pid)

Definition at line 3295 of file procarray.c.

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

References BackendPidGetProc().

Referenced by pg_stat_get_subscription().

◆ KnownAssignedTransactionIdsIdleMaintenance()

void KnownAssignedTransactionIdsIdleMaintenance ( void  )

Definition at line 4544 of file procarray.c.

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

References KAX_STARTUP_PROCESS_IDLE, and KnownAssignedXidsCompress().

Referenced by WaitForWALToBecomeAvailable().

◆ KnownAssignedXidExists()

static bool KnownAssignedXidExists ( TransactionId  xid)
static

Definition at line 4954 of file procarray.c.

4955 {
4957 
4958  return KnownAssignedXidsSearch(xid, false);
4959 }
static bool KnownAssignedXidsSearch(TransactionId xid, bool remove)
Definition: procarray.c:4866

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

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

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

5199 {
5200  ProcArrayStruct *pArray = procArray;
5202  int head,
5203  tail,
5204  i;
5205  int nxids = 0;
5206 
5207  tail = pArray->tailKnownAssignedXids;
5208  head = pArray->headKnownAssignedXids;
5209 
5210  initStringInfo(&buf);
5211 
5212  for (i = tail; i < head; i++)
5213  {
5215  {
5216  nxids++;
5217  appendStringInfo(&buf, "[%d]=%u ", i, KnownAssignedXids[i]);
5218  }
5219  }
5220 
5221  elog(trace_level, "%d KnownAssignedXids (num=%d tail=%d head=%d) %s",
5222  nxids,
5223  pArray->numKnownAssignedXids,
5224  pArray->tailKnownAssignedXids,
5225  pArray->headKnownAssignedXids,
5226  buf.data);
5227 
5228  pfree(buf.data);
5229 }
void pfree(void *pointer)
Definition: mcxt.c:1521
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 5093 of file procarray.c.

5094 {
5096 
5097  return KnownAssignedXidsGetAndSetXmin(xarray, &xtmp, xmax);
5098 }

References InvalidTransactionId, and KnownAssignedXidsGetAndSetXmin().

Referenced by TransactionIdIsInProgress().

◆ KnownAssignedXidsGetAndSetXmin()

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

Definition at line 5107 of file procarray.c.

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

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

5164 {
5165  int head,
5166  tail;
5167  int i;
5168 
5169  /*
5170  * Fetch head just once, since it may change while we loop.
5171  */
5174 
5175  pg_read_barrier(); /* pairs with KnownAssignedXidsAdd */
5176 
5177  for (i = tail; i < head; i++)
5178  {
5179  /* Skip any gaps in the array */
5181  return KnownAssignedXids[i];
5182  }
5183 
5184  return InvalidTransactionId;
5185 }

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

4968 {
4970 
4971  elog(DEBUG4, "remove KnownAssignedXid %u", xid);
4972 
4973  /*
4974  * Note: we cannot consider it an error to remove an XID that's not
4975  * present. We intentionally remove subxact IDs while processing
4976  * XLOG_XACT_ASSIGNMENT, to avoid array overflow. Then those XIDs will be
4977  * removed again when the top-level xact commits or aborts.
4978  *
4979  * It might be possible to track such XIDs to distinguish this case from
4980  * actual errors, but it would be complicated and probably not worth it.
4981  * So, just ignore the search result.
4982  */
4983  (void) KnownAssignedXidsSearch(xid, true);
4984 }
#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 5015 of file procarray.c.

5016 {
5017  ProcArrayStruct *pArray = procArray;
5018  int count = 0;
5019  int head,
5020  tail,
5021  i;
5022 
5023  if (!TransactionIdIsValid(removeXid))
5024  {
5025  elog(DEBUG4, "removing all KnownAssignedXids");
5026  pArray->numKnownAssignedXids = 0;
5027  pArray->headKnownAssignedXids = pArray->tailKnownAssignedXids = 0;
5028  return;
5029  }
5030 
5031  elog(DEBUG4, "prune KnownAssignedXids to %u", removeXid);
5032 
5033  /*
5034  * Mark entries invalid starting at the tail. Since array is sorted, we
5035  * can stop as soon as we reach an entry >= removeXid.
5036  */
5037  tail = pArray->tailKnownAssignedXids;
5038  head = pArray->headKnownAssignedXids;
5039 
5040  for (i = tail; i < head; i++)
5041  {
5043  {
5044  TransactionId knownXid = KnownAssignedXids[i];
5045 
5046  if (TransactionIdFollowsOrEquals(knownXid, removeXid))
5047  break;
5048 
5049  if (!StandbyTransactionIdIsPrepared(knownXid))
5050  {
5051  KnownAssignedXidsValid[i] = false;
5052  count++;
5053  }
5054  }
5055  }
5056 
5057  pArray->numKnownAssignedXids -= count;
5058  Assert(pArray->numKnownAssignedXids >= 0);
5059 
5060  /*
5061  * Advance the tail pointer if we've marked the tail item invalid.
5062  */
5063  for (i = tail; i < head; i++)
5064  {
5066  break;
5067  }
5068  if (i >= head)
5069  {
5070  /* Array is empty, so we can reset both pointers */
5071  pArray->headKnownAssignedXids = 0;
5072  pArray->tailKnownAssignedXids = 0;
5073  }
5074  else
5075  {
5076  pArray->tailKnownAssignedXids = i;
5077  }
5078 
5079  /* Opportunistically compress the array */
5081 }
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 4993 of file procarray.c.

4995 {
4996  int i;
4997 
4998  if (TransactionIdIsValid(xid))
5000 
5001  for (i = 0; i < nsubxids; i++)
5002  KnownAssignedXidsRemove(subxids[i]);
5003 
5004  /* Opportunistically compress the array */
5006 }
static void KnownAssignedXidsRemove(TransactionId xid)
Definition: procarray.c:4967

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

Referenced by ExpireTreeKnownAssignedTransactionIds(), and ProcArrayApplyXidAssignment().

◆ KnownAssignedXidsReset()

static void KnownAssignedXidsReset ( void  )
static

Definition at line 5236 of file procarray.c.

5237 {
5238  ProcArrayStruct *pArray = procArray;
5239 
5240  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
5241 
5242  pArray->numKnownAssignedXids = 0;
5243  pArray->tailKnownAssignedXids = 0;
5244  pArray->headKnownAssignedXids = 0;
5245 
5246  LWLockRelease(ProcArrayLock);
5247 }

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

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

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:118
#define AmStartupProcess()
Definition: miscadmin.h:382

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

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

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

Referenced by XLogFlush().

◆ ProcArrayAdd()

void ProcArrayAdd ( PGPROC proc)

Definition at line 468 of file procarray.c.

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

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

Referenced by InitProcessPhase2(), and MarkAsPrepared().

◆ ProcArrayApplyRecoveryInfo()

void ProcArrayApplyRecoveryInfo ( RunningTransactions  running)

Definition at line 1054 of file procarray.c.

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

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

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

◆ ProcArrayApplyXidAssignment()

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

Definition at line 1318 of file procarray.c.

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

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

Referenced by xact_redo().

◆ ProcArrayClearTransaction()

void ProcArrayClearTransaction ( PGPROC proc)

Definition at line 907 of file procarray.c.

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

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

Referenced by PrepareTransaction().

◆ ProcArrayEndTransaction()

void ProcArrayEndTransaction ( PGPROC proc,
TransactionId  latestXid 
)

Definition at line 667 of file procarray.c.

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

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

Referenced by AbortTransaction(), and CommitTransaction().

◆ 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:1937
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 3972 of file procarray.c.

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

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

Referenced by logical_begin_heap_rewrite().

◆ 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:342
static void pg_atomic_write_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
Definition: atomics.h:269
static uint32 pg_atomic_read_u32(volatile pg_atomic_uint32 *ptr)
Definition: atomics.h:232
static uint32 pg_atomic_exchange_u32(volatile pg_atomic_uint32 *ptr, uint32 newval)
Definition: atomics.h:323
unsigned int uint32
Definition: c.h:506
void PGSemaphoreUnlock(PGSemaphore sema)
Definition: posix_sema.c:340
void PGSemaphoreLock(PGSemaphore sema)
Definition: posix_sema.c:320
bool procArrayGroupMember
Definition: proc.h:264
pg_atomic_uint32 procArrayGroupNext
Definition: proc.h:266
TransactionId procArrayGroupMemberXid
Definition: proc.h:272
PGSemaphore sem
Definition: proc.h:161
Definition: proc.h:377
pg_atomic_uint32 procArrayGroupFirst
Definition: proc.h:407
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition: wait_event.h:85
static void pgstat_report_wait_end(void)
Definition: wait_event.h:101

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

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

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

Referenced by GetSerializableTransactionSnapshotInt(), and SetTransactionSnapshot().

◆ ProcArrayInstallRestoredXmin()

bool ProcArrayInstallRestoredXmin ( TransactionId  xmin,
PGPROC proc 
)

Definition at line 2620 of file procarray.c.

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

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

Referenced by SetTransactionSnapshot().

◆ ProcArrayRemove()

void ProcArrayRemove ( PGPROC proc,
TransactionId  latestXid 
)

Definition at line 565 of file procarray.c.

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

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

Referenced by FinishPreparedTransaction(), and RemoveProcFromArray().

◆ ProcArraySetReplicationSlotXmin()

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

Definition at line 3947 of file procarray.c.

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

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

Referenced by ReplicationSlotsComputeRequiredXmin().

◆ ProcArrayShmemSize()

Size ProcArrayShmemSize ( void  )

Definition at line 376 of file procarray.c.

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

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

Referenced by CalculateShmemSize().

◆ ProcNumberGetProc()

PGPROC* ProcNumberGetProc ( ProcNumber  procNumber)

Definition at line 3142 of file procarray.c.

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

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

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

◆ ProcNumberGetTransactionIds()

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

Definition at line 3164 of file procarray.c.

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

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

Referenced by pgstat_read_current_status().

◆ RecordKnownAssignedTransactionIds()

void RecordKnownAssignedTransactionIds ( TransactionId  xid)

Definition at line 4407 of file procarray.c.

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

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

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

◆ SignalVirtualTransaction()

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

Definition at line 3501 of file procarray.c.

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

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

Referenced by CancelVirtualTransaction(), and ResolveRecoveryConflictWithLock().

◆ TerminateOtherDBBackends()

void TerminateOtherDBBackends ( Oid  databaseId)

Definition at line 3832 of file procarray.c.

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

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

Referenced by dropdb().

◆ TransactionIdIsActive()

bool TransactionIdIsActive ( TransactionId  xid)

Definition at line 1634 of file procarray.c.

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

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

◆ TransactionIdIsInProgress()

bool TransactionIdIsInProgress ( TransactionId  xid)

Definition at line 1402 of file procarray.c.

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

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

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

◆ XidCacheRemoveRunningXids()

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

Definition at line 3995 of file procarray.c.

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