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 "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)
 
pid_t SignalVirtualTransaction (VirtualTransactionId vxid, ProcSignalReason sigmode)
 
bool MinimumActiveBackends (int min)
 
int CountDBBackends (Oid databaseid)
 
int CountDBConnections (Oid databaseid)
 
void CancelDBBackends (Oid databaseid, ProcSignalReason sigmode)
 
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 70 of file procarray.c.

◆ xc_by_child_xid_inc

#define xc_by_child_xid_inc ( )    ((void) 0)

Definition at line 342 of file procarray.c.

◆ xc_by_known_assigned_inc

#define xc_by_known_assigned_inc ( )    ((void) 0)

Definition at line 343 of file procarray.c.

◆ xc_by_known_xact_inc

#define xc_by_known_xact_inc ( )    ((void) 0)

Definition at line 338 of file procarray.c.

◆ xc_by_latest_xid_inc

#define xc_by_latest_xid_inc ( )    ((void) 0)

Definition at line 340 of file procarray.c.

◆ xc_by_main_xid_inc

#define xc_by_main_xid_inc ( )    ((void) 0)

Definition at line 341 of file procarray.c.

◆ xc_by_my_xact_inc

#define xc_by_my_xact_inc ( )    ((void) 0)

Definition at line 339 of file procarray.c.

◆ xc_by_recent_xmin_inc

#define xc_by_recent_xmin_inc ( )    ((void) 0)

Definition at line 337 of file procarray.c.

◆ xc_no_overflow_inc

#define xc_no_overflow_inc ( )    ((void) 0)

Definition at line 344 of file procarray.c.

◆ xc_slow_answer_inc

#define xc_slow_answer_inc ( )    ((void) 0)

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

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

◆ KAXCompressReason

Enumerator
KAX_NO_SPACE 
KAX_PRUNE 
KAX_TRANSACTION_END 
KAX_STARTUP_PROCESS_IDLE 

Definition at line 262 of file procarray.c.

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

Function Documentation

◆ BackendPidGetProc()

PGPROC * BackendPidGetProc ( int  pid)

Definition at line 3154 of file procarray.c.

3155{
3156 PGPROC *result;
3157
3158 if (pid == 0) /* never match dummy PGPROCs */
3159 return NULL;
3160
3162
3163 result = BackendPidGetProcWithLock(pid);
3164
3166
3167 return result;
3168}
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:3177
Definition proc.h:180

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

3178{
3179 PGPROC *result = NULL;
3181 int index;
3182
3183 if (pid == 0) /* never match dummy PGPROCs */
3184 return NULL;
3185
3186 for (index = 0; index < arrayP->numProcs; index++)
3187 {
3188 PGPROC *proc = &allProcs[arrayP->pgprocnos[index]];
3189
3190 if (proc->pid == pid)
3191 {
3192 result = proc;
3193 break;
3194 }
3195 }
3196
3197 return result;
3198}
static PGPROC * allProcs
Definition procarray.c:273
static ProcArrayStruct * procArray
Definition procarray.c:271
int pid
Definition proc.h:200
Definition type.h:96

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

Referenced by BackendPidGetProc(), and GetBlockerStatusData().

◆ BackendXidGetPid()

int BackendXidGetPid ( TransactionId  xid)

Definition at line 3214 of file procarray.c.

3215{
3216 int result = 0;
3219 int index;
3220
3221 if (xid == InvalidTransactionId) /* never match invalid xid */
3222 return 0;
3223
3225
3226 for (index = 0; index < arrayP->numProcs; index++)
3227 {
3228 if (other_xids[index] == xid)
3229 {
3230 int pgprocno = arrayP->pgprocnos[index];
3231 PGPROC *proc = &allProcs[pgprocno];
3232
3233 result = proc->pid;
3234 break;
3235 }
3236 }
3237
3239
3240 return result;
3241}
uint32 TransactionId
Definition c.h:666
PROC_HDR * ProcGlobal
Definition proc.c:79
TransactionId * xids
Definition proc.h:391
#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().

◆ CancelDBBackends()

void CancelDBBackends ( Oid  databaseid,
ProcSignalReason  sigmode 
)

Definition at line 3608 of file procarray.c.

3609{
3611 int index;
3612
3613 /* tell all backends to die */
3615
3616 for (index = 0; index < arrayP->numProcs; index++)
3617 {
3618 int pgprocno = arrayP->pgprocnos[index];
3619 PGPROC *proc = &allProcs[pgprocno];
3620
3621 if (databaseid == InvalidOid || proc->databaseId == databaseid)
3622 {
3624 pid_t pid;
3625
3627
3628 pid = proc->pid;
3629 if (pid != 0)
3630 {
3631 /*
3632 * Kill the pid if it's still here. If not, that's what we
3633 * wanted so ignore any errors.
3634 */
3635 (void) SendProcSignal(pid, sigmode, procvxid.procNumber);
3636 }
3637 }
3638 }
3639
3641}
#define GET_VXID_FROM_PGPROC(vxid_dst, proc)
Definition lock.h:79
@ LW_EXCLUSIVE
Definition lwlock.h:112
#define InvalidOid
int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber)
Definition procsignal.c:284
Oid databaseId
Definition proc.h:225

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

Referenced by ResolveRecoveryConflictWithDatabase(), and SendRecoveryConflictWithBufferPin().

◆ ComputeXidHorizons()

static void ComputeXidHorizons ( ComputeXidHorizonsResult h)
static

Definition at line 1680 of file procarray.c.

1681{
1686
1687 /* inferred after ProcArrayLock is released */
1689
1691
1693
1694 /*
1695 * We initialize the MIN() calculation with latestCompletedXid + 1. This
1696 * is a lower bound for the XIDs that might appear in the ProcArray later,
1697 * and so protects us against overestimating the result due to future
1698 * additions.
1699 */
1700 {
1702
1706
1710
1711 /*
1712 * Only modifications made by this backend affect the horizon for
1713 * temporary relations. Instead of a check in each iteration of the
1714 * loop over all PGPROCs it is cheaper to just initialize to the
1715 * current top-level xid any.
1716 *
1717 * Without an assigned xid we could use a horizon as aggressive as
1718 * GetNewTransactionId(), but we can get away with the much cheaper
1719 * latestCompletedXid + 1: If this backend has no xid there, by
1720 * definition, can't be any newer changes in the temp table than
1721 * latestCompletedXid.
1722 */
1725 else
1727 }
1728
1729 /*
1730 * Fetch slot horizons while ProcArrayLock is held - the
1731 * LWLockAcquire/LWLockRelease are a barrier, ensuring this happens inside
1732 * the lock.
1733 */
1736
1737 for (int index = 0; index < arrayP->numProcs; index++)
1738 {
1739 int pgprocno = arrayP->pgprocnos[index];
1740 PGPROC *proc = &allProcs[pgprocno];
1741 int8 statusFlags = ProcGlobal->statusFlags[index];
1742 TransactionId xid;
1743 TransactionId xmin;
1744
1745 /* Fetch xid just once - see GetNewTransactionId */
1747 xmin = UINT32_ACCESS_ONCE(proc->xmin);
1748
1749 /*
1750 * Consider both the transaction's Xmin, and its Xid.
1751 *
1752 * We must check both because a transaction might have an Xmin but not
1753 * (yet) an Xid; conversely, if it has an Xid, that could determine
1754 * some not-yet-set Xmin.
1755 */
1756 xmin = TransactionIdOlder(xmin, xid);
1757
1758 /* if neither is set, this proc doesn't influence the horizon */
1759 if (!TransactionIdIsValid(xmin))
1760 continue;
1761
1762 /*
1763 * Don't ignore any procs when determining which transactions might be
1764 * considered running. While slots should ensure logical decoding
1765 * backends are protected even without this check, it can't hurt to
1766 * include them here as well..
1767 */
1770
1771 /*
1772 * Skip over backends either vacuuming (which is ok with rows being
1773 * removed, as long as pg_subtrans is not truncated) or doing logical
1774 * decoding (which manages xmin separately, check below).
1775 */
1776 if (statusFlags & (PROC_IN_VACUUM | PROC_IN_LOGICAL_DECODING))
1777 continue;
1778
1779 /* shared tables need to take backends in all databases into account */
1782
1783 /*
1784 * Normally sessions in other databases are ignored for anything but
1785 * the shared horizon.
1786 *
1787 * However, include them when MyDatabaseId is not (yet) set. A
1788 * backend in the process of starting up must not compute a "too
1789 * aggressive" horizon, otherwise we could end up using it to prune
1790 * still-needed data away. If the current backend never connects to a
1791 * database this is harmless, because data_oldest_nonremovable will
1792 * never be utilized.
1793 *
1794 * Also, sessions marked with PROC_AFFECTS_ALL_HORIZONS should always
1795 * be included. (This flag is used for hot standby feedback, which
1796 * can't be tied to a specific database.)
1797 *
1798 * Also, while in recovery we cannot compute an accurate per-database
1799 * horizon, as all xids are managed via the KnownAssignedXids
1800 * machinery.
1801 */
1802 if (proc->databaseId == MyDatabaseId ||
1804 (statusFlags & PROC_AFFECTS_ALL_HORIZONS) ||
1806 {
1809 }
1810 }
1811
1812 /*
1813 * If in recovery fetch oldest xid in KnownAssignedXids, will be applied
1814 * after lock is released.
1815 */
1816 if (in_recovery)
1818
1819 /*
1820 * No other information from shared state is needed, release the lock
1821 * immediately. The rest of the computations can be done without a lock.
1822 */
1824
1825 if (in_recovery)
1826 {
1833 /* temp relations cannot be accessed in recovery */
1834 }
1835
1840
1841 /*
1842 * Check whether there are replication slots requiring an older xmin.
1843 */
1848
1849 /*
1850 * The only difference between catalog / data horizons is that the slot's
1851 * catalog xmin is applied to the catalog one (so catalogs can be accessed
1852 * for logical decoding). Initialize with data horizon, and then back up
1853 * further if necessary. Have to back up the shared horizon as well, since
1854 * that also can contain catalogs.
1855 */
1864
1865 /*
1866 * It's possible that slots backed up the horizons further than
1867 * oldest_considered_running. Fix.
1868 */
1878
1879 /*
1880 * shared horizons have to be at least as old as the oldest visible in
1881 * current db
1882 */
1887
1888 /*
1889 * Horizons need to ensure that pg_subtrans access is still possible for
1890 * the relevant backends.
1891 */
1902 h->slot_xmin));
1905 h->slot_catalog_xmin));
1906
1907 /* update approximate horizons with the computed horizons */
1909}
#define Assert(condition)
Definition c.h:873
int8_t int8
Definition c.h:540
Oid MyDatabaseId
Definition globals.c:94
#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:70
static void GlobalVisUpdateApply(ComputeXidHorizonsResult *horizons)
Definition procarray.c:4131
static TransactionId KnownAssignedXidsGetOldestXmin(void)
Definition procarray.c:5148
PGPROC * MyProc
Definition proc.c:67
TransactionId slot_catalog_xmin
Definition procarray.c:194
TransactionId data_oldest_nonremovable
Definition procarray.c:239
TransactionId temp_oldest_nonremovable
Definition procarray.c:245
TransactionId shared_oldest_nonremovable
Definition procarray.c:216
TransactionId oldest_considered_running
Definition procarray.c:207
TransactionId slot_xmin
Definition procarray.c:193
FullTransactionId latest_completed
Definition procarray.c:187
TransactionId catalog_oldest_nonremovable
Definition procarray.c:233
TransactionId shared_oldest_nonremovable_raw
Definition procarray.c:227
TransactionId xmin
Definition proc.h:195
TransactionId xid
Definition proc.h:190
uint8 * statusFlags
Definition proc.h:403
TransactionId replication_slot_xmin
Definition procarray.c:96
TransactionId replication_slot_catalog_xmin
Definition procarray.c:98
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 3548 of file procarray.c.

3549{
3551 int count = 0;
3552 int index;
3553
3555
3556 for (index = 0; index < arrayP->numProcs; index++)
3557 {
3558 int pgprocno = arrayP->pgprocnos[index];
3559 PGPROC *proc = &allProcs[pgprocno];
3560
3561 if (proc->pid == 0)
3562 continue; /* do not count prepared xacts */
3563 if (!OidIsValid(databaseid) ||
3564 proc->databaseId == databaseid)
3565 count++;
3566 }
3567
3569
3570 return count;
3571}
#define OidIsValid(objectId)
Definition c.h:788

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

3578{
3580 int count = 0;
3581 int index;
3582
3584
3585 for (index = 0; index < arrayP->numProcs; index++)
3586 {
3587 int pgprocno = arrayP->pgprocnos[index];
3588 PGPROC *proc = &allProcs[pgprocno];
3589
3590 if (proc->pid == 0)
3591 continue; /* do not count prepared xacts */
3592 if (proc->backendType != B_BACKEND)
3593 continue; /* count only regular backend processes */
3594 if (!OidIsValid(databaseid) ||
3595 proc->databaseId == databaseid)
3596 count++;
3597 }
3598
3600
3601 return count;
3602}
@ B_BACKEND
Definition miscadmin.h:342
BackendType backendType
Definition proc.h:231

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

3701{
3703
3704#define MAXAUTOVACPIDS 10 /* max autovacs to SIGTERM per iteration */
3706
3707 /*
3708 * Retry up to 50 times with 100ms between attempts (max 5s total). Can be
3709 * reduced to 3 attempts (max 0.3s total) to speed up tests.
3710 */
3711 int ntries = 50;
3712
3713#ifdef USE_INJECTION_POINTS
3714 if (IS_INJECTION_POINT_ATTACHED("procarray-reduce-count"))
3715 ntries = 3;
3716#endif
3717
3718 for (int tries = 0; tries < ntries; tries++)
3719 {
3720 int nautovacs = 0;
3721 bool found = false;
3722 int index;
3723
3725
3726 *nbackends = *nprepared = 0;
3727
3729
3730 for (index = 0; index < arrayP->numProcs; index++)
3731 {
3732 int pgprocno = arrayP->pgprocnos[index];
3733 PGPROC *proc = &allProcs[pgprocno];
3734 uint8 statusFlags = ProcGlobal->statusFlags[index];
3735
3736 if (proc->databaseId != databaseId)
3737 continue;
3738 if (proc == MyProc)
3739 continue;
3740
3741 found = true;
3742
3743 if (proc->pid == 0)
3744 (*nprepared)++;
3745 else
3746 {
3747 (*nbackends)++;
3748 if ((statusFlags & PROC_IS_AUTOVACUUM) &&
3750 autovac_pids[nautovacs++] = proc->pid;
3751 }
3752 }
3753
3755
3756 if (!found)
3757 return false; /* no conflicting backends, so done */
3758
3759 /*
3760 * Send SIGTERM to any conflicting autovacuums before sleeping. We
3761 * postpone this step until after the loop because we don't want to
3762 * hold ProcArrayLock while issuing kill(). We have no idea what might
3763 * block kill() inside the kernel...
3764 */
3765 for (index = 0; index < nautovacs; index++)
3766 (void) kill(autovac_pids[index], SIGTERM); /* ignore any error */
3767
3768 /*
3769 * Terminate all background workers for this database, if they have
3770 * requested it (BGWORKER_INTERRUPTIBLE).
3771 */
3773
3774 /* sleep, then try again */
3775 pg_usleep(100 * 1000L); /* 100ms */
3776 }
3777
3778 return true; /* timed out, still conflicts */
3779}
void TerminateBackgroundWorkersForDatabase(Oid databaseId)
Definition bgworker.c:1425
uint8_t uint8
Definition c.h:544
#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 3648 of file procarray.c.

3649{
3651 int count = 0;
3652 int index;
3653
3655
3656 for (index = 0; index < arrayP->numProcs; index++)
3657 {
3658 int pgprocno = arrayP->pgprocnos[index];
3659 PGPROC *proc = &allProcs[pgprocno];
3660
3661 if (proc->pid == 0)
3662 continue; /* do not count prepared xacts */
3663 if (proc->backendType != B_BACKEND)
3664 continue; /* count only regular backend processes */
3665 if (proc->roleId == roleid)
3666 count++;
3667 }
3668
3670
3671 return count;
3672}
Oid roleId
Definition proc.h:226

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

4464{
4466
4469
4470 /* Reset latestCompletedXid to nextXid - 1 */
4475
4476 /*
4477 * Any transactions that were in-progress were effectively aborted, so
4478 * advance xactCompletionCount.
4479 */
4481
4482 /*
4483 * Reset lastOverflowedXid. Currently, lastOverflowedXid has no use after
4484 * the call of this function. But do this for unification with what
4485 * ExpireOldKnownAssignedTransactionIds() do.
4486 */
4489}
static void KnownAssignedXidsRemovePreceding(TransactionId removeXid)
Definition procarray.c:5000
TransactionId lastOverflowedXid
Definition procarray.c:93
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 4497 of file procarray.c.

4498{
4500
4502
4503 /* As in ProcArrayEndTransaction, advance latestCompletedXid */
4504 latestXid = xid;
4507
4508 /* ... and xactCompletionCount */
4510
4511 /*
4512 * Reset lastOverflowedXid if we know all transactions that have been
4513 * possibly running are being gone. Not doing so could cause an incorrect
4514 * lastOverflowedXid value, which makes extra snapshots be marked as
4515 * suboverflowed.
4516 */
4521}
static void MaintainLatestCompletedXidRecovery(TransactionId latestXid)
Definition procarray.c:986
#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 4437 of file procarray.c.

4439{
4441
4442 /*
4443 * Uses same locking as transaction commit
4444 */
4446
4448
4449 /* As in ProcArrayEndTransaction, advance latestCompletedXid */
4451
4452 /* ... and xactCompletionCount */
4454
4456}
static void KnownAssignedXidsRemoveTree(TransactionId xid, int nsubxids, TransactionId *subxids)
Definition procarray.c:4978
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 4286 of file procarray.c.

4287{
4289
4292
4293 /* not guaranteed to find issues, but likely to catch mistakes */
4295
4297 + (int32) (xid - rel_xid));
4298}
int32_t int32
Definition c.h:542
#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 3374 of file procarray.c.

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

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

2026{
2028}
#define TOTAL_MAX_CACHED_SUBXIDS

References TOTAL_MAX_CACHED_SUBXIDS.

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

◆ GetMaxSnapshotXidCount()

int GetMaxSnapshotXidCount ( void  )

Definition at line 2014 of file procarray.c.

2015{
2016 return procArray->maxProcs;
2017}

References ProcArrayStruct::maxProcs, and procArray.

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

◆ GetOldestActiveTransactionId()

TransactionId GetOldestActiveTransactionId ( bool  inCommitOnly,
bool  allDbs 
)

Definition at line 2830 of file procarray.c.

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

1951{
1953
1955
1956 switch (GlobalVisHorizonKindForRel(rel))
1957 {
1958 case VISHORIZON_SHARED:
1959 return horizons.shared_oldest_nonremovable;
1960 case VISHORIZON_CATALOG:
1961 return horizons.catalog_oldest_nonremovable;
1962 case VISHORIZON_DATA:
1963 return horizons.data_oldest_nonremovable;
1964 case VISHORIZON_TEMP:
1965 return horizons.temp_oldest_nonremovable;
1966 }
1967
1968 /* just to prevent compiler warnings */
1969 return InvalidTransactionId;
1970}
static void ComputeXidHorizons(ComputeXidHorizonsResult *h)
Definition procarray.c:1680
static GlobalVisHorizonKind GlobalVisHorizonKindForRel(Relation rel)
Definition procarray.c:1916

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

2905{
2908 int index;
2910
2912
2913 /*
2914 * Acquire XidGenLock, so no transactions can acquire an xid while we're
2915 * running. If no transaction with xid were running concurrently a new xid
2916 * could influence the RecentXmin et al.
2917 *
2918 * We initialize the computation to nextXid since that's guaranteed to be
2919 * a safe, albeit pessimal, value.
2920 */
2923
2924 /*
2925 * If there's already a slot pegging the xmin horizon, we can start with
2926 * that value, it's guaranteed to be safe since it's computed by this
2927 * routine initially and has been enforced since. We can always use the
2928 * slot's general xmin horizon, but the catalog horizon is only usable
2929 * when only catalog data is going to be looked at.
2930 */
2935
2936 if (catalogOnly &&
2941
2942 /*
2943 * If we're not in recovery, we walk over the procarray and collect the
2944 * lowest xid. Since we're called with ProcArrayLock held and have
2945 * acquired XidGenLock, no entries can vanish concurrently, since
2946 * ProcGlobal->xids[i] is only set with XidGenLock held and only cleared
2947 * with ProcArrayLock held.
2948 *
2949 * In recovery we can't lower the safe value besides what we've computed
2950 * above, so we'll have to wait a bit longer there. We unfortunately can
2951 * *not* use KnownAssignedXidsGetOldestXmin() since the KnownAssignedXids
2952 * machinery can miss values and return an older value than is safe.
2953 */
2955 {
2957
2958 /*
2959 * Spin over procArray collecting min(ProcGlobal->xids[i])
2960 */
2961 for (index = 0; index < arrayP->numProcs; index++)
2962 {
2963 TransactionId xid;
2964
2965 /* Fetch xid just once - see GetNewTransactionId */
2967
2968 if (!TransactionIdIsNormal(xid))
2969 continue;
2970
2972 oldestSafeXid = xid;
2973 }
2974 }
2975
2977
2978 return oldestSafeXid;
2979}
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 1979 of file procarray.c.

1980{
1982
1984
1985 return horizons.oldest_considered_running;
1986}

References ComputeXidHorizons(), and fb().

Referenced by CreateCheckPoint(), and CreateRestartPoint().

◆ GetReplicationHorizons()

void GetReplicationHorizons ( TransactionId xmin,
TransactionId catalog_xmin 
)

Definition at line 1992 of file procarray.c.

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

References ComputeXidHorizons(), and fb().

Referenced by XLogWalRcvSendHSFeedback().

◆ GetRunningTransactionData()

RunningTransactions GetRunningTransactionData ( void  )

Definition at line 2634 of file procarray.c.

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

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

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

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

3003{
3006 int count = 0;
3007 int index;
3008
3009 Assert(type != 0);
3010
3011 /* allocate what's certainly enough result space */
3013
3015
3016 for (index = 0; index < arrayP->numProcs; index++)
3017 {
3018 int pgprocno = arrayP->pgprocnos[index];
3019 PGPROC *proc = &allProcs[pgprocno];
3020
3021 if ((proc->delayChkptFlags & type) != 0)
3022 {
3024
3025 GET_VXID_FROM_PGPROC(vxid, *proc);
3027 vxids[count++] = vxid;
3028 }
3029 }
3030
3032
3033 *nvxids = count;
3034 return vxids;
3035}
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 4251 of file procarray.c.

4252{
4254
4255 state = GlobalVisTestFor(rel);
4256
4258}
bool GlobalVisTestIsRemovableFullXid(GlobalVisState *state, FullTransactionId fxid)
Definition procarray.c:4187
GlobalVisState * GlobalVisTestFor(Relation rel)
Definition procarray.c:4072

References GlobalVisTestFor(), and GlobalVisTestIsRemovableFullXid().

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

◆ GlobalVisCheckRemovableXid()

bool GlobalVisCheckRemovableXid ( Relation  rel,
TransactionId  xid 
)

Definition at line 4265 of file procarray.c.

4266{
4268
4269 state = GlobalVisTestFor(rel);
4270
4272}
bool GlobalVisTestIsRemovableXid(GlobalVisState *state, TransactionId xid)
Definition procarray.c:4229

References GlobalVisTestFor(), and GlobalVisTestIsRemovableXid().

Referenced by GinPageIsRecyclable().

◆ GlobalVisHorizonKindForRel()

static GlobalVisHorizonKind GlobalVisHorizonKindForRel ( Relation  rel)
inlinestatic

Definition at line 1916 of file procarray.c.

1917{
1918 /*
1919 * Other relkinds currently don't contain xids, nor always the necessary
1920 * logical decoding markers.
1921 */
1922 Assert(!rel ||
1923 rel->rd_rel->relkind == RELKIND_RELATION ||
1924 rel->rd_rel->relkind == RELKIND_MATVIEW ||
1925 rel->rd_rel->relkind == RELKIND_TOASTVALUE);
1926
1927 if (rel == NULL || rel->rd_rel->relisshared || RecoveryInProgress())
1928 return VISHORIZON_SHARED;
1929 else if (IsCatalogRelation(rel) ||
1931 return VISHORIZON_CATALOG;
1932 else if (!RELATION_IS_LOCAL(rel))
1933 return VISHORIZON_DATA;
1934 else
1935 return VISHORIZON_TEMP;
1936}
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 4187 of file procarray.c.

4189{
4190 /*
4191 * If fxid is older than maybe_needed bound, it definitely is visible to
4192 * everyone.
4193 */
4194 if (FullTransactionIdPrecedes(fxid, state->maybe_needed))
4195 return true;
4196
4197 /*
4198 * If fxid is >= definitely_needed bound, it is very likely to still be
4199 * considered running.
4200 */
4201 if (FullTransactionIdFollowsOrEquals(fxid, state->definitely_needed))
4202 return false;
4203
4204 /*
4205 * fxid is between maybe_needed and definitely_needed, i.e. there might or
4206 * might not exist a snapshot considering fxid running. If it makes sense,
4207 * update boundaries and recheck.
4208 */
4210 {
4212
4213 Assert(FullTransactionIdPrecedes(fxid, state->definitely_needed));
4214
4215 return FullTransactionIdPrecedes(fxid, state->maybe_needed);
4216 }
4217 else
4218 return false;
4219}
static bool GlobalVisTestShouldUpdate(GlobalVisState *state)
Definition procarray.c:4112
static void GlobalVisUpdate(void)
Definition procarray.c:4170
#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 4229 of file procarray.c.

4230{
4231 FullTransactionId fxid;
4232
4233 /*
4234 * Convert 32 bit argument to FullTransactionId. We can do so safely
4235 * because we know the xid has to, at the very least, be between
4236 * [oldestXid, nextXid), i.e. within 2 billion of xid. To avoid taking a
4237 * lock to determine either, we can just compare with
4238 * state->definitely_needed, which was based on those value at the time
4239 * the current snapshot was built.
4240 */
4241 fxid = FullXidRelativeTo(state->definitely_needed, xid);
4242
4244}

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

4113{
4114 /* hasn't been updated yet */
4116 return true;
4117
4118 /*
4119 * If the maybe_needed/definitely_needed boundaries are the same, it's
4120 * unlikely to be beneficial to refresh boundaries.
4121 */
4122 if (FullTransactionIdFollowsOrEquals(state->maybe_needed,
4123 state->definitely_needed))
4124 return false;
4125
4126 /* does the last snapshot built have a different xmin? */
4128}
static TransactionId ComputeXidHorizonsResultLastXmin
Definition procarray.c:309

References ComputeXidHorizonsResultLastXmin, FullTransactionIdFollowsOrEquals, RecentXmin, and TransactionIdIsValid.

Referenced by GlobalVisTestIsRemovableFullXid().

◆ GlobalVisUpdate()

static void GlobalVisUpdate ( void  )
static

Definition at line 4170 of file procarray.c.

4171{
4173
4174 /* updates the horizons as a side-effect */
4176}

References ComputeXidHorizons(), and fb().

Referenced by GlobalVisTestIsRemovableFullXid().

◆ GlobalVisUpdateApply()

static void GlobalVisUpdateApply ( ComputeXidHorizonsResult horizons)
static

Definition at line 4131 of file procarray.c.

4132{
4134 FullXidRelativeTo(horizons->latest_completed,
4135 horizons->shared_oldest_nonremovable);
4137 FullXidRelativeTo(horizons->latest_completed,
4138 horizons->catalog_oldest_nonremovable);
4140 FullXidRelativeTo(horizons->latest_completed,
4141 horizons->data_oldest_nonremovable);
4143 FullXidRelativeTo(horizons->latest_completed,
4144 horizons->temp_oldest_nonremovable);
4145
4146 /*
4147 * In longer running transactions it's possible that transactions we
4148 * previously needed to treat as running aren't around anymore. So update
4149 * definitely_needed to not be earlier than maybe_needed.
4150 */
4161
4163}

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

3048{
3049 bool result = false;
3051 int index;
3052
3053 Assert(type != 0);
3054
3056
3057 for (index = 0; index < arrayP->numProcs; index++)
3058 {
3059 int pgprocno = arrayP->pgprocnos[index];
3060 PGPROC *proc = &allProcs[pgprocno];
3062
3063 GET_VXID_FROM_PGPROC(vxid, *proc);
3064
3065 if ((proc->delayChkptFlags & type) != 0 &&
3067 {
3068 int i;
3069
3070 for (i = 0; i < nvxids; i++)
3071 {
3073 {
3074 result = true;
3075 break;
3076 }
3077 }
3078 if (result)
3079 break;
3080 }
3081 }
3082
3084
3085 return result;
3086}
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 3249 of file procarray.c.

3250{
3251 return (BackendPidGetProc(pid) != NULL);
3252}
PGPROC * BackendPidGetProc(int pid)
Definition procarray.c:3154

References BackendPidGetProc(), and fb().

Referenced by pg_stat_get_subscription().

◆ KnownAssignedTransactionIdsIdleMaintenance()

void KnownAssignedTransactionIdsIdleMaintenance ( void  )

Definition at line 4529 of file procarray.c.

4530{
4532}
static void KnownAssignedXidsCompress(KAXCompressReason reason, bool haveLock)
Definition procarray.c:4630

References KAX_STARTUP_PROCESS_IDLE, and KnownAssignedXidsCompress().

Referenced by WaitForWALToBecomeAvailable().

◆ KnownAssignedXidExists()

static bool KnownAssignedXidExists ( TransactionId  xid)
static

Definition at line 4939 of file procarray.c.

4940{
4942
4943 return KnownAssignedXidsSearch(xid, false);
4944}
static bool KnownAssignedXidsSearch(TransactionId xid, bool remove)
Definition procarray.c:4851

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

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

4631{
4633 int head,
4634 tail,
4635 nelements;
4636 int compress_index;
4637 int i;
4638
4639 /* Counters for compression heuristics */
4640 static unsigned int transactionEndsCounter;
4642
4643 /* Tuning constants */
4644#define KAX_COMPRESS_FREQUENCY 128 /* in transactions */
4645#define KAX_COMPRESS_IDLE_INTERVAL 1000 /* in ms */
4646
4647 /*
4648 * Since only the startup process modifies the head/tail pointers, we
4649 * don't need a lock to read them here.
4650 */
4652 tail = pArray->tailKnownAssignedXids;
4653 nelements = head - tail;
4654
4655 /*
4656 * If we can choose whether to compress, use a heuristic to avoid
4657 * compressing too often or not often enough. "Compress" here simply
4658 * means moving the values to the beginning of the array, so it is not as
4659 * complex or costly as typical data compression algorithms.
4660 */
4661 if (nelements == pArray->numKnownAssignedXids)
4662 {
4663 /*
4664 * When there are no gaps between head and tail, don't bother to
4665 * compress, except in the KAX_NO_SPACE case where we must compress to
4666 * create some space after the head.
4667 */
4668 if (reason != KAX_NO_SPACE)
4669 return;
4670 }
4671 else if (reason == KAX_TRANSACTION_END)
4672 {
4673 /*
4674 * Consider compressing only once every so many commits. Frequency
4675 * determined by benchmarks.
4676 */
4678 return;
4679
4680 /*
4681 * Furthermore, compress only if the used part of the array is less
4682 * than 50% full (see comments above).
4683 */
4684 if (nelements < 2 * pArray->numKnownAssignedXids)
4685 return;
4686 }
4687 else if (reason == KAX_STARTUP_PROCESS_IDLE)
4688 {
4689 /*
4690 * We're about to go idle for lack of new WAL, so we might as well
4691 * compress. But not too often, to avoid ProcArray lock contention
4692 * with readers.
4693 */
4694 if (lastCompressTs != 0)
4695 {
4697
4701 return;
4702 }
4703 }
4704
4705 /* Need to compress, so get the lock if we don't have it. */
4706 if (!haveLock)
4708
4709 /*
4710 * We compress the array by reading the valid values from tail to head,
4711 * re-aligning data to 0th element.
4712 */
4713 compress_index = 0;
4714 for (i = tail; i < head; i++)
4715 {
4717 {
4721 }
4722 }
4723 Assert(compress_index == pArray->numKnownAssignedXids);
4724
4725 pArray->tailKnownAssignedXids = 0;
4726 pArray->headKnownAssignedXids = compress_index;
4727
4728 if (!haveLock)
4730
4731 /* Update timestamp for maintenance. No need to hold lock for this. */
4733}
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:84
#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 5183 of file procarray.c.

5184{
5187 int head,
5188 tail,
5189 i;
5190 int nxids = 0;
5191
5192 tail = pArray->tailKnownAssignedXids;
5193 head = pArray->headKnownAssignedXids;
5194
5196
5197 for (i = tail; i < head; i++)
5198 {
5200 {
5201 nxids++;
5202 appendStringInfo(&buf, "[%d]=%u ", i, KnownAssignedXids[i]);
5203 }
5204 }
5205
5206 elog(trace_level, "%d KnownAssignedXids (num=%d tail=%d head=%d) %s",
5207 nxids,
5208 pArray->numKnownAssignedXids,
5209 pArray->tailKnownAssignedXids,
5210 pArray->headKnownAssignedXids,
5211 buf.data);
5212
5213 pfree(buf.data);
5214}
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 5078 of file procarray.c.

5079{
5081
5083}

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

Referenced by TransactionIdIsInProgress().

◆ KnownAssignedXidsGetAndSetXmin()

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

Definition at line 5092 of file procarray.c.

5094{
5095 int count = 0;
5096 int head,
5097 tail;
5098 int i;
5099
5100 /*
5101 * Fetch head just once, since it may change while we loop. We can stop
5102 * once we reach the initially seen head, since we are certain that an xid
5103 * cannot enter and then leave the array while we hold ProcArrayLock. We
5104 * might miss newly-added xids, but they should be >= xmax so irrelevant
5105 * anyway.
5106 */
5109
5110 pg_read_barrier(); /* pairs with KnownAssignedXidsAdd */
5111
5112 for (i = tail; i < head; i++)
5113 {
5114 /* Skip any gaps in the array */
5116 {
5118
5119 /*
5120 * Update xmin if required. Only the first XID need be checked,
5121 * since the array is sorted.
5122 */
5123 if (count == 0 &&
5125 *xmin = knownXid;
5126
5127 /*
5128 * Filter out anything >= xmax, again relying on sorted property
5129 * of array.
5130 */
5131 if (TransactionIdIsValid(xmax) &&
5133 break;
5134
5135 /* Add knownXid into output array */
5136 xarray[count++] = knownXid;
5137 }
5138 }
5139
5140 return count;
5141}
int tailKnownAssignedXids
Definition procarray.c:83

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

5149{
5150 int head,
5151 tail;
5152 int i;
5153
5154 /*
5155 * Fetch head just once, since it may change while we loop.
5156 */
5159
5160 pg_read_barrier(); /* pairs with KnownAssignedXidsAdd */
5161
5162 for (i = tail; i < head; i++)
5163 {
5164 /* Skip any gaps in the array */
5166 return KnownAssignedXids[i];
5167 }
5168
5169 return InvalidTransactionId;
5170}

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

4953{
4955
4956 elog(DEBUG4, "remove KnownAssignedXid %u", xid);
4957
4958 /*
4959 * Note: we cannot consider it an error to remove an XID that's not
4960 * present. We intentionally remove subxact IDs while processing
4961 * XLOG_XACT_ASSIGNMENT, to avoid array overflow. Then those XIDs will be
4962 * removed again when the top-level xact commits or aborts.
4963 *
4964 * It might be possible to track such XIDs to distinguish this case from
4965 * actual errors, but it would be complicated and probably not worth it.
4966 * So, just ignore the search result.
4967 */
4968 (void) KnownAssignedXidsSearch(xid, true);
4969}
#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 5000 of file procarray.c.

5001{
5003 int count = 0;
5004 int head,
5005 tail,
5006 i;
5007
5009 {
5010 elog(DEBUG4, "removing all KnownAssignedXids");
5011 pArray->numKnownAssignedXids = 0;
5012 pArray->headKnownAssignedXids = pArray->tailKnownAssignedXids = 0;
5013 return;
5014 }
5015
5016 elog(DEBUG4, "prune KnownAssignedXids to %u", removeXid);
5017
5018 /*
5019 * Mark entries invalid starting at the tail. Since array is sorted, we
5020 * can stop as soon as we reach an entry >= removeXid.
5021 */
5022 tail = pArray->tailKnownAssignedXids;
5023 head = pArray->headKnownAssignedXids;
5024
5025 for (i = tail; i < head; i++)
5026 {
5028 {
5030
5032 break;
5033
5035 {
5036 KnownAssignedXidsValid[i] = false;
5037 count++;
5038 }
5039 }
5040 }
5041
5042 pArray->numKnownAssignedXids -= count;
5043 Assert(pArray->numKnownAssignedXids >= 0);
5044
5045 /*
5046 * Advance the tail pointer if we've marked the tail item invalid.
5047 */
5048 for (i = tail; i < head; i++)
5049 {
5051 break;
5052 }
5053 if (i >= head)
5054 {
5055 /* Array is empty, so we can reset both pointers */
5056 pArray->headKnownAssignedXids = 0;
5057 pArray->tailKnownAssignedXids = 0;
5058 }
5059 else
5060 {
5061 pArray->tailKnownAssignedXids = i;
5062 }
5063
5064 /* Opportunistically compress the array */
5066}
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 4978 of file procarray.c.

4980{
4981 int i;
4982
4983 if (TransactionIdIsValid(xid))
4985
4986 for (i = 0; i < nsubxids; i++)
4987 KnownAssignedXidsRemove(subxids[i]);
4988
4989 /* Opportunistically compress the array */
4991}
static void KnownAssignedXidsRemove(TransactionId xid)
Definition procarray.c:4952

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

Referenced by ExpireTreeKnownAssignedTransactionIds(), and ProcArrayApplyXidAssignment().

◆ KnownAssignedXidsReset()

static void KnownAssignedXidsReset ( void  )
static

Definition at line 5221 of file procarray.c.

5222{
5224
5226
5227 pArray->numKnownAssignedXids = 0;
5228 pArray->tailKnownAssignedXids = 0;
5229 pArray->headKnownAssignedXids = 0;
5230
5232}

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

Referenced by ProcArrayApplyRecoveryInfo().

◆ KnownAssignedXidsSearch()

static bool KnownAssignedXidsSearch ( TransactionId  xid,
bool  remove 
)
static

Definition at line 4851 of file procarray.c.

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

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

3496{
3498 int count = 0;
3499 int index;
3500
3501 /* Quick short-circuit if no minimum is specified */
3502 if (min == 0)
3503 return true;
3504
3505 /*
3506 * Note: for speed, we don't acquire ProcArrayLock. This is a little bit
3507 * bogus, but since we are only testing fields for zero or nonzero, it
3508 * should be OK. The result is only used for heuristic purposes anyway...
3509 */
3510 for (index = 0; index < arrayP->numProcs; index++)
3511 {
3512 int pgprocno = arrayP->pgprocnos[index];
3513 PGPROC *proc = &allProcs[pgprocno];
3514
3515 /*
3516 * Since we're not holding a lock, need to be prepared to deal with
3517 * garbage, as someone could have incremented numProcs but not yet
3518 * filled the structure.
3519 *
3520 * If someone just decremented numProcs, 'proc' could also point to a
3521 * PGPROC entry that's no longer in the array. It still points to a
3522 * PGPROC struct, though, because freed PGPROC entries just go to the
3523 * free list and are recycled. Its contents are nonsense in that case,
3524 * but that's acceptable for this function.
3525 */
3526 if (pgprocno == -1)
3527 continue; /* do not count deleted entries */
3528 if (proc == MyProc)
3529 continue; /* do not count myself */
3530 if (proc->xid == InvalidTransactionId)
3531 continue; /* do not count if no XID assigned */
3532 if (proc->pid == 0)
3533 continue; /* do not count prepared xacts */
3534 if (proc->waitLock != NULL)
3535 continue; /* do not count if blocked on a lock */
3536 count++;
3537 if (count >= min)
3538 break;
3539 }
3540
3541 return count >= min;
3542}
LOCK * waitLock
Definition proc.h:249

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

Referenced by XLogFlush().

◆ ProcArrayAdd()

void ProcArrayAdd ( PGPROC proc)

Definition at line 470 of file procarray.c.

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

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

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

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

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

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

Referenced by PrepareTransaction().

◆ ProcArrayEndTransaction()

void ProcArrayEndTransaction ( PGPROC proc,
TransactionId  latestXid 
)

Definition at line 669 of file procarray.c.

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

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

Referenced by AbortTransaction(), and CommitTransaction().

◆ ProcArrayEndTransactionInternal()

static void ProcArrayEndTransactionInternal ( PGPROC proc,
TransactionId  latestXid 
)
inlinestatic

Definition at line 731 of file procarray.c.

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

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

Referenced by ProcArrayEndTransaction(), and ProcArrayGroupClearXid().

◆ ProcArrayGetReplicationSlotXmin()

void ProcArrayGetReplicationSlotXmin ( TransactionId xmin,
TransactionId catalog_xmin 
)

Definition at line 3933 of file procarray.c.

3935{
3937
3938 if (xmin != NULL)
3940
3941 if (catalog_xmin != NULL)
3943
3945}

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

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

1021{
1024
1025 /*
1026 * we set latestObservedXid to the xid SUBTRANS has been initialized up
1027 * to, so we can extend it from that point onwards in
1028 * RecordKnownAssignedTransactionIds, and when we get consistent in
1029 * ProcArrayApplyRecoveryInfo().
1030 */
1033}

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

Referenced by StartupXLOG().

◆ ProcArrayInstallImportedXmin()

bool ProcArrayInstallImportedXmin ( TransactionId  xmin,
VirtualTransactionId sourcevxid 
)

Definition at line 2477 of file procarray.c.

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

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

2562{
2563 bool result = false;
2564 TransactionId xid;
2565
2567 Assert(proc != NULL);
2568
2569 /*
2570 * Get an exclusive lock so that we can copy statusFlags from source proc.
2571 */
2573
2574 /*
2575 * Be certain that the referenced PGPROC has an advertised xmin which is
2576 * no later than the one we're installing, so that the system-wide xmin
2577 * can't go backwards. Also, make sure it's running in the same database,
2578 * so that the per-database xmin cannot go backwards.
2579 */
2580 xid = UINT32_ACCESS_ONCE(proc->xmin);
2581 if (proc->databaseId == MyDatabaseId &&
2582 TransactionIdIsNormal(xid) &&
2584 {
2585 /*
2586 * Install xmin and propagate the statusFlags that affect how the
2587 * value is interpreted by vacuum.
2588 */
2589 MyProc->xmin = TransactionXmin = xmin;
2591 (proc->statusFlags & PROC_XMIN_FLAGS);
2593
2594 result = true;
2595 }
2596
2598
2599 return result;
2600}
#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 567 of file procarray.c.

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

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

3910{
3912
3913 if (!already_locked)
3915
3918
3919 if (!already_locked)
3921
3922 elog(DEBUG1, "xmin required by slots: data %u, catalog %u",
3923 xmin, catalog_xmin);
3924}

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

421{
422 bool found;
423
424 /* Create or attach to the ProcArray shared structure */
426 ShmemInitStruct("Proc Array",
428 mul_size(sizeof(int),
430 &found);
431
432 if (!found)
433 {
434 /*
435 * We're the first - initialize.
436 */
437 procArray->numProcs = 0;
447 }
448
450
451 /* Create or attach to the KnownAssignedXids arrays too, if needed */
453 {
455 ShmemInitStruct("KnownAssignedXids",
456 mul_size(sizeof(TransactionId),
458 &found);
459 KnownAssignedXidsValid = (bool *)
460 ShmemInitStruct("KnownAssignedXidsValid",
461 mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS),
462 &found);
463 }
464}
#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:81
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 378 of file procarray.c.

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

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

3097{
3098 PGPROC *result;
3099
3101 return NULL;
3102 result = GetPGProcByNumber(procNumber);
3103
3104 if (result->pid == 0)
3105 return NULL;
3106
3107 return result;
3108}
#define GetPGProcByNumber(n)
Definition proc.h:440
uint32 allProcCount
Definition proc.h:406

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

3120{
3121 PGPROC *proc;
3122
3123 *xid = InvalidTransactionId;
3124 *xmin = InvalidTransactionId;
3125 *nsubxid = 0;
3126 *overflowed = false;
3127
3129 return;
3130 proc = GetPGProcByNumber(procNumber);
3131
3132 /* Need to lock out additions/removals of backends */
3134
3135 if (proc->pid != 0)
3136 {
3137 *xid = proc->xid;
3138 *xmin = proc->xmin;
3139 *nsubxid = proc->subxidStatus.count;
3140 *overflowed = proc->subxidStatus.overflowed;
3141 }
3142
3144}

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

4369{
4373
4374 elog(DEBUG4, "record known xact %u latestObservedXid %u",
4375 xid, latestObservedXid);
4376
4377 /*
4378 * When a newly observed xid arrives, it is frequently the case that it is
4379 * *not* the next xid in sequence. When this occurs, we must treat the
4380 * intervening xids as running also.
4381 */
4383 {
4385
4386 /*
4387 * Extend subtrans like we do in GetNewTransactionId() during normal
4388 * operation using individual extend steps. Note that we do not need
4389 * to extend clog since its extensions are WAL logged.
4390 *
4391 * This part has to be done regardless of standbyState since we
4392 * immediately start assigning subtransactions to their toplevel
4393 * transactions.
4394 */
4397 {
4400 }
4401 Assert(next_expected_xid == xid);
4402
4403 /*
4404 * If the KnownAssignedXids machinery isn't up yet, there's nothing
4405 * more to do since we don't track assigned xids yet.
4406 */
4408 {
4409 latestObservedXid = xid;
4410 return;
4411 }
4412
4413 /*
4414 * Add (latestObservedXid, xid] onto the KnownAssignedXids array.
4415 */
4419
4420 /*
4421 * Now we can advance latestObservedXid
4422 */
4423 latestObservedXid = xid;
4424
4425 /* TransamVariables->nextXid must be beyond any observed xid */
4427 }
4428}

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().

◆ SignalVirtualTransaction()

pid_t SignalVirtualTransaction ( VirtualTransactionId  vxid,
ProcSignalReason  sigmode 
)

Definition at line 3448 of file procarray.c.

3449{
3451 int index;
3452 pid_t pid = 0;
3453
3455
3456 for (index = 0; index < arrayP->numProcs; index++)
3457 {
3458 int pgprocno = arrayP->pgprocnos[index];
3459 PGPROC *proc = &allProcs[pgprocno];
3461
3463
3464 if (procvxid.procNumber == vxid.procNumber &&
3465 procvxid.localTransactionId == vxid.localTransactionId)
3466 {
3467 pid = proc->pid;
3468 if (pid != 0)
3469 {
3470 /*
3471 * Kill the pid if it's still here. If not, that's what we
3472 * wanted so ignore any errors.
3473 */
3474 (void) SendProcSignal(pid, sigmode, vxid.procNumber);
3475 }
3476 break;
3477 }
3478 }
3479
3481
3482 return pid;
3483}
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::pid, procArray, VirtualTransactionId::procNumber, and SendProcSignal().

Referenced by ResolveRecoveryConflictWithLock(), and ResolveRecoveryConflictWithVirtualXIDs().

◆ TerminateOtherDBBackends()

void TerminateOtherDBBackends ( Oid  databaseId)

Definition at line 3793 of file procarray.c.

3794{
3796 List *pids = NIL;
3797 int nprepared = 0;
3798 int i;
3799
3801
3802 for (i = 0; i < procArray->numProcs; i++)
3803 {
3804 int pgprocno = arrayP->pgprocnos[i];
3805 PGPROC *proc = &allProcs[pgprocno];
3806
3807 if (proc->databaseId != databaseId)
3808 continue;
3809 if (proc == MyProc)
3810 continue;
3811
3812 if (proc->pid != 0)
3813 pids = lappend_int(pids, proc->pid);
3814 else
3815 nprepared++;
3816 }
3817
3819
3820 if (nprepared > 0)
3821 ereport(ERROR,
3823 errmsg("database \"%s\" is being used by prepared transactions",
3824 get_database_name(databaseId)),
3825 errdetail_plural("There is %d prepared transaction using the database.",
3826 "There are %d prepared transactions using the database.",
3827 nprepared,
3828 nprepared)));
3829
3830 if (pids)
3831 {
3832 ListCell *lc;
3833
3834 /*
3835 * Permissions checks relax the pg_terminate_backend checks in two
3836 * ways, both by omitting the !OidIsValid(proc->roleId) check:
3837 *
3838 * - Accept terminating autovacuum workers, since DROP DATABASE
3839 * without FORCE terminates them.
3840 *
3841 * - Accept terminating bgworkers. For bgworker authors, it's
3842 * convenient to be able to recommend FORCE if a worker is blocking
3843 * DROP DATABASE unexpectedly.
3844 *
3845 * Unlike pg_terminate_backend, we don't raise some warnings - like
3846 * "PID %d is not a PostgreSQL server process", because for us already
3847 * finished session is not a problem.
3848 */
3849 foreach(lc, pids)
3850 {
3851 int pid = lfirst_int(lc);
3852 PGPROC *proc = BackendPidGetProc(pid);
3853
3854 if (proc != NULL)
3855 {
3856 if (superuser_arg(proc->roleId) && !superuser())
3857 ereport(ERROR,
3859 errmsg("permission denied to terminate process"),
3860 errdetail("Only roles with the %s attribute may terminate processes of roles with the %s attribute.",
3861 "SUPERUSER", "SUPERUSER")));
3862
3863 if (!has_privs_of_role(GetUserId(), proc->roleId) &&
3865 ereport(ERROR,
3867 errmsg("permission denied to terminate process"),
3868 errdetail("Only roles with privileges of the role whose process is being terminated or with privileges of the \"%s\" role may terminate this process.",
3869 "pg_signal_backend")));
3870 }
3871 }
3872
3873 /*
3874 * There's a race condition here: once we release the ProcArrayLock,
3875 * it's possible for the session to exit before we issue kill. That
3876 * race condition possibility seems too unlikely to worry about. See
3877 * pg_signal_backend.
3878 */
3879 foreach(lc, pids)
3880 {
3881 int pid = lfirst_int(lc);
3882 PGPROC *proc = BackendPidGetProc(pid);
3883
3884 if (proc != NULL)
3885 {
3886 /*
3887 * If we have setsid(), signal the backend's whole process
3888 * group
3889 */
3890#ifdef HAVE_SETSID
3891 (void) kill(-pid, SIGTERM);
3892#else
3893 (void) kill(pid, SIGTERM);
3894#endif
3895 }
3896 }
3897 }
3898}
bool has_privs_of_role(Oid member, Oid role)
Definition acl.c:5284
int errdetail(const char *fmt,...)
Definition elog.c:1216
int errdetail_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n,...)
Definition elog.c:1308
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:56
bool superuser(void)
Definition superuser.c:46

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

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

3959{
3960 int i,
3961 j;
3963
3965
3966 /*
3967 * We must hold ProcArrayLock exclusively in order to remove transactions
3968 * from the PGPROC array. (See src/backend/access/transam/README.) It's
3969 * possible this could be relaxed since we know this routine is only used
3970 * to abort subtransactions, but pending closer analysis we'd best be
3971 * conservative.
3972 *
3973 * Note that we do not have to be careful about memory ordering of our own
3974 * reads wrt. GetNewTransactionId() here - only this process can modify
3975 * relevant fields of MyProc/ProcGlobal->xids[]. But we do have to be
3976 * careful about our own writes being well ordered.
3977 */
3979
3981
3982 /*
3983 * Under normal circumstances xid and xids[] will be in increasing order,
3984 * as will be the entries in subxids. Scan backwards to avoid O(N^2)
3985 * behavior when removing a lot of xids.
3986 */
3987 for (i = nxids - 1; i >= 0; i--)
3988 {
3989 TransactionId anxid = xids[i];
3990
3991 for (j = MyProc->subxidStatus.count - 1; j >= 0; j--)
3992 {
3994 {
3997 mysubxidstat->count--;
3999 break;
4000 }
4001 }
4002
4003 /*
4004 * Ordinarily we should have found it, unless the cache has
4005 * overflowed. However it's also possible for this routine to be
4006 * invoked multiple times for the same subtransaction, in case of an
4007 * error during AbortSubTransaction. So instead of Assert, emit a
4008 * debug warning.
4009 */
4010 if (j < 0 && !MyProc->subxidStatus.overflowed)
4011 elog(WARNING, "did not find subXID %u in MyProc", anxid);
4012 }
4013
4014 for (j = MyProc->subxidStatus.count - 1; j >= 0; j--)
4015 {
4017 {
4020 mysubxidstat->count--;
4022 break;
4023 }
4024 }
4025 /* Ordinarily we should have found it, unless the cache has overflowed */
4026 if (j < 0 && !MyProc->subxidStatus.overflowed)
4027 elog(WARNING, "did not find subXID %u in MyProc", xid);
4028
4029 /* Also advance global latestCompletedXid while holding the lock */
4031
4032 /* ... and xactCompletionCount */
4034
4036}
#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 278 of file procarray.c.

Referenced by TransactionIdIsInProgress().

◆ ComputeXidHorizonsResultLastXmin

TransactionId ComputeXidHorizonsResultLastXmin
static

Definition at line 309 of file procarray.c.

Referenced by GlobalVisTestShouldUpdate(), and GlobalVisUpdateApply().

◆ GlobalVisCatalogRels

GlobalVisState GlobalVisCatalogRels
static

Definition at line 300 of file procarray.c.

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

◆ GlobalVisDataRels

GlobalVisState GlobalVisDataRels
static

Definition at line 301 of file procarray.c.

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

◆ GlobalVisSharedRels

GlobalVisState GlobalVisSharedRels
static

Definition at line 299 of file procarray.c.

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

◆ GlobalVisTempRels

GlobalVisState GlobalVisTempRels
static

Definition at line 302 of file procarray.c.

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

◆ KnownAssignedXids

◆ KnownAssignedXidsValid

◆ latestObservedXid

◆ procArray

◆ standbySnapshotPendingXmin

TransactionId standbySnapshotPendingXmin
static

Definition at line 292 of file procarray.c.

Referenced by ProcArrayApplyRecoveryInfo().