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 "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 dependency graph for procarray.c:

Go to the source code of this file.

Data Structures

struct  ProcArrayStruct
 
struct  GlobalVisState
 
struct  ComputeXidHorizonsResult
 

Macros

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

Typedefs

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

Enumerations

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

Functions

static void KnownAssignedXidsCompress (KAXCompressReason reason, bool haveLock)
 
static void KnownAssignedXidsAdd (TransactionId from_xid, TransactionId to_xid, bool exclusive_lock)
 
static bool KnownAssignedXidsSearch (TransactionId xid, bool remove)
 
static bool KnownAssignedXidExists (TransactionId xid)
 
static void KnownAssignedXidsRemove (TransactionId xid)
 
static void KnownAssignedXidsRemoveTree (TransactionId xid, int nsubxids, TransactionId *subxids)
 
static void KnownAssignedXidsRemovePreceding (TransactionId removeXid)
 
static int KnownAssignedXidsGet (TransactionId *xarray, TransactionId xmax)
 
static int KnownAssignedXidsGetAndSetXmin (TransactionId *xarray, TransactionId *xmin, TransactionId xmax)
 
static TransactionId KnownAssignedXidsGetOldestXmin (void)
 
static void KnownAssignedXidsDisplay (int trace_level)
 
static void KnownAssignedXidsReset (void)
 
static void ProcArrayEndTransactionInternal (PGPROC *proc, TransactionId latestXid)
 
static void ProcArrayGroupClearXid (PGPROC *proc, TransactionId latestXid)
 
static void MaintainLatestCompletedXid (TransactionId latestXid)
 
static void MaintainLatestCompletedXidRecovery (TransactionId latestXid)
 
static FullTransactionId FullXidRelativeTo (FullTransactionId rel, TransactionId xid)
 
static void GlobalVisUpdateApply (ComputeXidHorizonsResult *horizons)
 
Size ProcArrayShmemSize (void)
 
void ProcArrayShmemInit (void)
 
void ProcArrayAdd (PGPROC *proc)
 
void ProcArrayRemove (PGPROC *proc, TransactionId latestXid)
 
void ProcArrayEndTransaction (PGPROC *proc, TransactionId latestXid)
 
void ProcArrayClearTransaction (PGPROC *proc)
 
void ProcArrayInitRecovery (TransactionId initializedUptoXID)
 
void ProcArrayApplyRecoveryInfo (RunningTransactions running)
 
void ProcArrayApplyXidAssignment (TransactionId topxid, int nsubxids, TransactionId *subxids)
 
bool TransactionIdIsInProgress (TransactionId xid)
 
static void ComputeXidHorizons (ComputeXidHorizonsResult *h)
 
static GlobalVisHorizonKind GlobalVisHorizonKindForRel (Relation rel)
 
TransactionId GetOldestNonRemovableTransactionId (Relation rel)
 
TransactionId GetOldestTransactionIdConsideredRunning (void)
 
void GetReplicationHorizons (TransactionId *xmin, TransactionId *catalog_xmin)
 
int GetMaxSnapshotXidCount (void)
 
int GetMaxSnapshotSubxidCount (void)
 
static bool GetSnapshotDataReuse (Snapshot snapshot)
 
Snapshot GetSnapshotData (Snapshot snapshot)
 
bool ProcArrayInstallImportedXmin (TransactionId xmin, VirtualTransactionId *sourcevxid)
 
bool ProcArrayInstallRestoredXmin (TransactionId xmin, PGPROC *proc)
 
RunningTransactions GetRunningTransactionData (void)
 
TransactionId GetOldestActiveTransactionId (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 GlobalVisTestIsRemovableXid (GlobalVisState *state, TransactionId xid)
 
bool GlobalVisCheckRemovableFullXid (Relation rel, FullTransactionId fxid)
 
bool GlobalVisCheckRemovableXid (Relation rel, TransactionId xid)
 
void RecordKnownAssignedTransactionIds (TransactionId xid)
 
void ExpireTreeKnownAssignedTransactionIds (TransactionId xid, int nsubxids, TransactionId *subxids, TransactionId max_xid)
 
void ExpireAllKnownAssignedTransactionIds (void)
 
void ExpireOldKnownAssignedTransactionIds (TransactionId xid)
 
void KnownAssignedTransactionIdsIdleMaintenance (void)
 

Variables

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

Macro Definition Documentation

◆ KAX_COMPRESS_FREQUENCY

#define KAX_COMPRESS_FREQUENCY   128 /* in transactions */

◆ KAX_COMPRESS_IDLE_INTERVAL

#define KAX_COMPRESS_IDLE_INTERVAL   1000 /* in ms */

◆ MAXAUTOVACPIDS

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

◆ PROCARRAY_MAXPROCS

#define PROCARRAY_MAXPROCS   (MaxBackends + max_prepared_xacts)

◆ TOTAL_MAX_CACHED_SUBXIDS

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

◆ UINT32_ACCESS_ONCE

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

Definition at line 71 of file procarray.c.

◆ xc_by_child_xid_inc

#define xc_by_child_xid_inc ( )    ((void) 0)

Definition at line 343 of file procarray.c.

◆ xc_by_known_assigned_inc

#define xc_by_known_assigned_inc ( )    ((void) 0)

Definition at line 344 of file procarray.c.

◆ xc_by_known_xact_inc

#define xc_by_known_xact_inc ( )    ((void) 0)

Definition at line 339 of file procarray.c.

◆ xc_by_latest_xid_inc

#define xc_by_latest_xid_inc ( )    ((void) 0)

Definition at line 341 of file procarray.c.

◆ xc_by_main_xid_inc

#define xc_by_main_xid_inc ( )    ((void) 0)

Definition at line 342 of file procarray.c.

◆ xc_by_my_xact_inc

#define xc_by_my_xact_inc ( )    ((void) 0)

Definition at line 340 of file procarray.c.

◆ xc_by_recent_xmin_inc

#define xc_by_recent_xmin_inc ( )    ((void) 0)

Definition at line 338 of file procarray.c.

◆ xc_no_overflow_inc

#define xc_no_overflow_inc ( )    ((void) 0)

Definition at line 345 of file procarray.c.

◆ xc_slow_answer_inc

#define xc_slow_answer_inc ( )    ((void) 0)

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

253{
GlobalVisHorizonKind
Definition procarray.c:253
@ VISHORIZON_SHARED
Definition procarray.c:254
@ VISHORIZON_DATA
Definition procarray.c:256
@ VISHORIZON_CATALOG
Definition procarray.c:255
@ VISHORIZON_TEMP
Definition procarray.c:257

◆ KAXCompressReason

Enumerator
KAX_NO_SPACE 
KAX_PRUNE 
KAX_TRANSACTION_END 
KAX_STARTUP_PROCESS_IDLE 

Definition at line 263 of file procarray.c.

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

Function Documentation

◆ BackendPidGetProc()

PGPROC * BackendPidGetProc ( int  pid)

Definition at line 3160 of file procarray.c.

3161{
3162 PGPROC *result;
3163
3164 if (pid == 0) /* never match dummy PGPROCs */
3165 return NULL;
3166
3168
3169 result = BackendPidGetProcWithLock(pid);
3170
3172
3173 return result;
3174}
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition lwlock.c:1176
void LWLockRelease(LWLock *lock)
Definition lwlock.c:1793
@ LW_SHARED
Definition lwlock.h:113
static int fb(int x)
PGPROC * BackendPidGetProcWithLock(int pid)
Definition procarray.c:3183
Definition proc.h:176

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

Referenced by IsBackendPid(), pg_isolation_test_session_is_blocked(), pg_log_backend_memory_contexts(), pg_signal_backend(), pg_stat_get_activity(), pg_stat_get_backend_wait_event(), pg_stat_get_backend_wait_event_type(), 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 3183 of file procarray.c.

3184{
3185 PGPROC *result = NULL;
3187 int index;
3188
3189 if (pid == 0) /* never match dummy PGPROCs */
3190 return NULL;
3191
3192 for (index = 0; index < arrayP->numProcs; index++)
3193 {
3194 PGPROC *proc = &allProcs[arrayP->pgprocnos[index]];
3195
3196 if (proc->pid == pid)
3197 {
3198 result = proc;
3199 break;
3200 }
3201 }
3202
3203 return result;
3204}
static PGPROC * allProcs
Definition procarray.c:274
static ProcArrayStruct * procArray
Definition procarray.c:272
int pid
Definition proc.h:189
Definition type.h:96

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

Referenced by BackendPidGetProc(), and GetBlockerStatusData().

◆ BackendXidGetPid()

int BackendXidGetPid ( TransactionId  xid)

Definition at line 3220 of file procarray.c.

3221{
3222 int result = 0;
3225 int index;
3226
3227 if (xid == InvalidTransactionId) /* never match invalid xid */
3228 return 0;
3229
3231
3232 for (index = 0; index < arrayP->numProcs; index++)
3233 {
3234 if (other_xids[index] == xid)
3235 {
3236 int pgprocno = arrayP->pgprocnos[index];
3237 PGPROC *proc = &allProcs[pgprocno];
3238
3239 result = proc->pid;
3240 break;
3241 }
3242 }
3243
3245
3246 return result;
3247}
uint32 TransactionId
Definition c.h:678
PROC_HDR * ProcGlobal
Definition proc.c:70
TransactionId * xids
Definition proc.h:444
#define InvalidTransactionId
Definition transam.h:31

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

Referenced by pgrowlocks().

◆ ComputeXidHorizons()

static void ComputeXidHorizons ( ComputeXidHorizonsResult h)
static

Definition at line 1686 of file procarray.c.

1687{
1692
1693 /* inferred after ProcArrayLock is released */
1695
1697
1699
1700 /*
1701 * We initialize the MIN() calculation with latestCompletedXid + 1. This
1702 * is a lower bound for the XIDs that might appear in the ProcArray later,
1703 * and so protects us against overestimating the result due to future
1704 * additions.
1705 */
1706 {
1708
1712
1716
1717 /*
1718 * Only modifications made by this backend affect the horizon for
1719 * temporary relations. Instead of a check in each iteration of the
1720 * loop over all PGPROCs it is cheaper to just initialize to the
1721 * current top-level xid any.
1722 *
1723 * Without an assigned xid we could use a horizon as aggressive as
1724 * GetNewTransactionId(), but we can get away with the much cheaper
1725 * latestCompletedXid + 1: If this backend has no xid there, by
1726 * definition, can't be any newer changes in the temp table than
1727 * latestCompletedXid.
1728 */
1731 else
1733 }
1734
1735 /*
1736 * Fetch slot horizons while ProcArrayLock is held - the
1737 * LWLockAcquire/LWLockRelease are a barrier, ensuring this happens inside
1738 * the lock.
1739 */
1742
1743 for (int index = 0; index < arrayP->numProcs; index++)
1744 {
1745 int pgprocno = arrayP->pgprocnos[index];
1746 PGPROC *proc = &allProcs[pgprocno];
1747 int8 statusFlags = ProcGlobal->statusFlags[index];
1748 TransactionId xid;
1749 TransactionId xmin;
1750
1751 /* Fetch xid just once - see GetNewTransactionId */
1753 xmin = UINT32_ACCESS_ONCE(proc->xmin);
1754
1755 /*
1756 * Consider both the transaction's Xmin, and its Xid.
1757 *
1758 * We must check both because a transaction might have an Xmin but not
1759 * (yet) an Xid; conversely, if it has an Xid, that could determine
1760 * some not-yet-set Xmin.
1761 */
1762 xmin = TransactionIdOlder(xmin, xid);
1763
1764 /* if neither is set, this proc doesn't influence the horizon */
1765 if (!TransactionIdIsValid(xmin))
1766 continue;
1767
1768 /*
1769 * Don't ignore any procs when determining which transactions might be
1770 * considered running. While slots should ensure logical decoding
1771 * backends are protected even without this check, it can't hurt to
1772 * include them here as well..
1773 */
1776
1777 /*
1778 * Skip over backends either vacuuming (which is ok with rows being
1779 * removed, as long as pg_subtrans is not truncated) or doing logical
1780 * decoding (which manages xmin separately, check below).
1781 */
1782 if (statusFlags & (PROC_IN_VACUUM | PROC_IN_LOGICAL_DECODING))
1783 continue;
1784
1785 /* shared tables need to take backends in all databases into account */
1788
1789 /*
1790 * Normally sessions in other databases are ignored for anything but
1791 * the shared horizon.
1792 *
1793 * However, include them when MyDatabaseId is not (yet) set. A
1794 * backend in the process of starting up must not compute a "too
1795 * aggressive" horizon, otherwise we could end up using it to prune
1796 * still-needed data away. If the current backend never connects to a
1797 * database this is harmless, because data_oldest_nonremovable will
1798 * never be utilized.
1799 *
1800 * Also, sessions marked with PROC_AFFECTS_ALL_HORIZONS should always
1801 * be included. (This flag is used for hot standby feedback, which
1802 * can't be tied to a specific database.)
1803 *
1804 * Also, while in recovery we cannot compute an accurate per-database
1805 * horizon, as all xids are managed via the KnownAssignedXids
1806 * machinery.
1807 */
1808 if (proc->databaseId == MyDatabaseId ||
1810 (statusFlags & PROC_AFFECTS_ALL_HORIZONS) ||
1812 {
1815 }
1816 }
1817
1818 /*
1819 * If in recovery fetch oldest xid in KnownAssignedXids, will be applied
1820 * after lock is released.
1821 */
1822 if (in_recovery)
1824
1825 /*
1826 * No other information from shared state is needed, release the lock
1827 * immediately. The rest of the computations can be done without a lock.
1828 */
1830
1831 if (in_recovery)
1832 {
1839 /* temp relations cannot be accessed in recovery */
1840 }
1841
1846
1847 /*
1848 * Check whether there are replication slots requiring an older xmin.
1849 */
1854
1855 /*
1856 * The only difference between catalog / data horizons is that the slot's
1857 * catalog xmin is applied to the catalog one (so catalogs can be accessed
1858 * for logical decoding). Initialize with data horizon, and then back up
1859 * further if necessary. Have to back up the shared horizon as well, since
1860 * that also can contain catalogs.
1861 */
1870
1871 /*
1872 * It's possible that slots backed up the horizons further than
1873 * oldest_considered_running. Fix.
1874 */
1884
1885 /*
1886 * shared horizons have to be at least as old as the oldest visible in
1887 * current db
1888 */
1893
1894 /*
1895 * Horizons need to ensure that pg_subtrans access is still possible for
1896 * the relevant backends.
1897 */
1908 h->slot_xmin));
1911 h->slot_catalog_xmin));
1912
1913 /* update approximate horizons with the computed horizons */
1915}
#define Assert(condition)
Definition c.h:885
int8_t int8
Definition c.h:552
Oid MyDatabaseId
Definition globals.c:94
#define InvalidOid
#define PROC_IN_LOGICAL_DECODING
Definition proc.h:62
#define PROC_AFFECTS_ALL_HORIZONS
Definition proc.h:63
#define PROC_IN_VACUUM
Definition proc.h:59
#define UINT32_ACCESS_ONCE(var)
Definition procarray.c:71
static void GlobalVisUpdateApply(ComputeXidHorizonsResult *horizons)
Definition procarray.c:4177
static TransactionId KnownAssignedXidsGetOldestXmin(void)
Definition procarray.c:5194
PGPROC * MyProc
Definition proc.c:67
TransactionId slot_catalog_xmin
Definition procarray.c:195
TransactionId data_oldest_nonremovable
Definition procarray.c:240
TransactionId temp_oldest_nonremovable
Definition procarray.c:246
TransactionId shared_oldest_nonremovable
Definition procarray.c:217
TransactionId oldest_considered_running
Definition procarray.c:208
TransactionId slot_xmin
Definition procarray.c:194
FullTransactionId latest_completed
Definition procarray.c:188
TransactionId catalog_oldest_nonremovable
Definition procarray.c:234
TransactionId shared_oldest_nonremovable_raw
Definition procarray.c:228
TransactionId xmin
Definition proc.h:234
Oid databaseId
Definition proc.h:193
TransactionId xid
Definition proc.h:229
uint8 * statusFlags
Definition proc.h:456
TransactionId replication_slot_xmin
Definition procarray.c:97
TransactionId replication_slot_catalog_xmin
Definition procarray.c:99
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:396
TransamVariablesData * TransamVariables
Definition varsup.c:34
bool RecoveryInProgress(void)
Definition xlog.c:6460

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

3634{
3636 int count = 0;
3637 int index;
3638
3640
3641 for (index = 0; index < arrayP->numProcs; index++)
3642 {
3643 int pgprocno = arrayP->pgprocnos[index];
3644 PGPROC *proc = &allProcs[pgprocno];
3645
3646 if (proc->pid == 0)
3647 continue; /* do not count prepared xacts */
3648 if (!OidIsValid(databaseid) ||
3649 proc->databaseId == databaseid)
3650 count++;
3651 }
3652
3654
3655 return count;
3656}
#define OidIsValid(objectId)
Definition c.h:800

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

3663{
3665 int count = 0;
3666 int index;
3667
3669
3670 for (index = 0; index < arrayP->numProcs; index++)
3671 {
3672 int pgprocno = arrayP->pgprocnos[index];
3673 PGPROC *proc = &allProcs[pgprocno];
3674
3675 if (proc->pid == 0)
3676 continue; /* do not count prepared xacts */
3677 if (proc->backendType != B_BACKEND)
3678 continue; /* count only regular backend processes */
3679 if (!OidIsValid(databaseid) ||
3680 proc->databaseId == databaseid)
3681 count++;
3682 }
3683
3685
3686 return count;
3687}
@ B_BACKEND
Definition miscadmin.h:342
BackendType backendType
Definition proc.h:190

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

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

3695{
3697 int count = 0;
3698 int index;
3699
3701
3702 for (index = 0; index < arrayP->numProcs; index++)
3703 {
3704 int pgprocno = arrayP->pgprocnos[index];
3705 PGPROC *proc = &allProcs[pgprocno];
3706
3707 if (proc->pid == 0)
3708 continue; /* do not count prepared xacts */
3709 if (proc->backendType != B_BACKEND)
3710 continue; /* count only regular backend processes */
3711 if (proc->roleId == roleid)
3712 count++;
3713 }
3714
3716
3717 return count;
3718}
Oid roleId
Definition proc.h:194

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

4510{
4512
4515
4516 /* Reset latestCompletedXid to nextXid - 1 */
4521
4522 /*
4523 * Any transactions that were in-progress were effectively aborted, so
4524 * advance xactCompletionCount.
4525 */
4527
4528 /*
4529 * Reset lastOverflowedXid. Currently, lastOverflowedXid has no use after
4530 * the call of this function. But do this for unification with what
4531 * ExpireOldKnownAssignedTransactionIds() do.
4532 */
4535}
@ LW_EXCLUSIVE
Definition lwlock.h:112
static void KnownAssignedXidsRemovePreceding(TransactionId removeXid)
Definition procarray.c:5046
TransactionId lastOverflowedXid
Definition procarray.c:94
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 4543 of file procarray.c.

4544{
4546
4548
4549 /* As in ProcArrayEndTransaction, advance latestCompletedXid */
4550 latestXid = xid;
4553
4554 /* ... and xactCompletionCount */
4556
4557 /*
4558 * Reset lastOverflowedXid if we know all transactions that have been
4559 * possibly running are being gone. Not doing so could cause an incorrect
4560 * lastOverflowedXid value, which makes extra snapshots be marked as
4561 * suboverflowed.
4562 */
4567}
static void MaintainLatestCompletedXidRecovery(TransactionId latestXid)
Definition procarray.c:992
#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 4483 of file procarray.c.

4485{
4487
4488 /*
4489 * Uses same locking as transaction commit
4490 */
4492
4494
4495 /* As in ProcArrayEndTransaction, advance latestCompletedXid */
4497
4498 /* ... and xactCompletionCount */
4500
4502}
static void KnownAssignedXidsRemoveTree(TransactionId xid, int nsubxids, TransactionId *subxids)
Definition procarray.c:5024
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 4332 of file procarray.c.

4333{
4335
4338
4339 /* not guaranteed to find issues, but likely to catch mistakes */
4341
4343 + (int32) (xid - rel_xid));
4344}
int32_t int32
Definition c.h:554
#define U64FromFullTransactionId(x)
Definition transam.h:49
static FullTransactionId FullTransactionIdFromU64(uint64 value)
Definition transam.h:81
#define AssertTransactionIdInAllowableRange(xid)
Definition transam.h:363

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

3381{
3384 int count = 0;
3385 int index;
3386
3387 /*
3388 * If first time through, get workspace to remember main XIDs in. We
3389 * malloc it permanently to avoid repeated palloc/pfree overhead. Allow
3390 * result space, remembering room for a terminator.
3391 */
3392 if (vxids == NULL)
3393 {
3395 malloc(sizeof(VirtualTransactionId) * (arrayP->maxProcs + 1));
3396 if (vxids == NULL)
3397 ereport(ERROR,
3399 errmsg("out of memory")));
3400 }
3401
3403
3404 for (index = 0; index < arrayP->numProcs; index++)
3405 {
3406 int pgprocno = arrayP->pgprocnos[index];
3407 PGPROC *proc = &allProcs[pgprocno];
3408
3409 /* Exclude prepared transactions */
3410 if (proc->pid == 0)
3411 continue;
3412
3413 if (!OidIsValid(dbOid) ||
3414 proc->databaseId == dbOid)
3415 {
3416 /* Fetch xmin just once - can't change on us, but good coding */
3418
3419 /*
3420 * We ignore an invalid pxmin because this means that backend has
3421 * no snapshot currently. We hold a Share lock to avoid contention
3422 * with users taking snapshots. That is not a problem because the
3423 * current xmin is always at least one higher than the latest
3424 * removed xid, so any new snapshot would never conflict with the
3425 * test here.
3426 */
3429 {
3431
3432 GET_VXID_FROM_PGPROC(vxid, *proc);
3434 vxids[count++] = vxid;
3435 }
3436 }
3437 }
3438
3440
3441 /* add the terminator */
3442 vxids[count].procNumber = INVALID_PROC_NUMBER;
3443 vxids[count].localTransactionId = InvalidLocalTransactionId;
3444
3445 return vxids;
3446}
int errcode(int sqlerrcode)
Definition elog.c:874
int errmsg(const char *fmt,...)
Definition elog.c:1093
#define ERROR
Definition elog.h:39
#define ereport(elevel,...)
Definition elog.h:150
#define VirtualTransactionIdIsValid(vxid)
Definition lock.h:69
#define GET_VXID_FROM_PGPROC(vxid_dst, proc)
Definition lock.h:79
#define InvalidLocalTransactionId
Definition lock.h:67
#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 3288 of file procarray.c.

3291{
3294 int count = 0;
3295 int index;
3296
3297 /* allocate what's certainly enough result space */
3299
3301
3302 for (index = 0; index < arrayP->numProcs; index++)
3303 {
3304 int pgprocno = arrayP->pgprocnos[index];
3305 PGPROC *proc = &allProcs[pgprocno];
3306 uint8 statusFlags = ProcGlobal->statusFlags[index];
3307
3308 if (proc == MyProc)
3309 continue;
3310
3311 if (excludeVacuum & statusFlags)
3312 continue;
3313
3314 if (allDbs || proc->databaseId == MyDatabaseId)
3315 {
3316 /* Fetch xmin just once - might change on us */
3318
3320 continue;
3321
3322 /*
3323 * InvalidTransactionId precedes all other XIDs, so a proc that
3324 * hasn't set xmin yet will not be rejected by this test.
3325 */
3328 {
3330
3331 GET_VXID_FROM_PGPROC(vxid, *proc);
3333 vxids[count++] = vxid;
3334 }
3335 }
3336 }
3337
3339
3340 *nvxids = count;
3341 return vxids;
3342}
#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 2031 of file procarray.c.

2032{
2034}
#define TOTAL_MAX_CACHED_SUBXIDS

References TOTAL_MAX_CACHED_SUBXIDS.

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

◆ GetMaxSnapshotXidCount()

int GetMaxSnapshotXidCount ( void  )

Definition at line 2020 of file procarray.c.

2021{
2022 return procArray->maxProcs;
2023}

References ProcArrayStruct::maxProcs, and procArray.

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

◆ GetOldestActiveTransactionId()

TransactionId GetOldestActiveTransactionId ( bool  inCommitOnly,
bool  allDbs 
)

Definition at line 2836 of file procarray.c.

2837{
2840 TransactionId oldestRunningXid;
2841 int index;
2842
2844
2845 /*
2846 * Read nextXid, as the upper bound of what's still active.
2847 *
2848 * Reading a TransactionId is atomic, but we must grab the lock to make
2849 * sure that all XIDs < nextXid are already present in the proc array (or
2850 * have already completed), when we spin over it.
2851 */
2855
2856 /*
2857 * Spin over procArray collecting all xids and subxids.
2858 */
2860 for (index = 0; index < arrayP->numProcs; index++)
2861 {
2862 TransactionId xid;
2863 int pgprocno = arrayP->pgprocnos[index];
2864 PGPROC *proc = &allProcs[pgprocno];
2865
2866 /* Fetch xid just once - see GetNewTransactionId */
2868
2869 if (!TransactionIdIsNormal(xid))
2870 continue;
2871
2872 if (inCommitOnly &&
2874 continue;
2875
2876 if (!allDbs && proc->databaseId != MyDatabaseId)
2877 continue;
2878
2879 if (TransactionIdPrecedes(xid, oldestRunningXid))
2880 oldestRunningXid = xid;
2881
2882 /*
2883 * Top-level XID of a transaction is always less than any of its
2884 * subxids, so we don't need to check if any of the subxids are
2885 * smaller than oldestRunningXid
2886 */
2887 }
2889
2890 return oldestRunningXid;
2891}
#define DELAY_CHKPT_IN_COMMIT
Definition proc.h:138
int delayChkptFlags
Definition proc.h:252
#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(), and ProcessStandbyPSRequestMessage().

◆ GetOldestNonRemovableTransactionId()

TransactionId GetOldestNonRemovableTransactionId ( Relation  rel)

Definition at line 1956 of file procarray.c.

1957{
1959
1961
1962 switch (GlobalVisHorizonKindForRel(rel))
1963 {
1964 case VISHORIZON_SHARED:
1965 return horizons.shared_oldest_nonremovable;
1966 case VISHORIZON_CATALOG:
1967 return horizons.catalog_oldest_nonremovable;
1968 case VISHORIZON_DATA:
1969 return horizons.data_oldest_nonremovable;
1970 case VISHORIZON_TEMP:
1971 return horizons.temp_oldest_nonremovable;
1972 }
1973
1974 /* just to prevent compiler warnings */
1975 return InvalidTransactionId;
1976}
static void ComputeXidHorizons(ComputeXidHorizonsResult *h)
Definition procarray.c:1686
static GlobalVisHorizonKind GlobalVisHorizonKindForRel(Relation rel)
Definition procarray.c:1922

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

Referenced by _bt_pendingfsm_finalize(), acquire_sample_rows(), 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 2910 of file procarray.c.

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

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

1986{
1988
1990
1991 return horizons.oldest_considered_running;
1992}

References ComputeXidHorizons(), and fb().

Referenced by CreateCheckPoint(), and CreateRestartPoint().

◆ GetReplicationHorizons()

void GetReplicationHorizons ( TransactionId xmin,
TransactionId catalog_xmin 
)

Definition at line 1998 of file procarray.c.

1999{
2001
2003
2004 /*
2005 * Don't want to use shared_oldest_nonremovable here, as that contains the
2006 * effect of replication slot's catalog_xmin. We want to send a separate
2007 * feedback for the catalog horizon, so the primary can remove data table
2008 * contents more aggressively.
2009 */
2010 *xmin = horizons.shared_oldest_nonremovable_raw;
2011 *catalog_xmin = horizons.slot_catalog_xmin;
2012}

References ComputeXidHorizons(), and fb().

Referenced by XLogWalRcvSendHSFeedback().

◆ GetRunningTransactionData()

RunningTransactions GetRunningTransactionData ( void  )

Definition at line 2640 of file procarray.c.

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

References allProcs, Assert, PGPROC::databaseId, ereport, errcode(), errmsg(), ERROR, fb(), TransamVariablesData::latestCompletedXid, LW_SHARED, LWLockAcquire(), malloc, MyDatabaseId, TransamVariablesData::nextXid, 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 2126 of file procarray.c.

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

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

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

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

3009{
3012 int count = 0;
3013 int index;
3014
3015 Assert(type != 0);
3016
3017 /* allocate what's certainly enough result space */
3019
3021
3022 for (index = 0; index < arrayP->numProcs; index++)
3023 {
3024 int pgprocno = arrayP->pgprocnos[index];
3025 PGPROC *proc = &allProcs[pgprocno];
3026
3027 if ((proc->delayChkptFlags & type) != 0)
3028 {
3030
3031 GET_VXID_FROM_PGPROC(vxid, *proc);
3033 vxids[count++] = vxid;
3034 }
3035 }
3036
3038
3039 *nvxids = count;
3040 return vxids;
3041}
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 4297 of file procarray.c.

4298{
4300
4301 state = GlobalVisTestFor(rel);
4302
4304}
bool GlobalVisTestIsRemovableFullXid(GlobalVisState *state, FullTransactionId fxid)
Definition procarray.c:4233
GlobalVisState * GlobalVisTestFor(Relation rel)
Definition procarray.c:4118

References GlobalVisTestFor(), and GlobalVisTestIsRemovableFullXid().

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

◆ GlobalVisCheckRemovableXid()

bool GlobalVisCheckRemovableXid ( Relation  rel,
TransactionId  xid 
)

Definition at line 4311 of file procarray.c.

4312{
4314
4315 state = GlobalVisTestFor(rel);
4316
4318}
bool GlobalVisTestIsRemovableXid(GlobalVisState *state, TransactionId xid)
Definition procarray.c:4275

References GlobalVisTestFor(), and GlobalVisTestIsRemovableXid().

Referenced by GinPageIsRecyclable().

◆ GlobalVisHorizonKindForRel()

static GlobalVisHorizonKind GlobalVisHorizonKindForRel ( Relation  rel)
inlinestatic

Definition at line 1922 of file procarray.c.

1923{
1924 /*
1925 * Other relkinds currently don't contain xids, nor always the necessary
1926 * logical decoding markers.
1927 */
1928 Assert(!rel ||
1929 rel->rd_rel->relkind == RELKIND_RELATION ||
1930 rel->rd_rel->relkind == RELKIND_MATVIEW ||
1931 rel->rd_rel->relkind == RELKIND_TOASTVALUE);
1932
1933 if (rel == NULL || rel->rd_rel->relisshared || RecoveryInProgress())
1934 return VISHORIZON_SHARED;
1935 else if (IsCatalogRelation(rel) ||
1937 return VISHORIZON_CATALOG;
1938 else if (!RELATION_IS_LOCAL(rel))
1939 return VISHORIZON_DATA;
1940 else
1941 return VISHORIZON_TEMP;
1942}
bool IsCatalogRelation(Relation relation)
Definition catalog.c:104
#define RELATION_IS_LOCAL(relation)
Definition rel.h:657
#define RelationIsAccessibleInLogicalDecoding(relation)
Definition rel.h:693
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 
)

Definition at line 4233 of file procarray.c.

4235{
4236 /*
4237 * If fxid is older than maybe_needed bound, it definitely is visible to
4238 * everyone.
4239 */
4240 if (FullTransactionIdPrecedes(fxid, state->maybe_needed))
4241 return true;
4242
4243 /*
4244 * If fxid is >= definitely_needed bound, it is very likely to still be
4245 * considered running.
4246 */
4247 if (FullTransactionIdFollowsOrEquals(fxid, state->definitely_needed))
4248 return false;
4249
4250 /*
4251 * fxid is between maybe_needed and definitely_needed, i.e. there might or
4252 * might not exist a snapshot considering fxid running. If it makes sense,
4253 * update boundaries and recheck.
4254 */
4256 {
4258
4259 Assert(FullTransactionIdPrecedes(fxid, state->definitely_needed));
4260
4261 return FullTransactionIdPrecedes(fxid, state->maybe_needed);
4262 }
4263 else
4264 return false;
4265}
static bool GlobalVisTestShouldUpdate(GlobalVisState *state)
Definition procarray.c:4158
static void GlobalVisUpdate(void)
Definition procarray.c:4216
#define FullTransactionIdFollowsOrEquals(a, b)
Definition transam.h:54
#define FullTransactionIdPrecedes(a, b)
Definition transam.h:51

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

Referenced by GlobalVisCheckRemovableFullXid(), and GlobalVisTestIsRemovableXid().

◆ GlobalVisTestIsRemovableXid()

bool GlobalVisTestIsRemovableXid ( GlobalVisState state,
TransactionId  xid 
)

Definition at line 4275 of file procarray.c.

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

References FullXidRelativeTo(), and GlobalVisTestIsRemovableFullXid().

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

◆ GlobalVisTestShouldUpdate()

static bool GlobalVisTestShouldUpdate ( GlobalVisState state)
static

Definition at line 4158 of file procarray.c.

4159{
4160 /* hasn't been updated yet */
4162 return true;
4163
4164 /*
4165 * If the maybe_needed/definitely_needed boundaries are the same, it's
4166 * unlikely to be beneficial to refresh boundaries.
4167 */
4168 if (FullTransactionIdFollowsOrEquals(state->maybe_needed,
4169 state->definitely_needed))
4170 return false;
4171
4172 /* does the last snapshot built have a different xmin? */
4174}
static TransactionId ComputeXidHorizonsResultLastXmin
Definition procarray.c:310

References ComputeXidHorizonsResultLastXmin, FullTransactionIdFollowsOrEquals, RecentXmin, and TransactionIdIsValid.

Referenced by GlobalVisTestIsRemovableFullXid().

◆ GlobalVisUpdate()

static void GlobalVisUpdate ( void  )
static

Definition at line 4216 of file procarray.c.

4217{
4219
4220 /* updates the horizons as a side-effect */
4222}

References ComputeXidHorizons(), and fb().

Referenced by GlobalVisTestIsRemovableFullXid().

◆ GlobalVisUpdateApply()

static void GlobalVisUpdateApply ( ComputeXidHorizonsResult horizons)
static

Definition at line 4177 of file procarray.c.

4178{
4180 FullXidRelativeTo(horizons->latest_completed,
4181 horizons->shared_oldest_nonremovable);
4183 FullXidRelativeTo(horizons->latest_completed,
4184 horizons->catalog_oldest_nonremovable);
4186 FullXidRelativeTo(horizons->latest_completed,
4187 horizons->data_oldest_nonremovable);
4189 FullXidRelativeTo(horizons->latest_completed,
4190 horizons->temp_oldest_nonremovable);
4191
4192 /*
4193 * In longer running transactions it's possible that transactions we
4194 * previously needed to treat as running aren't around anymore. So update
4195 * definitely_needed to not be earlier than maybe_needed.
4196 */
4207
4209}

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

3054{
3055 bool result = false;
3057 int index;
3058
3059 Assert(type != 0);
3060
3062
3063 for (index = 0; index < arrayP->numProcs; index++)
3064 {
3065 int pgprocno = arrayP->pgprocnos[index];
3066 PGPROC *proc = &allProcs[pgprocno];
3068
3069 GET_VXID_FROM_PGPROC(vxid, *proc);
3070
3071 if ((proc->delayChkptFlags & type) != 0 &&
3073 {
3074 int i;
3075
3076 for (i = 0; i < nvxids; i++)
3077 {
3079 {
3080 result = true;
3081 break;
3082 }
3083 }
3084 if (result)
3085 break;
3086 }
3087 }
3088
3090
3091 return result;
3092}
int i
Definition isn.c:77
#define VirtualTransactionIdEquals(vxid1, vxid2)
Definition lock.h:73

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

Referenced by CreateCheckPoint().

◆ IsBackendPid()

bool IsBackendPid ( int  pid)

Definition at line 3255 of file procarray.c.

3256{
3257 return (BackendPidGetProc(pid) != NULL);
3258}
PGPROC * BackendPidGetProc(int pid)
Definition procarray.c:3160

References BackendPidGetProc(), and fb().

Referenced by pg_stat_get_subscription().

◆ KnownAssignedTransactionIdsIdleMaintenance()

void KnownAssignedTransactionIdsIdleMaintenance ( void  )

Definition at line 4575 of file procarray.c.

4576{
4578}
static void KnownAssignedXidsCompress(KAXCompressReason reason, bool haveLock)
Definition procarray.c:4676

References KAX_STARTUP_PROCESS_IDLE, and KnownAssignedXidsCompress().

Referenced by WaitForWALToBecomeAvailable().

◆ KnownAssignedXidExists()

static bool KnownAssignedXidExists ( TransactionId  xid)
static

Definition at line 4985 of file procarray.c.

4986{
4988
4989 return KnownAssignedXidsSearch(xid, false);
4990}
static bool KnownAssignedXidsSearch(TransactionId xid, bool remove)
Definition procarray.c:4897

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

4795{
4797 TransactionId next_xid;
4798 int head,
4799 tail;
4800 int nxids;
4801 int i;
4802
4804
4805 /*
4806 * Calculate how many array slots we'll need. Normally this is cheap; in
4807 * the unusual case where the XIDs cross the wrap point, we do it the hard
4808 * way.
4809 */
4810 if (to_xid >= from_xid)
4811 nxids = to_xid - from_xid + 1;
4812 else
4813 {
4814 nxids = 1;
4815 next_xid = from_xid;
4816 while (TransactionIdPrecedes(next_xid, to_xid))
4817 {
4818 nxids++;
4819 TransactionIdAdvance(next_xid);
4820 }
4821 }
4822
4823 /*
4824 * Since only the startup process modifies the head/tail pointers, we
4825 * don't need a lock to read them here.
4826 */
4827 head = pArray->headKnownAssignedXids;
4828 tail = pArray->tailKnownAssignedXids;
4829
4830 Assert(head >= 0 && head <= pArray->maxKnownAssignedXids);
4831 Assert(tail >= 0 && tail < pArray->maxKnownAssignedXids);
4832
4833 /*
4834 * Verify that insertions occur in TransactionId sequence. Note that even
4835 * if the last existing element is marked invalid, it must still have a
4836 * correctly sequenced XID value.
4837 */
4838 if (head > tail &&
4840 {
4842 elog(ERROR, "out-of-order XID insertion in KnownAssignedXids");
4843 }
4844
4845 /*
4846 * If our xids won't fit in the remaining space, compress out free space
4847 */
4848 if (head + nxids > pArray->maxKnownAssignedXids)
4849 {
4851
4852 head = pArray->headKnownAssignedXids;
4853 /* note: we no longer care about the tail pointer */
4854
4855 /*
4856 * If it still won't fit then we're out of memory
4857 */
4858 if (head + nxids > pArray->maxKnownAssignedXids)
4859 elog(ERROR, "too many KnownAssignedXids");
4860 }
4861
4862 /* Now we can insert the xids into the space starting at head */
4863 next_xid = from_xid;
4864 for (i = 0; i < nxids; i++)
4865 {
4866 KnownAssignedXids[head] = next_xid;
4867 KnownAssignedXidsValid[head] = true;
4868 TransactionIdAdvance(next_xid);
4869 head++;
4870 }
4871
4872 /* Adjust count of number of valid entries */
4873 pArray->numKnownAssignedXids += nxids;
4874
4875 /*
4876 * Now update the head pointer. We use a write barrier to ensure that
4877 * other processors see the above array updates before they see the head
4878 * pointer change. The barrier isn't required if we're holding
4879 * ProcArrayLock exclusively.
4880 */
4881 if (!exclusive_lock)
4883
4884 pArray->headKnownAssignedXids = head;
4885}
#define pg_write_barrier()
Definition atomics.h:155
#define LOG
Definition elog.h:31
#define elog(elevel,...)
Definition elog.h:226
static TransactionId * KnownAssignedXids
Definition procarray.c:284
static bool * KnownAssignedXidsValid
Definition procarray.c:285
static void KnownAssignedXidsDisplay(int trace_level)
Definition procarray.c:5229
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 4676 of file procarray.c.

4677{
4679 int head,
4680 tail,
4681 nelements;
4682 int compress_index;
4683 int i;
4684
4685 /* Counters for compression heuristics */
4686 static unsigned int transactionEndsCounter;
4688
4689 /* Tuning constants */
4690#define KAX_COMPRESS_FREQUENCY 128 /* in transactions */
4691#define KAX_COMPRESS_IDLE_INTERVAL 1000 /* in ms */
4692
4693 /*
4694 * Since only the startup process modifies the head/tail pointers, we
4695 * don't need a lock to read them here.
4696 */
4698 tail = pArray->tailKnownAssignedXids;
4699 nelements = head - tail;
4700
4701 /*
4702 * If we can choose whether to compress, use a heuristic to avoid
4703 * compressing too often or not often enough. "Compress" here simply
4704 * means moving the values to the beginning of the array, so it is not as
4705 * complex or costly as typical data compression algorithms.
4706 */
4707 if (nelements == pArray->numKnownAssignedXids)
4708 {
4709 /*
4710 * When there are no gaps between head and tail, don't bother to
4711 * compress, except in the KAX_NO_SPACE case where we must compress to
4712 * create some space after the head.
4713 */
4714 if (reason != KAX_NO_SPACE)
4715 return;
4716 }
4717 else if (reason == KAX_TRANSACTION_END)
4718 {
4719 /*
4720 * Consider compressing only once every so many commits. Frequency
4721 * determined by benchmarks.
4722 */
4724 return;
4725
4726 /*
4727 * Furthermore, compress only if the used part of the array is less
4728 * than 50% full (see comments above).
4729 */
4730 if (nelements < 2 * pArray->numKnownAssignedXids)
4731 return;
4732 }
4733 else if (reason == KAX_STARTUP_PROCESS_IDLE)
4734 {
4735 /*
4736 * We're about to go idle for lack of new WAL, so we might as well
4737 * compress. But not too often, to avoid ProcArray lock contention
4738 * with readers.
4739 */
4740 if (lastCompressTs != 0)
4741 {
4743
4747 return;
4748 }
4749 }
4750
4751 /* Need to compress, so get the lock if we don't have it. */
4752 if (!haveLock)
4754
4755 /*
4756 * We compress the array by reading the valid values from tail to head,
4757 * re-aligning data to 0th element.
4758 */
4759 compress_index = 0;
4760 for (i = tail; i < head; i++)
4761 {
4763 {
4767 }
4768 }
4769 Assert(compress_index == pArray->numKnownAssignedXids);
4770
4771 pArray->tailKnownAssignedXids = 0;
4772 pArray->headKnownAssignedXids = compress_index;
4773
4774 if (!haveLock)
4776
4777 /* Update timestamp for maintenance. No need to hold lock for this. */
4779}
TimestampTz GetCurrentTimestamp(void)
Definition timestamp.c:1645
int64 TimestampTz
Definition timestamp.h:39
#define KAX_COMPRESS_FREQUENCY
#define KAX_COMPRESS_IDLE_INTERVAL
int headKnownAssignedXids
Definition procarray.c:85
#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 5229 of file procarray.c.

5230{
5233 int head,
5234 tail,
5235 i;
5236 int nxids = 0;
5237
5238 tail = pArray->tailKnownAssignedXids;
5239 head = pArray->headKnownAssignedXids;
5240
5242
5243 for (i = tail; i < head; i++)
5244 {
5246 {
5247 nxids++;
5248 appendStringInfo(&buf, "[%d]=%u ", i, KnownAssignedXids[i]);
5249 }
5250 }
5251
5252 elog(trace_level, "%d KnownAssignedXids (num=%d tail=%d head=%d) %s",
5253 nxids,
5254 pArray->numKnownAssignedXids,
5255 pArray->tailKnownAssignedXids,
5256 pArray->headKnownAssignedXids,
5257 buf.data);
5258
5259 pfree(buf.data);
5260}
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 5124 of file procarray.c.

5125{
5127
5129}

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

Referenced by TransactionIdIsInProgress().

◆ KnownAssignedXidsGetAndSetXmin()

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

Definition at line 5138 of file procarray.c.

5140{
5141 int count = 0;
5142 int head,
5143 tail;
5144 int i;
5145
5146 /*
5147 * Fetch head just once, since it may change while we loop. We can stop
5148 * once we reach the initially seen head, since we are certain that an xid
5149 * cannot enter and then leave the array while we hold ProcArrayLock. We
5150 * might miss newly-added xids, but they should be >= xmax so irrelevant
5151 * anyway.
5152 */
5155
5156 pg_read_barrier(); /* pairs with KnownAssignedXidsAdd */
5157
5158 for (i = tail; i < head; i++)
5159 {
5160 /* Skip any gaps in the array */
5162 {
5164
5165 /*
5166 * Update xmin if required. Only the first XID need be checked,
5167 * since the array is sorted.
5168 */
5169 if (count == 0 &&
5171 *xmin = knownXid;
5172
5173 /*
5174 * Filter out anything >= xmax, again relying on sorted property
5175 * of array.
5176 */
5177 if (TransactionIdIsValid(xmax) &&
5179 break;
5180
5181 /* Add knownXid into output array */
5182 xarray[count++] = knownXid;
5183 }
5184 }
5185
5186 return count;
5187}
int tailKnownAssignedXids
Definition procarray.c:84

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

5195{
5196 int head,
5197 tail;
5198 int i;
5199
5200 /*
5201 * Fetch head just once, since it may change while we loop.
5202 */
5205
5206 pg_read_barrier(); /* pairs with KnownAssignedXidsAdd */
5207
5208 for (i = tail; i < head; i++)
5209 {
5210 /* Skip any gaps in the array */
5212 return KnownAssignedXids[i];
5213 }
5214
5215 return InvalidTransactionId;
5216}

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

4999{
5001
5002 elog(DEBUG4, "remove KnownAssignedXid %u", xid);
5003
5004 /*
5005 * Note: we cannot consider it an error to remove an XID that's not
5006 * present. We intentionally remove subxact IDs while processing
5007 * XLOG_XACT_ASSIGNMENT, to avoid array overflow. Then those XIDs will be
5008 * removed again when the top-level xact commits or aborts.
5009 *
5010 * It might be possible to track such XIDs to distinguish this case from
5011 * actual errors, but it would be complicated and probably not worth it.
5012 * So, just ignore the search result.
5013 */
5014 (void) KnownAssignedXidsSearch(xid, true);
5015}
#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 5046 of file procarray.c.

5047{
5049 int count = 0;
5050 int head,
5051 tail,
5052 i;
5053
5055 {
5056 elog(DEBUG4, "removing all KnownAssignedXids");
5057 pArray->numKnownAssignedXids = 0;
5058 pArray->headKnownAssignedXids = pArray->tailKnownAssignedXids = 0;
5059 return;
5060 }
5061
5062 elog(DEBUG4, "prune KnownAssignedXids to %u", removeXid);
5063
5064 /*
5065 * Mark entries invalid starting at the tail. Since array is sorted, we
5066 * can stop as soon as we reach an entry >= removeXid.
5067 */
5068 tail = pArray->tailKnownAssignedXids;
5069 head = pArray->headKnownAssignedXids;
5070
5071 for (i = tail; i < head; i++)
5072 {
5074 {
5076
5078 break;
5079
5081 {
5082 KnownAssignedXidsValid[i] = false;
5083 count++;
5084 }
5085 }
5086 }
5087
5088 pArray->numKnownAssignedXids -= count;
5089 Assert(pArray->numKnownAssignedXids >= 0);
5090
5091 /*
5092 * Advance the tail pointer if we've marked the tail item invalid.
5093 */
5094 for (i = tail; i < head; i++)
5095 {
5097 break;
5098 }
5099 if (i >= head)
5100 {
5101 /* Array is empty, so we can reset both pointers */
5102 pArray->headKnownAssignedXids = 0;
5103 pArray->tailKnownAssignedXids = 0;
5104 }
5105 else
5106 {
5107 pArray->tailKnownAssignedXids = i;
5108 }
5109
5110 /* Opportunistically compress the array */
5112}
bool StandbyTransactionIdIsPrepared(TransactionId xid)
Definition twophase.c:1467

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

5026{
5027 int i;
5028
5029 if (TransactionIdIsValid(xid))
5031
5032 for (i = 0; i < nsubxids; i++)
5033 KnownAssignedXidsRemove(subxids[i]);
5034
5035 /* Opportunistically compress the array */
5037}
static void KnownAssignedXidsRemove(TransactionId xid)
Definition procarray.c:4998

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

Referenced by ExpireTreeKnownAssignedTransactionIds(), and ProcArrayApplyXidAssignment().

◆ KnownAssignedXidsReset()

static void KnownAssignedXidsReset ( void  )
static

Definition at line 5267 of file procarray.c.

5268{
5270
5272
5273 pArray->numKnownAssignedXids = 0;
5274 pArray->tailKnownAssignedXids = 0;
5275 pArray->headKnownAssignedXids = 0;
5276
5278}

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

Referenced by ProcArrayApplyRecoveryInfo().

◆ KnownAssignedXidsSearch()

static bool KnownAssignedXidsSearch ( TransactionId  xid,
bool  remove 
)
static

Definition at line 4897 of file procarray.c.

4898{
4900 int first,
4901 last;
4902 int head;
4903 int tail;
4904 int result_index = -1;
4905
4907 head = pArray->headKnownAssignedXids;
4908
4909 /*
4910 * Only the startup process removes entries, so we don't need the read
4911 * barrier in that case.
4912 */
4913 if (!remove)
4914 pg_read_barrier(); /* pairs with KnownAssignedXidsAdd */
4915
4916 /*
4917 * Standard binary search. Note we can ignore the KnownAssignedXidsValid
4918 * array here, since even invalid entries will contain sorted XIDs.
4919 */
4920 first = tail;
4921 last = head - 1;
4922 while (first <= last)
4923 {
4924 int mid_index;
4926
4927 mid_index = (first + last) / 2;
4929
4930 if (xid == mid_xid)
4931 {
4933 break;
4934 }
4935 else if (TransactionIdPrecedes(xid, mid_xid))
4936 last = mid_index - 1;
4937 else
4938 first = mid_index + 1;
4939 }
4940
4941 if (result_index < 0)
4942 return false; /* not in array */
4943
4945 return false; /* in array, but invalid */
4946
4947 if (remove)
4948 {
4950
4951 pArray->numKnownAssignedXids--;
4952 Assert(pArray->numKnownAssignedXids >= 0);
4953
4954 /*
4955 * If we're removing the tail element then advance tail pointer over
4956 * any invalid elements. This will speed future searches.
4957 */
4958 if (result_index == tail)
4959 {
4960 tail++;
4961 while (tail < head && !KnownAssignedXidsValid[tail])
4962 tail++;
4963 if (tail >= head)
4964 {
4965 /* Array is empty, so we can reset both pointers */
4966 pArray->headKnownAssignedXids = 0;
4967 pArray->tailKnownAssignedXids = 0;
4968 }
4969 else
4970 {
4971 pArray->tailKnownAssignedXids = tail;
4972 }
4973 }
4974 }
4975
4976 return true;
4977}

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

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

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

Referenced by XLogFlush().

◆ ProcArrayAdd()

void ProcArrayAdd ( PGPROC proc)

Definition at line 471 of file procarray.c.

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

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

1058{
1059 TransactionId *xids;
1061 int nxids;
1062 int i;
1063
1068
1069 /*
1070 * Remove stale transactions, if any.
1071 */
1073
1074 /*
1075 * Adjust TransamVariables->nextXid before StandbyReleaseOldLocks(),
1076 * because we will need it up to date for accessing two-phase transactions
1077 * in StandbyReleaseOldLocks().
1078 */
1079 advanceNextXid = running->nextXid;
1083
1084 /*
1085 * Remove stale locks, if any.
1086 */
1088
1089 /*
1090 * If our snapshot is already valid, nothing else to do...
1091 */
1093 return;
1094
1095 /*
1096 * If our initial RunningTransactionsData had an overflowed snapshot then
1097 * we knew we were missing some subxids from our snapshot. If we continue
1098 * to see overflowed snapshots then we might never be able to start up, so
1099 * we make another test to see if our snapshot is now valid. We know that
1100 * the missing subxids are equal to or earlier than nextXid. After we
1101 * initialise we continue to apply changes during recovery, so once the
1102 * oldestRunningXid is later than the nextXid from the initial snapshot we
1103 * know that we no longer have missing information and can mark the
1104 * snapshot as valid.
1105 */
1107 {
1108 /*
1109 * If the snapshot isn't overflowed or if its empty we can reset our
1110 * pending state and use this snapshot instead.
1111 */
1112 if (running->subxid_status != SUBXIDS_MISSING || running->xcnt == 0)
1113 {
1114 /*
1115 * If we have already collected known assigned xids, we need to
1116 * throw them away before we apply the recovery snapshot.
1117 */
1120 }
1121 else
1122 {
1124 running->oldestRunningXid))
1125 {
1127 elog(DEBUG1,
1128 "recovery snapshots are now enabled");
1129 }
1130 else
1131 elog(DEBUG1,
1132 "recovery snapshot waiting for non-overflowed snapshot or "
1133 "until oldest active xid on standby is at least %u (now %u)",
1135 running->oldestRunningXid);
1136 return;
1137 }
1138 }
1139
1141
1142 /*
1143 * NB: this can be reached at least twice, so make sure new code can deal
1144 * with that.
1145 */
1146
1147 /*
1148 * Nobody else is running yet, but take locks anyhow
1149 */
1151
1152 /*
1153 * KnownAssignedXids is sorted so we cannot just add the xids, we have to
1154 * sort them first.
1155 *
1156 * Some of the new xids are top-level xids and some are subtransactions.
1157 * We don't call SubTransSetParent because it doesn't matter yet. If we
1158 * aren't overflowed then all xids will fit in snapshot and so we don't
1159 * need subtrans. If we later overflow, an xid assignment record will add
1160 * xids to subtrans. If RunningTransactionsData is overflowed then we
1161 * don't have enough information to correctly update subtrans anyway.
1162 */
1163
1164 /*
1165 * Allocate a temporary array to avoid modifying the array passed as
1166 * argument.
1167 */
1168 xids = palloc_array(TransactionId, running->xcnt + running->subxcnt);
1169
1170 /*
1171 * Add to the temp array any xids which have not already completed.
1172 */
1173 nxids = 0;
1174 for (i = 0; i < running->xcnt + running->subxcnt; i++)
1175 {
1176 TransactionId xid = running->xids[i];
1177
1178 /*
1179 * The running-xacts snapshot can contain xids that were still visible
1180 * in the procarray when the snapshot was taken, but were already
1181 * WAL-logged as completed. They're not running anymore, so ignore
1182 * them.
1183 */
1185 continue;
1186
1187 xids[nxids++] = xid;
1188 }
1189
1190 if (nxids > 0)
1191 {
1193 {
1195 elog(ERROR, "KnownAssignedXids is not empty");
1196 }
1197
1198 /*
1199 * Sort the array so that we can add them safely into
1200 * KnownAssignedXids.
1201 *
1202 * We have to sort them logically, because in KnownAssignedXidsAdd we
1203 * call TransactionIdFollowsOrEquals and so on. But we know these XIDs
1204 * come from RUNNING_XACTS, which means there are only normal XIDs
1205 * from the same epoch, so this is safe.
1206 */
1208
1209 /*
1210 * Add the sorted snapshot into KnownAssignedXids. The running-xacts
1211 * snapshot may include duplicated xids because of prepared
1212 * transactions, so ignore them.
1213 */
1214 for (i = 0; i < nxids; i++)
1215 {
1216 if (i > 0 && TransactionIdEquals(xids[i - 1], xids[i]))
1217 {
1218 elog(DEBUG1,
1219 "found duplicated transaction %u for KnownAssignedXids insertion",
1220 xids[i]);
1221 continue;
1222 }
1223 KnownAssignedXidsAdd(xids[i], xids[i], true);
1224 }
1225
1227 }
1228
1229 pfree(xids);
1230
1231 /*
1232 * latestObservedXid is at least set to the point where SUBTRANS was
1233 * started up to (cf. ProcArrayInitRecovery()) or to the biggest xid
1234 * RecordKnownAssignedTransactionIds() was called for. Initialize
1235 * subtrans from thereon, up to nextXid - 1.
1236 *
1237 * We need to duplicate parts of RecordKnownAssignedTransactionId() here,
1238 * because we've just added xids to the known assigned xids machinery that
1239 * haven't gone through RecordKnownAssignedTransactionId().
1240 */
1244 {
1247 }
1248 TransactionIdRetreat(latestObservedXid); /* = running->nextXid - 1 */
1249
1250 /* ----------
1251 * Now we've got the running xids we need to set the global values that
1252 * are used to track snapshots as they evolve further.
1253 *
1254 * - latestCompletedXid which will be the xmax for snapshots
1255 * - lastOverflowedXid which shows whether snapshots overflow
1256 * - nextXid
1257 *
1258 * If the snapshot overflowed, then we still initialise with what we know,
1259 * but the recovery snapshot isn't fully valid yet because we know there
1260 * are some subxids missing. We don't know the specific subxids that are
1261 * missing, so conservatively assume the last one is latestObservedXid.
1262 * ----------
1263 */
1264 if (running->subxid_status == SUBXIDS_MISSING)
1265 {
1267
1270 }
1271 else
1272 {
1274
1276
1277 /*
1278 * If the 'xids' array didn't include all subtransactions, we have to
1279 * mark any snapshots taken as overflowed.
1280 */
1281 if (running->subxid_status == SUBXIDS_IN_SUBTRANS)
1283 else
1284 {
1287 }
1288 }
1289
1290 /*
1291 * If a transaction wrote a commit record in the gap between taking and
1292 * logging the snapshot then latestCompletedXid may already be higher than
1293 * the value from the snapshot, so check before we use the incoming value.
1294 * It also might not yet be set at all.
1295 */
1297
1298 /*
1299 * NB: No need to increment TransamVariables->xactCompletionCount here,
1300 * nobody can see it yet.
1301 */
1302
1304
1307 elog(DEBUG1, "recovery snapshots are now enabled");
1308 else
1309 elog(DEBUG1,
1310 "recovery snapshot waiting for non-overflowed snapshot or "
1311 "until oldest active xid on standby is at least %u (now %u)",
1313 running->oldestRunningXid);
1314}
#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:293
static TransactionId latestObservedXid
Definition procarray.c:286
static void KnownAssignedXidsReset(void)
Definition procarray.c:5267
static void KnownAssignedXidsAdd(TransactionId from_xid, TransactionId to_xid, bool exclusive_lock)
Definition procarray.c:4793
void ExpireOldKnownAssignedTransactionIds(TransactionId xid)
Definition procarray.c:4543
void StandbyReleaseOldLocks(TransactionId oldxid)
Definition standby.c:1130
@ SUBXIDS_MISSING
Definition standby.h:119
int numKnownAssignedXids
Definition procarray.c:83
TransactionId oldestRunningXid
Definition standby.h:130
TransactionId nextXid
Definition standby.h:129
TransactionId latestCompletedXid
Definition standby.h:133
subxids_array_status subxid_status
Definition standby.h:128
TransactionId * xids
Definition standby.h:135
void ExtendSUBTRANS(TransactionId newestXact)
Definition subtrans.c:353
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:304
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 1321 of file procarray.c.

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

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

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

671{
673 {
674 /*
675 * We must lock ProcArrayLock while clearing our advertised XID, so
676 * that we do not exit the set of "running" transactions while someone
677 * else is taking a snapshot. See discussion in
678 * src/backend/access/transam/README.
679 */
681
682 /*
683 * If we can immediately acquire ProcArrayLock, we clear our own XID
684 * and release the lock. If not, use group XID clearing to improve
685 * efficiency.
686 */
688 {
691 }
692 else
694 }
695 else
696 {
697 /*
698 * If we have no XID, we don't need to lock, since we won't affect
699 * anyone else's calculation of a snapshot. We might change their
700 * estimate of global xmin, but that's OK.
701 */
703 Assert(proc->subxidStatus.count == 0);
705
708
709 /* be sure this is cleared in abort */
710 proc->delayChkptFlags = 0;
711
713
714 /* must be cleared with xid/xmin: */
715 /* avoid unnecessarily dirtying shared cachelines */
717 {
724 }
725 }
726}
bool LWLockConditionalAcquire(LWLock *lock, LWLockMode mode)
Definition lwlock.c:1347
static void ProcArrayEndTransactionInternal(PGPROC *proc, TransactionId latestXid)
Definition procarray.c:734
static void ProcArrayGroupClearXid(PGPROC *proc, TransactionId latestXid)
Definition procarray.c:795

References Assert, XidCacheStatus::count, PGPROC::delayChkptFlags, fb(), InvalidLocalTransactionId, InvalidTransactionId, LW_EXCLUSIVE, LWLockAcquire(), LWLockConditionalAcquire(), LWLockHeldByMe(), LWLockRelease(), PGPROC::lxid, XidCacheStatus::overflowed, PGPROC::pendingRecoveryConflicts, pg_atomic_write_u32(), 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 734 of file procarray.c.

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

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

3981{
3983
3984 if (xmin != NULL)
3986
3987 if (catalog_xmin != NULL)
3989
3991}

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

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

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

1027{
1030
1031 /*
1032 * we set latestObservedXid to the xid SUBTRANS has been initialized up
1033 * to, so we can extend it from that point onwards in
1034 * RecordKnownAssignedTransactionIds, and when we get consistent in
1035 * ProcArrayApplyRecoveryInfo().
1036 */
1039}

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

Referenced by StartupXLOG().

◆ ProcArrayInstallImportedXmin()

bool ProcArrayInstallImportedXmin ( TransactionId  xmin,
VirtualTransactionId sourcevxid 
)

Definition at line 2483 of file procarray.c.

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

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

Referenced by GetSerializableTransactionSnapshotInt(), and SetTransactionSnapshot().

◆ ProcArrayInstallRestoredXmin()

bool ProcArrayInstallRestoredXmin ( TransactionId  xmin,
PGPROC proc 
)

Definition at line 2567 of file procarray.c.

2568{
2569 bool result = false;
2570 TransactionId xid;
2571
2573 Assert(proc != NULL);
2574
2575 /*
2576 * Get an exclusive lock so that we can copy statusFlags from source proc.
2577 */
2579
2580 /*
2581 * Be certain that the referenced PGPROC has an advertised xmin which is
2582 * no later than the one we're installing, so that the system-wide xmin
2583 * can't go backwards. Also, make sure it's running in the same database,
2584 * so that the per-database xmin cannot go backwards.
2585 */
2586 xid = UINT32_ACCESS_ONCE(proc->xmin);
2587 if (proc->databaseId == MyDatabaseId &&
2588 TransactionIdIsNormal(xid) &&
2590 {
2591 /*
2592 * Install xmin and propagate the statusFlags that affect how the
2593 * value is interpreted by vacuum.
2594 */
2595 MyProc->xmin = TransactionXmin = xmin;
2597 (proc->statusFlags & PROC_XMIN_FLAGS);
2599
2600 result = true;
2601 }
2602
2604
2605 return result;
2606}
#define PROC_XMIN_FLAGS
Definition proc.h:73

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

Referenced by SetTransactionSnapshot().

◆ ProcArrayRemove()

void ProcArrayRemove ( PGPROC proc,
TransactionId  latestXid 
)

Definition at line 568 of file procarray.c.

569{
571 int myoff;
572 int movecount;
573
574#ifdef XIDCACHE_DEBUG
575 /* dump stats at backend shutdown, but not prepared-xact end */
576 if (proc->pid != 0)
578#endif
579
580 /* See ProcGlobal comment explaining why both locks are held */
583
584 myoff = proc->pgxactoff;
585
586 Assert(myoff >= 0 && myoff < arrayP->numProcs);
588
590 {
592
593 /* Advance global latestCompletedXid while holding the lock */
595
596 /* Same with xactCompletionCount */
598
602 }
603 else
604 {
605 /* Shouldn't be trying to remove a live transaction here */
607 }
608
612
614
615 /* Keep the PGPROC array sorted. See notes above */
616 movecount = arrayP->numProcs - myoff - 1;
617 memmove(&arrayP->pgprocnos[myoff],
618 &arrayP->pgprocnos[myoff + 1],
619 movecount * sizeof(*arrayP->pgprocnos));
621 &ProcGlobal->xids[myoff + 1],
622 movecount * sizeof(*ProcGlobal->xids));
625 movecount * sizeof(*ProcGlobal->subxidStates));
628 movecount * sizeof(*ProcGlobal->statusFlags));
629
630 arrayP->pgprocnos[arrayP->numProcs - 1] = -1; /* for debugging */
631 arrayP->numProcs--;
632
633 /*
634 * Adjust pgxactoff of following procs for removed PGPROC (note that
635 * numProcs already has been decremented).
636 */
637 for (int index = myoff; index < arrayP->numProcs; index++)
638 {
639 int procno = arrayP->pgprocnos[index];
640
641 Assert(procno >= 0 && procno < (arrayP->maxProcs + NUM_AUXILIARY_PROCS));
642 Assert(allProcs[procno].pgxactoff - 1 == index);
643
644 allProcs[procno].pgxactoff = index;
645 }
646
647 /*
648 * Release in reversed acquisition order, to reduce frequency of having to
649 * wait for XidGenLock while holding ProcArrayLock.
650 */
653}
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 3954 of file procarray.c.

3956{
3958
3959 if (!already_locked)
3961
3964
3965 if (!already_locked)
3967
3968 elog(DEBUG1, "xmin required by slots: data %u, catalog %u",
3969 xmin, catalog_xmin);
3970}

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

Referenced by ReplicationSlotsComputeRequiredXmin().

◆ ProcArrayShmemInit()

void ProcArrayShmemInit ( void  )

Definition at line 421 of file procarray.c.

422{
423 bool found;
424
425 /* Create or attach to the ProcArray shared structure */
427 ShmemInitStruct("Proc Array",
429 mul_size(sizeof(int),
431 &found);
432
433 if (!found)
434 {
435 /*
436 * We're the first - initialize.
437 */
438 procArray->numProcs = 0;
448 }
449
451
452 /* Create or attach to the KnownAssignedXids arrays too, if needed */
454 {
456 ShmemInitStruct("KnownAssignedXids",
457 mul_size(sizeof(TransactionId),
459 &found);
460 KnownAssignedXidsValid = (bool *)
461 ShmemInitStruct("KnownAssignedXidsValid",
462 mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS),
463 &found);
464 }
465}
#define PROCARRAY_MAXPROCS
Size add_size(Size s1, Size s2)
Definition shmem.c:482
Size mul_size(Size s1, Size s2)
Definition shmem.c:497
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition shmem.c:378
int maxKnownAssignedXids
Definition procarray.c:82
bool EnableHotStandby
Definition xlog.c:124

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

Referenced by CreateOrAttachShmemStructs().

◆ ProcArrayShmemSize()

Size ProcArrayShmemSize ( void  )

Definition at line 379 of file procarray.c.

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

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

Referenced by CalculateShmemSize().

◆ ProcNumberGetProc()

PGPROC * ProcNumberGetProc ( ProcNumber  procNumber)

Definition at line 3102 of file procarray.c.

3103{
3104 PGPROC *result;
3105
3107 return NULL;
3108 result = GetPGProcByNumber(procNumber);
3109
3110 if (result->pid == 0)
3111 return NULL;
3112
3113 return result;
3114}
#define GetPGProcByNumber(n)
Definition proc.h:504
uint32 allProcCount
Definition proc.h:459

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

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

◆ ProcNumberGetTransactionIds()

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

Definition at line 3124 of file procarray.c.

3126{
3127 PGPROC *proc;
3128
3129 *xid = InvalidTransactionId;
3130 *xmin = InvalidTransactionId;
3131 *nsubxid = 0;
3132 *overflowed = false;
3133
3135 return;
3136 proc = GetPGProcByNumber(procNumber);
3137
3138 /* Need to lock out additions/removals of backends */
3140
3141 if (proc->pid != 0)
3142 {
3143 *xid = proc->xid;
3144 *xmin = proc->xmin;
3145 *nsubxid = proc->subxidStatus.count;
3146 *overflowed = proc->subxidStatus.overflowed;
3147 }
3148
3150}

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

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

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

3459{
3460 bool found = false;
3461
3463
3464 /*
3465 * Kill the pid if it's still here. If not, that's what we wanted so
3466 * ignore any errors.
3467 */
3468 if (proc->pid == pid)
3469 {
3470 (void) pg_atomic_fetch_or_u32(&proc->pendingRecoveryConflicts, (1 << reason));
3471
3472 /* wake up the process */
3474 found = true;
3475 }
3476
3478
3479 return found;
3480}
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:285
@ PROCSIG_RECOVERY_CONFLICT
Definition procsignal.h:39

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

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

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

3489{
3491 int index;
3492 pid_t pid = 0;
3493
3495
3496 for (index = 0; index < arrayP->numProcs; index++)
3497 {
3498 int pgprocno = arrayP->pgprocnos[index];
3499 PGPROC *proc = &allProcs[pgprocno];
3501
3503
3504 if (procvxid.procNumber == vxid.procNumber &&
3505 procvxid.localTransactionId == vxid.localTransactionId)
3506 {
3507 pid = proc->pid;
3508 if (pid != 0)
3509 {
3510 (void) pg_atomic_fetch_or_u32(&proc->pendingRecoveryConflicts, (1 << reason));
3511
3512 /*
3513 * Kill the pid if it's still here. If not, that's what we
3514 * wanted so ignore any errors.
3515 */
3517 }
3518 break;
3519 }
3520 }
3521
3523
3524 return pid != 0;
3525}
LocalTransactionId localTransactionId
Definition lock.h:64
ProcNumber procNumber
Definition lock.h:63

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

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

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

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

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

Referenced by TransactionIdIsInProgress().

◆ ComputeXidHorizonsResultLastXmin

TransactionId ComputeXidHorizonsResultLastXmin
static

Definition at line 310 of file procarray.c.

Referenced by GlobalVisTestShouldUpdate(), and GlobalVisUpdateApply().

◆ GlobalVisCatalogRels

GlobalVisState GlobalVisCatalogRels
static

Definition at line 301 of file procarray.c.

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

◆ GlobalVisDataRels

GlobalVisState GlobalVisDataRels
static

Definition at line 302 of file procarray.c.

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

◆ GlobalVisSharedRels

GlobalVisState GlobalVisSharedRels
static

Definition at line 300 of file procarray.c.

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

◆ GlobalVisTempRels

GlobalVisState GlobalVisTempRels
static

Definition at line 303 of file procarray.c.

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

◆ KnownAssignedXids

◆ KnownAssignedXidsValid

◆ latestObservedXid

◆ procArray

◆ standbySnapshotPendingXmin

TransactionId standbySnapshotPendingXmin
static

Definition at line 293 of file procarray.c.

Referenced by ProcArrayApplyRecoveryInfo().