PostgreSQL Source Code git master
Loading...
Searching...
No Matches
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 "miscadmin.h"
#include "pgstat.h"
#include "postmaster/bgworker.h"
#include "port/pg_lfind.h"
#include "storage/proc.h"
#include "storage/procarray.h"
#include "storage/procsignal.h"
#include "storage/subsystems.h"
#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/injection_point.h"
#include "utils/lsyscache.h"
#include "utils/rel.h"
#include "utils/snapmgr.h"
#include "utils/wait_event.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 ProcArrayShmemRequest (void *arg)
 
static void ProcArrayShmemInit (void *arg)
 
static void ProcArrayShmemAttach (void *arg)
 
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)
 
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)
 
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 (Oid dbid)
 
TransactionId GetOldestActiveTransactionId (bool inCommitOnly, bool allDbs)
 
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)
 
bool SignalRecoveryConflict (PGPROC *proc, pid_t pid, RecoveryConflictReason reason)
 
bool SignalRecoveryConflictWithVirtualXID (VirtualTransactionId vxid, RecoveryConflictReason reason)
 
void SignalRecoveryConflictWithDatabase (Oid databaseid, RecoveryConflictReason reason)
 
bool MinimumActiveBackends (int min)
 
int CountDBBackends (Oid databaseid)
 
int CountDBConnections (Oid databaseid)
 
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 allow_update)
 
bool GlobalVisTestIsRemovableXid (GlobalVisState *state, TransactionId xid, bool allow_update)
 
bool GlobalVisTestXidConsideredRunning (GlobalVisState *state, TransactionId xid, bool allow_update)
 
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
 
const struct ShmemCallbacks ProcArrayShmemCallbacks
 
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 73 of file procarray.c.

◆ xc_by_child_xid_inc

#define xc_by_child_xid_inc ( )    ((void) 0)

Definition at line 357 of file procarray.c.

◆ xc_by_known_assigned_inc

#define xc_by_known_assigned_inc ( )    ((void) 0)

Definition at line 358 of file procarray.c.

◆ xc_by_known_xact_inc

#define xc_by_known_xact_inc ( )    ((void) 0)

Definition at line 353 of file procarray.c.

◆ xc_by_latest_xid_inc

#define xc_by_latest_xid_inc ( )    ((void) 0)

Definition at line 355 of file procarray.c.

◆ xc_by_main_xid_inc

#define xc_by_main_xid_inc ( )    ((void) 0)

Definition at line 356 of file procarray.c.

◆ xc_by_my_xact_inc

#define xc_by_my_xact_inc ( )    ((void) 0)

Definition at line 354 of file procarray.c.

◆ xc_by_recent_xmin_inc

#define xc_by_recent_xmin_inc ( )    ((void) 0)

Definition at line 352 of file procarray.c.

◆ xc_no_overflow_inc

#define xc_no_overflow_inc ( )    ((void) 0)

Definition at line 359 of file procarray.c.

◆ xc_slow_answer_inc

#define xc_slow_answer_inc ( )    ((void) 0)

Definition at line 360 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 266 of file procarray.c.

267{
GlobalVisHorizonKind
Definition procarray.c:267
@ VISHORIZON_SHARED
Definition procarray.c:268
@ VISHORIZON_DATA
Definition procarray.c:270
@ VISHORIZON_CATALOG
Definition procarray.c:269
@ VISHORIZON_TEMP
Definition procarray.c:271

◆ KAXCompressReason

Enumerator
KAX_NO_SPACE 
KAX_PRUNE 
KAX_TRANSACTION_END 
KAX_STARTUP_PROCESS_IDLE 

Definition at line 277 of file procarray.c.

278{
279 KAX_NO_SPACE, /* need to free up space at array end */
280 KAX_PRUNE, /* we just pruned old entries */
281 KAX_TRANSACTION_END, /* we just committed/removed some XIDs */
282 KAX_STARTUP_PROCESS_IDLE, /* startup process is about to sleep */
KAXCompressReason
Definition procarray.c:278
@ KAX_PRUNE
Definition procarray.c:280
@ KAX_NO_SPACE
Definition procarray.c:279
@ KAX_TRANSACTION_END
Definition procarray.c:281
@ KAX_STARTUP_PROCESS_IDLE
Definition procarray.c:282

Function Documentation

◆ BackendPidGetProc()

PGPROC * BackendPidGetProc ( int  pid)

Definition at line 3169 of file procarray.c.

3170{
3171 PGPROC *result;
3172
3173 if (pid == 0) /* never match dummy PGPROCs */
3174 return NULL;
3175
3177
3179
3181
3182 return result;
3183}
uint32 result
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition lwlock.c:1150
void LWLockRelease(LWLock *lock)
Definition lwlock.c:1767
@ LW_SHARED
Definition lwlock.h:105
static int fb(int x)
PGPROC * BackendPidGetProcWithLock(int pid)
Definition procarray.c:3192
Definition proc.h:179

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

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(), pg_stat_reset_backend_stats(), pgstat_fetch_stat_backend_by_pid(), TerminateBackgroundWorkersForDatabase(), TerminateOtherDBBackends(), and test_shm_mq_main().

◆ BackendPidGetProcWithLock()

PGPROC * BackendPidGetProcWithLock ( int  pid)

Definition at line 3192 of file procarray.c.

3193{
3194 PGPROC *result = NULL;
3196 int index;
3197
3198 if (pid == 0) /* never match dummy PGPROCs */
3199 return NULL;
3200
3201 for (index = 0; index < arrayP->numProcs; index++)
3202 {
3203 PGPROC *proc = &allProcs[arrayP->pgprocnos[index]];
3204
3205 if (proc->pid == pid)
3206 {
3207 result = proc;
3208 break;
3209 }
3210 }
3211
3212 return result;
3213}
static PGPROC * allProcs
Definition procarray.c:285
static ProcArrayStruct * procArray
Definition procarray.c:111
int pid
Definition proc.h:197
Definition type.h:96

References allProcs, fb(), PGPROC::pid, procArray, and result.

Referenced by BackendPidGetProc(), and GetBlockerStatusData().

◆ BackendXidGetPid()

int BackendXidGetPid ( TransactionId  xid)

Definition at line 3229 of file procarray.c.

3230{
3231 int result = 0;
3234 int index;
3235
3236 if (xid == InvalidTransactionId) /* never match invalid xid */
3237 return 0;
3238
3240
3241 for (index = 0; index < arrayP->numProcs; index++)
3242 {
3243 if (other_xids[index] == xid)
3244 {
3245 int pgprocno = arrayP->pgprocnos[index];
3246 PGPROC *proc = &allProcs[pgprocno];
3247
3248 result = proc->pid;
3249 break;
3250 }
3251 }
3252
3254
3255 return result;
3256}
uint32 TransactionId
Definition c.h:736
PROC_HDR * ProcGlobal
Definition proc.c:74
TransactionId * xids
Definition proc.h:444
#define InvalidTransactionId
Definition transam.h:31

References allProcs, fb(), InvalidTransactionId, LW_SHARED, LWLockAcquire(), LWLockRelease(), PGPROC::pid, procArray, ProcGlobal, result, and PROC_HDR::xids.

Referenced by pgrowlocks().

◆ ComputeXidHorizons()

static void ComputeXidHorizons ( ComputeXidHorizonsResult h)
static

Definition at line 1674 of file procarray.c.

1675{
1680
1681 /* inferred after ProcArrayLock is released */
1683
1685
1687
1688 /*
1689 * We initialize the MIN() calculation with latestCompletedXid + 1. This
1690 * is a lower bound for the XIDs that might appear in the ProcArray later,
1691 * and so protects us against overestimating the result due to future
1692 * additions.
1693 */
1694 {
1696
1700
1704
1705 /*
1706 * Only modifications made by this backend affect the horizon for
1707 * temporary relations. Instead of a check in each iteration of the
1708 * loop over all PGPROCs it is cheaper to just initialize to the
1709 * current top-level xid any.
1710 *
1711 * Without an assigned xid we could use a horizon as aggressive as
1712 * GetNewTransactionId(), but we can get away with the much cheaper
1713 * latestCompletedXid + 1: If this backend has no xid there, by
1714 * definition, can't be any newer changes in the temp table than
1715 * latestCompletedXid.
1716 */
1719 else
1721 }
1722
1723 /*
1724 * Fetch slot horizons while ProcArrayLock is held - the
1725 * LWLockAcquire/LWLockRelease are a barrier, ensuring this happens inside
1726 * the lock.
1727 */
1730
1731 for (int index = 0; index < arrayP->numProcs; index++)
1732 {
1733 int pgprocno = arrayP->pgprocnos[index];
1734 PGPROC *proc = &allProcs[pgprocno];
1735 int8 statusFlags = ProcGlobal->statusFlags[index];
1736 TransactionId xid;
1737 TransactionId xmin;
1738
1739 /* Fetch xid just once - see GetNewTransactionId */
1741 xmin = UINT32_ACCESS_ONCE(proc->xmin);
1742
1743 /*
1744 * Consider both the transaction's Xmin, and its Xid.
1745 *
1746 * We must check both because a transaction might have an Xmin but not
1747 * (yet) an Xid; conversely, if it has an Xid, that could determine
1748 * some not-yet-set Xmin.
1749 */
1750 xmin = TransactionIdOlder(xmin, xid);
1751
1752 /* if neither is set, this proc doesn't influence the horizon */
1753 if (!TransactionIdIsValid(xmin))
1754 continue;
1755
1756 /*
1757 * Don't ignore any procs when determining which transactions might be
1758 * considered running. While slots should ensure logical decoding
1759 * backends are protected even without this check, it can't hurt to
1760 * include them here as well..
1761 */
1764
1765 /*
1766 * Skip over backends either vacuuming (which is ok with rows being
1767 * removed, as long as pg_subtrans is not truncated) or doing logical
1768 * decoding (which manages xmin separately, check below).
1769 */
1770 if (statusFlags & (PROC_IN_VACUUM | PROC_IN_LOGICAL_DECODING))
1771 continue;
1772
1773 /* shared tables need to take backends in all databases into account */
1776
1777 /*
1778 * Normally sessions in other databases are ignored for anything but
1779 * the shared horizon.
1780 *
1781 * However, include them when MyDatabaseId is not (yet) set. A
1782 * backend in the process of starting up must not compute a "too
1783 * aggressive" horizon, otherwise we could end up using it to prune
1784 * still-needed data away. If the current backend never connects to a
1785 * database this is harmless, because data_oldest_nonremovable will
1786 * never be utilized.
1787 *
1788 * Also, sessions marked with PROC_AFFECTS_ALL_HORIZONS should always
1789 * be included. (This flag is used for hot standby feedback, which
1790 * can't be tied to a specific database.)
1791 *
1792 * Also, while in recovery we cannot compute an accurate per-database
1793 * horizon, as all xids are managed via the KnownAssignedXids
1794 * machinery.
1795 */
1796 if (proc->databaseId == MyDatabaseId ||
1798 (statusFlags & PROC_AFFECTS_ALL_HORIZONS) ||
1800 {
1803 }
1804 }
1805
1806 /*
1807 * If in recovery fetch oldest xid in KnownAssignedXids, will be applied
1808 * after lock is released.
1809 */
1810 if (in_recovery)
1812
1813 /*
1814 * No other information from shared state is needed, release the lock
1815 * immediately. The rest of the computations can be done without a lock.
1816 */
1818
1819 if (in_recovery)
1820 {
1827 /* temp relations cannot be accessed in recovery */
1828 }
1829
1834
1835 /*
1836 * Check whether there are replication slots requiring an older xmin.
1837 */
1842
1843 /*
1844 * The only difference between catalog / data horizons is that the slot's
1845 * catalog xmin is applied to the catalog one (so catalogs can be accessed
1846 * for logical decoding). Initialize with data horizon, and then back up
1847 * further if necessary. Have to back up the shared horizon as well, since
1848 * that also can contain catalogs.
1849 */
1858
1859 /*
1860 * It's possible that slots backed up the horizons further than
1861 * oldest_considered_running. Fix.
1862 */
1872
1873 /*
1874 * shared horizons have to be at least as old as the oldest visible in
1875 * current db
1876 */
1881
1882 /*
1883 * Horizons need to ensure that pg_subtrans access is still possible for
1884 * the relevant backends.
1885 */
1896 h->slot_xmin));
1899 h->slot_catalog_xmin));
1900
1901 /* update approximate horizons with the computed horizons */
1903}
#define Assert(condition)
Definition c.h:943
int8_t int8
Definition c.h:618
Oid MyDatabaseId
Definition globals.c:96
#define InvalidOid
#define PROC_IN_LOGICAL_DECODING
Definition proc.h:65
#define PROC_AFFECTS_ALL_HORIZONS
Definition proc.h:66
#define PROC_IN_VACUUM
Definition proc.h:62
#define UINT32_ACCESS_ONCE(var)
Definition procarray.c:73
static void GlobalVisUpdateApply(ComputeXidHorizonsResult *horizons)
Definition procarray.c:4186
static TransactionId KnownAssignedXidsGetOldestXmin(void)
Definition procarray.c:5236
PGPROC * MyProc
Definition proc.c:71
TransactionId slot_catalog_xmin
Definition procarray.c:209
TransactionId data_oldest_nonremovable
Definition procarray.c:254
TransactionId temp_oldest_nonremovable
Definition procarray.c:260
TransactionId shared_oldest_nonremovable
Definition procarray.c:231
TransactionId oldest_considered_running
Definition procarray.c:222
TransactionId slot_xmin
Definition procarray.c:208
FullTransactionId latest_completed
Definition procarray.c:202
TransactionId catalog_oldest_nonremovable
Definition procarray.c:248
TransactionId shared_oldest_nonremovable_raw
Definition procarray.c:242
TransactionId xmin
Definition proc.h:242
Oid databaseId
Definition proc.h:201
TransactionId xid
Definition proc.h:237
uint8 * statusFlags
Definition proc.h:456
TransactionId replication_slot_xmin
Definition procarray.c:99
TransactionId replication_slot_catalog_xmin
Definition procarray.c:101
FullTransactionId latestCompletedXid
Definition transam.h:238
static bool TransactionIdPrecedesOrEquals(TransactionId id1, TransactionId id2)
Definition transam.h:282
#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:394
TransamVariablesData * TransamVariables
Definition varsup.c:37
bool RecoveryInProgress(void)
Definition xlog.c:6830

References allProcs, Assert, ComputeXidHorizonsResult::catalog_oldest_nonremovable, ComputeXidHorizonsResult::data_oldest_nonremovable, PGPROC::databaseId, fb(), GlobalVisUpdateApply(), InvalidOid, InvalidTransactionId, KnownAssignedXidsGetOldestXmin(), ComputeXidHorizonsResult::latest_completed, TransamVariablesData::latestCompletedXid, LW_SHARED, LWLockAcquire(), LWLockRelease(), MyDatabaseId, MyProc, ComputeXidHorizonsResult::oldest_considered_running, 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 3642 of file procarray.c.

3643{
3645 int count = 0;
3646 int index;
3647
3649
3650 for (index = 0; index < arrayP->numProcs; index++)
3651 {
3652 int pgprocno = arrayP->pgprocnos[index];
3653 PGPROC *proc = &allProcs[pgprocno];
3654
3655 if (proc->pid == 0)
3656 continue; /* do not count prepared xacts */
3657 if (!OidIsValid(databaseid) ||
3658 proc->databaseId == databaseid)
3659 count++;
3660 }
3661
3663
3664 return count;
3665}
#define OidIsValid(objectId)
Definition c.h:858

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

Referenced by ResolveRecoveryConflictWithDatabase().

◆ CountDBConnections()

int CountDBConnections ( Oid  databaseid)

Definition at line 3671 of file procarray.c.

3672{
3674 int count = 0;
3675 int index;
3676
3678
3679 for (index = 0; index < arrayP->numProcs; index++)
3680 {
3681 int pgprocno = arrayP->pgprocnos[index];
3682 PGPROC *proc = &allProcs[pgprocno];
3683
3684 if (proc->pid == 0)
3685 continue; /* do not count prepared xacts */
3686 if (proc->backendType != B_BACKEND)
3687 continue; /* count only regular backend processes */
3688 if (!OidIsValid(databaseid) ||
3689 proc->databaseId == databaseid)
3690 count++;
3691 }
3692
3694
3695 return count;
3696}
@ B_BACKEND
Definition miscadmin.h:354
BackendType backendType
Definition proc.h:198

References allProcs, B_BACKEND, PGPROC::backendType, PGPROC::databaseId, fb(), LW_SHARED, LWLockAcquire(), LWLockRelease(), OidIsValid, PGPROC::pid, and procArray.

Referenced by CheckMyDatabase().

◆ CountOtherDBBackends()

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

Definition at line 3755 of file procarray.c.

3756{
3758
3759#define MAXAUTOVACPIDS 10 /* max autovacs to SIGTERM per iteration */
3761
3762 /*
3763 * Retry up to 50 times with 100ms between attempts (max 5s total). Can be
3764 * reduced to 3 attempts (max 0.3s total) to speed up tests.
3765 */
3766 int ntries = 50;
3767
3768#ifdef USE_INJECTION_POINTS
3769 if (IS_INJECTION_POINT_ATTACHED("procarray-reduce-count"))
3770 ntries = 3;
3771#endif
3772
3773 for (int tries = 0; tries < ntries; tries++)
3774 {
3775 int nautovacs = 0;
3776 bool found = false;
3777 int index;
3778
3780
3781 *nbackends = *nprepared = 0;
3782
3784
3785 for (index = 0; index < arrayP->numProcs; index++)
3786 {
3787 int pgprocno = arrayP->pgprocnos[index];
3788 PGPROC *proc = &allProcs[pgprocno];
3789 uint8 statusFlags = ProcGlobal->statusFlags[index];
3790
3791 if (proc->databaseId != databaseId)
3792 continue;
3793 if (proc == MyProc)
3794 continue;
3795
3796 found = true;
3797
3798 if (proc->pid == 0)
3799 (*nprepared)++;
3800 else
3801 {
3802 (*nbackends)++;
3803 if ((statusFlags & PROC_IS_AUTOVACUUM) &&
3805 autovac_pids[nautovacs++] = proc->pid;
3806 }
3807 }
3808
3810
3811 if (!found)
3812 return false; /* no conflicting backends, so done */
3813
3814 /*
3815 * Send SIGTERM to any conflicting autovacuums before sleeping. We
3816 * postpone this step until after the loop because we don't want to
3817 * hold ProcArrayLock while issuing kill(). We have no idea what might
3818 * block kill() inside the kernel...
3819 */
3820 for (index = 0; index < nautovacs; index++)
3821 (void) kill(autovac_pids[index], SIGTERM); /* ignore any error */
3822
3823 /*
3824 * Terminate all background workers for this database, if they have
3825 * requested it (BGWORKER_INTERRUPTIBLE).
3826 */
3828
3829 /* sleep, then try again */
3830 pg_usleep(100 * 1000L); /* 100ms */
3831 }
3832
3833 return true; /* timed out, still conflicts */
3834}
void TerminateBackgroundWorkersForDatabase(Oid databaseId)
Definition bgworker.c:1427
uint8_t uint8
Definition c.h:622
#define IS_INJECTION_POINT_ATTACHED(name)
#define CHECK_FOR_INTERRUPTS()
Definition miscadmin.h:125
#define PROC_IS_AUTOVACUUM
Definition proc.h:61
#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, fb(), IS_INJECTION_POINT_ATTACHED, kill, LW_SHARED, LWLockAcquire(), LWLockRelease(), MAXAUTOVACPIDS, MyProc, pg_usleep(), PGPROC::pid, PROC_IS_AUTOVACUUM, procArray, ProcGlobal, PROC_HDR::statusFlags, and TerminateBackgroundWorkersForDatabase().

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

◆ CountUserBackends()

int CountUserBackends ( Oid  roleid)

Definition at line 3703 of file procarray.c.

3704{
3706 int count = 0;
3707 int index;
3708
3710
3711 for (index = 0; index < arrayP->numProcs; index++)
3712 {
3713 int pgprocno = arrayP->pgprocnos[index];
3714 PGPROC *proc = &allProcs[pgprocno];
3715
3716 if (proc->pid == 0)
3717 continue; /* do not count prepared xacts */
3718 if (proc->backendType != B_BACKEND)
3719 continue; /* count only regular backend processes */
3720 if (proc->roleId == roleid)
3721 count++;
3722 }
3723
3725
3726 return count;
3727}
Oid roleId
Definition proc.h:202

References allProcs, B_BACKEND, PGPROC::backendType, fb(), LW_SHARED, LWLockAcquire(), LWLockRelease(), PGPROC::pid, procArray, and PGPROC::roleId.

Referenced by InitializeSessionUserId().

◆ ExpireAllKnownAssignedTransactionIds()

void ExpireAllKnownAssignedTransactionIds ( void  )

Definition at line 4551 of file procarray.c.

4552{
4554
4557
4558 /* Reset latestCompletedXid to nextXid - 1 */
4563
4564 /*
4565 * Any transactions that were in-progress were effectively aborted, so
4566 * advance xactCompletionCount.
4567 */
4569
4570 /*
4571 * Reset lastOverflowedXid. Currently, lastOverflowedXid has no use after
4572 * the call of this function. But do this for unification with what
4573 * ExpireOldKnownAssignedTransactionIds() do.
4574 */
4577}
@ LW_EXCLUSIVE
Definition lwlock.h:104
static void KnownAssignedXidsRemovePreceding(TransactionId removeXid)
Definition procarray.c:5088
TransactionId lastOverflowedXid
Definition procarray.c:96
FullTransactionId nextXid
Definition transam.h:220
uint64 xactCompletionCount
Definition transam.h:248
static void FullTransactionIdRetreat(FullTransactionId *dest)
Definition transam.h:103
#define FullTransactionIdIsValid(x)
Definition transam.h:55

References Assert, fb(), FullTransactionIdIsValid, FullTransactionIdRetreat(), InvalidTransactionId, KnownAssignedXidsRemovePreceding(), ProcArrayStruct::lastOverflowedXid, TransamVariablesData::latestCompletedXid, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), TransamVariablesData::nextXid, procArray, TransamVariables, and TransamVariablesData::xactCompletionCount.

Referenced by ShutdownRecoveryTransactionEnvironment().

◆ ExpireOldKnownAssignedTransactionIds()

void ExpireOldKnownAssignedTransactionIds ( TransactionId  xid)

Definition at line 4585 of file procarray.c.

4586{
4588
4590
4591 /* As in ProcArrayEndTransaction, advance latestCompletedXid */
4592 latestXid = xid;
4595
4596 /* ... and xactCompletionCount */
4598
4599 /*
4600 * Reset lastOverflowedXid if we know all transactions that have been
4601 * possibly running are being gone. Not doing so could cause an incorrect
4602 * lastOverflowedXid value, which makes extra snapshots be marked as
4603 * suboverflowed.
4604 */
4609}
static void MaintainLatestCompletedXidRecovery(TransactionId latestXid)
Definition procarray.c:980
#define TransactionIdRetreat(dest)
Definition transam.h:141
static bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition transam.h:263

References fb(), InvalidTransactionId, KnownAssignedXidsRemovePreceding(), ProcArrayStruct::lastOverflowedXid, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MaintainLatestCompletedXidRecovery(), procArray, TransactionIdPrecedes(), TransactionIdRetreat, TransamVariables, and TransamVariablesData::xactCompletionCount.

Referenced by ProcArrayApplyRecoveryInfo().

◆ ExpireTreeKnownAssignedTransactionIds()

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

Definition at line 4525 of file procarray.c.

4527{
4529
4530 /*
4531 * Uses same locking as transaction commit
4532 */
4534
4536
4537 /* As in ProcArrayEndTransaction, advance latestCompletedXid */
4539
4540 /* ... and xactCompletionCount */
4542
4544}
static void KnownAssignedXidsRemoveTree(TransactionId xid, int nsubxids, TransactionId *subxids)
Definition procarray.c:5066
HotStandbyState standbyState
Definition xlogutils.c:53
@ STANDBY_INITIALIZED
Definition xlogutils.h:53

References Assert, fb(), 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 4374 of file procarray.c.

4375{
4377
4380
4381 /* not guaranteed to find issues, but likely to catch mistakes */
4383
4385 + (int32) (xid - rel_xid));
4386}
int32_t int32
Definition c.h:620
#define U64FromFullTransactionId(x)
Definition transam.h:49
static FullTransactionId FullTransactionIdFromU64(uint64 value)
Definition transam.h:81
#define AssertTransactionIdInAllowableRange(xid)
Definition transam.h:361

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

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

◆ GetConflictingVirtualXIDs()

VirtualTransactionId * GetConflictingVirtualXIDs ( TransactionId  limitXmin,
Oid  dbOid 
)

Definition at line 3389 of file procarray.c.

3390{
3393 int count = 0;
3394 int index;
3395
3396 /*
3397 * If first time through, get workspace to remember main XIDs in. We
3398 * malloc it permanently to avoid repeated palloc/pfree overhead. Allow
3399 * result space, remembering room for a terminator.
3400 */
3401 if (vxids == NULL)
3402 {
3404 malloc(sizeof(VirtualTransactionId) * (arrayP->maxProcs + 1));
3405 if (vxids == NULL)
3406 ereport(ERROR,
3408 errmsg("out of memory")));
3409 }
3410
3412
3413 for (index = 0; index < arrayP->numProcs; index++)
3414 {
3415 int pgprocno = arrayP->pgprocnos[index];
3416 PGPROC *proc = &allProcs[pgprocno];
3417
3418 /* Exclude prepared transactions */
3419 if (proc->pid == 0)
3420 continue;
3421
3422 if (!OidIsValid(dbOid) ||
3423 proc->databaseId == dbOid)
3424 {
3425 /* Fetch xmin just once - can't change on us, but good coding */
3427
3428 /*
3429 * We ignore an invalid pxmin because this means that backend has
3430 * no snapshot currently. We hold a Share lock to avoid contention
3431 * with users taking snapshots. That is not a problem because the
3432 * current xmin is always at least one higher than the latest
3433 * removed xid, so any new snapshot would never conflict with the
3434 * test here.
3435 */
3438 {
3440
3441 GET_VXID_FROM_PGPROC(vxid, *proc);
3443 vxids[count++] = vxid;
3444 }
3445 }
3446 }
3447
3449
3450 /* add the terminator */
3451 vxids[count].procNumber = INVALID_PROC_NUMBER;
3452 vxids[count].localTransactionId = InvalidLocalTransactionId;
3453
3454 return vxids;
3455}
int errcode(int sqlerrcode)
Definition elog.c:874
#define ERROR
Definition elog.h:39
#define ereport(elevel,...)
Definition elog.h:151
#define VirtualTransactionIdIsValid(vxid)
Definition lock.h:70
#define GET_VXID_FROM_PGPROC(vxid_dst, proc)
Definition lock.h:80
#define InvalidLocalTransactionId
Definition lock.h:68
static char * errmsg
#define INVALID_PROC_NUMBER
Definition procnumber.h:26
#define malloc(a)
static bool TransactionIdFollows(TransactionId id1, TransactionId id2)
Definition transam.h:297

References allProcs, PGPROC::databaseId, ereport, errcode(), errmsg, ERROR, fb(), GET_VXID_FROM_PGPROC, INVALID_PROC_NUMBER, InvalidLocalTransactionId, LW_SHARED, LWLockAcquire(), LWLockRelease(), malloc, OidIsValid, PGPROC::pid, procArray, 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 3297 of file procarray.c.

3300{
3303 int count = 0;
3304 int index;
3305
3306 /* allocate what's certainly enough result space */
3308
3310
3311 for (index = 0; index < arrayP->numProcs; index++)
3312 {
3313 int pgprocno = arrayP->pgprocnos[index];
3314 PGPROC *proc = &allProcs[pgprocno];
3315 uint8 statusFlags = ProcGlobal->statusFlags[index];
3316
3317 if (proc == MyProc)
3318 continue;
3319
3320 if (excludeVacuum & statusFlags)
3321 continue;
3322
3323 if (allDbs || proc->databaseId == MyDatabaseId)
3324 {
3325 /* Fetch xmin just once - might change on us */
3327
3329 continue;
3330
3331 /*
3332 * InvalidTransactionId precedes all other XIDs, so a proc that
3333 * hasn't set xmin yet will not be rejected by this test.
3334 */
3337 {
3339
3340 GET_VXID_FROM_PGPROC(vxid, *proc);
3342 vxids[count++] = vxid;
3343 }
3344 }
3345 }
3346
3348
3349 *nvxids = count;
3350 return vxids;
3351}
#define palloc_array(type, count)
Definition fe_memutils.h:76

References allProcs, PGPROC::databaseId, fb(), GET_VXID_FROM_PGPROC, LW_SHARED, LWLockAcquire(), LWLockRelease(), MyDatabaseId, MyProc, palloc_array, procArray, ProcGlobal, PROC_HDR::statusFlags, TransactionIdIsValid, TransactionIdPrecedesOrEquals(), UINT32_ACCESS_ONCE, VirtualTransactionIdIsValid, and PGPROC::xmin.

Referenced by WaitForOlderSnapshots().

◆ GetMaxSnapshotSubxidCount()

int GetMaxSnapshotSubxidCount ( void  )

Definition at line 2019 of file procarray.c.

2020{
2022}
#define TOTAL_MAX_CACHED_SUBXIDS

References TOTAL_MAX_CACHED_SUBXIDS.

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

◆ GetMaxSnapshotXidCount()

int GetMaxSnapshotXidCount ( void  )

Definition at line 2008 of file procarray.c.

2009{
2010 return procArray->maxProcs;
2011}

References ProcArrayStruct::maxProcs, and procArray.

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

◆ GetOldestActiveTransactionId()

TransactionId GetOldestActiveTransactionId ( bool  inCommitOnly,
bool  allDbs 
)

Definition at line 2845 of file procarray.c.

2846{
2849 TransactionId oldestRunningXid;
2850 int index;
2851
2853
2854 /*
2855 * Read nextXid, as the upper bound of what's still active.
2856 *
2857 * Reading a TransactionId is atomic, but we must grab the lock to make
2858 * sure that all XIDs < nextXid are already present in the proc array (or
2859 * have already completed), when we spin over it.
2860 */
2864
2865 /*
2866 * Spin over procArray collecting all xids and subxids.
2867 */
2869 for (index = 0; index < arrayP->numProcs; index++)
2870 {
2871 TransactionId xid;
2872 int pgprocno = arrayP->pgprocnos[index];
2873 PGPROC *proc = &allProcs[pgprocno];
2874
2875 /* Fetch xid just once - see GetNewTransactionId */
2877
2878 if (!TransactionIdIsNormal(xid))
2879 continue;
2880
2881 if (inCommitOnly &&
2883 continue;
2884
2885 if (!allDbs && proc->databaseId != MyDatabaseId)
2886 continue;
2887
2888 if (TransactionIdPrecedes(xid, oldestRunningXid))
2889 oldestRunningXid = xid;
2890
2891 /*
2892 * Top-level XID of a transaction is always less than any of its
2893 * subxids, so we don't need to check if any of the subxids are
2894 * smaller than oldestRunningXid
2895 */
2896 }
2898
2899 return oldestRunningXid;
2900}
#define DELAY_CHKPT_IN_COMMIT
Definition proc.h:141
int delayChkptFlags
Definition proc.h:260
#define TransactionIdIsNormal(xid)
Definition transam.h:42

References allProcs, Assert, PGPROC::databaseId, DELAY_CHKPT_IN_COMMIT, PGPROC::delayChkptFlags, fb(), LW_SHARED, LWLockAcquire(), LWLockRelease(), MyDatabaseId, TransamVariablesData::nextXid, procArray, ProcGlobal, RecoveryInProgress(), TransactionIdIsNormal, TransactionIdPrecedes(), TransamVariables, UINT32_ACCESS_ONCE, XidFromFullTransactionId, and PROC_HDR::xids.

Referenced by CreateCheckPoint(), get_candidate_xid(), ProcessStandbyPSRequestMessage(), and WaitForAllTransactionsToFinish().

◆ GetOldestNonRemovableTransactionId()

TransactionId GetOldestNonRemovableTransactionId ( Relation  rel)

Definition at line 1944 of file procarray.c.

1945{
1947
1949
1950 switch (GlobalVisHorizonKindForRel(rel))
1951 {
1952 case VISHORIZON_SHARED:
1953 return horizons.shared_oldest_nonremovable;
1954 case VISHORIZON_CATALOG:
1955 return horizons.catalog_oldest_nonremovable;
1956 case VISHORIZON_DATA:
1957 return horizons.data_oldest_nonremovable;
1958 case VISHORIZON_TEMP:
1959 return horizons.temp_oldest_nonremovable;
1960 }
1961
1962 /* just to prevent compiler warnings */
1963 return InvalidTransactionId;
1964}
static void ComputeXidHorizons(ComputeXidHorizonsResult *h)
Definition procarray.c:1674
static GlobalVisHorizonKind GlobalVisHorizonKindForRel(Relation rel)
Definition procarray.c:1910

References ComputeXidHorizons(), fb(), GlobalVisHorizonKindForRel(), InvalidTransactionId, VISHORIZON_CATALOG, VISHORIZON_DATA, VISHORIZON_SHARED, and VISHORIZON_TEMP.

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

◆ GetOldestSafeDecodingTransactionId()

TransactionId GetOldestSafeDecodingTransactionId ( bool  catalogOnly)

Definition at line 2919 of file procarray.c.

2920{
2923 int index;
2925
2927
2928 /*
2929 * Acquire XidGenLock, so no transactions can acquire an xid while we're
2930 * running. If no transaction with xid were running concurrently a new xid
2931 * could influence the RecentXmin et al.
2932 *
2933 * We initialize the computation to nextXid since that's guaranteed to be
2934 * a safe, albeit pessimal, value.
2935 */
2938
2939 /*
2940 * If there's already a slot pegging the xmin horizon, we can start with
2941 * that value, it's guaranteed to be safe since it's computed by this
2942 * routine initially and has been enforced since. We can always use the
2943 * slot's general xmin horizon, but the catalog horizon is only usable
2944 * when only catalog data is going to be looked at.
2945 */
2950
2951 if (catalogOnly &&
2956
2957 /*
2958 * If we're not in recovery, we walk over the procarray and collect the
2959 * lowest xid. Since we're called with ProcArrayLock held and have
2960 * acquired XidGenLock, no entries can vanish concurrently, since
2961 * ProcGlobal->xids[i] is only set with XidGenLock held and only cleared
2962 * with ProcArrayLock held.
2963 *
2964 * In recovery we can't lower the safe value besides what we've computed
2965 * above, so we'll have to wait a bit longer there. We unfortunately can
2966 * *not* use KnownAssignedXidsGetOldestXmin() since the KnownAssignedXids
2967 * machinery can miss values and return an older value than is safe.
2968 */
2970 {
2972
2973 /*
2974 * Spin over procArray collecting min(ProcGlobal->xids[i])
2975 */
2976 for (index = 0; index < arrayP->numProcs; index++)
2977 {
2978 TransactionId xid;
2979
2980 /* Fetch xid just once - see GetNewTransactionId */
2982
2983 if (!TransactionIdIsNormal(xid))
2984 continue;
2985
2987 oldestSafeXid = xid;
2988 }
2989 }
2990
2992
2993 return oldestSafeXid;
2994}
bool LWLockHeldByMe(LWLock *lock)
Definition lwlock.c:1885

References Assert, fb(), LW_SHARED, LWLockAcquire(), LWLockHeldByMe(), LWLockRelease(), TransamVariablesData::nextXid, 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(), init_conflict_slot_xmin(), SnapBuildInitialSnapshot(), and synchronize_one_slot().

◆ GetOldestTransactionIdConsideredRunning()

TransactionId GetOldestTransactionIdConsideredRunning ( void  )

Definition at line 1973 of file procarray.c.

1974{
1976
1978
1979 return horizons.oldest_considered_running;
1980}

References ComputeXidHorizons(), and fb().

Referenced by CreateCheckPoint(), and CreateRestartPoint().

◆ GetReplicationHorizons()

void GetReplicationHorizons ( TransactionId xmin,
TransactionId catalog_xmin 
)

Definition at line 1986 of file procarray.c.

1987{
1989
1991
1992 /*
1993 * Don't want to use shared_oldest_nonremovable here, as that contains the
1994 * effect of replication slot's catalog_xmin. We want to send a separate
1995 * feedback for the catalog horizon, so the primary can remove data table
1996 * contents more aggressively.
1997 */
1998 *xmin = horizons.shared_oldest_nonremovable_raw;
1999 *catalog_xmin = horizons.slot_catalog_xmin;
2000}

References ComputeXidHorizons(), and fb().

Referenced by XLogWalRcvSendHSFeedback().

◆ GetRunningTransactionData()

RunningTransactions GetRunningTransactionData ( Oid  dbid)

Definition at line 2630 of file procarray.c.

2631{
2632 /* result workspace */
2634
2638 TransactionId latestCompletedXid;
2639 TransactionId oldestRunningXid;
2640 TransactionId oldestDatabaseRunningXid;
2641 TransactionId *xids;
2642 int index;
2643 int count;
2644 int subcount;
2645 bool suboverflowed;
2646
2648
2649 /*
2650 * Allocating space for maxProcs xids is usually overkill; numProcs would
2651 * be sufficient. But it seems better to do the malloc while not holding
2652 * the lock, so we can't look at numProcs. Likewise, we allocate much
2653 * more subxip storage than is probably needed.
2654 *
2655 * Should only be allocated in bgwriter, since only ever executed during
2656 * checkpoints.
2657 */
2658 if (CurrentRunningXacts->xids == NULL)
2659 {
2660 /*
2661 * First call
2662 */
2665 if (CurrentRunningXacts->xids == NULL)
2666 ereport(ERROR,
2668 errmsg("out of memory")));
2669 }
2670
2671 xids = CurrentRunningXacts->xids;
2672
2673 count = subcount = 0;
2674 suboverflowed = false;
2675
2676 /*
2677 * Ensure that no xids enter or leave the procarray while we obtain
2678 * snapshot.
2679 */
2682
2683 latestCompletedXid =
2685 oldestDatabaseRunningXid = oldestRunningXid =
2687
2688 /*
2689 * Spin over procArray collecting all xids
2690 */
2691 for (index = 0; index < arrayP->numProcs; index++)
2692 {
2693 TransactionId xid;
2694
2695 /* Fetch xid just once - see GetNewTransactionId */
2697
2698 /*
2699 * We don't need to store transactions that don't have a TransactionId
2700 * yet because they will not show as running on a standby server.
2701 */
2702 if (!TransactionIdIsValid(xid))
2703 continue;
2704
2705 /*
2706 * Filter by database OID if requested.
2707 */
2708 if (OidIsValid(dbid))
2709 {
2710 int pgprocno = arrayP->pgprocnos[index];
2711 PGPROC *proc = &allProcs[pgprocno];
2712
2713 if (proc->databaseId != dbid)
2714 continue;
2715 }
2716
2717 /*
2718 * Be careful not to exclude any xids before calculating the values of
2719 * oldestRunningXid and suboverflowed, since these are used to clean
2720 * up transaction information held on standbys.
2721 */
2722 if (TransactionIdPrecedes(xid, oldestRunningXid))
2723 oldestRunningXid = xid;
2724
2725 /*
2726 * Also, update the oldest running xid within the current database. As
2727 * fetching pgprocno and PGPROC could cause cache misses, we do cheap
2728 * TransactionId comparison first.
2729 */
2730 if (TransactionIdPrecedes(xid, oldestDatabaseRunningXid))
2731 {
2732 int pgprocno = arrayP->pgprocnos[index];
2733 PGPROC *proc = &allProcs[pgprocno];
2734
2735 if (proc->databaseId == MyDatabaseId)
2736 oldestDatabaseRunningXid = xid;
2737 }
2738
2740 suboverflowed = true;
2741
2742 /*
2743 * If we wished to exclude xids this would be the right place for it.
2744 * Procs with the PROC_IN_VACUUM flag set don't usually assign xids,
2745 * but they do during truncation at the end when they get the lock and
2746 * truncate, so it is not much of a problem to include them if they
2747 * are seen and it is cleaner to include them.
2748 */
2749
2750 xids[count++] = xid;
2751 }
2752
2753 /*
2754 * Spin over procArray collecting all subxids, but only if there hasn't
2755 * been a suboverflow.
2756 */
2757 if (!suboverflowed)
2758 {
2760
2761 for (index = 0; index < arrayP->numProcs; index++)
2762 {
2763 int pgprocno = arrayP->pgprocnos[index];
2764 PGPROC *proc = &allProcs[pgprocno];
2765 int nsubxids;
2766
2767 /*
2768 * Filter by database OID if requested.
2769 */
2770 if (OidIsValid(dbid) && proc->databaseId != dbid)
2771 continue;
2772
2773 /*
2774 * Save subtransaction XIDs. Other backends can't add or remove
2775 * entries while we're holding XidGenLock.
2776 */
2778 if (nsubxids > 0)
2779 {
2780 /* barrier not really required, as XidGenLock is held, but ... */
2781 pg_read_barrier(); /* pairs with GetNewTransactionId */
2782
2783 memcpy(&xids[count], proc->subxids.xids,
2784 nsubxids * sizeof(TransactionId));
2785 count += nsubxids;
2786 subcount += nsubxids;
2787
2788 /*
2789 * Top-level XID of a transaction is always less than any of
2790 * its subxids, so we don't need to check if any of the
2791 * subxids are smaller than oldestRunningXid
2792 */
2793 }
2794 }
2795 }
2796
2797 /*
2798 * It's important *not* to include the limits set by slots here because
2799 * snapbuild.c uses oldestRunningXid to manage its xmin horizon. If those
2800 * were to be included here the initial value could never increase because
2801 * of a circular dependency where slots only increase their limits when
2802 * running xacts increases oldestRunningXid and running xacts only
2803 * increases if slots do.
2804 */
2805
2806 CurrentRunningXacts->dbid = dbid;
2807 CurrentRunningXacts->xcnt = count - subcount;
2808 CurrentRunningXacts->subxcnt = subcount;
2809 CurrentRunningXacts->subxid_status = suboverflowed ? SUBXIDS_IN_SUBTRANS : SUBXIDS_IN_ARRAY;
2811 CurrentRunningXacts->oldestRunningXid = oldestRunningXid;
2812 CurrentRunningXacts->oldestDatabaseRunningXid = oldestDatabaseRunningXid;
2813 CurrentRunningXacts->latestCompletedXid = latestCompletedXid;
2814
2817 Assert(TransactionIdIsNormal(CurrentRunningXacts->latestCompletedXid));
2818
2819 /* We don't release the locks here, the caller is responsible for that */
2820
2821 return CurrentRunningXacts;
2822}
#define pg_read_barrier()
Definition atomics.h:154
memcpy(sums, checksumBaseOffsets, sizeof(checksumBaseOffsets))
@ SUBXIDS_IN_SUBTRANS
Definition standby.h:123
@ SUBXIDS_IN_ARRAY
Definition standby.h:121
struct XidCache subxids
Definition proc.h:249
XidCacheStatus * subxidStates
Definition proc.h:450
bool overflowed
Definition proc.h:50
TransactionId xids[PGPROC_MAX_CACHED_SUBXIDS]
Definition proc.h:55

References allProcs, Assert, PGPROC::databaseId, ereport, errcode(), errmsg, ERROR, fb(), TransamVariablesData::latestCompletedXid, LW_SHARED, LWLockAcquire(), malloc, memcpy(), MyDatabaseId, TransamVariablesData::nextXid, OidIsValid, XidCacheStatus::overflowed, pg_read_barrier, procArray, ProcGlobal, RecoveryInProgress(), PGPROC::subxids, SUBXIDS_IN_ARRAY, SUBXIDS_IN_SUBTRANS, PROC_HDR::subxidStates, TOTAL_MAX_CACHED_SUBXIDS, TransactionIdIsNormal, TransactionIdIsValid, TransactionIdPrecedes(), TransamVariables, UINT32_ACCESS_ONCE, XidFromFullTransactionId, XidCache::xids, and PROC_HDR::xids.

Referenced by GetStrictOldestNonRemovableTransactionId(), and LogStandbySnapshot().

◆ GetSnapshotData()

Snapshot GetSnapshotData ( Snapshot  snapshot)

Definition at line 2114 of file procarray.c.

2115{
2118 TransactionId xmin;
2119 TransactionId xmax;
2120 int count = 0;
2121 int subcount = 0;
2122 bool suboverflowed = false;
2123 FullTransactionId latest_completed;
2125 int mypgxactoff;
2128
2129 TransactionId replication_slot_xmin = InvalidTransactionId;
2130 TransactionId replication_slot_catalog_xmin = InvalidTransactionId;
2131
2132 Assert(snapshot != NULL);
2133
2134 /*
2135 * Allocating space for maxProcs xids is usually overkill; numProcs would
2136 * be sufficient. But it seems better to do the malloc while not holding
2137 * the lock, so we can't look at numProcs. Likewise, we allocate much
2138 * more subxip storage than is probably needed.
2139 *
2140 * This does open a possibility for avoiding repeated malloc/free: since
2141 * maxProcs does not change at runtime, we can simply reuse the previous
2142 * xip arrays if any. (This relies on the fact that all callers pass
2143 * static SnapshotData structs.)
2144 */
2145 if (snapshot->xip == NULL)
2146 {
2147 /*
2148 * First call for this snapshot. Snapshot is same size whether or not
2149 * we are in recovery, see later comments.
2150 */
2151 snapshot->xip = (TransactionId *)
2153 if (snapshot->xip == NULL)
2154 ereport(ERROR,
2156 errmsg("out of memory")));
2157 Assert(snapshot->subxip == NULL);
2158 snapshot->subxip = (TransactionId *)
2160 if (snapshot->subxip == NULL)
2161 ereport(ERROR,
2163 errmsg("out of memory")));
2164 }
2165
2166 /*
2167 * It is sufficient to get shared lock on ProcArrayLock, even if we are
2168 * going to set MyProc->xmin.
2169 */
2171
2172 if (GetSnapshotDataReuse(snapshot))
2173 {
2175 return snapshot;
2176 }
2177
2178 latest_completed = TransamVariables->latestCompletedXid;
2181 Assert(myxid == MyProc->xid);
2182
2185
2186 /* xmax is always latestCompletedXid + 1 */
2187 xmax = XidFromFullTransactionId(latest_completed);
2190
2191 /* initialize xmin calculation with xmax */
2192 xmin = xmax;
2193
2194 /* take own xid into account, saves a check inside the loop */
2196 xmin = myxid;
2197
2199
2200 if (!snapshot->takenDuringRecovery)
2201 {
2202 int numProcs = arrayP->numProcs;
2203 TransactionId *xip = snapshot->xip;
2204 int *pgprocnos = arrayP->pgprocnos;
2205 XidCacheStatus *subxidStates = ProcGlobal->subxidStates;
2207
2208 /*
2209 * First collect set of pgxactoff/xids that need to be included in the
2210 * snapshot.
2211 */
2212 for (int pgxactoff = 0; pgxactoff < numProcs; pgxactoff++)
2213 {
2214 /* Fetch xid just once - see GetNewTransactionId */
2216 uint8 statusFlags;
2217
2218 Assert(allProcs[arrayP->pgprocnos[pgxactoff]].pgxactoff == pgxactoff);
2219
2220 /*
2221 * If the transaction has no XID assigned, we can skip it; it
2222 * won't have sub-XIDs either.
2223 */
2224 if (likely(xid == InvalidTransactionId))
2225 continue;
2226
2227 /*
2228 * We don't include our own XIDs (if any) in the snapshot. It
2229 * needs to be included in the xmin computation, but we did so
2230 * outside the loop.
2231 */
2232 if (pgxactoff == mypgxactoff)
2233 continue;
2234
2235 /*
2236 * The only way we are able to get here with a non-normal xid is
2237 * during bootstrap - with this backend using
2238 * BootstrapTransactionId. But the above test should filter that
2239 * out.
2240 */
2242
2243 /*
2244 * If the XID is >= xmax, we can skip it; such transactions will
2245 * be treated as running anyway (and any sub-XIDs will also be >=
2246 * xmax).
2247 */
2248 if (!NormalTransactionIdPrecedes(xid, xmax))
2249 continue;
2250
2251 /*
2252 * Skip over backends doing logical decoding which manages xmin
2253 * separately (check below) and ones running LAZY VACUUM.
2254 */
2255 statusFlags = allStatusFlags[pgxactoff];
2256 if (statusFlags & (PROC_IN_LOGICAL_DECODING | PROC_IN_VACUUM))
2257 continue;
2258
2259 if (NormalTransactionIdPrecedes(xid, xmin))
2260 xmin = xid;
2261
2262 /* Add XID to snapshot. */
2263 xip[count++] = xid;
2264
2265 /*
2266 * Save subtransaction XIDs if possible (if we've already
2267 * overflowed, there's no point). Note that the subxact XIDs must
2268 * be later than their parent, so no need to check them against
2269 * xmin. We could filter against xmax, but it seems better not to
2270 * do that much work while holding the ProcArrayLock.
2271 *
2272 * The other backend can add more subxids concurrently, but cannot
2273 * remove any. Hence it's important to fetch nxids just once.
2274 * Should be safe to use memcpy, though. (We needn't worry about
2275 * missing any xids added concurrently, because they must postdate
2276 * xmax.)
2277 *
2278 * Again, our own XIDs are not included in the snapshot.
2279 */
2280 if (!suboverflowed)
2281 {
2282
2283 if (subxidStates[pgxactoff].overflowed)
2284 suboverflowed = true;
2285 else
2286 {
2287 int nsubxids = subxidStates[pgxactoff].count;
2288
2289 if (nsubxids > 0)
2290 {
2291 int pgprocno = pgprocnos[pgxactoff];
2292 PGPROC *proc = &allProcs[pgprocno];
2293
2294 pg_read_barrier(); /* pairs with GetNewTransactionId */
2295
2296 memcpy(snapshot->subxip + subcount,
2297 proc->subxids.xids,
2298 nsubxids * sizeof(TransactionId));
2299 subcount += nsubxids;
2300 }
2301 }
2302 }
2303 }
2304 }
2305 else
2306 {
2307 /*
2308 * We're in hot standby, so get XIDs from KnownAssignedXids.
2309 *
2310 * We store all xids directly into subxip[]. Here's why:
2311 *
2312 * In recovery we don't know which xids are top-level and which are
2313 * subxacts, a design choice that greatly simplifies xid processing.
2314 *
2315 * It seems like we would want to try to put xids into xip[] only, but
2316 * that is fairly small. We would either need to make that bigger or
2317 * to increase the rate at which we WAL-log xid assignment; neither is
2318 * an appealing choice.
2319 *
2320 * We could try to store xids into xip[] first and then into subxip[]
2321 * if there are too many xids. That only works if the snapshot doesn't
2322 * overflow because we do not search subxip[] in that case. A simpler
2323 * way is to just store all xids in the subxip array because this is
2324 * by far the bigger array. We just leave the xip array empty.
2325 *
2326 * Either way we need to change the way XidInMVCCSnapshot() works
2327 * depending upon when the snapshot was taken, or change normal
2328 * snapshot processing so it matches.
2329 *
2330 * Note: It is possible for recovery to end before we finish taking
2331 * the snapshot, and for newly assigned transaction ids to be added to
2332 * the ProcArray. xmax cannot change while we hold ProcArrayLock, so
2333 * those newly added transaction ids would be filtered away, so we
2334 * need not be concerned about them.
2335 */
2337 xmax);
2338
2340 suboverflowed = true;
2341 }
2342
2343
2344 /*
2345 * Fetch into local variable while ProcArrayLock is held - the
2346 * LWLockRelease below is a barrier, ensuring this happens inside the
2347 * lock.
2348 */
2349 replication_slot_xmin = procArray->replication_slot_xmin;
2350 replication_slot_catalog_xmin = procArray->replication_slot_catalog_xmin;
2351
2353 MyProc->xmin = TransactionXmin = xmin;
2354
2356
2357 /* maintain state for GlobalVis* */
2358 {
2364
2365 /*
2366 * Converting oldestXid is only safe when xid horizon cannot advance,
2367 * i.e. holding locks. While we don't hold the lock anymore, all the
2368 * necessary data has been gathered with lock held.
2369 */
2370 oldestfxid = FullXidRelativeTo(latest_completed, oldestxid);
2371
2372 /* Check whether there's a replication slot requiring an older xmin. */
2374 TransactionIdOlder(xmin, replication_slot_xmin);
2375
2376 /*
2377 * Rows in non-shared, non-catalog tables possibly could be vacuumed
2378 * if older than this xid.
2379 */
2381
2382 /*
2383 * Check whether there's a replication slot requiring an older catalog
2384 * xmin.
2385 */
2386 def_vis_xid =
2387 TransactionIdOlder(replication_slot_catalog_xmin, def_vis_xid);
2388
2389 def_vis_fxid = FullXidRelativeTo(latest_completed, def_vis_xid);
2391
2392 /*
2393 * Check if we can increase upper bound. As a previous
2394 * GlobalVisUpdate() might have computed more aggressive values, don't
2395 * overwrite them if so.
2396 */
2406 /* See temp_oldest_nonremovable computation in ComputeXidHorizons() */
2409 FullXidRelativeTo(latest_completed, myxid);
2410 else
2411 {
2412 GlobalVisTempRels.definitely_needed = latest_completed;
2414 }
2415
2416 /*
2417 * Check if we know that we can initialize or increase the lower
2418 * bound. Currently the only cheap way to do so is to use
2419 * TransamVariables->oldestXid as input.
2420 *
2421 * We should definitely be able to do better. We could e.g. put a
2422 * global lower bound value into TransamVariables.
2423 */
2426 oldestfxid);
2429 oldestfxid);
2432 oldestfxid);
2433 /* accurate value known */
2435 }
2436
2437 RecentXmin = xmin;
2439
2440 snapshot->xmin = xmin;
2441 snapshot->xmax = xmax;
2442 snapshot->xcnt = count;
2443 snapshot->subxcnt = subcount;
2444 snapshot->suboverflowed = suboverflowed;
2446
2447 snapshot->curcid = GetCurrentCommandId(false);
2448
2449 /*
2450 * This is a new snapshot, so set both refcounts are zero, and mark it as
2451 * not copied in persistent memory.
2452 */
2453 snapshot->active_count = 0;
2454 snapshot->regd_count = 0;
2455 snapshot->copied = false;
2456
2457 return snapshot;
2458}
#define likely(x)
Definition c.h:437
uint64_t uint64
Definition c.h:625
static GlobalVisState GlobalVisDataRels
Definition procarray.c:316
static GlobalVisState GlobalVisSharedRels
Definition procarray.c:314
static GlobalVisState GlobalVisCatalogRels
Definition procarray.c:315
static FullTransactionId FullXidRelativeTo(FullTransactionId rel, TransactionId xid)
Definition procarray.c:4374
static int KnownAssignedXidsGetAndSetXmin(TransactionId *xarray, TransactionId *xmin, TransactionId xmax)
Definition procarray.c:5180
int GetMaxSnapshotSubxidCount(void)
Definition procarray.c:2019
static GlobalVisState GlobalVisTempRels
Definition procarray.c:317
int GetMaxSnapshotXidCount(void)
Definition procarray.c:2008
static bool GetSnapshotDataReuse(Snapshot snapshot)
Definition procarray.c:2034
TransactionId RecentXmin
Definition snapmgr.c:160
TransactionId TransactionXmin
Definition snapmgr.c:159
FullTransactionId definitely_needed
Definition procarray.c:187
FullTransactionId maybe_needed
Definition procarray.c:190
int pgxactoff
Definition proc.h:207
TransactionId xmin
Definition snapshot.h:153
int32 subxcnt
Definition snapshot.h:177
uint32 regd_count
Definition snapshot.h:201
uint32 active_count
Definition snapshot.h:200
CommandId curcid
Definition snapshot.h:183
uint32 xcnt
Definition snapshot.h:165
TransactionId * subxip
Definition snapshot.h:176
uint64 snapXactCompletionCount
Definition snapshot.h:209
TransactionId xmax
Definition snapshot.h:154
TransactionId * xip
Definition snapshot.h:164
bool suboverflowed
Definition snapshot.h:178
bool takenDuringRecovery
Definition snapshot.h:180
TransactionId oldestXid
Definition transam.h:222
uint8 count
Definition proc.h:48
static FullTransactionId FullTransactionIdNewer(FullTransactionId a, FullTransactionId b)
Definition transam.h:420
#define NormalTransactionIdPrecedes(id1, id2)
Definition transam.h:147
static void FullTransactionIdAdvance(FullTransactionId *dest)
Definition transam.h:128
CommandId GetCurrentCommandId(bool used)
Definition xact.c:831

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

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

◆ GetSnapshotDataReuse()

static bool GetSnapshotDataReuse ( Snapshot  snapshot)
static

Definition at line 2034 of file procarray.c.

2035{
2037
2039
2040 if (unlikely(snapshot->snapXactCompletionCount == 0))
2041 return false;
2042
2045 return false;
2046
2047 /*
2048 * If the current xactCompletionCount is still the same as it was at the
2049 * time the snapshot was built, we can be sure that rebuilding the
2050 * contents of the snapshot the hard way would result in the same snapshot
2051 * contents:
2052 *
2053 * As explained in transam/README, the set of xids considered running by
2054 * GetSnapshotData() cannot change while ProcArrayLock is held. Snapshot
2055 * contents only depend on transactions with xids and xactCompletionCount
2056 * is incremented whenever a transaction with an xid finishes (while
2057 * holding ProcArrayLock exclusively). Thus the xactCompletionCount check
2058 * ensures we would detect if the snapshot would have changed.
2059 *
2060 * As the snapshot contents are the same as it was before, it is safe to
2061 * re-enter the snapshot's xmin into the PGPROC array. None of the rows
2062 * visible under the snapshot could already have been removed (that'd
2063 * require the set of running transactions to change) and it fulfills the
2064 * requirement that concurrent GetSnapshotData() calls yield the same
2065 * xmin.
2066 */
2068 MyProc->xmin = TransactionXmin = snapshot->xmin;
2069
2070 RecentXmin = snapshot->xmin;
2072
2073 snapshot->curcid = GetCurrentCommandId(false);
2074 snapshot->active_count = 0;
2075 snapshot->regd_count = 0;
2076 snapshot->copied = false;
2077
2078 return true;
2079}
#define unlikely(x)
Definition c.h:438

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

Referenced by GetSnapshotData().

◆ GetVirtualXIDsDelayingChkpt()

VirtualTransactionId * GetVirtualXIDsDelayingChkpt ( int nvxids,
int  type 
)

Definition at line 3017 of file procarray.c.

3018{
3021 int count = 0;
3022 int index;
3023
3024 Assert(type != 0);
3025
3026 /* allocate what's certainly enough result space */
3028
3030
3031 for (index = 0; index < arrayP->numProcs; index++)
3032 {
3033 int pgprocno = arrayP->pgprocnos[index];
3034 PGPROC *proc = &allProcs[pgprocno];
3035
3036 if ((proc->delayChkptFlags & type) != 0)
3037 {
3039
3040 GET_VXID_FROM_PGPROC(vxid, *proc);
3042 vxids[count++] = vxid;
3043 }
3044 }
3045
3047
3048 *nvxids = count;
3049 return vxids;
3050}
const char * type

References allProcs, Assert, PGPROC::delayChkptFlags, fb(), GET_VXID_FROM_PGPROC, LW_SHARED, LWLockAcquire(), LWLockRelease(), palloc_array, procArray, type, and VirtualTransactionIdIsValid.

Referenced by CreateCheckPoint().

◆ GlobalVisCheckRemovableFullXid()

bool GlobalVisCheckRemovableFullXid ( Relation  rel,
FullTransactionId  fxid 
)

Definition at line 4339 of file procarray.c.

4340{
4342
4343 state = GlobalVisTestFor(rel);
4344
4345 return GlobalVisTestIsRemovableFullXid(state, fxid, true);
4346}
GlobalVisState * GlobalVisTestFor(Relation rel)
Definition procarray.c:4127
bool GlobalVisTestIsRemovableFullXid(GlobalVisState *state, FullTransactionId fxid, bool allow_update)
Definition procarray.c:4247

References GlobalVisTestFor(), and GlobalVisTestIsRemovableFullXid().

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

◆ GlobalVisCheckRemovableXid()

bool GlobalVisCheckRemovableXid ( Relation  rel,
TransactionId  xid 
)

Definition at line 4353 of file procarray.c.

4354{
4356
4357 state = GlobalVisTestFor(rel);
4358
4359 return GlobalVisTestIsRemovableXid(state, xid, true);
4360}
bool GlobalVisTestIsRemovableXid(GlobalVisState *state, TransactionId xid, bool allow_update)
Definition procarray.c:4290

References GlobalVisTestFor(), and GlobalVisTestIsRemovableXid().

Referenced by GinPageIsRecyclable().

◆ GlobalVisHorizonKindForRel()

static GlobalVisHorizonKind GlobalVisHorizonKindForRel ( Relation  rel)
inlinestatic

Definition at line 1910 of file procarray.c.

1911{
1912 /*
1913 * Other relkinds currently don't contain xids, nor always the necessary
1914 * logical decoding markers.
1915 */
1916 Assert(!rel ||
1917 rel->rd_rel->relkind == RELKIND_RELATION ||
1918 rel->rd_rel->relkind == RELKIND_MATVIEW ||
1919 rel->rd_rel->relkind == RELKIND_TOASTVALUE);
1920
1921 if (rel == NULL || rel->rd_rel->relisshared || RecoveryInProgress())
1922 return VISHORIZON_SHARED;
1923 else if (IsCatalogRelation(rel) ||
1925 return VISHORIZON_CATALOG;
1926 else if (!RELATION_IS_LOCAL(rel))
1927 return VISHORIZON_DATA;
1928 else
1929 return VISHORIZON_TEMP;
1930}
bool IsCatalogRelation(Relation relation)
Definition catalog.c:104
#define RELATION_IS_LOCAL(relation)
Definition rel.h:659
#define RelationIsAccessibleInLogicalDecoding(relation)
Definition rel.h:695
Form_pg_class rd_rel
Definition rel.h:111

References Assert, fb(), 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)

◆ GlobalVisTestIsRemovableFullXid()

bool GlobalVisTestIsRemovableFullXid ( GlobalVisState state,
FullTransactionId  fxid,
bool  allow_update 
)

Definition at line 4247 of file procarray.c.

4250{
4251 /*
4252 * If fxid is older than maybe_needed bound, it definitely is visible to
4253 * everyone.
4254 */
4255 if (FullTransactionIdPrecedes(fxid, state->maybe_needed))
4256 return true;
4257
4258 /*
4259 * If fxid is >= definitely_needed bound, it is very likely to still be
4260 * considered running.
4261 */
4262 if (FullTransactionIdFollowsOrEquals(fxid, state->definitely_needed))
4263 return false;
4264
4265 /*
4266 * fxid is between maybe_needed and definitely_needed, i.e. there might or
4267 * might not exist a snapshot considering fxid running. If it makes sense,
4268 * update boundaries and recheck.
4269 */
4271 {
4273
4274 Assert(FullTransactionIdPrecedes(fxid, state->definitely_needed));
4275
4276 return FullTransactionIdPrecedes(fxid, state->maybe_needed);
4277 }
4278 else
4279 return false;
4280}
static bool GlobalVisTestShouldUpdate(GlobalVisState *state)
Definition procarray.c:4167
static void GlobalVisUpdate(void)
Definition procarray.c:4225
#define FullTransactionIdFollowsOrEquals(a, b)
Definition transam.h:54
#define FullTransactionIdPrecedes(a, b)
Definition transam.h:51

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

Referenced by GlobalVisCheckRemovableFullXid(), and GlobalVisTestIsRemovableXid().

◆ GlobalVisTestIsRemovableXid()

bool GlobalVisTestIsRemovableXid ( GlobalVisState state,
TransactionId  xid,
bool  allow_update 
)

Definition at line 4290 of file procarray.c.

4292{
4293 FullTransactionId fxid;
4294
4295 /*
4296 * Convert 32 bit argument to FullTransactionId. We can do so safely
4297 * because we know the xid has to, at the very least, be between
4298 * [oldestXid, nextXid), i.e. within 2 billion of xid. To avoid taking a
4299 * lock to determine either, we can just compare with
4300 * state->definitely_needed, which was based on those value at the time
4301 * the current snapshot was built.
4302 */
4303 fxid = FullXidRelativeTo(state->definitely_needed, xid);
4304
4306}

References fb(), FullXidRelativeTo(), and GlobalVisTestIsRemovableFullXid().

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

◆ GlobalVisTestShouldUpdate()

static bool GlobalVisTestShouldUpdate ( GlobalVisState state)
static

Definition at line 4167 of file procarray.c.

4168{
4169 /* hasn't been updated yet */
4171 return true;
4172
4173 /*
4174 * If the maybe_needed/definitely_needed boundaries are the same, it's
4175 * unlikely to be beneficial to refresh boundaries.
4176 */
4177 if (FullTransactionIdFollowsOrEquals(state->maybe_needed,
4178 state->definitely_needed))
4179 return false;
4180
4181 /* does the last snapshot built have a different xmin? */
4183}
static TransactionId ComputeXidHorizonsResultLastXmin
Definition procarray.c:324

References ComputeXidHorizonsResultLastXmin, FullTransactionIdFollowsOrEquals, RecentXmin, and TransactionIdIsValid.

Referenced by GlobalVisTestIsRemovableFullXid().

◆ GlobalVisTestXidConsideredRunning()

bool GlobalVisTestXidConsideredRunning ( GlobalVisState state,
TransactionId  xid,
bool  allow_update 
)

Definition at line 4328 of file procarray.c.

4330{
4332}

References fb(), and GlobalVisTestIsRemovableXid().

Referenced by heap_page_prune_and_freeze(), and heap_page_would_be_all_visible().

◆ GlobalVisUpdate()

static void GlobalVisUpdate ( void  )
static

Definition at line 4225 of file procarray.c.

4226{
4228
4229 /* updates the horizons as a side-effect */
4231}

References ComputeXidHorizons(), and fb().

Referenced by GlobalVisTestIsRemovableFullXid().

◆ GlobalVisUpdateApply()

static void GlobalVisUpdateApply ( ComputeXidHorizonsResult horizons)
static

Definition at line 4186 of file procarray.c.

4187{
4189 FullXidRelativeTo(horizons->latest_completed,
4190 horizons->shared_oldest_nonremovable);
4192 FullXidRelativeTo(horizons->latest_completed,
4193 horizons->catalog_oldest_nonremovable);
4195 FullXidRelativeTo(horizons->latest_completed,
4196 horizons->data_oldest_nonremovable);
4198 FullXidRelativeTo(horizons->latest_completed,
4199 horizons->temp_oldest_nonremovable);
4200
4201 /*
4202 * In longer running transactions it's possible that transactions we
4203 * previously needed to treat as running aren't around anymore. So update
4204 * definitely_needed to not be earlier than maybe_needed.
4205 */
4216
4218}

References ComputeXidHorizonsResultLastXmin, GlobalVisState::definitely_needed, fb(), FullTransactionIdNewer(), FullXidRelativeTo(), GlobalVisCatalogRels, GlobalVisDataRels, GlobalVisSharedRels, GlobalVisTempRels, GlobalVisState::maybe_needed, and RecentXmin.

Referenced by ComputeXidHorizons().

◆ HaveVirtualXIDsDelayingChkpt()

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

Definition at line 3062 of file procarray.c.

3063{
3064 bool result = false;
3066 int index;
3067
3068 Assert(type != 0);
3069
3071
3072 for (index = 0; index < arrayP->numProcs; index++)
3073 {
3074 int pgprocno = arrayP->pgprocnos[index];
3075 PGPROC *proc = &allProcs[pgprocno];
3077
3078 GET_VXID_FROM_PGPROC(vxid, *proc);
3079
3080 if ((proc->delayChkptFlags & type) != 0 &&
3082 {
3083 int i;
3084
3085 for (i = 0; i < nvxids; i++)
3086 {
3088 {
3089 result = true;
3090 break;
3091 }
3092 }
3093 if (result)
3094 break;
3095 }
3096 }
3097
3099
3100 return result;
3101}
int i
Definition isn.c:77
#define VirtualTransactionIdEquals(vxid1, vxid2)
Definition lock.h:74

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

Referenced by CreateCheckPoint().

◆ IsBackendPid()

bool IsBackendPid ( int  pid)

Definition at line 3264 of file procarray.c.

3265{
3266 return (BackendPidGetProc(pid) != NULL);
3267}
PGPROC * BackendPidGetProc(int pid)
Definition procarray.c:3169

References BackendPidGetProc(), and fb().

Referenced by pg_stat_get_subscription().

◆ KnownAssignedTransactionIdsIdleMaintenance()

void KnownAssignedTransactionIdsIdleMaintenance ( void  )

Definition at line 4617 of file procarray.c.

4618{
4620}
static void KnownAssignedXidsCompress(KAXCompressReason reason, bool haveLock)
Definition procarray.c:4718

References KAX_STARTUP_PROCESS_IDLE, and KnownAssignedXidsCompress().

Referenced by WaitForWALToBecomeAvailable().

◆ KnownAssignedXidExists()

static bool KnownAssignedXidExists ( TransactionId  xid)
static

Definition at line 5027 of file procarray.c.

5028{
5030
5031 return KnownAssignedXidsSearch(xid, false);
5032}
static bool KnownAssignedXidsSearch(TransactionId xid, bool remove)
Definition procarray.c:4939

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

4837{
4839 TransactionId next_xid;
4840 int head,
4841 tail;
4842 int nxids;
4843 int i;
4844
4846
4847 /*
4848 * Calculate how many array slots we'll need. Normally this is cheap; in
4849 * the unusual case where the XIDs cross the wrap point, we do it the hard
4850 * way.
4851 */
4852 if (to_xid >= from_xid)
4853 nxids = to_xid - from_xid + 1;
4854 else
4855 {
4856 nxids = 1;
4857 next_xid = from_xid;
4858 while (TransactionIdPrecedes(next_xid, to_xid))
4859 {
4860 nxids++;
4861 TransactionIdAdvance(next_xid);
4862 }
4863 }
4864
4865 /*
4866 * Since only the startup process modifies the head/tail pointers, we
4867 * don't need a lock to read them here.
4868 */
4869 head = pArray->headKnownAssignedXids;
4870 tail = pArray->tailKnownAssignedXids;
4871
4872 Assert(head >= 0 && head <= pArray->maxKnownAssignedXids);
4873 Assert(tail >= 0 && tail < pArray->maxKnownAssignedXids);
4874
4875 /*
4876 * Verify that insertions occur in TransactionId sequence. Note that even
4877 * if the last existing element is marked invalid, it must still have a
4878 * correctly sequenced XID value.
4879 */
4880 if (head > tail &&
4882 {
4884 elog(ERROR, "out-of-order XID insertion in KnownAssignedXids");
4885 }
4886
4887 /*
4888 * If our xids won't fit in the remaining space, compress out free space
4889 */
4890 if (head + nxids > pArray->maxKnownAssignedXids)
4891 {
4893
4894 head = pArray->headKnownAssignedXids;
4895 /* note: we no longer care about the tail pointer */
4896
4897 /*
4898 * If it still won't fit then we're out of memory
4899 */
4900 if (head + nxids > pArray->maxKnownAssignedXids)
4901 elog(ERROR, "too many KnownAssignedXids");
4902 }
4903
4904 /* Now we can insert the xids into the space starting at head */
4905 next_xid = from_xid;
4906 for (i = 0; i < nxids; i++)
4907 {
4908 KnownAssignedXids[head] = next_xid;
4909 KnownAssignedXidsValid[head] = true;
4910 TransactionIdAdvance(next_xid);
4911 head++;
4912 }
4913
4914 /* Adjust count of number of valid entries */
4915 pArray->numKnownAssignedXids += nxids;
4916
4917 /*
4918 * Now update the head pointer. We use a write barrier to ensure that
4919 * other processors see the above array updates before they see the head
4920 * pointer change. The barrier isn't required if we're holding
4921 * ProcArrayLock exclusively.
4922 */
4923 if (!exclusive_lock)
4925
4926 pArray->headKnownAssignedXids = head;
4927}
#define pg_write_barrier()
Definition atomics.h:155
#define LOG
Definition elog.h:31
#define elog(elevel,...)
Definition elog.h:227
static TransactionId * KnownAssignedXids
Definition procarray.c:296
static bool * KnownAssignedXidsValid
Definition procarray.c:298
static void KnownAssignedXidsDisplay(int trace_level)
Definition procarray.c:5271
static bool TransactionIdFollowsOrEquals(TransactionId id1, TransactionId id2)
Definition transam.h:312

References Assert, elog, ERROR, fb(), i, KAX_NO_SPACE, KnownAssignedXids, KnownAssignedXidsCompress(), KnownAssignedXidsDisplay(), KnownAssignedXidsValid, LOG, pg_write_barrier, procArray, TransactionIdAdvance, TransactionIdFollowsOrEquals(), TransactionIdPrecedes(), and TransactionIdPrecedesOrEquals().

Referenced by ProcArrayApplyRecoveryInfo(), and RecordKnownAssignedTransactionIds().

◆ KnownAssignedXidsCompress()

static void KnownAssignedXidsCompress ( KAXCompressReason  reason,
bool  haveLock 
)
static

Definition at line 4718 of file procarray.c.

4719{
4721 int head,
4722 tail,
4723 nelements;
4724 int compress_index;
4725 int i;
4726
4727 /* Counters for compression heuristics */
4728 static unsigned int transactionEndsCounter;
4730
4731 /* Tuning constants */
4732#define KAX_COMPRESS_FREQUENCY 128 /* in transactions */
4733#define KAX_COMPRESS_IDLE_INTERVAL 1000 /* in ms */
4734
4735 /*
4736 * Since only the startup process modifies the head/tail pointers, we
4737 * don't need a lock to read them here.
4738 */
4740 tail = pArray->tailKnownAssignedXids;
4741 nelements = head - tail;
4742
4743 /*
4744 * If we can choose whether to compress, use a heuristic to avoid
4745 * compressing too often or not often enough. "Compress" here simply
4746 * means moving the values to the beginning of the array, so it is not as
4747 * complex or costly as typical data compression algorithms.
4748 */
4749 if (nelements == pArray->numKnownAssignedXids)
4750 {
4751 /*
4752 * When there are no gaps between head and tail, don't bother to
4753 * compress, except in the KAX_NO_SPACE case where we must compress to
4754 * create some space after the head.
4755 */
4756 if (reason != KAX_NO_SPACE)
4757 return;
4758 }
4759 else if (reason == KAX_TRANSACTION_END)
4760 {
4761 /*
4762 * Consider compressing only once every so many commits. Frequency
4763 * determined by benchmarks.
4764 */
4766 return;
4767
4768 /*
4769 * Furthermore, compress only if the used part of the array is less
4770 * than 50% full (see comments above).
4771 */
4772 if (nelements < 2 * pArray->numKnownAssignedXids)
4773 return;
4774 }
4775 else if (reason == KAX_STARTUP_PROCESS_IDLE)
4776 {
4777 /*
4778 * We're about to go idle for lack of new WAL, so we might as well
4779 * compress. But not too often, to avoid ProcArray lock contention
4780 * with readers.
4781 */
4782 if (lastCompressTs != 0)
4783 {
4785
4789 return;
4790 }
4791 }
4792
4793 /* Need to compress, so get the lock if we don't have it. */
4794 if (!haveLock)
4796
4797 /*
4798 * We compress the array by reading the valid values from tail to head,
4799 * re-aligning data to 0th element.
4800 */
4801 compress_index = 0;
4802 for (i = tail; i < head; i++)
4803 {
4805 {
4809 }
4810 }
4811 Assert(compress_index == pArray->numKnownAssignedXids);
4812
4813 pArray->tailKnownAssignedXids = 0;
4814 pArray->headKnownAssignedXids = compress_index;
4815
4816 if (!haveLock)
4818
4819 /* Update timestamp for maintenance. No need to hold lock for this. */
4821}
TimestampTz GetCurrentTimestamp(void)
Definition timestamp.c:1639
int64 TimestampTz
Definition timestamp.h:39
#define KAX_COMPRESS_FREQUENCY
#define KAX_COMPRESS_IDLE_INTERVAL
int headKnownAssignedXids
Definition procarray.c:87
#define TimestampTzPlusMilliseconds(tz, ms)
Definition timestamp.h:85

References Assert, fb(), 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(), procArray, and TimestampTzPlusMilliseconds.

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

◆ KnownAssignedXidsDisplay()

static void KnownAssignedXidsDisplay ( int  trace_level)
static

Definition at line 5271 of file procarray.c.

5272{
5275 int head,
5276 tail,
5277 i;
5278 int nxids = 0;
5279
5280 tail = pArray->tailKnownAssignedXids;
5281 head = pArray->headKnownAssignedXids;
5282
5284
5285 for (i = tail; i < head; i++)
5286 {
5288 {
5289 nxids++;
5290 appendStringInfo(&buf, "[%d]=%u ", i, KnownAssignedXids[i]);
5291 }
5292 }
5293
5294 elog(trace_level, "%d KnownAssignedXids (num=%d tail=%d head=%d) %s",
5295 nxids,
5296 pArray->numKnownAssignedXids,
5297 pArray->tailKnownAssignedXids,
5298 pArray->headKnownAssignedXids,
5299 buf.data);
5300
5301 pfree(buf.data);
5302}
void pfree(void *pointer)
Definition mcxt.c:1616
static char buf[DEFAULT_XLOG_SEG_SIZE]
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition stringinfo.c:145
void initStringInfo(StringInfo str)
Definition stringinfo.c:97

References appendStringInfo(), buf, elog, fb(), i, initStringInfo(), KnownAssignedXids, KnownAssignedXidsValid, pfree(), and procArray.

Referenced by KnownAssignedXidsAdd(), and ProcArrayApplyRecoveryInfo().

◆ KnownAssignedXidsGet()

static int KnownAssignedXidsGet ( TransactionId xarray,
TransactionId  xmax 
)
static

Definition at line 5166 of file procarray.c.

5167{
5169
5171}

References fb(), InvalidTransactionId, and KnownAssignedXidsGetAndSetXmin().

Referenced by TransactionIdIsInProgress().

◆ KnownAssignedXidsGetAndSetXmin()

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

Definition at line 5180 of file procarray.c.

5182{
5183 int count = 0;
5184 int head,
5185 tail;
5186 int i;
5187
5188 /*
5189 * Fetch head just once, since it may change while we loop. We can stop
5190 * once we reach the initially seen head, since we are certain that an xid
5191 * cannot enter and then leave the array while we hold ProcArrayLock. We
5192 * might miss newly-added xids, but they should be >= xmax so irrelevant
5193 * anyway.
5194 */
5197
5198 pg_read_barrier(); /* pairs with KnownAssignedXidsAdd */
5199
5200 for (i = tail; i < head; i++)
5201 {
5202 /* Skip any gaps in the array */
5204 {
5206
5207 /*
5208 * Update xmin if required. Only the first XID need be checked,
5209 * since the array is sorted.
5210 */
5211 if (count == 0 &&
5213 *xmin = knownXid;
5214
5215 /*
5216 * Filter out anything >= xmax, again relying on sorted property
5217 * of array.
5218 */
5219 if (TransactionIdIsValid(xmax) &&
5221 break;
5222
5223 /* Add knownXid into output array */
5224 xarray[count++] = knownXid;
5225 }
5226 }
5227
5228 return count;
5229}
int tailKnownAssignedXids
Definition procarray.c:86

References fb(), 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 5236 of file procarray.c.

5237{
5238 int head,
5239 tail;
5240 int i;
5241
5242 /*
5243 * Fetch head just once, since it may change while we loop.
5244 */
5247
5248 pg_read_barrier(); /* pairs with KnownAssignedXidsAdd */
5249
5250 for (i = tail; i < head; i++)
5251 {
5252 /* Skip any gaps in the array */
5254 return KnownAssignedXids[i];
5255 }
5256
5257 return InvalidTransactionId;
5258}

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

5041{
5043
5044 elog(DEBUG4, "remove KnownAssignedXid %u", xid);
5045
5046 /*
5047 * Note: we cannot consider it an error to remove an XID that's not
5048 * present. We intentionally remove subxact IDs while processing
5049 * XLOG_XACT_ASSIGNMENT, to avoid array overflow. Then those XIDs will be
5050 * removed again when the top-level xact commits or aborts.
5051 *
5052 * It might be possible to track such XIDs to distinguish this case from
5053 * actual errors, but it would be complicated and probably not worth it.
5054 * So, just ignore the search result.
5055 */
5056 (void) KnownAssignedXidsSearch(xid, true);
5057}
#define DEBUG4
Definition elog.h:27

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

Referenced by KnownAssignedXidsRemoveTree().

◆ KnownAssignedXidsRemovePreceding()

static void KnownAssignedXidsRemovePreceding ( TransactionId  removeXid)
static

Definition at line 5088 of file procarray.c.

5089{
5091 int count = 0;
5092 int head,
5093 tail,
5094 i;
5095
5097 {
5098 elog(DEBUG4, "removing all KnownAssignedXids");
5099 pArray->numKnownAssignedXids = 0;
5100 pArray->headKnownAssignedXids = pArray->tailKnownAssignedXids = 0;
5101 return;
5102 }
5103
5104 elog(DEBUG4, "prune KnownAssignedXids to %u", removeXid);
5105
5106 /*
5107 * Mark entries invalid starting at the tail. Since array is sorted, we
5108 * can stop as soon as we reach an entry >= removeXid.
5109 */
5110 tail = pArray->tailKnownAssignedXids;
5111 head = pArray->headKnownAssignedXids;
5112
5113 for (i = tail; i < head; i++)
5114 {
5116 {
5118
5120 break;
5121
5123 {
5124 KnownAssignedXidsValid[i] = false;
5125 count++;
5126 }
5127 }
5128 }
5129
5130 pArray->numKnownAssignedXids -= count;
5131 Assert(pArray->numKnownAssignedXids >= 0);
5132
5133 /*
5134 * Advance the tail pointer if we've marked the tail item invalid.
5135 */
5136 for (i = tail; i < head; i++)
5137 {
5139 break;
5140 }
5141 if (i >= head)
5142 {
5143 /* Array is empty, so we can reset both pointers */
5144 pArray->headKnownAssignedXids = 0;
5145 pArray->tailKnownAssignedXids = 0;
5146 }
5147 else
5148 {
5149 pArray->tailKnownAssignedXids = i;
5150 }
5151
5152 /* Opportunistically compress the array */
5154}
bool StandbyTransactionIdIsPrepared(TransactionId xid)
Definition twophase.c:1473

References Assert, DEBUG4, elog, fb(), i, KAX_PRUNE, KnownAssignedXids, KnownAssignedXidsCompress(), KnownAssignedXidsValid, procArray, StandbyTransactionIdIsPrepared(), TransactionIdFollowsOrEquals(), and TransactionIdIsValid.

Referenced by ExpireAllKnownAssignedTransactionIds(), and ExpireOldKnownAssignedTransactionIds().

◆ KnownAssignedXidsRemoveTree()

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

Definition at line 5066 of file procarray.c.

5068{
5069 int i;
5070
5071 if (TransactionIdIsValid(xid))
5073
5074 for (i = 0; i < nsubxids; i++)
5075 KnownAssignedXidsRemove(subxids[i]);
5076
5077 /* Opportunistically compress the array */
5079}
static void KnownAssignedXidsRemove(TransactionId xid)
Definition procarray.c:5040

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

Referenced by ExpireTreeKnownAssignedTransactionIds(), and ProcArrayApplyXidAssignment().

◆ KnownAssignedXidsReset()

static void KnownAssignedXidsReset ( void  )
static

Definition at line 5309 of file procarray.c.

5310{
5312
5314
5315 pArray->numKnownAssignedXids = 0;
5316 pArray->tailKnownAssignedXids = 0;
5317 pArray->headKnownAssignedXids = 0;
5318
5320}

References fb(), LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), and procArray.

Referenced by ProcArrayApplyRecoveryInfo().

◆ KnownAssignedXidsSearch()

static bool KnownAssignedXidsSearch ( TransactionId  xid,
bool  remove 
)
static

Definition at line 4939 of file procarray.c.

4940{
4942 int first,
4943 last;
4944 int head;
4945 int tail;
4946 int result_index = -1;
4947
4949 head = pArray->headKnownAssignedXids;
4950
4951 /*
4952 * Only the startup process removes entries, so we don't need the read
4953 * barrier in that case.
4954 */
4955 if (!remove)
4956 pg_read_barrier(); /* pairs with KnownAssignedXidsAdd */
4957
4958 /*
4959 * Standard binary search. Note we can ignore the KnownAssignedXidsValid
4960 * array here, since even invalid entries will contain sorted XIDs.
4961 */
4962 first = tail;
4963 last = head - 1;
4964 while (first <= last)
4965 {
4966 int mid_index;
4968
4969 mid_index = (first + last) / 2;
4971
4972 if (xid == mid_xid)
4973 {
4975 break;
4976 }
4977 else if (TransactionIdPrecedes(xid, mid_xid))
4978 last = mid_index - 1;
4979 else
4980 first = mid_index + 1;
4981 }
4982
4983 if (result_index < 0)
4984 return false; /* not in array */
4985
4987 return false; /* in array, but invalid */
4988
4989 if (remove)
4990 {
4992
4993 pArray->numKnownAssignedXids--;
4994 Assert(pArray->numKnownAssignedXids >= 0);
4995
4996 /*
4997 * If we're removing the tail element then advance tail pointer over
4998 * any invalid elements. This will speed future searches.
4999 */
5000 if (result_index == tail)
5001 {
5002 tail++;
5003 while (tail < head && !KnownAssignedXidsValid[tail])
5004 tail++;
5005 if (tail >= head)
5006 {
5007 /* Array is empty, so we can reset both pointers */
5008 pArray->headKnownAssignedXids = 0;
5009 pArray->tailKnownAssignedXids = 0;
5010 }
5011 else
5012 {
5013 pArray->tailKnownAssignedXids = tail;
5014 }
5015 }
5016 }
5017
5018 return true;
5019}

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

Referenced by KnownAssignedXidExists(), and KnownAssignedXidsRemove().

◆ MaintainLatestCompletedXid()

◆ MaintainLatestCompletedXidRecovery()

static void MaintainLatestCompletedXidRecovery ( TransactionId  latestXid)
static

◆ MinimumActiveBackends()

bool MinimumActiveBackends ( int  min)

Definition at line 3589 of file procarray.c.

3590{
3592 int count = 0;
3593 int index;
3594
3595 /* Quick short-circuit if no minimum is specified */
3596 if (min == 0)
3597 return true;
3598
3599 /*
3600 * Note: for speed, we don't acquire ProcArrayLock. This is a little bit
3601 * bogus, but since we are only testing fields for zero or nonzero, it
3602 * should be OK. The result is only used for heuristic purposes anyway...
3603 */
3604 for (index = 0; index < arrayP->numProcs; index++)
3605 {
3606 int pgprocno = arrayP->pgprocnos[index];
3607 PGPROC *proc = &allProcs[pgprocno];
3608
3609 /*
3610 * Since we're not holding a lock, need to be prepared to deal with
3611 * garbage, as someone could have incremented numProcs but not yet
3612 * filled the structure.
3613 *
3614 * If someone just decremented numProcs, 'proc' could also point to a
3615 * PGPROC entry that's no longer in the array. It still points to a
3616 * PGPROC struct, though, because freed PGPROC entries just go to the
3617 * free list and are recycled. Its contents are nonsense in that case,
3618 * but that's acceptable for this function.
3619 */
3620 if (pgprocno == -1)
3621 continue; /* do not count deleted entries */
3622 if (proc == MyProc)
3623 continue; /* do not count myself */
3624 if (proc->xid == InvalidTransactionId)
3625 continue; /* do not count if no XID assigned */
3626 if (proc->pid == 0)
3627 continue; /* do not count prepared xacts */
3628 if (proc->waitLock != NULL)
3629 continue; /* do not count if blocked on a lock */
3630 count++;
3631 if (count >= min)
3632 break;
3633 }
3634
3635 return count >= min;
3636}
LOCK * waitLock
Definition proc.h:304

References allProcs, fb(), InvalidTransactionId, MyProc, PGPROC::pid, procArray, PGPROC::waitLock, and PGPROC::xid.

Referenced by XLogFlush().

◆ ProcArrayAdd()

void ProcArrayAdd ( PGPROC proc)

Definition at line 464 of file procarray.c.

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

References allProcs, Assert, ereport, errcode(), errmsg, FATAL, fb(), GetNumberFromPGProc, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), NUM_AUXILIARY_PROCS, 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 1045 of file procarray.c.

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

References AdvanceNextFullTransactionIdPastXid(), Assert, DEBUG1, DEBUG3, elog, ERROR, ExpireOldKnownAssignedTransactionIds(), ExtendSUBTRANS(), fb(), 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_array, 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 1309 of file procarray.c.

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

References Assert, fb(), 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 899 of file procarray.c.

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

References Assert, XidCacheStatus::count, PGPROC::delayChkptFlags, fb(), InvalidLocalTransactionId, InvalidTransactionId, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), PGPROC::lxid, XidCacheStatus::overflowed, PGPROC::pgxactoff, PROC_VACUUM_STATE_MASK, ProcGlobal, 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 663 of file procarray.c.

664{
666 {
667 /*
668 * We must lock ProcArrayLock while clearing our advertised XID, so
669 * that we do not exit the set of "running" transactions while someone
670 * else is taking a snapshot. See discussion in
671 * src/backend/access/transam/README.
672 */
674
675 /*
676 * If we can immediately acquire ProcArrayLock, we clear our own XID
677 * and release the lock. If not, use group XID clearing to improve
678 * efficiency.
679 */
681 {
684 }
685 else
687 }
688 else
689 {
690 /*
691 * If we have no XID, we don't need to lock, since we won't affect
692 * anyone else's calculation of a snapshot. We might change their
693 * estimate of global xmin, but that's OK.
694 */
696 Assert(proc->subxidStatus.count == 0);
698
701
702 /* be sure this is cleared in abort */
703 proc->delayChkptFlags = 0;
704
705 /* must be cleared with xid/xmin: */
706 /* avoid unnecessarily dirtying shared cachelines */
708 {
715 }
716 }
717}
bool LWLockConditionalAcquire(LWLock *lock, LWLockMode mode)
Definition lwlock.c:1321
static void ProcArrayEndTransactionInternal(PGPROC *proc, TransactionId latestXid)
Definition procarray.c:725
static void ProcArrayGroupClearXid(PGPROC *proc, TransactionId latestXid)
Definition procarray.c:784

References Assert, XidCacheStatus::count, PGPROC::delayChkptFlags, fb(), InvalidLocalTransactionId, InvalidTransactionId, LW_EXCLUSIVE, LWLockAcquire(), LWLockConditionalAcquire(), LWLockHeldByMe(), LWLockRelease(), PGPROC::lxid, XidCacheStatus::overflowed, PGPROC::pgxactoff, PROC_VACUUM_STATE_MASK, ProcArrayEndTransactionInternal(), ProcArrayGroupClearXid(), ProcGlobal, 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 725 of file procarray.c.

726{
727 int pgxactoff = proc->pgxactoff;
728
729 /*
730 * Note: we need exclusive lock here because we're going to change other
731 * processes' PGPROC entries.
732 */
735 Assert(ProcGlobal->xids[pgxactoff] == proc->xid);
736
741
742 /* be sure this is cleared in abort */
743 proc->delayChkptFlags = 0;
744
745 /* must be cleared with xid/xmin: */
746 /* avoid unnecessarily dirtying shared cachelines */
748 {
751 }
752
753 /* Clear the subtransaction-XID cache too while holding the lock */
754 Assert(ProcGlobal->subxidStates[pgxactoff].count == proc->subxidStatus.count &&
756 if (proc->subxidStatus.count > 0 || proc->subxidStatus.overflowed)
757 {
758 ProcGlobal->subxidStates[pgxactoff].count = 0;
759 ProcGlobal->subxidStates[pgxactoff].overflowed = false;
760 proc->subxidStatus.count = 0;
761 proc->subxidStatus.overflowed = false;
762 }
763
764 /* Also advance global latestCompletedXid while holding the lock */
766
767 /* Same with xactCompletionCount */
769}
bool LWLockHeldByMeInMode(LWLock *lock, LWLockMode mode)
Definition lwlock.c:1929
static void MaintainLatestCompletedXid(TransactionId latestXid)
Definition procarray.c:958

References Assert, XidCacheStatus::count, PGPROC::delayChkptFlags, fb(), InvalidLocalTransactionId, InvalidTransactionId, LW_EXCLUSIVE, LWLockHeldByMeInMode(), PGPROC::lxid, MaintainLatestCompletedXid(), XidCacheStatus::overflowed, PGPROC::pgxactoff, PROC_VACUUM_STATE_MASK, ProcGlobal, 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 3988 of file procarray.c.

3990{
3992
3993 if (xmin != NULL)
3995
3996 if (catalog_xmin != NULL)
3998
4000}

References fb(), 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 784 of file procarray.c.

785{
786 int pgprocno = GetNumberFromPGProc(proc);
790
791 /* We should definitely have an XID to clear. */
793
794 /* Add ourselves to the list of processes needing a group XID clear. */
795 proc->procArrayGroupMember = true;
797 nextidx = pg_atomic_read_u32(&procglobal->procArrayGroupFirst);
798 while (true)
799 {
801
802 if (pg_atomic_compare_exchange_u32(&procglobal->procArrayGroupFirst,
803 &nextidx,
804 (uint32) pgprocno))
805 break;
806 }
807
808 /*
809 * If the list was not empty, the leader will clear our XID. It is
810 * impossible to have followers without a leader because the first process
811 * that has added itself to the list will always have nextidx as
812 * INVALID_PROC_NUMBER.
813 */
815 {
816 int extraWaits = 0;
817
818 /* Sleep until the leader clears our XID. */
820 for (;;)
821 {
822 /* acts as a read barrier */
823 PGSemaphoreLock(proc->sem);
824 if (!proc->procArrayGroupMember)
825 break;
826 extraWaits++;
827 }
829
831
832 /* Fix semaphore count for any absorbed wakeups */
833 while (extraWaits-- > 0)
834 PGSemaphoreUnlock(proc->sem);
835 return;
836 }
837
838 /* We are the leader. Acquire the lock on behalf of everyone. */
840
841 /*
842 * Now that we've got the lock, clear the list of processes waiting for
843 * group XID clearing, saving a pointer to the head of the list. Trying
844 * to pop elements one at a time could lead to an ABA problem.
845 */
846 nextidx = pg_atomic_exchange_u32(&procglobal->procArrayGroupFirst,
848
849 /* Remember head of list so we can perform wakeups after dropping lock. */
851
852 /* Walk the list and clear all XIDs. */
854 {
856
857 ProcArrayEndTransactionInternal(nextproc, nextproc->procArrayGroupMemberXid);
858
859 /* Move to next proc in list. */
860 nextidx = pg_atomic_read_u32(&nextproc->procArrayGroupNext);
861 }
862
863 /* We're done with the lock now. */
865
866 /*
867 * Now that we've released the lock, go back and wake everybody up. We
868 * don't do this under the lock so as to keep lock hold times to a
869 * minimum. The system calls we need to perform to wake other processes
870 * up are probably much slower than the simple memory writes we did while
871 * holding the lock.
872 */
874 {
876
877 wakeidx = pg_atomic_read_u32(&nextproc->procArrayGroupNext);
878 pg_atomic_write_u32(&nextproc->procArrayGroupNext, INVALID_PROC_NUMBER);
879
880 /* ensure all previous writes are visible before follower continues. */
882
883 nextproc->procArrayGroupMember = false;
884
885 if (nextproc != MyProc)
887 }
888}
static bool pg_atomic_compare_exchange_u32(volatile pg_atomic_uint32 *ptr, uint32 *expected, uint32 newval)
Definition atomics.h:349
static void pg_atomic_write_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
Definition atomics.h:274
static uint32 pg_atomic_read_u32(volatile pg_atomic_uint32 *ptr)
Definition atomics.h:237
static uint32 pg_atomic_exchange_u32(volatile pg_atomic_uint32 *ptr, uint32 newval)
Definition atomics.h:330
uint32_t uint32
Definition c.h:624
void PGSemaphoreUnlock(PGSemaphore sema)
Definition posix_sema.c:333
void PGSemaphoreLock(PGSemaphore sema)
Definition posix_sema.c:313
bool procArrayGroupMember
Definition proc.h:350
pg_atomic_uint32 procArrayGroupNext
Definition proc.h:352
TransactionId procArrayGroupMemberXid
Definition proc.h:358
PGSemaphore sem
Definition proc.h:258
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition wait_event.h:67
static void pgstat_report_wait_end(void)
Definition wait_event.h:83

References allProcs, Assert, fb(), 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(), PGPROC::procArrayGroupMember, PGPROC::procArrayGroupMemberXid, PGPROC::procArrayGroupNext, ProcGlobal, PGPROC::sem, TransactionIdIsValid, and PGPROC::xid.

Referenced by ProcArrayEndTransaction().

◆ ProcArrayInitRecovery()

void ProcArrayInitRecovery ( TransactionId  initializedUptoXID)

Definition at line 1014 of file procarray.c.

1015{
1018
1019 /*
1020 * we set latestObservedXid to the xid SUBTRANS has been initialized up
1021 * to, so we can extend it from that point onwards in
1022 * RecordKnownAssignedTransactionIds, and when we get consistent in
1023 * ProcArrayApplyRecoveryInfo().
1024 */
1027}

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

Referenced by StartupXLOG().

◆ ProcArrayInstallImportedXmin()

bool ProcArrayInstallImportedXmin ( TransactionId  xmin,
VirtualTransactionId sourcevxid 
)

Definition at line 2471 of file procarray.c.

2473{
2474 bool result = false;
2476 int index;
2477
2479 if (!sourcevxid)
2480 return false;
2481
2482 /* Get lock so source xact can't end while we're doing this */
2484
2485 /*
2486 * Find the PGPROC entry of the source transaction. (This could use
2487 * GetPGProcByNumber(), unless it's a prepared xact. But this isn't
2488 * performance critical.)
2489 */
2490 for (index = 0; index < arrayP->numProcs; index++)
2491 {
2492 int pgprocno = arrayP->pgprocnos[index];
2493 PGPROC *proc = &allProcs[pgprocno];
2494 int statusFlags = ProcGlobal->statusFlags[index];
2495 TransactionId xid;
2496
2497 /* Ignore procs running LAZY VACUUM */
2498 if (statusFlags & PROC_IN_VACUUM)
2499 continue;
2500
2501 /* We are only interested in the specific virtual transaction. */
2502 if (proc->vxid.procNumber != sourcevxid->procNumber)
2503 continue;
2504 if (proc->vxid.lxid != sourcevxid->localTransactionId)
2505 continue;
2506
2507 /*
2508 * We check the transaction's database ID for paranoia's sake: if it's
2509 * in another DB then its xmin does not cover us. Caller should have
2510 * detected this already, so we just treat any funny cases as
2511 * "transaction not found".
2512 */
2513 if (proc->databaseId != MyDatabaseId)
2514 continue;
2515
2516 /*
2517 * Likewise, let's just make real sure its xmin does cover us.
2518 */
2519 xid = UINT32_ACCESS_ONCE(proc->xmin);
2520 if (!TransactionIdIsNormal(xid) ||
2522 continue;
2523
2524 /*
2525 * We're good. Install the new xmin. As in GetSnapshotData, set
2526 * TransactionXmin too. (Note that because snapmgr.c called
2527 * GetSnapshotData first, we'll be overwriting a valid xmin here, so
2528 * we don't check that.)
2529 */
2530 MyProc->xmin = TransactionXmin = xmin;
2531
2532 result = true;
2533 break;
2534 }
2535
2537
2538 return result;
2539}
ProcNumber procNumber
Definition proc.h:226

References allProcs, Assert, PGPROC::databaseId, fb(), LW_SHARED, LWLockAcquire(), LWLockRelease(), PGPROC::lxid, MyDatabaseId, MyProc, PROC_IN_VACUUM, procArray, ProcGlobal, PGPROC::procNumber, result, 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 2555 of file procarray.c.

2556{
2557 bool result = false;
2558 TransactionId xid;
2559
2561 Assert(proc != NULL);
2562
2563 /*
2564 * Get an exclusive lock so that we can copy statusFlags from source proc.
2565 */
2567
2568 /*
2569 * Be certain that the referenced PGPROC has an advertised xmin which is
2570 * no later than the one we're installing, so that the system-wide xmin
2571 * can't go backwards. Also, make sure it's running in the same database,
2572 * so that the per-database xmin cannot go backwards.
2573 */
2574 xid = UINT32_ACCESS_ONCE(proc->xmin);
2575 if (proc->databaseId == MyDatabaseId &&
2576 TransactionIdIsNormal(xid) &&
2578 {
2579 /*
2580 * Install xmin and propagate the statusFlags that affect how the
2581 * value is interpreted by vacuum.
2582 */
2583 MyProc->xmin = TransactionXmin = xmin;
2585 (proc->statusFlags & PROC_XMIN_FLAGS);
2587
2588 result = true;
2589 }
2590
2592
2593 return result;
2594}
#define PROC_XMIN_FLAGS
Definition proc.h:76

References Assert, PGPROC::databaseId, fb(), LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MyDatabaseId, MyProc, PGPROC::pgxactoff, PROC_XMIN_FLAGS, ProcGlobal, result, 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 561 of file procarray.c.

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

References allProcs, PROC_HDR::allProcs, Assert, XidCacheStatus::count, fb(), InvalidTransactionId, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MaintainLatestCompletedXid(), NUM_AUXILIARY_PROCS, XidCacheStatus::overflowed, 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 3963 of file procarray.c.

3965{
3967
3968 if (!already_locked)
3970
3973
3974 if (!already_locked)
3976
3977 elog(DEBUG1, "xmin required by slots: data %u, catalog %u",
3978 xmin, catalog_xmin);
3979}

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

Referenced by ReplicationSlotsComputeRequiredXmin().

◆ ProcArrayShmemAttach()

static void ProcArrayShmemAttach ( void arg)
static

Definition at line 455 of file procarray.c.

456{
458}

References allProcs, PROC_HDR::allProcs, and ProcGlobal.

◆ ProcArrayShmemInit()

◆ ProcArrayShmemRequest()

static void ProcArrayShmemRequest ( void arg)
static

Definition at line 393 of file procarray.c.

394{
395#define PROCARRAY_MAXPROCS (MaxBackends + max_prepared_xacts)
396
397 /*
398 * During Hot Standby processing we have a data structure called
399 * KnownAssignedXids, created in shared memory. Local data structures are
400 * also created in various backends during GetSnapshotData(),
401 * TransactionIdIsInProgress() and GetRunningTransactionData(). All of the
402 * main structures created in those functions must be identically sized,
403 * since we may at times copy the whole of the data structures around. We
404 * refer to this size as TOTAL_MAX_CACHED_SUBXIDS.
405 *
406 * Ideally we'd only create this structure if we were actually doing hot
407 * standby in the current run, but we don't know that yet at the time
408 * shared memory is being set up.
409 */
410#define TOTAL_MAX_CACHED_SUBXIDS \
411 ((PGPROC_MAX_CACHED_SUBXIDS + 1) * PROCARRAY_MAXPROCS)
412
414 {
415 ShmemRequestStruct(.name = "KnownAssignedXids",
417 .ptr = (void **) &KnownAssignedXids,
418 );
419
420 ShmemRequestStruct(.name = "KnownAssignedXidsValid",
421 .size = mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS),
422 .ptr = (void **) &KnownAssignedXidsValid,
423 );
424 }
425
426 /* Register the ProcArray shared structure */
427 ShmemRequestStruct(.name = "Proc Array",
428 .size = add_size(offsetof(ProcArrayStruct, pgprocnos),
429 mul_size(sizeof(int), PROCARRAY_MAXPROCS)),
430 .ptr = (void **) &procArray,
431 );
432}
Size add_size(Size s1, Size s2)
Definition shmem.c:1048
Size mul_size(Size s1, Size s2)
Definition shmem.c:1063
#define ShmemRequestStruct(...)
Definition shmem.h:176
const char * name
bool EnableHotStandby
Definition xlog.c:128

References add_size(), EnableHotStandby, fb(), KnownAssignedXids, KnownAssignedXidsValid, mul_size(), name, procArray, PROCARRAY_MAXPROCS, ShmemRequestStruct, and TOTAL_MAX_CACHED_SUBXIDS.

◆ ProcNumberGetProc()

PGPROC * ProcNumberGetProc ( ProcNumber  procNumber)

Definition at line 3111 of file procarray.c.

3112{
3113 PGPROC *result;
3114
3116 return NULL;
3117 result = GetPGProcByNumber(procNumber);
3118
3119 if (result->pid == 0)
3120 return NULL;
3121
3122 return result;
3123}
#define GetPGProcByNumber(n)
Definition proc.h:504
uint32 allProcCount
Definition proc.h:459

References PROC_HDR::allProcCount, fb(), GetPGProcByNumber, ProcGlobal, and result.

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

◆ ProcNumberGetTransactionIds()

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

Definition at line 3133 of file procarray.c.

3135{
3136 PGPROC *proc;
3137
3138 *xid = InvalidTransactionId;
3139 *xmin = InvalidTransactionId;
3140 *nsubxid = 0;
3141 *overflowed = false;
3142
3144 return;
3145 proc = GetPGProcByNumber(procNumber);
3146
3147 /* Need to lock out additions/removals of backends */
3149
3150 if (proc->pid != 0)
3151 {
3152 *xid = proc->xid;
3153 *xmin = proc->xmin;
3154 *nsubxid = proc->subxidStatus.count;
3155 *overflowed = proc->subxidStatus.overflowed;
3156 }
3157
3159}

References PROC_HDR::allProcCount, XidCacheStatus::count, fb(), 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 4456 of file procarray.c.

4457{
4461
4462 elog(DEBUG4, "record known xact %u latestObservedXid %u",
4463 xid, latestObservedXid);
4464
4465 /*
4466 * When a newly observed xid arrives, it is frequently the case that it is
4467 * *not* the next xid in sequence. When this occurs, we must treat the
4468 * intervening xids as running also.
4469 */
4471 {
4473
4474 /*
4475 * Extend subtrans like we do in GetNewTransactionId() during normal
4476 * operation using individual extend steps. Note that we do not need
4477 * to extend clog since its extensions are WAL logged.
4478 *
4479 * This part has to be done regardless of standbyState since we
4480 * immediately start assigning subtransactions to their toplevel
4481 * transactions.
4482 */
4485 {
4488 }
4489 Assert(next_expected_xid == xid);
4490
4491 /*
4492 * If the KnownAssignedXids machinery isn't up yet, there's nothing
4493 * more to do since we don't track assigned xids yet.
4494 */
4496 {
4497 latestObservedXid = xid;
4498 return;
4499 }
4500
4501 /*
4502 * Add (latestObservedXid, xid] onto the KnownAssignedXids array.
4503 */
4507
4508 /*
4509 * Now we can advance latestObservedXid
4510 */
4511 latestObservedXid = xid;
4512
4513 /* TransamVariables->nextXid must be beyond any observed xid */
4515 }
4516}

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

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

◆ SignalRecoveryConflict()

bool SignalRecoveryConflict ( PGPROC proc,
pid_t  pid,
RecoveryConflictReason  reason 
)

Definition at line 3467 of file procarray.c.

3468{
3469 bool found = false;
3470
3472
3473 /*
3474 * Kill the pid if it's still here. If not, that's what we wanted so
3475 * ignore any errors.
3476 */
3477 if (proc->pid == pid)
3478 {
3479 (void) pg_atomic_fetch_or_u32(&proc->pendingRecoveryConflicts, (1 << reason));
3480
3481 /* wake up the process */
3483 found = true;
3484 }
3485
3487
3488 return found;
3489}
static uint32 pg_atomic_fetch_or_u32(volatile pg_atomic_uint32 *ptr, uint32 or_)
Definition atomics.h:410
int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber)
Definition procsignal.c:288
@ PROCSIG_RECOVERY_CONFLICT
Definition procsignal.h:41
pg_atomic_uint32 pendingRecoveryConflicts
Definition proc.h:270

References fb(), GetNumberFromPGProc, LW_SHARED, LWLockAcquire(), LWLockRelease(), PGPROC::pendingRecoveryConflicts, pg_atomic_fetch_or_u32(), PGPROC::pid, PROCSIG_RECOVERY_CONFLICT, and SendProcSignal().

Referenced by InvalidatePossiblyObsoleteSlot().

◆ SignalRecoveryConflictWithDatabase()

void SignalRecoveryConflictWithDatabase ( Oid  databaseid,
RecoveryConflictReason  reason 
)

Definition at line 3542 of file procarray.c.

3543{
3545 int index;
3546
3547 /* tell all backends to die */
3549
3550 for (index = 0; index < arrayP->numProcs; index++)
3551 {
3552 int pgprocno = arrayP->pgprocnos[index];
3553 PGPROC *proc = &allProcs[pgprocno];
3554
3555 if (databaseid == InvalidOid || proc->databaseId == databaseid)
3556 {
3558 pid_t pid;
3559
3561
3562 pid = proc->pid;
3563 if (pid != 0)
3564 {
3565 (void) pg_atomic_fetch_or_u32(&proc->pendingRecoveryConflicts, (1 << reason));
3566
3567 /*
3568 * Kill the pid if it's still here. If not, that's what we
3569 * wanted so ignore any errors.
3570 */
3572 }
3573 }
3574 }
3575
3577}

References allProcs, PGPROC::databaseId, fb(), GET_VXID_FROM_PGPROC, InvalidOid, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), PGPROC::pendingRecoveryConflicts, pg_atomic_fetch_or_u32(), PGPROC::pid, procArray, PROCSIG_RECOVERY_CONFLICT, and SendProcSignal().

Referenced by ResolveRecoveryConflictWithDatabase(), and SendRecoveryConflictWithBufferPin().

◆ SignalRecoveryConflictWithVirtualXID()

bool SignalRecoveryConflictWithVirtualXID ( VirtualTransactionId  vxid,
RecoveryConflictReason  reason 
)

Definition at line 3497 of file procarray.c.

3498{
3500 int index;
3501 pid_t pid = 0;
3502
3504
3505 for (index = 0; index < arrayP->numProcs; index++)
3506 {
3507 int pgprocno = arrayP->pgprocnos[index];
3508 PGPROC *proc = &allProcs[pgprocno];
3510
3512
3513 if (procvxid.procNumber == vxid.procNumber &&
3514 procvxid.localTransactionId == vxid.localTransactionId)
3515 {
3516 pid = proc->pid;
3517 if (pid != 0)
3518 {
3519 (void) pg_atomic_fetch_or_u32(&proc->pendingRecoveryConflicts, (1 << reason));
3520
3521 /*
3522 * Kill the pid if it's still here. If not, that's what we
3523 * wanted so ignore any errors.
3524 */
3526 }
3527 break;
3528 }
3529 }
3530
3532
3533 return pid != 0;
3534}
LocalTransactionId localTransactionId
Definition lock.h:65
ProcNumber procNumber
Definition lock.h:64

References allProcs, fb(), GET_VXID_FROM_PGPROC, VirtualTransactionId::localTransactionId, LW_SHARED, LWLockAcquire(), LWLockRelease(), PGPROC::pendingRecoveryConflicts, pg_atomic_fetch_or_u32(), PGPROC::pid, procArray, VirtualTransactionId::procNumber, PROCSIG_RECOVERY_CONFLICT, and SendProcSignal().

Referenced by ResolveRecoveryConflictWithLock(), and ResolveRecoveryConflictWithVirtualXIDs().

◆ TerminateOtherDBBackends()

void TerminateOtherDBBackends ( Oid  databaseId)

Definition at line 3848 of file procarray.c.

3849{
3851 List *pids = NIL;
3852 int nprepared = 0;
3853 int i;
3854
3856
3857 for (i = 0; i < procArray->numProcs; i++)
3858 {
3859 int pgprocno = arrayP->pgprocnos[i];
3860 PGPROC *proc = &allProcs[pgprocno];
3861
3862 if (proc->databaseId != databaseId)
3863 continue;
3864 if (proc == MyProc)
3865 continue;
3866
3867 if (proc->pid != 0)
3868 pids = lappend_int(pids, proc->pid);
3869 else
3870 nprepared++;
3871 }
3872
3874
3875 if (nprepared > 0)
3876 ereport(ERROR,
3878 errmsg("database \"%s\" is being used by prepared transactions",
3879 get_database_name(databaseId)),
3880 errdetail_plural("There is %d prepared transaction using the database.",
3881 "There are %d prepared transactions using the database.",
3882 nprepared,
3883 nprepared)));
3884
3885 if (pids)
3886 {
3887 ListCell *lc;
3888
3889 /*
3890 * Permissions checks relax the pg_terminate_backend checks in two
3891 * ways, both by omitting the !OidIsValid(proc->roleId) check:
3892 *
3893 * - Accept terminating autovacuum workers, since DROP DATABASE
3894 * without FORCE terminates them.
3895 *
3896 * - Accept terminating bgworkers. For bgworker authors, it's
3897 * convenient to be able to recommend FORCE if a worker is blocking
3898 * DROP DATABASE unexpectedly.
3899 *
3900 * Unlike pg_terminate_backend, we don't raise some warnings - like
3901 * "PID %d is not a PostgreSQL server process", because for us already
3902 * finished session is not a problem.
3903 */
3904 foreach(lc, pids)
3905 {
3906 int pid = lfirst_int(lc);
3907 PGPROC *proc = BackendPidGetProc(pid);
3908
3909 if (proc != NULL)
3910 {
3911 if (superuser_arg(proc->roleId) && !superuser())
3912 ereport(ERROR,
3914 errmsg("permission denied to terminate process"),
3915 errdetail("Only roles with the %s attribute may terminate processes of roles with the %s attribute.",
3916 "SUPERUSER", "SUPERUSER")));
3917
3918 if (!has_privs_of_role(GetUserId(), proc->roleId) &&
3920 ereport(ERROR,
3922 errmsg("permission denied to terminate process"),
3923 errdetail("Only roles with privileges of the role whose process is being terminated or with privileges of the \"%s\" role may terminate this process.",
3924 "pg_signal_backend")));
3925 }
3926 }
3927
3928 /*
3929 * There's a race condition here: once we release the ProcArrayLock,
3930 * it's possible for the session to exit before we issue kill. That
3931 * race condition possibility seems too unlikely to worry about. See
3932 * pg_signal_backend.
3933 */
3934 foreach(lc, pids)
3935 {
3936 int pid = lfirst_int(lc);
3937 PGPROC *proc = BackendPidGetProc(pid);
3938
3939 if (proc != NULL)
3940 {
3941 /*
3942 * If we have setsid(), signal the backend's whole process
3943 * group
3944 */
3945#ifdef HAVE_SETSID
3946 (void) kill(-pid, SIGTERM);
3947#else
3948 (void) kill(pid, SIGTERM);
3949#endif
3950 }
3951 }
3952 }
3953}
bool has_privs_of_role(Oid member, Oid role)
Definition acl.c:5314
int errdetail(const char *fmt,...) pg_attribute_printf(1
int errdetail_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n,...) pg_attribute_printf(1
List * lappend_int(List *list, int datum)
Definition list.c:357
char * get_database_name(Oid dbid)
Definition lsyscache.c:1312
Oid GetUserId(void)
Definition miscinit.c:470
#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:57
bool superuser(void)
Definition superuser.c:47

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

Referenced by dropdb().

◆ TransactionIdIsInProgress()

bool TransactionIdIsInProgress ( TransactionId  xid)

Definition at line 1393 of file procarray.c.

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

References allProcs, Assert, cachedXidIsNotInProgress, ereport, errcode(), errmsg, ERROR, fb(), j, KnownAssignedXidExists(), KnownAssignedXidsGet(), ProcArrayStruct::lastOverflowedXid, TransamVariablesData::latestCompletedXid, LW_SHARED, LWLockAcquire(), LWLockRelease(), malloc, MyProc, pg_lfind32(), pg_read_barrier, 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(), get_xid_status(), HandleConcurrentAbort(), HeapTupleCleanMoved(), HeapTupleHeaderIsOnlyLocked(), HeapTupleSatisfiesDirty(), HeapTupleSatisfiesSelf(), HeapTupleSatisfiesUpdate(), HeapTupleSatisfiesVacuumHorizon(), MultiXactIdExpand(), MultiXactIdIsRunning(), pg_xact_status(), ReorderBufferCheckAndTruncateAbortedTXN(), test_lockmode_for_conflict(), verify_heapam(), and XactLockTableWait().

◆ XidCacheRemoveRunningXids()

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

Definition at line 4011 of file procarray.c.

4014{
4015 int i,
4016 j;
4018
4020
4021 /*
4022 * We must hold ProcArrayLock exclusively in order to remove transactions
4023 * from the PGPROC array. (See src/backend/access/transam/README.) It's
4024 * possible this could be relaxed since we know this routine is only used
4025 * to abort subtransactions, but pending closer analysis we'd best be
4026 * conservative.
4027 *
4028 * Note that we do not have to be careful about memory ordering of our own
4029 * reads wrt. GetNewTransactionId() here - only this process can modify
4030 * relevant fields of MyProc/ProcGlobal->xids[]. But we do have to be
4031 * careful about our own writes being well ordered.
4032 */
4034
4036
4037 /*
4038 * Under normal circumstances xid and xids[] will be in increasing order,
4039 * as will be the entries in subxids. Scan backwards to avoid O(N^2)
4040 * behavior when removing a lot of xids.
4041 */
4042 for (i = nxids - 1; i >= 0; i--)
4043 {
4044 TransactionId anxid = xids[i];
4045
4046 for (j = MyProc->subxidStatus.count - 1; j >= 0; j--)
4047 {
4049 {
4052 mysubxidstat->count--;
4054 break;
4055 }
4056 }
4057
4058 /*
4059 * Ordinarily we should have found it, unless the cache has
4060 * overflowed. However it's also possible for this routine to be
4061 * invoked multiple times for the same subtransaction, in case of an
4062 * error during AbortSubTransaction. So instead of Assert, emit a
4063 * debug warning.
4064 */
4065 if (j < 0 && !MyProc->subxidStatus.overflowed)
4066 elog(WARNING, "did not find subXID %u in MyProc", anxid);
4067 }
4068
4069 for (j = MyProc->subxidStatus.count - 1; j >= 0; j--)
4070 {
4072 {
4075 mysubxidstat->count--;
4077 break;
4078 }
4079 }
4080 /* Ordinarily we should have found it, unless the cache has overflowed */
4081 if (j < 0 && !MyProc->subxidStatus.overflowed)
4082 elog(WARNING, "did not find subXID %u in MyProc", xid);
4083
4084 /* Also advance global latestCompletedXid while holding the lock */
4086
4087 /* ... and xactCompletionCount */
4089
4091}
#define WARNING
Definition elog.h:36

References Assert, XidCacheStatus::count, elog, fb(), 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 290 of file procarray.c.

Referenced by TransactionIdIsInProgress().

◆ ComputeXidHorizonsResultLastXmin

TransactionId ComputeXidHorizonsResultLastXmin
static

Definition at line 324 of file procarray.c.

Referenced by GlobalVisTestShouldUpdate(), and GlobalVisUpdateApply().

◆ GlobalVisCatalogRels

GlobalVisState GlobalVisCatalogRels
static

Definition at line 315 of file procarray.c.

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

◆ GlobalVisDataRels

GlobalVisState GlobalVisDataRels
static

Definition at line 316 of file procarray.c.

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

◆ GlobalVisSharedRels

GlobalVisState GlobalVisSharedRels
static

Definition at line 314 of file procarray.c.

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

◆ GlobalVisTempRels

GlobalVisState GlobalVisTempRels
static

Definition at line 317 of file procarray.c.

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

◆ KnownAssignedXids

◆ KnownAssignedXidsValid

◆ latestObservedXid

◆ procArray

◆ ProcArrayShmemCallbacks

const struct ShmemCallbacks ProcArrayShmemCallbacks
Initial value:
= {
.request_fn = ProcArrayShmemRequest,
.init_fn = ProcArrayShmemInit,
.attach_fn = ProcArrayShmemAttach,
}
static void ProcArrayShmemInit(void *arg)
Definition procarray.c:438
static void ProcArrayShmemRequest(void *arg)
Definition procarray.c:393
static void ProcArrayShmemAttach(void *arg)
Definition procarray.c:455

Definition at line 113 of file procarray.c.

113 {
114 .request_fn = ProcArrayShmemRequest,
115 .init_fn = ProcArrayShmemInit,
116 .attach_fn = ProcArrayShmemAttach,
117};

◆ standbySnapshotPendingXmin

TransactionId standbySnapshotPendingXmin
static

Definition at line 307 of file procarray.c.

Referenced by ProcArrayApplyRecoveryInfo().