PostgreSQL Source Code  git master
procarray.c File Reference
#include "postgres.h"
#include <signal.h>
#include "access/clog.h"
#include "access/subtrans.h"
#include "access/transam.h"
#include "access/twophase.h"
#include "access/xact.h"
#include "access/xlog.h"
#include "catalog/catalog.h"
#include "miscadmin.h"
#include "pgstat.h"
#include "storage/proc.h"
#include "storage/procarray.h"
#include "storage/spin.h"
#include "utils/builtins.h"
#include "utils/rel.h"
#include "utils/snapmgr.h"
Include dependency graph for procarray.c:

Go to the source code of this file.

Data Structures

struct  ProcArrayStruct
 

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 XidCacheRemove(i)
 

Typedefs

typedef struct ProcArrayStruct ProcArrayStruct
 

Functions

static void KnownAssignedXidsCompress (bool force)
 
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 xid)
 
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, PGXACT *pgxact, TransactionId latestXid)
 
static void ProcArrayGroupClearXid (PGPROC *proc, TransactionId latestXid)
 
Size ProcArrayShmemSize (void)
 
void CreateSharedProcArray (void)
 
void ProcArrayAdd (PGPROC *proc)
 
void ProcArrayRemove (PGPROC *proc, TransactionId latestXid)
 
void ProcArrayEndTransaction (PGPROC *proc, TransactionId latestXid)
 
void ProcArrayClearTransaction (PGPROC *proc)
 
void ProcArrayInitRecovery (TransactionId initializedUptoXID)
 
void ProcArrayApplyRecoveryInfo (RunningTransactions running)
 
void ProcArrayApplyXidAssignment (TransactionId topxid, int nsubxids, TransactionId *subxids)
 
bool TransactionIdIsInProgress (TransactionId xid)
 
bool TransactionIdIsActive (TransactionId xid)
 
TransactionId GetOldestXmin (Relation rel, int flags)
 
int GetMaxSnapshotXidCount (void)
 
int GetMaxSnapshotSubxidCount (void)
 
Snapshot GetSnapshotData (Snapshot snapshot)
 
bool ProcArrayInstallImportedXmin (TransactionId xmin, VirtualTransactionId *sourcevxid)
 
bool ProcArrayInstallRestoredXmin (TransactionId xmin, PGPROC *proc)
 
RunningTransactions GetRunningTransactionData (void)
 
TransactionId GetOldestActiveTransactionId (void)
 
TransactionId GetOldestSafeDecodingTransactionId (bool catalogOnly)
 
VirtualTransactionIdGetVirtualXIDsDelayingChkpt (int *nvxids)
 
bool HaveVirtualXIDsDelayingChkpt (VirtualTransactionId *vxids, int nvxids)
 
PGPROCBackendPidGetProc (int pid)
 
PGPROCBackendPidGetProcWithLock (int pid)
 
int BackendXidGetPid (TransactionId xid)
 
bool IsBackendPid (int pid)
 
VirtualTransactionIdGetCurrentVirtualXIDs (TransactionId limitXmin, bool excludeXmin0, bool allDbs, int excludeVacuum, int *nvxids)
 
VirtualTransactionIdGetConflictingVirtualXIDs (TransactionId limitXmin, Oid dbOid)
 
pid_t CancelVirtualTransaction (VirtualTransactionId vxid, ProcSignalReason sigmode)
 
bool MinimumActiveBackends (int min)
 
int CountDBBackends (Oid databaseid)
 
int CountDBConnections (Oid databaseid)
 
void CancelDBBackends (Oid databaseid, ProcSignalReason sigmode, bool conflictPending)
 
int CountUserBackends (Oid roleid)
 
bool CountOtherDBBackends (Oid databaseId, int *nbackends, int *nprepared)
 
void 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)
 
void RecordKnownAssignedTransactionIds (TransactionId xid)
 
void ExpireTreeKnownAssignedTransactionIds (TransactionId xid, int nsubxids, TransactionId *subxids, TransactionId max_xid)
 
void ExpireAllKnownAssignedTransactionIds (void)
 
void ExpireOldKnownAssignedTransactionIds (TransactionId xid)
 

Variables

static ProcArrayStructprocArray
 
static PGPROCallProcs
 
static PGXACTallPgXact
 
static TransactionIdKnownAssignedXids
 
static boolKnownAssignedXidsValid
 
static TransactionId latestObservedXid = InvalidTransactionId
 
static TransactionId standbySnapshotPendingXmin
 

Macro Definition Documentation

◆ MAXAUTOVACPIDS

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

Referenced by CountOtherDBBackends().

◆ PROCARRAY_MAXPROCS

◆ TOTAL_MAX_CACHED_SUBXIDS

◆ UINT32_ACCESS_ONCE

◆ xc_by_child_xid_inc

#define xc_by_child_xid_inc ( )    ((void) 0)

Definition at line 149 of file procarray.c.

Referenced by TransactionIdIsInProgress().

◆ xc_by_known_assigned_inc

#define xc_by_known_assigned_inc ( )    ((void) 0)

Definition at line 150 of file procarray.c.

Referenced by TransactionIdIsInProgress().

◆ xc_by_known_xact_inc

#define xc_by_known_xact_inc ( )    ((void) 0)

Definition at line 145 of file procarray.c.

Referenced by TransactionIdIsInProgress().

◆ xc_by_latest_xid_inc

#define xc_by_latest_xid_inc ( )    ((void) 0)

Definition at line 147 of file procarray.c.

Referenced by TransactionIdIsInProgress().

◆ xc_by_main_xid_inc

#define xc_by_main_xid_inc ( )    ((void) 0)

Definition at line 148 of file procarray.c.

Referenced by TransactionIdIsInProgress().

◆ xc_by_my_xact_inc

#define xc_by_my_xact_inc ( )    ((void) 0)

Definition at line 146 of file procarray.c.

Referenced by TransactionIdIsInProgress().

◆ xc_by_recent_xmin_inc

#define xc_by_recent_xmin_inc ( )    ((void) 0)

Definition at line 144 of file procarray.c.

Referenced by TransactionIdIsInProgress().

◆ xc_no_overflow_inc

#define xc_no_overflow_inc ( )    ((void) 0)

Definition at line 151 of file procarray.c.

Referenced by TransactionIdIsInProgress().

◆ xc_slow_answer_inc

#define xc_slow_answer_inc ( )    ((void) 0)

Definition at line 152 of file procarray.c.

Referenced by TransactionIdIsInProgress().

◆ XidCacheRemove

#define XidCacheRemove (   i)
Value:
do { \
MyProc->subxids.xids[i] = MyProc->subxids.xids[MyPgXact->nxids - 1]; \
pg_write_barrier(); \
MyPgXact->nxids--; \
} while (0)
PGPROC * MyProc
Definition: proc.c:68
PGXACT * MyPgXact
Definition: proc.c:69
uint8 nxids
Definition: proc.h:238
struct XidCache subxids
Definition: proc.h:162
TransactionId xids[PGPROC_MAX_CACHED_SUBXIDS]
Definition: proc.h:40
int i

Definition at line 3020 of file procarray.c.

Referenced by XidCacheRemoveRunningXids().

Typedef Documentation

◆ ProcArrayStruct

Function Documentation

◆ BackendPidGetProc()

PGPROC* BackendPidGetProc ( int  pid)

Definition at line 2365 of file procarray.c.

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

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

2366 {
2367  PGPROC *result;
2368 
2369  if (pid == 0) /* never match dummy PGPROCs */
2370  return NULL;
2371 
2372  LWLockAcquire(ProcArrayLock, LW_SHARED);
2373 
2374  result = BackendPidGetProcWithLock(pid);
2375 
2376  LWLockRelease(ProcArrayLock);
2377 
2378  return result;
2379 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726
PGPROC * BackendPidGetProcWithLock(int pid)
Definition: procarray.c:2388
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122
Definition: proc.h:95

◆ BackendPidGetProcWithLock()

PGPROC* BackendPidGetProcWithLock ( int  pid)

Definition at line 2388 of file procarray.c.

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

Referenced by BackendPidGetProc(), and GetBlockerStatusData().

2389 {
2390  PGPROC *result = NULL;
2391  ProcArrayStruct *arrayP = procArray;
2392  int index;
2393 
2394  if (pid == 0) /* never match dummy PGPROCs */
2395  return NULL;
2396 
2397  for (index = 0; index < arrayP->numProcs; index++)
2398  {
2399  PGPROC *proc = &allProcs[arrayP->pgprocnos[index]];
2400 
2401  if (proc->pid == pid)
2402  {
2403  result = proc;
2404  break;
2405  }
2406  }
2407 
2408  return result;
2409 }
Definition: type.h:89
static PGPROC * allProcs
Definition: procarray.c:101
static ProcArrayStruct * procArray
Definition: procarray.c:99
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:96
Definition: proc.h:95
int pid
Definition: proc.h:109

◆ BackendXidGetPid()

int BackendXidGetPid ( TransactionId  xid)

Definition at line 2425 of file procarray.c.

References InvalidTransactionId, LW_SHARED, LWLockAcquire(), LWLockRelease(), ProcArrayStruct::numProcs, ProcArrayStruct::pgprocnos, PGPROC::pid, procArray, and PGXACT::xid.

Referenced by pgrowlocks().

2426 {
2427  int result = 0;
2428  ProcArrayStruct *arrayP = procArray;
2429  int index;
2430 
2431  if (xid == InvalidTransactionId) /* never match invalid xid */
2432  return 0;
2433 
2434  LWLockAcquire(ProcArrayLock, LW_SHARED);
2435 
2436  for (index = 0; index < arrayP->numProcs; index++)
2437  {
2438  int pgprocno = arrayP->pgprocnos[index];
2439  PGPROC *proc = &allProcs[pgprocno];
2440  PGXACT *pgxact = &allPgXact[pgprocno];
2441 
2442  if (pgxact->xid == xid)
2443  {
2444  result = proc->pid;
2445  break;
2446  }
2447  }
2448 
2449  LWLockRelease(ProcArrayLock);
2450 
2451  return result;
2452 }
Definition: proc.h:222
TransactionId xid
Definition: proc.h:224
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726
#define InvalidTransactionId
Definition: transam.h:31
static PGPROC * allProcs
Definition: procarray.c:101
static ProcArrayStruct * procArray
Definition: procarray.c:99
static PGXACT * allPgXact
Definition: procarray.c:102
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:96
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122
Definition: proc.h:95
int pid
Definition: proc.h:109

◆ CancelDBBackends()

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

Definition at line 2819 of file procarray.c.

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

Referenced by ResolveRecoveryConflictWithDatabase(), and SendRecoveryConflictWithBufferPin().

2820 {
2821  ProcArrayStruct *arrayP = procArray;
2822  int index;
2823  pid_t pid = 0;
2824 
2825  /* tell all backends to die */
2826  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
2827 
2828  for (index = 0; index < arrayP->numProcs; index++)
2829  {
2830  int pgprocno = arrayP->pgprocnos[index];
2831  PGPROC *proc = &allProcs[pgprocno];
2832 
2833  if (databaseid == InvalidOid || proc->databaseId == databaseid)
2834  {
2835  VirtualTransactionId procvxid;
2836 
2837  GET_VXID_FROM_PGPROC(procvxid, *proc);
2838 
2839  proc->recoveryConflictPending = conflictPending;
2840  pid = proc->pid;
2841  if (pid != 0)
2842  {
2843  /*
2844  * Kill the pid if it's still here. If not, that's what we
2845  * wanted so ignore any errors.
2846  */
2847  (void) SendProcSignal(pid, sigmode, procvxid.backendId);
2848  }
2849  }
2850  }
2851 
2852  LWLockRelease(ProcArrayLock);
2853 }
#define GET_VXID_FROM_PGPROC(vxid, proc)
Definition: lock.h:80
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726
int SendProcSignal(pid_t pid, ProcSignalReason reason, BackendId backendId)
Definition: procsignal.c:180
bool recoveryConflictPending
Definition: proc.h:127
static PGPROC * allProcs
Definition: procarray.c:101
Oid databaseId
Definition: proc.h:114
static ProcArrayStruct * procArray
Definition: procarray.c:99
#define InvalidOid
Definition: postgres_ext.h:36
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:96
BackendId backendId
Definition: lock.h:65
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122
Definition: proc.h:95
int pid
Definition: proc.h:109

◆ CancelVirtualTransaction()

pid_t CancelVirtualTransaction ( VirtualTransactionId  vxid,
ProcSignalReason  sigmode 
)

Definition at line 2656 of file procarray.c.

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

Referenced by ResolveRecoveryConflictWithVirtualXIDs().

2657 {
2658  ProcArrayStruct *arrayP = procArray;
2659  int index;
2660  pid_t pid = 0;
2661 
2662  LWLockAcquire(ProcArrayLock, LW_SHARED);
2663 
2664  for (index = 0; index < arrayP->numProcs; index++)
2665  {
2666  int pgprocno = arrayP->pgprocnos[index];
2667  PGPROC *proc = &allProcs[pgprocno];
2668  VirtualTransactionId procvxid;
2669 
2670  GET_VXID_FROM_PGPROC(procvxid, *proc);
2671 
2672  if (procvxid.backendId == vxid.backendId &&
2673  procvxid.localTransactionId == vxid.localTransactionId)
2674  {
2675  proc->recoveryConflictPending = true;
2676  pid = proc->pid;
2677  if (pid != 0)
2678  {
2679  /*
2680  * Kill the pid if it's still here. If not, that's what we
2681  * wanted so ignore any errors.
2682  */
2683  (void) SendProcSignal(pid, sigmode, vxid.backendId);
2684  }
2685  break;
2686  }
2687  }
2688 
2689  LWLockRelease(ProcArrayLock);
2690 
2691  return pid;
2692 }
#define GET_VXID_FROM_PGPROC(vxid, proc)
Definition: lock.h:80
LocalTransactionId localTransactionId
Definition: lock.h:66
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726
int SendProcSignal(pid_t pid, ProcSignalReason reason, BackendId backendId)
Definition: procsignal.c:180
bool recoveryConflictPending
Definition: proc.h:127
static PGPROC * allProcs
Definition: procarray.c:101
static ProcArrayStruct * procArray
Definition: procarray.c:99
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:96
BackendId backendId
Definition: lock.h:65
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122
Definition: proc.h:95
int pid
Definition: proc.h:109

◆ CountDBBackends()

int CountDBBackends ( Oid  databaseid)

Definition at line 2758 of file procarray.c.

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

Referenced by ResolveRecoveryConflictWithDatabase().

2759 {
2760  ProcArrayStruct *arrayP = procArray;
2761  int count = 0;
2762  int index;
2763 
2764  LWLockAcquire(ProcArrayLock, LW_SHARED);
2765 
2766  for (index = 0; index < arrayP->numProcs; index++)
2767  {
2768  int pgprocno = arrayP->pgprocnos[index];
2769  PGPROC *proc = &allProcs[pgprocno];
2770 
2771  if (proc->pid == 0)
2772  continue; /* do not count prepared xacts */
2773  if (!OidIsValid(databaseid) ||
2774  proc->databaseId == databaseid)
2775  count++;
2776  }
2777 
2778  LWLockRelease(ProcArrayLock);
2779 
2780  return count;
2781 }
#define OidIsValid(objectId)
Definition: c.h:638
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726
static PGPROC * allProcs
Definition: procarray.c:101
Oid databaseId
Definition: proc.h:114
static ProcArrayStruct * procArray
Definition: procarray.c:99
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:96
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122
Definition: proc.h:95
int pid
Definition: proc.h:109

◆ CountDBConnections()

int CountDBConnections ( Oid  databaseid)

Definition at line 2788 of file procarray.c.

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

Referenced by CheckMyDatabase().

2789 {
2790  ProcArrayStruct *arrayP = procArray;
2791  int count = 0;
2792  int index;
2793 
2794  LWLockAcquire(ProcArrayLock, LW_SHARED);
2795 
2796  for (index = 0; index < arrayP->numProcs; index++)
2797  {
2798  int pgprocno = arrayP->pgprocnos[index];
2799  PGPROC *proc = &allProcs[pgprocno];
2800 
2801  if (proc->pid == 0)
2802  continue; /* do not count prepared xacts */
2803  if (proc->isBackgroundWorker)
2804  continue; /* do not count background workers */
2805  if (!OidIsValid(databaseid) ||
2806  proc->databaseId == databaseid)
2807  count++;
2808  }
2809 
2810  LWLockRelease(ProcArrayLock);
2811 
2812  return count;
2813 }
#define OidIsValid(objectId)
Definition: c.h:638
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726
bool isBackgroundWorker
Definition: proc.h:120
static PGPROC * allProcs
Definition: procarray.c:101
Oid databaseId
Definition: proc.h:114
static ProcArrayStruct * procArray
Definition: procarray.c:99
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:96
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122
Definition: proc.h:95
int pid
Definition: proc.h:109

◆ CountOtherDBBackends()

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

Definition at line 2909 of file procarray.c.

References CHECK_FOR_INTERRUPTS, PGPROC::databaseId, kill, LW_SHARED, LWLockAcquire(), LWLockRelease(), MAXAUTOVACPIDS, MyProc, ProcArrayStruct::numProcs, pg_usleep(), ProcArrayStruct::pgprocnos, PGPROC::pid, PROC_IS_AUTOVACUUM, procArray, and PGXACT::vacuumFlags.

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

2910 {
2911  ProcArrayStruct *arrayP = procArray;
2912 
2913 #define MAXAUTOVACPIDS 10 /* max autovacs to SIGTERM per iteration */
2914  int autovac_pids[MAXAUTOVACPIDS];
2915  int tries;
2916 
2917  /* 50 tries with 100ms sleep between tries makes 5 sec total wait */
2918  for (tries = 0; tries < 50; tries++)
2919  {
2920  int nautovacs = 0;
2921  bool found = false;
2922  int index;
2923 
2925 
2926  *nbackends = *nprepared = 0;
2927 
2928  LWLockAcquire(ProcArrayLock, LW_SHARED);
2929 
2930  for (index = 0; index < arrayP->numProcs; index++)
2931  {
2932  int pgprocno = arrayP->pgprocnos[index];
2933  PGPROC *proc = &allProcs[pgprocno];
2934  PGXACT *pgxact = &allPgXact[pgprocno];
2935 
2936  if (proc->databaseId != databaseId)
2937  continue;
2938  if (proc == MyProc)
2939  continue;
2940 
2941  found = true;
2942 
2943  if (proc->pid == 0)
2944  (*nprepared)++;
2945  else
2946  {
2947  (*nbackends)++;
2948  if ((pgxact->vacuumFlags & PROC_IS_AUTOVACUUM) &&
2949  nautovacs < MAXAUTOVACPIDS)
2950  autovac_pids[nautovacs++] = proc->pid;
2951  }
2952  }
2953 
2954  LWLockRelease(ProcArrayLock);
2955 
2956  if (!found)
2957  return false; /* no conflicting backends, so done */
2958 
2959  /*
2960  * Send SIGTERM to any conflicting autovacuums before sleeping. We
2961  * postpone this step until after the loop because we don't want to
2962  * hold ProcArrayLock while issuing kill(). We have no idea what might
2963  * block kill() inside the kernel...
2964  */
2965  for (index = 0; index < nautovacs; index++)
2966  (void) kill(autovac_pids[index], SIGTERM); /* ignore any error */
2967 
2968  /* sleep, then try again */
2969  pg_usleep(100 * 1000L); /* 100ms */
2970  }
2971 
2972  return true; /* timed out, still conflicts */
2973 }
Definition: proc.h:222
PGPROC * MyProc
Definition: proc.c:68
#define kill(pid, sig)
Definition: win32_port.h:435
#define MAXAUTOVACPIDS
uint8 vacuumFlags
Definition: proc.h:233
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726
void pg_usleep(long microsec)
Definition: signal.c:53
static PGPROC * allProcs
Definition: procarray.c:101
Oid databaseId
Definition: proc.h:114
static ProcArrayStruct * procArray
Definition: procarray.c:99
static PGXACT * allPgXact
Definition: procarray.c:102
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:96
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:99
Definition: proc.h:95
int pid
Definition: proc.h:109
#define PROC_IS_AUTOVACUUM
Definition: proc.h:53

◆ CountUserBackends()

int CountUserBackends ( Oid  roleid)

Definition at line 2859 of file procarray.c.

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

Referenced by InitializeSessionUserId().

2860 {
2861  ProcArrayStruct *arrayP = procArray;
2862  int count = 0;
2863  int index;
2864 
2865  LWLockAcquire(ProcArrayLock, LW_SHARED);
2866 
2867  for (index = 0; index < arrayP->numProcs; index++)
2868  {
2869  int pgprocno = arrayP->pgprocnos[index];
2870  PGPROC *proc = &allProcs[pgprocno];
2871 
2872  if (proc->pid == 0)
2873  continue; /* do not count prepared xacts */
2874  if (proc->isBackgroundWorker)
2875  continue; /* do not count background workers */
2876  if (proc->roleId == roleid)
2877  count++;
2878  }
2879 
2880  LWLockRelease(ProcArrayLock);
2881 
2882  return count;
2883 }
Oid roleId
Definition: proc.h:115
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726
bool isBackgroundWorker
Definition: proc.h:120
static PGPROC * allProcs
Definition: procarray.c:101
static ProcArrayStruct * procArray
Definition: procarray.c:99
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:96
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122
Definition: proc.h:95
int pid
Definition: proc.h:109

◆ CreateSharedProcArray()

void CreateSharedProcArray ( void  )

Definition at line 222 of file procarray.c.

References add_size(), PROC_HDR::allPgXact, PROC_HDR::allProcs, EnableHotStandby, ProcArrayStruct::headKnownAssignedXids, InvalidTransactionId, ProcArrayStruct::known_assigned_xids_lck, KnownAssignedXids, KnownAssignedXidsValid, ProcArrayStruct::lastOverflowedXid, LWLockRegisterTranche(), LWTRANCHE_PROC, ProcArrayStruct::maxKnownAssignedXids, ProcArrayStruct::maxProcs, mul_size(), ProcArrayStruct::numKnownAssignedXids, ProcArrayStruct::numProcs, offsetof, ProcArrayStruct::pgprocnos, PROCARRAY_MAXPROCS, ProcGlobal, ProcArrayStruct::replication_slot_catalog_xmin, ProcArrayStruct::replication_slot_xmin, ShmemInitStruct(), SpinLockInit, ProcArrayStruct::tailKnownAssignedXids, and TOTAL_MAX_CACHED_SUBXIDS.

Referenced by CreateSharedMemoryAndSemaphores().

223 {
224  bool found;
225 
226  /* Create or attach to the ProcArray shared structure */
228  ShmemInitStruct("Proc Array",
229  add_size(offsetof(ProcArrayStruct, pgprocnos),
230  mul_size(sizeof(int),
232  &found);
233 
234  if (!found)
235  {
236  /*
237  * We're the first - initialize.
238  */
239  procArray->numProcs = 0;
249  }
250 
253 
254  /* Create or attach to the KnownAssignedXids arrays too, if needed */
255  if (EnableHotStandby)
256  {
258  ShmemInitStruct("KnownAssignedXids",
259  mul_size(sizeof(TransactionId),
261  &found);
262  KnownAssignedXidsValid = (bool *)
263  ShmemInitStruct("KnownAssignedXidsValid",
264  mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS),
265  &found);
266  }
267 
268  /* Register and initialize fields of ProcLWLockTranche */
270 }
#define PROCARRAY_MAXPROCS
uint32 TransactionId
Definition: c.h:507
PGXACT * allPgXact
Definition: proc.h:249
#define SpinLockInit(lock)
Definition: spin.h:60
TransactionId replication_slot_catalog_xmin
Definition: procarray.c:93
slock_t known_assigned_xids_lck
Definition: procarray.c:79
PROC_HDR * ProcGlobal
Definition: proc.c:81
void LWLockRegisterTranche(int tranche_id, const char *tranche_name)
Definition: lwlock.c:603
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition: shmem.c:372
int maxKnownAssignedXids
Definition: procarray.c:75
#define InvalidTransactionId
Definition: transam.h:31
static PGPROC * allProcs
Definition: procarray.c:101
int numKnownAssignedXids
Definition: procarray.c:76
static bool * KnownAssignedXidsValid
Definition: procarray.c:108
TransactionId lastOverflowedXid
Definition: procarray.c:88
static ProcArrayStruct * procArray
Definition: procarray.c:99
TransactionId replication_slot_xmin
Definition: procarray.c:91
Size mul_size(Size s1, Size s2)
Definition: shmem.c:492
static PGXACT * allPgXact
Definition: procarray.c:102
Size add_size(Size s1, Size s2)
Definition: shmem.c:475
#define TOTAL_MAX_CACHED_SUBXIDS
static TransactionId * KnownAssignedXids
Definition: procarray.c:107
bool EnableHotStandby
Definition: xlog.c:93
PGPROC * allProcs
Definition: proc.h:247
int tailKnownAssignedXids
Definition: procarray.c:77
#define offsetof(type, field)
Definition: c.h:655
int headKnownAssignedXids
Definition: procarray.c:78

◆ ExpireAllKnownAssignedTransactionIds()

void ExpireAllKnownAssignedTransactionIds ( void  )

Definition at line 3294 of file procarray.c.

References InvalidTransactionId, KnownAssignedXidsRemovePreceding(), LW_EXCLUSIVE, LWLockAcquire(), and LWLockRelease().

Referenced by ShutdownRecoveryTransactionEnvironment().

3295 {
3296  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3298  LWLockRelease(ProcArrayLock);
3299 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726
static void KnownAssignedXidsRemovePreceding(TransactionId xid)
Definition: procarray.c:3743
#define InvalidTransactionId
Definition: transam.h:31
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122

◆ ExpireOldKnownAssignedTransactionIds()

void ExpireOldKnownAssignedTransactionIds ( TransactionId  xid)

Definition at line 3306 of file procarray.c.

References KnownAssignedXidsRemovePreceding(), LW_EXCLUSIVE, LWLockAcquire(), and LWLockRelease().

Referenced by ProcArrayApplyRecoveryInfo().

3307 {
3308  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3310  LWLockRelease(ProcArrayLock);
3311 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726
static void KnownAssignedXidsRemovePreceding(TransactionId xid)
Definition: procarray.c:3743
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122

◆ ExpireTreeKnownAssignedTransactionIds()

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

Definition at line 3269 of file procarray.c.

References Assert, KnownAssignedXidsRemoveTree(), VariableCacheData::latestCompletedXid, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), ShmemVariableCache, STANDBY_INITIALIZED, standbyState, and TransactionIdPrecedes().

Referenced by xact_redo_abort(), and xact_redo_commit().

3271 {
3273 
3274  /*
3275  * Uses same locking as transaction commit
3276  */
3277  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3278 
3279  KnownAssignedXidsRemoveTree(xid, nsubxids, subxids);
3280 
3281  /* As in ProcArrayEndTransaction, advance latestCompletedXid */
3283  max_xid))
3285 
3286  LWLockRelease(ProcArrayLock);
3287 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726
VariableCache ShmemVariableCache
Definition: varsup.c:34
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
static void KnownAssignedXidsRemoveTree(TransactionId xid, int nsubxids, TransactionId *subxids)
Definition: procarray.c:3721
#define Assert(condition)
Definition: c.h:732
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122
HotStandbyState standbyState
Definition: xlog.c:203
TransactionId latestCompletedXid
Definition: transam.h:182

◆ GetConflictingVirtualXIDs()

VirtualTransactionId* GetConflictingVirtualXIDs ( TransactionId  limitXmin,
Oid  dbOid 
)

Definition at line 2581 of file procarray.c.

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

Referenced by ResolveRecoveryConflictWithSnapshot(), and ResolveRecoveryConflictWithTablespace().

2582 {
2583  static VirtualTransactionId *vxids;
2584  ProcArrayStruct *arrayP = procArray;
2585  int count = 0;
2586  int index;
2587 
2588  /*
2589  * If first time through, get workspace to remember main XIDs in. We
2590  * malloc it permanently to avoid repeated palloc/pfree overhead. Allow
2591  * result space, remembering room for a terminator.
2592  */
2593  if (vxids == NULL)
2594  {
2595  vxids = (VirtualTransactionId *)
2596  malloc(sizeof(VirtualTransactionId) * (arrayP->maxProcs + 1));
2597  if (vxids == NULL)
2598  ereport(ERROR,
2599  (errcode(ERRCODE_OUT_OF_MEMORY),
2600  errmsg("out of memory")));
2601  }
2602 
2603  LWLockAcquire(ProcArrayLock, LW_SHARED);
2604 
2605  for (index = 0; index < arrayP->numProcs; index++)
2606  {
2607  int pgprocno = arrayP->pgprocnos[index];
2608  PGPROC *proc = &allProcs[pgprocno];
2609  PGXACT *pgxact = &allPgXact[pgprocno];
2610 
2611  /* Exclude prepared transactions */
2612  if (proc->pid == 0)
2613  continue;
2614 
2615  if (!OidIsValid(dbOid) ||
2616  proc->databaseId == dbOid)
2617  {
2618  /* Fetch xmin just once - can't change on us, but good coding */
2619  TransactionId pxmin = UINT32_ACCESS_ONCE(pgxact->xmin);
2620 
2621  /*
2622  * We ignore an invalid pxmin because this means that backend has
2623  * no snapshot currently. We hold a Share lock to avoid contention
2624  * with users taking snapshots. That is not a problem because the
2625  * current xmin is always at least one higher than the latest
2626  * removed xid, so any new snapshot would never conflict with the
2627  * test here.
2628  */
2629  if (!TransactionIdIsValid(limitXmin) ||
2630  (TransactionIdIsValid(pxmin) && !TransactionIdFollows(pxmin, limitXmin)))
2631  {
2632  VirtualTransactionId vxid;
2633 
2634  GET_VXID_FROM_PGPROC(vxid, *proc);
2635  if (VirtualTransactionIdIsValid(vxid))
2636  vxids[count++] = vxid;
2637  }
2638  }
2639  }
2640 
2641  LWLockRelease(ProcArrayLock);
2642 
2643  /* add the terminator */
2644  vxids[count].backendId = InvalidBackendId;
2646 
2647  return vxids;
2648 }
#define GET_VXID_FROM_PGPROC(vxid, proc)
Definition: lock.h:80
bool TransactionIdFollows(TransactionId id1, TransactionId id2)
Definition: transam.c:334
uint32 TransactionId
Definition: c.h:507
Definition: proc.h:222
TransactionId xmin
Definition: proc.h:228
#define UINT32_ACCESS_ONCE(var)
Definition: procarray.c:64
int errcode(int sqlerrcode)
Definition: elog.c:570
LocalTransactionId localTransactionId
Definition: lock.h:66
#define OidIsValid(objectId)
Definition: c.h:638
Definition: type.h:89
#define malloc(a)
Definition: header.h:50
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726
#define ERROR
Definition: elog.h:43
static PGPROC * allProcs
Definition: procarray.c:101
Oid databaseId
Definition: proc.h:114
#define ereport(elevel, rest)
Definition: elog.h:141
static ProcArrayStruct * procArray
Definition: procarray.c:99
#define VirtualTransactionIdIsValid(vxid)
Definition: lock.h:71
#define InvalidBackendId
Definition: backendid.h:23
static PGXACT * allPgXact
Definition: procarray.c:102
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:96
BackendId backendId
Definition: lock.h:65
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122
int errmsg(const char *fmt,...)
Definition: elog.c:784
#define InvalidLocalTransactionId
Definition: lock.h:69
#define TransactionIdIsValid(xid)
Definition: transam.h:41
Definition: proc.h:95
int pid
Definition: proc.h:109

◆ GetCurrentVirtualXIDs()

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

Definition at line 2493 of file procarray.c.

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

Referenced by WaitForOlderSnapshots().

2496 {
2497  VirtualTransactionId *vxids;
2498  ProcArrayStruct *arrayP = procArray;
2499  int count = 0;
2500  int index;
2501 
2502  /* allocate what's certainly enough result space */
2503  vxids = (VirtualTransactionId *)
2504  palloc(sizeof(VirtualTransactionId) * arrayP->maxProcs);
2505 
2506  LWLockAcquire(ProcArrayLock, LW_SHARED);
2507 
2508  for (index = 0; index < arrayP->numProcs; index++)
2509  {
2510  int pgprocno = arrayP->pgprocnos[index];
2511  PGPROC *proc = &allProcs[pgprocno];
2512  PGXACT *pgxact = &allPgXact[pgprocno];
2513 
2514  if (proc == MyProc)
2515  continue;
2516 
2517  if (excludeVacuum & pgxact->vacuumFlags)
2518  continue;
2519 
2520  if (allDbs || proc->databaseId == MyDatabaseId)
2521  {
2522  /* Fetch xmin just once - might change on us */
2523  TransactionId pxmin = UINT32_ACCESS_ONCE(pgxact->xmin);
2524 
2525  if (excludeXmin0 && !TransactionIdIsValid(pxmin))
2526  continue;
2527 
2528  /*
2529  * InvalidTransactionId precedes all other XIDs, so a proc that
2530  * hasn't set xmin yet will not be rejected by this test.
2531  */
2532  if (!TransactionIdIsValid(limitXmin) ||
2533  TransactionIdPrecedesOrEquals(pxmin, limitXmin))
2534  {
2535  VirtualTransactionId vxid;
2536 
2537  GET_VXID_FROM_PGPROC(vxid, *proc);
2538  if (VirtualTransactionIdIsValid(vxid))
2539  vxids[count++] = vxid;
2540  }
2541  }
2542  }
2543 
2544  LWLockRelease(ProcArrayLock);
2545 
2546  *nvxids = count;
2547  return vxids;
2548 }
#define GET_VXID_FROM_PGPROC(vxid, proc)
Definition: lock.h:80
uint32 TransactionId
Definition: c.h:507
Definition: proc.h:222
TransactionId xmin
Definition: proc.h:228
PGPROC * MyProc
Definition: proc.c:68
#define UINT32_ACCESS_ONCE(var)
Definition: procarray.c:64
uint8 vacuumFlags
Definition: proc.h:233
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726
bool TransactionIdPrecedesOrEquals(TransactionId id1, TransactionId id2)
Definition: transam.c:319
static PGPROC * allProcs
Definition: procarray.c:101
Oid databaseId
Definition: proc.h:114
static ProcArrayStruct * procArray
Definition: procarray.c:99
#define VirtualTransactionIdIsValid(vxid)
Definition: lock.h:71
static PGXACT * allPgXact
Definition: procarray.c:102
Oid MyDatabaseId
Definition: globals.c:85
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:96
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122
void * palloc(Size size)
Definition: mcxt.c:924
#define TransactionIdIsValid(xid)
Definition: transam.h:41
Definition: proc.h:95

◆ GetMaxSnapshotSubxidCount()

int GetMaxSnapshotSubxidCount ( void  )

Definition at line 1463 of file procarray.c.

References TOTAL_MAX_CACHED_SUBXIDS.

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

1464 {
1465  return TOTAL_MAX_CACHED_SUBXIDS;
1466 }
#define TOTAL_MAX_CACHED_SUBXIDS

◆ GetMaxSnapshotXidCount()

int GetMaxSnapshotXidCount ( void  )

Definition at line 1452 of file procarray.c.

References ProcArrayStruct::maxProcs.

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

1453 {
1454  return procArray->maxProcs;
1455 }
static ProcArrayStruct * procArray
Definition: procarray.c:99

◆ GetOldestActiveTransactionId()

TransactionId GetOldestActiveTransactionId ( void  )

Definition at line 2111 of file procarray.c.

References Assert, LW_SHARED, LWLockAcquire(), LWLockRelease(), VariableCacheData::nextFullXid, ProcArrayStruct::numProcs, ProcArrayStruct::pgprocnos, procArray, RecoveryInProgress(), ShmemVariableCache, TransactionIdIsNormal, TransactionIdPrecedes(), UINT32_ACCESS_ONCE, PGXACT::xid, and XidFromFullTransactionId.

Referenced by CreateCheckPoint().

2112 {
2113  ProcArrayStruct *arrayP = procArray;
2114  TransactionId oldestRunningXid;
2115  int index;
2116 
2118 
2119  /*
2120  * Read nextXid, as the upper bound of what's still active.
2121  *
2122  * Reading a TransactionId is atomic, but we must grab the lock to make
2123  * sure that all XIDs < nextXid are already present in the proc array (or
2124  * have already completed), when we spin over it.
2125  */
2126  LWLockAcquire(XidGenLock, LW_SHARED);
2128  LWLockRelease(XidGenLock);
2129 
2130  /*
2131  * Spin over procArray collecting all xids and subxids.
2132  */
2133  LWLockAcquire(ProcArrayLock, LW_SHARED);
2134  for (index = 0; index < arrayP->numProcs; index++)
2135  {
2136  int pgprocno = arrayP->pgprocnos[index];
2137  PGXACT *pgxact = &allPgXact[pgprocno];
2138  TransactionId xid;
2139 
2140  /* Fetch xid just once - see GetNewTransactionId */
2141  xid = UINT32_ACCESS_ONCE(pgxact->xid);
2142 
2143  if (!TransactionIdIsNormal(xid))
2144  continue;
2145 
2146  if (TransactionIdPrecedes(xid, oldestRunningXid))
2147  oldestRunningXid = xid;
2148 
2149  /*
2150  * Top-level XID of a transaction is always less than any of its
2151  * subxids, so we don't need to check if any of the subxids are
2152  * smaller than oldestRunningXid
2153  */
2154  }
2155  LWLockRelease(ProcArrayLock);
2156 
2157  return oldestRunningXid;
2158 }
uint32 TransactionId
Definition: c.h:507
Definition: proc.h:222
TransactionId xid
Definition: proc.h:224
#define UINT32_ACCESS_ONCE(var)
Definition: procarray.c:64
FullTransactionId nextFullXid
Definition: transam.h:164
bool RecoveryInProgress(void)
Definition: xlog.c:7882
#define XidFromFullTransactionId(x)
Definition: transam.h:48
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726
VariableCache ShmemVariableCache
Definition: varsup.c:34
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
static ProcArrayStruct * procArray
Definition: procarray.c:99
static PGXACT * allPgXact
Definition: procarray.c:102
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:96
#define Assert(condition)
Definition: c.h:732
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122
#define TransactionIdIsNormal(xid)
Definition: transam.h:42

◆ GetOldestSafeDecodingTransactionId()

TransactionId GetOldestSafeDecodingTransactionId ( bool  catalogOnly)

Definition at line 2177 of file procarray.c.

References Assert, LW_SHARED, LWLockAcquire(), LWLockHeldByMe(), LWLockRelease(), VariableCacheData::nextFullXid, ProcArrayStruct::numProcs, ProcArrayStruct::pgprocnos, procArray, RecoveryInProgress(), ProcArrayStruct::replication_slot_catalog_xmin, ProcArrayStruct::replication_slot_xmin, ShmemVariableCache, TransactionIdIsNormal, TransactionIdIsValid, TransactionIdPrecedes(), UINT32_ACCESS_ONCE, PGXACT::xid, and XidFromFullTransactionId.

Referenced by CreateInitDecodingContext(), and SnapBuildInitialSnapshot().

2178 {
2179  ProcArrayStruct *arrayP = procArray;
2180  TransactionId oldestSafeXid;
2181  int index;
2182  bool recovery_in_progress = RecoveryInProgress();
2183 
2184  Assert(LWLockHeldByMe(ProcArrayLock));
2185 
2186  /*
2187  * Acquire XidGenLock, so no transactions can acquire an xid while we're
2188  * running. If no transaction with xid were running concurrently a new xid
2189  * could influence the RecentXmin et al.
2190  *
2191  * We initialize the computation to nextXid since that's guaranteed to be
2192  * a safe, albeit pessimal, value.
2193  */
2194  LWLockAcquire(XidGenLock, LW_SHARED);
2196 
2197  /*
2198  * If there's already a slot pegging the xmin horizon, we can start with
2199  * that value, it's guaranteed to be safe since it's computed by this
2200  * routine initially and has been enforced since. We can always use the
2201  * slot's general xmin horizon, but the catalog horizon is only usable
2202  * when only catalog data is going to be looked at.
2203  */
2206  oldestSafeXid))
2207  oldestSafeXid = procArray->replication_slot_xmin;
2208 
2209  if (catalogOnly &&
2212  oldestSafeXid))
2213  oldestSafeXid = procArray->replication_slot_catalog_xmin;
2214 
2215  /*
2216  * If we're not in recovery, we walk over the procarray and collect the
2217  * lowest xid. Since we're called with ProcArrayLock held and have
2218  * acquired XidGenLock, no entries can vanish concurrently, since
2219  * PGXACT->xid is only set with XidGenLock held and only cleared with
2220  * ProcArrayLock held.
2221  *
2222  * In recovery we can't lower the safe value besides what we've computed
2223  * above, so we'll have to wait a bit longer there. We unfortunately can
2224  * *not* use KnownAssignedXidsGetOldestXmin() since the KnownAssignedXids
2225  * machinery can miss values and return an older value than is safe.
2226  */
2227  if (!recovery_in_progress)
2228  {
2229  /*
2230  * Spin over procArray collecting all min(PGXACT->xid)
2231  */
2232  for (index = 0; index < arrayP->numProcs; index++)
2233  {
2234  int pgprocno = arrayP->pgprocnos[index];
2235  PGXACT *pgxact = &allPgXact[pgprocno];
2236  TransactionId xid;
2237 
2238  /* Fetch xid just once - see GetNewTransactionId */
2239  xid = UINT32_ACCESS_ONCE(pgxact->xid);
2240 
2241  if (!TransactionIdIsNormal(xid))
2242  continue;
2243 
2244  if (TransactionIdPrecedes(xid, oldestSafeXid))
2245  oldestSafeXid = xid;
2246  }
2247  }
2248 
2249  LWLockRelease(XidGenLock);
2250 
2251  return oldestSafeXid;
2252 }
uint32 TransactionId
Definition: c.h:507
Definition: proc.h:222
bool LWLockHeldByMe(LWLock *l)
Definition: lwlock.c:1842
TransactionId xid
Definition: proc.h:224
#define UINT32_ACCESS_ONCE(var)
Definition: procarray.c:64
TransactionId replication_slot_catalog_xmin
Definition: procarray.c:93
FullTransactionId nextFullXid
Definition: transam.h:164
bool RecoveryInProgress(void)
Definition: xlog.c:7882
#define XidFromFullTransactionId(x)
Definition: transam.h:48
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726
VariableCache ShmemVariableCache
Definition: varsup.c:34
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
static ProcArrayStruct * procArray
Definition: procarray.c:99
TransactionId replication_slot_xmin
Definition: procarray.c:91
static PGXACT * allPgXact
Definition: procarray.c:102
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:96
#define Assert(condition)
Definition: c.h:732
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122
#define TransactionIdIsValid(xid)
Definition: transam.h:41
#define TransactionIdIsNormal(xid)
Definition: transam.h:42

◆ GetOldestXmin()

TransactionId GetOldestXmin ( Relation  rel,
int  flags 
)

Definition at line 1307 of file procarray.c.

References Assert, PGPROC::databaseId, FirstNormalTransactionId, InvalidTransactionId, KnownAssignedXidsGetOldestXmin(), VariableCacheData::latestCompletedXid, LW_SHARED, LWLockAcquire(), LWLockRelease(), MyDatabaseId, NormalTransactionIdPrecedes, ProcArrayStruct::numProcs, ProcArrayStruct::pgprocnos, procArray, PROCARRAY_PROC_FLAGS_MASK, PROCARRAY_SLOTS_XMIN, RelationData::rd_rel, RecoveryInProgress(), RelationIsAccessibleInLogicalDecoding, ProcArrayStruct::replication_slot_catalog_xmin, ProcArrayStruct::replication_slot_xmin, ShmemVariableCache, TransactionIdAdvance, TransactionIdIsNormal, TransactionIdIsValid, TransactionIdPrecedes(), UINT32_ACCESS_ONCE, vacuum_defer_cleanup_age, PGXACT::vacuumFlags, PGXACT::xid, and PGXACT::xmin.

Referenced by acquire_sample_rows(), collect_corrupt_items(), CreateCheckPoint(), CreateRestartPoint(), heapam_index_build_range_scan(), statapprox_heap(), vac_update_datfrozenxid(), vacuum_set_xid_limits(), and XLogWalRcvSendHSFeedback().

1308 {
1309  ProcArrayStruct *arrayP = procArray;
1310  TransactionId result;
1311  int index;
1312  bool allDbs;
1313 
1314  TransactionId replication_slot_xmin = InvalidTransactionId;
1315  TransactionId replication_slot_catalog_xmin = InvalidTransactionId;
1316 
1317  /*
1318  * If we're not computing a relation specific limit, or if a shared
1319  * relation has been passed in, backends in all databases have to be
1320  * considered.
1321  */
1322  allDbs = rel == NULL || rel->rd_rel->relisshared;
1323 
1324  /* Cannot look for individual databases during recovery */
1325  Assert(allDbs || !RecoveryInProgress());
1326 
1327  LWLockAcquire(ProcArrayLock, LW_SHARED);
1328 
1329  /*
1330  * We initialize the MIN() calculation with latestCompletedXid + 1. This
1331  * is a lower bound for the XIDs that might appear in the ProcArray later,
1332  * and so protects us against overestimating the result due to future
1333  * additions.
1334  */
1336  Assert(TransactionIdIsNormal(result));
1337  TransactionIdAdvance(result);
1338 
1339  for (index = 0; index < arrayP->numProcs; index++)
1340  {
1341  int pgprocno = arrayP->pgprocnos[index];
1342  PGPROC *proc = &allProcs[pgprocno];
1343  PGXACT *pgxact = &allPgXact[pgprocno];
1344 
1345  if (pgxact->vacuumFlags & (flags & PROCARRAY_PROC_FLAGS_MASK))
1346  continue;
1347 
1348  if (allDbs ||
1349  proc->databaseId == MyDatabaseId ||
1350  proc->databaseId == 0) /* always include WalSender */
1351  {
1352  /* Fetch xid just once - see GetNewTransactionId */
1353  TransactionId xid = UINT32_ACCESS_ONCE(pgxact->xid);
1354 
1355  /* First consider the transaction's own Xid, if any */
1356  if (TransactionIdIsNormal(xid) &&
1357  TransactionIdPrecedes(xid, result))
1358  result = xid;
1359 
1360  /*
1361  * Also consider the transaction's Xmin, if set.
1362  *
1363  * We must check both Xid and Xmin because a transaction might
1364  * have an Xmin but not (yet) an Xid; conversely, if it has an
1365  * Xid, that could determine some not-yet-set Xmin.
1366  */
1367  xid = UINT32_ACCESS_ONCE(pgxact->xmin);
1368  if (TransactionIdIsNormal(xid) &&
1369  TransactionIdPrecedes(xid, result))
1370  result = xid;
1371  }
1372  }
1373 
1374  /*
1375  * Fetch into local variable while ProcArrayLock is held - the
1376  * LWLockRelease below is a barrier, ensuring this happens inside the
1377  * lock.
1378  */
1379  replication_slot_xmin = procArray->replication_slot_xmin;
1380  replication_slot_catalog_xmin = procArray->replication_slot_catalog_xmin;
1381 
1382  if (RecoveryInProgress())
1383  {
1384  /*
1385  * Check to see whether KnownAssignedXids contains an xid value older
1386  * than the main procarray.
1387  */
1389 
1390  LWLockRelease(ProcArrayLock);
1391 
1392  if (TransactionIdIsNormal(kaxmin) &&
1393  TransactionIdPrecedes(kaxmin, result))
1394  result = kaxmin;
1395  }
1396  else
1397  {
1398  /*
1399  * No other information needed, so release the lock immediately.
1400  */
1401  LWLockRelease(ProcArrayLock);
1402 
1403  /*
1404  * Compute the cutoff XID by subtracting vacuum_defer_cleanup_age,
1405  * being careful not to generate a "permanent" XID.
1406  *
1407  * vacuum_defer_cleanup_age provides some additional "slop" for the
1408  * benefit of hot standby queries on standby servers. This is quick
1409  * and dirty, and perhaps not all that useful unless the master has a
1410  * predictable transaction rate, but it offers some protection when
1411  * there's no walsender connection. Note that we are assuming
1412  * vacuum_defer_cleanup_age isn't large enough to cause wraparound ---
1413  * so guc.c should limit it to no more than the xidStopLimit threshold
1414  * in varsup.c. Also note that we intentionally don't apply
1415  * vacuum_defer_cleanup_age on standby servers.
1416  */
1417  result -= vacuum_defer_cleanup_age;
1418  if (!TransactionIdIsNormal(result))
1419  result = FirstNormalTransactionId;
1420  }
1421 
1422  /*
1423  * Check whether there are replication slots requiring an older xmin.
1424  */
1425  if (!(flags & PROCARRAY_SLOTS_XMIN) &&
1426  TransactionIdIsValid(replication_slot_xmin) &&
1427  NormalTransactionIdPrecedes(replication_slot_xmin, result))
1428  result = replication_slot_xmin;
1429 
1430  /*
1431  * After locks have been released and defer_cleanup_age has been applied,
1432  * check whether we need to back up further to make logical decoding
1433  * possible. We need to do so if we're computing the global limit (rel =
1434  * NULL) or if the passed relation is a catalog relation of some kind.
1435  */
1436  if (!(flags & PROCARRAY_SLOTS_XMIN) &&
1437  (rel == NULL ||
1439  TransactionIdIsValid(replication_slot_catalog_xmin) &&
1440  NormalTransactionIdPrecedes(replication_slot_catalog_xmin, result))
1441  result = replication_slot_catalog_xmin;
1442 
1443  return result;
1444 }
#define TransactionIdAdvance(dest)
Definition: transam.h:75
uint32 TransactionId
Definition: c.h:507
Definition: proc.h:222
TransactionId xmin
Definition: proc.h:228
TransactionId xid
Definition: proc.h:224
int vacuum_defer_cleanup_age
Definition: standby.c:39
#define UINT32_ACCESS_ONCE(var)
Definition: procarray.c:64
TransactionId replication_slot_catalog_xmin
Definition: procarray.c:93
Form_pg_class rd_rel
Definition: rel.h:84
bool RecoveryInProgress(void)
Definition: xlog.c:7882
uint8 vacuumFlags
Definition: proc.h:233
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726
#define FirstNormalTransactionId
Definition: transam.h:34
#define PROCARRAY_SLOTS_XMIN
Definition: procarray.h:37
#define PROCARRAY_PROC_FLAGS_MASK
Definition: procarray.h:44
VariableCache ShmemVariableCache
Definition: varsup.c:34
#define InvalidTransactionId
Definition: transam.h:31
static PGPROC * allProcs
Definition: procarray.c:101
Oid databaseId
Definition: proc.h:114
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
static ProcArrayStruct * procArray
Definition: procarray.c:99
TransactionId replication_slot_xmin
Definition: procarray.c:91
static PGXACT * allPgXact
Definition: procarray.c:102
#define RelationIsAccessibleInLogicalDecoding(relation)
Definition: rel.h:570
Oid MyDatabaseId
Definition: globals.c:85
static TransactionId KnownAssignedXidsGetOldestXmin(void)
Definition: procarray.c:3893
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:96
#define Assert(condition)
Definition: c.h:732
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122
#define NormalTransactionIdPrecedes(id1, id2)
Definition: transam.h:98
#define TransactionIdIsValid(xid)
Definition: transam.h:41
#define TransactionIdIsNormal(xid)
Definition: transam.h:42
Definition: proc.h:95
TransactionId latestCompletedXid
Definition: transam.h:182

◆ GetRunningTransactionData()

RunningTransactions GetRunningTransactionData ( void  )

Definition at line 1937 of file procarray.c.

References Assert, ereport, errcode(), errmsg(), ERROR, RunningTransactionsData::latestCompletedXid, VariableCacheData::latestCompletedXid, LW_SHARED, LWLockAcquire(), malloc, VariableCacheData::nextFullXid, RunningTransactionsData::nextXid, ProcArrayStruct::numProcs, PGXACT::nxids, RunningTransactionsData::oldestRunningXid, PGXACT::overflowed, pg_read_barrier, ProcArrayStruct::pgprocnos, procArray, RecoveryInProgress(), ShmemVariableCache, RunningTransactionsData::subxcnt, RunningTransactionsData::subxid_overflow, PGPROC::subxids, TOTAL_MAX_CACHED_SUBXIDS, TransactionIdIsNormal, TransactionIdIsValid, TransactionIdPrecedes(), UINT32_ACCESS_ONCE, RunningTransactionsData::xcnt, PGXACT::xid, XidFromFullTransactionId, XidCache::xids, and RunningTransactionsData::xids.

Referenced by LogStandbySnapshot().

1938 {
1939  /* result workspace */
1940  static RunningTransactionsData CurrentRunningXactsData;
1941 
1942  ProcArrayStruct *arrayP = procArray;
1943  RunningTransactions CurrentRunningXacts = &CurrentRunningXactsData;
1944  TransactionId latestCompletedXid;
1945  TransactionId oldestRunningXid;
1946  TransactionId *xids;
1947  int index;
1948  int count;
1949  int subcount;
1950  bool suboverflowed;
1951 
1953 
1954  /*
1955  * Allocating space for maxProcs xids is usually overkill; numProcs would
1956  * be sufficient. But it seems better to do the malloc while not holding
1957  * the lock, so we can't look at numProcs. Likewise, we allocate much
1958  * more subxip storage than is probably needed.
1959  *
1960  * Should only be allocated in bgwriter, since only ever executed during
1961  * checkpoints.
1962  */
1963  if (CurrentRunningXacts->xids == NULL)
1964  {
1965  /*
1966  * First call
1967  */
1968  CurrentRunningXacts->xids = (TransactionId *)
1970  if (CurrentRunningXacts->xids == NULL)
1971  ereport(ERROR,
1972  (errcode(ERRCODE_OUT_OF_MEMORY),
1973  errmsg("out of memory")));
1974  }
1975 
1976  xids = CurrentRunningXacts->xids;
1977 
1978  count = subcount = 0;
1979  suboverflowed = false;
1980 
1981  /*
1982  * Ensure that no xids enter or leave the procarray while we obtain
1983  * snapshot.
1984  */
1985  LWLockAcquire(ProcArrayLock, LW_SHARED);
1986  LWLockAcquire(XidGenLock, LW_SHARED);
1987 
1988  latestCompletedXid = ShmemVariableCache->latestCompletedXid;
1989 
1991 
1992  /*
1993  * Spin over procArray collecting all xids
1994  */
1995  for (index = 0; index < arrayP->numProcs; index++)
1996  {
1997  int pgprocno = arrayP->pgprocnos[index];
1998  PGXACT *pgxact = &allPgXact[pgprocno];
1999  TransactionId xid;
2000 
2001  /* Fetch xid just once - see GetNewTransactionId */
2002  xid = UINT32_ACCESS_ONCE(pgxact->xid);
2003 
2004  /*
2005  * We don't need to store transactions that don't have a TransactionId
2006  * yet because they will not show as running on a standby server.
2007  */
2008  if (!TransactionIdIsValid(xid))
2009  continue;
2010 
2011  /*
2012  * Be careful not to exclude any xids before calculating the values of
2013  * oldestRunningXid and suboverflowed, since these are used to clean
2014  * up transaction information held on standbys.
2015  */
2016  if (TransactionIdPrecedes(xid, oldestRunningXid))
2017  oldestRunningXid = xid;
2018 
2019  if (pgxact->overflowed)
2020  suboverflowed = true;
2021 
2022  /*
2023  * If we wished to exclude xids this would be the right place for it.
2024  * Procs with the PROC_IN_VACUUM flag set don't usually assign xids,
2025  * but they do during truncation at the end when they get the lock and
2026  * truncate, so it is not much of a problem to include them if they
2027  * are seen and it is cleaner to include them.
2028  */
2029 
2030  xids[count++] = xid;
2031  }
2032 
2033  /*
2034  * Spin over procArray collecting all subxids, but only if there hasn't
2035  * been a suboverflow.
2036  */
2037  if (!suboverflowed)
2038  {
2039  for (index = 0; index < arrayP->numProcs; index++)
2040  {
2041  int pgprocno = arrayP->pgprocnos[index];
2042  PGPROC *proc = &allProcs[pgprocno];
2043  PGXACT *pgxact = &allPgXact[pgprocno];
2044  int nxids;
2045 
2046  /*
2047  * Save subtransaction XIDs. Other backends can't add or remove
2048  * entries while we're holding XidGenLock.
2049  */
2050  nxids = pgxact->nxids;
2051  if (nxids > 0)
2052  {
2053  /* barrier not really required, as XidGenLock is held, but ... */
2054  pg_read_barrier(); /* pairs with GetNewTransactionId */
2055 
2056  memcpy(&xids[count], (void *) proc->subxids.xids,
2057  nxids * sizeof(TransactionId));
2058  count += nxids;
2059  subcount += nxids;
2060 
2061  /*
2062  * Top-level XID of a transaction is always less than any of
2063  * its subxids, so we don't need to check if any of the
2064  * subxids are smaller than oldestRunningXid
2065  */
2066  }
2067  }
2068  }
2069 
2070  /*
2071  * It's important *not* to include the limits set by slots here because
2072  * snapbuild.c uses oldestRunningXid to manage its xmin horizon. If those
2073  * were to be included here the initial value could never increase because
2074  * of a circular dependency where slots only increase their limits when
2075  * running xacts increases oldestRunningXid and running xacts only
2076  * increases if slots do.
2077  */
2078 
2079  CurrentRunningXacts->xcnt = count - subcount;
2080  CurrentRunningXacts->subxcnt = subcount;
2081  CurrentRunningXacts->subxid_overflow = suboverflowed;
2083  CurrentRunningXacts->oldestRunningXid = oldestRunningXid;
2084  CurrentRunningXacts->latestCompletedXid = latestCompletedXid;
2085 
2086  Assert(TransactionIdIsValid(CurrentRunningXacts->nextXid));
2087  Assert(TransactionIdIsValid(CurrentRunningXacts->oldestRunningXid));
2088  Assert(TransactionIdIsNormal(CurrentRunningXacts->latestCompletedXid));
2089 
2090  /* We don't release the locks here, the caller is responsible for that */
2091 
2092  return CurrentRunningXacts;
2093 }
TransactionId oldestRunningXid
Definition: standby.h:76
uint32 TransactionId
Definition: c.h:507
Definition: proc.h:222
TransactionId xid
Definition: proc.h:224
#define UINT32_ACCESS_ONCE(var)
Definition: procarray.c:64
int errcode(int sqlerrcode)
Definition: elog.c:570
TransactionId * xids
Definition: standby.h:79
FullTransactionId nextFullXid
Definition: transam.h:164
bool RecoveryInProgress(void)
Definition: xlog.c:7882
#define XidFromFullTransactionId(x)
Definition: transam.h:48
TransactionId latestCompletedXid
Definition: standby.h:77
Definition: type.h:89
#define malloc(a)
Definition: header.h:50
#define ERROR
Definition: elog.h:43
uint8 nxids
Definition: proc.h:238
VariableCache ShmemVariableCache
Definition: varsup.c:34
static PGPROC * allProcs
Definition: procarray.c:101
struct XidCache subxids
Definition: proc.h:162
#define ereport(elevel, rest)
Definition: elog.h:141
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
static ProcArrayStruct * procArray
Definition: procarray.c:99
static PGXACT * allPgXact
Definition: procarray.c:102
bool overflowed
Definition: proc.h:234
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:96
TransactionId xids[PGPROC_MAX_CACHED_SUBXIDS]
Definition: proc.h:40
#define TOTAL_MAX_CACHED_SUBXIDS
#define Assert(condition)
Definition: c.h:732
#define pg_read_barrier()
Definition: atomics.h:161
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122
TransactionId nextXid
Definition: standby.h:75
int errmsg(const char *fmt,...)
Definition: elog.c:784
#define TransactionIdIsValid(xid)
Definition: transam.h:41
#define TransactionIdIsNormal(xid)
Definition: transam.h:42
Definition: proc.h:95
TransactionId latestCompletedXid
Definition: transam.h:182

◆ GetSnapshotData()

Snapshot GetSnapshotData ( Snapshot  snapshot)

Definition at line 1505 of file procarray.c.

References SnapshotData::active_count, Assert, SnapshotData::copied, SnapshotData::curcid, ereport, errcode(), errmsg(), ERROR, FirstNormalTransactionId, GetCurrentCommandId(), GetMaxSnapshotSubxidCount(), GetMaxSnapshotXidCount(), GetSnapshotCurrentTimestamp(), GetXLogInsertRecPtr(), InvalidTransactionId, InvalidXLogRecPtr, KnownAssignedXidsGetAndSetXmin(), ProcArrayStruct::lastOverflowedXid, VariableCacheData::latestCompletedXid, SnapshotData::lsn, LW_SHARED, LWLockAcquire(), LWLockRelease(), MaintainOldSnapshotTimeMapping(), malloc, MyPgXact, NormalTransactionIdPrecedes, ProcArrayStruct::numProcs, PGXACT::nxids, old_snapshot_threshold, PGXACT::overflowed, pg_read_barrier, ProcArrayStruct::pgprocnos, PROC_IN_LOGICAL_DECODING, PROC_IN_VACUUM, procArray, RecentGlobalDataXmin, RecentGlobalXmin, RecentXmin, RecoveryInProgress(), SnapshotData::regd_count, ProcArrayStruct::replication_slot_catalog_xmin, ProcArrayStruct::replication_slot_xmin, ShmemVariableCache, SnapshotData::suboverflowed, SnapshotData::subxcnt, PGPROC::subxids, SnapshotData::subxip, SnapshotData::takenDuringRecovery, TransactionIdAdvance, TransactionIdIsNormal, TransactionIdIsValid, TransactionIdPrecedes(), TransactionIdPrecedesOrEquals(), TransactionXmin, UINT32_ACCESS_ONCE, vacuum_defer_cleanup_age, PGXACT::vacuumFlags, SnapshotData::whenTaken, SnapshotData::xcnt, PGXACT::xid, XidCache::xids, SnapshotData::xip, SnapshotData::xmax, SnapshotData::xmin, and PGXACT::xmin.

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

1506 {
1507  ProcArrayStruct *arrayP = procArray;
1508  TransactionId xmin;
1509  TransactionId xmax;
1510  TransactionId globalxmin;
1511  int index;
1512  int count = 0;
1513  int subcount = 0;
1514  bool suboverflowed = false;
1515  TransactionId replication_slot_xmin = InvalidTransactionId;
1516  TransactionId replication_slot_catalog_xmin = InvalidTransactionId;
1517 
1518  Assert(snapshot != NULL);
1519 
1520  /*
1521  * Allocating space for maxProcs xids is usually overkill; numProcs would
1522  * be sufficient. But it seems better to do the malloc while not holding
1523  * the lock, so we can't look at numProcs. Likewise, we allocate much
1524  * more subxip storage than is probably needed.
1525  *
1526  * This does open a possibility for avoiding repeated malloc/free: since
1527  * maxProcs does not change at runtime, we can simply reuse the previous
1528  * xip arrays if any. (This relies on the fact that all callers pass
1529  * static SnapshotData structs.)
1530  */
1531  if (snapshot->xip == NULL)
1532  {
1533  /*
1534  * First call for this snapshot. Snapshot is same size whether or not
1535  * we are in recovery, see later comments.
1536  */
1537  snapshot->xip = (TransactionId *)
1539  if (snapshot->xip == NULL)
1540  ereport(ERROR,
1541  (errcode(ERRCODE_OUT_OF_MEMORY),
1542  errmsg("out of memory")));
1543  Assert(snapshot->subxip == NULL);
1544  snapshot->subxip = (TransactionId *)
1546  if (snapshot->subxip == NULL)
1547  ereport(ERROR,
1548  (errcode(ERRCODE_OUT_OF_MEMORY),
1549  errmsg("out of memory")));
1550  }
1551 
1552  /*
1553  * It is sufficient to get shared lock on ProcArrayLock, even if we are
1554  * going to set MyPgXact->xmin.
1555  */
1556  LWLockAcquire(ProcArrayLock, LW_SHARED);
1557 
1558  /* xmax is always latestCompletedXid + 1 */
1561  TransactionIdAdvance(xmax);
1562 
1563  /* initialize xmin calculation with xmax */
1564  globalxmin = xmin = xmax;
1565 
1567 
1568  if (!snapshot->takenDuringRecovery)
1569  {
1570  int *pgprocnos = arrayP->pgprocnos;
1571  int numProcs;
1572 
1573  /*
1574  * Spin over procArray checking xid, xmin, and subxids. The goal is
1575  * to gather all active xids, find the lowest xmin, and try to record
1576  * subxids.
1577  */
1578  numProcs = arrayP->numProcs;
1579  for (index = 0; index < numProcs; index++)
1580  {
1581  int pgprocno = pgprocnos[index];
1582  PGXACT *pgxact = &allPgXact[pgprocno];
1583  TransactionId xid;
1584 
1585  /*
1586  * Skip over backends doing logical decoding which manages xmin
1587  * separately (check below) and ones running LAZY VACUUM.
1588  */
1589  if (pgxact->vacuumFlags &
1591  continue;
1592 
1593  /* Update globalxmin to be the smallest valid xmin */
1594  xid = UINT32_ACCESS_ONCE(pgxact->xmin);
1595  if (TransactionIdIsNormal(xid) &&
1596  NormalTransactionIdPrecedes(xid, globalxmin))
1597  globalxmin = xid;
1598 
1599  /* Fetch xid just once - see GetNewTransactionId */
1600  xid = UINT32_ACCESS_ONCE(pgxact->xid);
1601 
1602  /*
1603  * If the transaction has no XID assigned, we can skip it; it
1604  * won't have sub-XIDs either. If the XID is >= xmax, we can also
1605  * skip it; such transactions will be treated as running anyway
1606  * (and any sub-XIDs will also be >= xmax).
1607  */
1608  if (!TransactionIdIsNormal(xid)
1609  || !NormalTransactionIdPrecedes(xid, xmax))
1610  continue;
1611 
1612  /*
1613  * We don't include our own XIDs (if any) in the snapshot, but we
1614  * must include them in xmin.
1615  */
1616  if (NormalTransactionIdPrecedes(xid, xmin))
1617  xmin = xid;
1618  if (pgxact == MyPgXact)
1619  continue;
1620 
1621  /* Add XID to snapshot. */
1622  snapshot->xip[count++] = xid;
1623 
1624  /*
1625  * Save subtransaction XIDs if possible (if we've already
1626  * overflowed, there's no point). Note that the subxact XIDs must
1627  * be later than their parent, so no need to check them against
1628  * xmin. We could filter against xmax, but it seems better not to
1629  * do that much work while holding the ProcArrayLock.
1630  *
1631  * The other backend can add more subxids concurrently, but cannot
1632  * remove any. Hence it's important to fetch nxids just once.
1633  * Should be safe to use memcpy, though. (We needn't worry about
1634  * missing any xids added concurrently, because they must postdate
1635  * xmax.)
1636  *
1637  * Again, our own XIDs are not included in the snapshot.
1638  */
1639  if (!suboverflowed)
1640  {
1641  if (pgxact->overflowed)
1642  suboverflowed = true;
1643  else
1644  {
1645  int nxids = pgxact->nxids;
1646 
1647  if (nxids > 0)
1648  {
1649  PGPROC *proc = &allProcs[pgprocno];
1650 
1651  pg_read_barrier(); /* pairs with GetNewTransactionId */
1652 
1653  memcpy(snapshot->subxip + subcount,
1654  (void *) proc->subxids.xids,
1655  nxids * sizeof(TransactionId));
1656  subcount += nxids;
1657  }
1658  }
1659  }
1660  }
1661  }
1662  else
1663  {
1664  /*
1665  * We're in hot standby, so get XIDs from KnownAssignedXids.
1666  *
1667  * We store all xids directly into subxip[]. Here's why:
1668  *
1669  * In recovery we don't know which xids are top-level and which are
1670  * subxacts, a design choice that greatly simplifies xid processing.
1671  *
1672  * It seems like we would want to try to put xids into xip[] only, but
1673  * that is fairly small. We would either need to make that bigger or
1674  * to increase the rate at which we WAL-log xid assignment; neither is
1675  * an appealing choice.
1676  *
1677  * We could try to store xids into xip[] first and then into subxip[]
1678  * if there are too many xids. That only works if the snapshot doesn't
1679  * overflow because we do not search subxip[] in that case. A simpler
1680  * way is to just store all xids in the subxact array because this is
1681  * by far the bigger array. We just leave the xip array empty.
1682  *
1683  * Either way we need to change the way XidInMVCCSnapshot() works
1684  * depending upon when the snapshot was taken, or change normal
1685  * snapshot processing so it matches.
1686  *
1687  * Note: It is possible for recovery to end before we finish taking
1688  * the snapshot, and for newly assigned transaction ids to be added to
1689  * the ProcArray. xmax cannot change while we hold ProcArrayLock, so
1690  * those newly added transaction ids would be filtered away, so we
1691  * need not be concerned about them.
1692  */
1693  subcount = KnownAssignedXidsGetAndSetXmin(snapshot->subxip, &xmin,
1694  xmax);
1695 
1697  suboverflowed = true;
1698  }
1699 
1700 
1701  /*
1702  * Fetch into local variable while ProcArrayLock is held - the
1703  * LWLockRelease below is a barrier, ensuring this happens inside the
1704  * lock.
1705  */
1706  replication_slot_xmin = procArray->replication_slot_xmin;
1707  replication_slot_catalog_xmin = procArray->replication_slot_catalog_xmin;
1708 
1710  MyPgXact->xmin = TransactionXmin = xmin;
1711 
1712  LWLockRelease(ProcArrayLock);
1713 
1714  /*
1715  * Update globalxmin to include actual process xids. This is a slightly
1716  * different way of computing it than GetOldestXmin uses, but should give
1717  * the same result.
1718  */
1719  if (TransactionIdPrecedes(xmin, globalxmin))
1720  globalxmin = xmin;
1721 
1722  /* Update global variables too */
1726 
1727  /* Check whether there's a replication slot requiring an older xmin. */
1728  if (TransactionIdIsValid(replication_slot_xmin) &&
1729  NormalTransactionIdPrecedes(replication_slot_xmin, RecentGlobalXmin))
1730  RecentGlobalXmin = replication_slot_xmin;
1731 
1732  /* Non-catalog tables can be vacuumed if older than this xid */
1734 
1735  /*
1736  * Check whether there's a replication slot requiring an older catalog
1737  * xmin.
1738  */
1739  if (TransactionIdIsNormal(replication_slot_catalog_xmin) &&
1740  NormalTransactionIdPrecedes(replication_slot_catalog_xmin, RecentGlobalXmin))
1741  RecentGlobalXmin = replication_slot_catalog_xmin;
1742 
1743  RecentXmin = xmin;
1744 
1745  snapshot->xmin = xmin;
1746  snapshot->xmax = xmax;
1747  snapshot->xcnt = count;
1748  snapshot->subxcnt = subcount;
1749  snapshot->suboverflowed = suboverflowed;
1750 
1751  snapshot->curcid = GetCurrentCommandId(false);
1752 
1753  /*
1754  * This is a new snapshot, so set both refcounts are zero, and mark it as
1755  * not copied in persistent memory.
1756  */
1757  snapshot->active_count = 0;
1758  snapshot->regd_count = 0;
1759  snapshot->copied = false;
1760 
1761  if (old_snapshot_threshold < 0)
1762  {
1763  /*
1764  * If not using "snapshot too old" feature, fill related fields with
1765  * dummy values that don't require any locking.
1766  */
1767  snapshot->lsn = InvalidXLogRecPtr;
1768  snapshot->whenTaken = 0;
1769  }
1770  else
1771  {
1772  /*
1773  * Capture the current time and WAL stream location in case this
1774  * snapshot becomes old enough to need to fall back on the special
1775  * "old snapshot" logic.
1776  */
1777  snapshot->lsn = GetXLogInsertRecPtr();
1778  snapshot->whenTaken = GetSnapshotCurrentTimestamp();
1779  MaintainOldSnapshotTimeMapping(snapshot->whenTaken, xmin);
1780  }
1781 
1782  return snapshot;
1783 }
#define TransactionIdAdvance(dest)
Definition: transam.h:75
#define InvalidXLogRecPtr
Definition: xlogdefs.h:28
#define PROC_IN_LOGICAL_DECODING
Definition: proc.h:57
uint32 TransactionId
Definition: c.h:507
bool copied
Definition: snapshot.h:185
Definition: proc.h:222
TransactionId xmin
Definition: proc.h:228
TransactionId xid
Definition: proc.h:224
int vacuum_defer_cleanup_age
Definition: standby.c:39
#define UINT32_ACCESS_ONCE(var)
Definition: procarray.c:64
TransactionId replication_slot_catalog_xmin
Definition: procarray.c:93
XLogRecPtr lsn
Definition: snapshot.h:203
int errcode(int sqlerrcode)
Definition: elog.c:570
TransactionId RecentXmin
Definition: snapmgr.c:167
bool suboverflowed
Definition: snapshot.h:182
bool RecoveryInProgress(void)
Definition: xlog.c:7882
uint32 regd_count
Definition: snapshot.h:199
PGXACT * MyPgXact
Definition: proc.c:69
uint8 vacuumFlags
Definition: proc.h:233
TransactionId TransactionXmin
Definition: snapmgr.c:166
Definition: type.h:89
#define malloc(a)
Definition: header.h:50
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726
#define PROC_IN_VACUUM
Definition: proc.h:54
bool TransactionIdPrecedesOrEquals(TransactionId id1, TransactionId id2)
Definition: transam.c:319
#define FirstNormalTransactionId
Definition: transam.h:34
#define ERROR
Definition: elog.h:43
TimestampTz GetSnapshotCurrentTimestamp(void)
Definition: snapmgr.c:1690
XLogRecPtr GetXLogInsertRecPtr(void)
Definition: xlog.c:11133
TransactionId RecentGlobalXmin
Definition: snapmgr.c:168
uint8 nxids
Definition: proc.h:238
VariableCache ShmemVariableCache
Definition: varsup.c:34
#define InvalidTransactionId
Definition: transam.h:31
static PGPROC * allProcs
Definition: procarray.c:101
TransactionId xmax
Definition: snapshot.h:158
TransactionId xmin
Definition: snapshot.h:157
TransactionId RecentGlobalDataXmin
Definition: snapmgr.c:169
struct XidCache subxids
Definition: proc.h:162
TransactionId lastOverflowedXid
Definition: procarray.c:88
#define ereport(elevel, rest)
Definition: elog.h:141
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
TransactionId * xip
Definition: snapshot.h:168
static ProcArrayStruct * procArray
Definition: procarray.c:99
TransactionId replication_slot_xmin
Definition: procarray.c:91
static PGXACT * allPgXact
Definition: procarray.c:102
bool overflowed
Definition: proc.h:234
CommandId curcid
Definition: snapshot.h:187
int GetMaxSnapshotXidCount(void)
Definition: procarray.c:1452
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:96
TransactionId xids[PGPROC_MAX_CACHED_SUBXIDS]
Definition: proc.h:40
#define Assert(condition)
Definition: c.h:732
#define pg_read_barrier()
Definition: atomics.h:161
bool takenDuringRecovery
Definition: snapshot.h:184
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122
static int KnownAssignedXidsGetAndSetXmin(TransactionId *xarray, TransactionId *xmin, TransactionId xmax)
Definition: procarray.c:3835
#define NormalTransactionIdPrecedes(id1, id2)
Definition: transam.h:98
uint32 xcnt
Definition: snapshot.h:169
int errmsg(const char *fmt,...)
Definition: elog.c:784
int old_snapshot_threshold
Definition: snapmgr.c:75
int GetMaxSnapshotSubxidCount(void)
Definition: procarray.c:1463
TimestampTz whenTaken
Definition: snapshot.h:202
CommandId GetCurrentCommandId(bool used)
Definition: xact.c:746
#define TransactionIdIsValid(xid)
Definition: transam.h:41
void MaintainOldSnapshotTimeMapping(TimestampTz whenTaken, TransactionId xmin)
Definition: snapmgr.c:1852
#define TransactionIdIsNormal(xid)
Definition: transam.h:42
Definition: proc.h:95
TransactionId * subxip
Definition: snapshot.h:180
uint32 active_count
Definition: snapshot.h:198
int32 subxcnt
Definition: snapshot.h:181
TransactionId latestCompletedXid
Definition: transam.h:182

◆ GetVirtualXIDsDelayingChkpt()

VirtualTransactionId* GetVirtualXIDsDelayingChkpt ( int *  nvxids)

Definition at line 2273 of file procarray.c.

References PGXACT::delayChkpt, GET_VXID_FROM_PGPROC, LW_SHARED, LWLockAcquire(), LWLockRelease(), ProcArrayStruct::maxProcs, ProcArrayStruct::numProcs, palloc(), ProcArrayStruct::pgprocnos, procArray, and VirtualTransactionIdIsValid.

Referenced by CreateCheckPoint().

2274 {
2275  VirtualTransactionId *vxids;
2276  ProcArrayStruct *arrayP = procArray;
2277  int count = 0;
2278  int index;
2279 
2280  /* allocate what's certainly enough result space */
2281  vxids = (VirtualTransactionId *)
2282  palloc(sizeof(VirtualTransactionId) * arrayP->maxProcs);
2283 
2284  LWLockAcquire(ProcArrayLock, LW_SHARED);
2285 
2286  for (index = 0; index < arrayP->numProcs; index++)
2287  {
2288  int pgprocno = arrayP->pgprocnos[index];
2289  PGPROC *proc = &allProcs[pgprocno];
2290  PGXACT *pgxact = &allPgXact[pgprocno];
2291 
2292  if (pgxact->delayChkpt)
2293  {
2294  VirtualTransactionId vxid;
2295 
2296  GET_VXID_FROM_PGPROC(vxid, *proc);
2297  if (VirtualTransactionIdIsValid(vxid))
2298  vxids[count++] = vxid;
2299  }
2300  }
2301 
2302  LWLockRelease(ProcArrayLock);
2303 
2304  *nvxids = count;
2305  return vxids;
2306 }
#define GET_VXID_FROM_PGPROC(vxid, proc)
Definition: lock.h:80
Definition: proc.h:222
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726
static PGPROC * allProcs
Definition: procarray.c:101
bool delayChkpt
Definition: proc.h:235
static ProcArrayStruct * procArray
Definition: procarray.c:99
#define VirtualTransactionIdIsValid(vxid)
Definition: lock.h:71
static PGXACT * allPgXact
Definition: procarray.c:102
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:96
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122
void * palloc(Size size)
Definition: mcxt.c:924
Definition: proc.h:95

◆ HaveVirtualXIDsDelayingChkpt()

bool HaveVirtualXIDsDelayingChkpt ( VirtualTransactionId vxids,
int  nvxids 
)

Definition at line 2318 of file procarray.c.

References PGXACT::delayChkpt, GET_VXID_FROM_PGPROC, i, LW_SHARED, LWLockAcquire(), LWLockRelease(), ProcArrayStruct::numProcs, ProcArrayStruct::pgprocnos, procArray, VirtualTransactionIdEquals, and VirtualTransactionIdIsValid.

Referenced by CreateCheckPoint().

2319 {
2320  bool result = false;
2321  ProcArrayStruct *arrayP = procArray;
2322  int index;
2323 
2324  LWLockAcquire(ProcArrayLock, LW_SHARED);
2325 
2326  for (index = 0; index < arrayP->numProcs; index++)
2327  {
2328  int pgprocno = arrayP->pgprocnos[index];
2329  PGPROC *proc = &allProcs[pgprocno];
2330  PGXACT *pgxact = &allPgXact[pgprocno];
2331  VirtualTransactionId vxid;
2332 
2333  GET_VXID_FROM_PGPROC(vxid, *proc);
2334 
2335  if (pgxact->delayChkpt && VirtualTransactionIdIsValid(vxid))
2336  {
2337  int i;
2338 
2339  for (i = 0; i < nvxids; i++)
2340  {
2341  if (VirtualTransactionIdEquals(vxid, vxids[i]))
2342  {
2343  result = true;
2344  break;
2345  }
2346  }
2347  if (result)
2348  break;
2349  }
2350  }
2351 
2352  LWLockRelease(ProcArrayLock);
2353 
2354  return result;
2355 }
#define GET_VXID_FROM_PGPROC(vxid, proc)
Definition: lock.h:80
Definition: proc.h:222
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726
#define VirtualTransactionIdEquals(vxid1, vxid2)
Definition: lock.h:74
static PGPROC * allProcs
Definition: procarray.c:101
bool delayChkpt
Definition: proc.h:235
static ProcArrayStruct * procArray
Definition: procarray.c:99
#define VirtualTransactionIdIsValid(vxid)
Definition: lock.h:71
static PGXACT * allPgXact
Definition: procarray.c:102
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:96
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122
int i
Definition: proc.h:95

◆ IsBackendPid()

bool IsBackendPid ( int  pid)

Definition at line 2460 of file procarray.c.

References BackendPidGetProc().

Referenced by pg_stat_get_subscription().

2461 {
2462  return (BackendPidGetProc(pid) != NULL);
2463 }
PGPROC * BackendPidGetProc(int pid)
Definition: procarray.c:2365

◆ KnownAssignedXidExists()

static bool KnownAssignedXidExists ( TransactionId  xid)
static

Definition at line 3682 of file procarray.c.

References Assert, KnownAssignedXidsSearch(), and TransactionIdIsValid.

Referenced by TransactionIdIsInProgress().

3683 {
3685 
3686  return KnownAssignedXidsSearch(xid, false);
3687 }
#define Assert(condition)
Definition: c.h:732
static bool KnownAssignedXidsSearch(TransactionId xid, bool remove)
Definition: procarray.c:3589
#define TransactionIdIsValid(xid)
Definition: transam.h:41

◆ KnownAssignedXidsAdd()

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

Definition at line 3471 of file procarray.c.

References Assert, elog, ERROR, ProcArrayStruct::headKnownAssignedXids, i, ProcArrayStruct::known_assigned_xids_lck, KnownAssignedXids, KnownAssignedXidsCompress(), KnownAssignedXidsDisplay(), KnownAssignedXidsValid, LOG, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), ProcArrayStruct::maxKnownAssignedXids, ProcArrayStruct::numKnownAssignedXids, procArray, SpinLockAcquire, SpinLockRelease, ProcArrayStruct::tailKnownAssignedXids, TransactionIdAdvance, TransactionIdFollowsOrEquals(), TransactionIdPrecedes(), and TransactionIdPrecedesOrEquals().

Referenced by ProcArrayApplyRecoveryInfo(), and RecordKnownAssignedTransactionIds().

3473 {
3474  ProcArrayStruct *pArray = procArray;
3475  TransactionId next_xid;
3476  int head,
3477  tail;
3478  int nxids;
3479  int i;
3480 
3481  Assert(TransactionIdPrecedesOrEquals(from_xid, to_xid));
3482 
3483  /*
3484  * Calculate how many array slots we'll need. Normally this is cheap; in
3485  * the unusual case where the XIDs cross the wrap point, we do it the hard
3486  * way.
3487  */
3488  if (to_xid >= from_xid)
3489  nxids = to_xid - from_xid + 1;
3490  else
3491  {
3492  nxids = 1;
3493  next_xid = from_xid;
3494  while (TransactionIdPrecedes(next_xid, to_xid))
3495  {
3496  nxids++;
3497  TransactionIdAdvance(next_xid);
3498  }
3499  }
3500 
3501  /*
3502  * Since only the startup process modifies the head/tail pointers, we
3503  * don't need a lock to read them here.
3504  */
3505  head = pArray->headKnownAssignedXids;
3506  tail = pArray->tailKnownAssignedXids;
3507 
3508  Assert(head >= 0 && head <= pArray->maxKnownAssignedXids);
3509  Assert(tail >= 0 && tail < pArray->maxKnownAssignedXids);
3510 
3511  /*
3512  * Verify that insertions occur in TransactionId sequence. Note that even
3513  * if the last existing element is marked invalid, it must still have a
3514  * correctly sequenced XID value.
3515  */
3516  if (head > tail &&
3517  TransactionIdFollowsOrEquals(KnownAssignedXids[head - 1], from_xid))
3518  {
3520  elog(ERROR, "out-of-order XID insertion in KnownAssignedXids");
3521  }
3522 
3523  /*
3524  * If our xids won't fit in the remaining space, compress out free space
3525  */
3526  if (head + nxids > pArray->maxKnownAssignedXids)
3527  {
3528  /* must hold lock to compress */
3529  if (!exclusive_lock)
3530  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3531 
3533 
3534  head = pArray->headKnownAssignedXids;
3535  /* note: we no longer care about the tail pointer */
3536 
3537  if (!exclusive_lock)
3538  LWLockRelease(ProcArrayLock);
3539 
3540  /*
3541  * If it still won't fit then we're out of memory
3542  */
3543  if (head + nxids > pArray->maxKnownAssignedXids)
3544  elog(ERROR, "too many KnownAssignedXids");
3545  }
3546 
3547  /* Now we can insert the xids into the space starting at head */
3548  next_xid = from_xid;
3549  for (i = 0; i < nxids; i++)
3550  {
3551  KnownAssignedXids[head] = next_xid;
3552  KnownAssignedXidsValid[head] = true;
3553  TransactionIdAdvance(next_xid);
3554  head++;
3555  }
3556 
3557  /* Adjust count of number of valid entries */
3558  pArray->numKnownAssignedXids += nxids;
3559 
3560  /*
3561  * Now update the head pointer. We use a spinlock to protect this
3562  * pointer, not because the update is likely to be non-atomic, but to
3563  * ensure that other processors see the above array updates before they
3564  * see the head pointer change.
3565  *
3566  * If we're holding ProcArrayLock exclusively, there's no need to take the
3567  * spinlock.
3568  */
3569  if (exclusive_lock)
3570  pArray->headKnownAssignedXids = head;
3571  else
3572  {
3574  pArray->headKnownAssignedXids = head;
3576  }
3577 }
#define TransactionIdAdvance(dest)
Definition: transam.h:75
static void KnownAssignedXidsDisplay(int trace_level)
Definition: procarray.c:3928
uint32 TransactionId
Definition: c.h:507
bool TransactionIdFollowsOrEquals(TransactionId id1, TransactionId id2)
Definition: transam.c:349
slock_t known_assigned_xids_lck
Definition: procarray.c:79
#define LOG
Definition: elog.h:26
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726
#define SpinLockAcquire(lock)
Definition: spin.h:62
bool TransactionIdPrecedesOrEquals(TransactionId id1, TransactionId id2)
Definition: transam.c:319
#define ERROR
Definition: elog.h:43
int maxKnownAssignedXids
Definition: procarray.c:75
int numKnownAssignedXids
Definition: procarray.c:76
static bool * KnownAssignedXidsValid
Definition: procarray.c:108
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
static ProcArrayStruct * procArray
Definition: procarray.c:99
#define SpinLockRelease(lock)
Definition: spin.h:64
#define Assert(condition)
Definition: c.h:732
static TransactionId * KnownAssignedXids
Definition: procarray.c:107
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122
static void KnownAssignedXidsCompress(bool force)
Definition: procarray.c:3409
#define elog(elevel,...)
Definition: elog.h:226
int i
int tailKnownAssignedXids
Definition: procarray.c:77
int headKnownAssignedXids
Definition: procarray.c:78

◆ KnownAssignedXidsCompress()

static void KnownAssignedXidsCompress ( bool  force)
static

Definition at line 3409 of file procarray.c.

References ProcArrayStruct::headKnownAssignedXids, i, KnownAssignedXids, KnownAssignedXidsValid, ProcArrayStruct::numKnownAssignedXids, procArray, PROCARRAY_MAXPROCS, and ProcArrayStruct::tailKnownAssignedXids.

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

3410 {
3411  ProcArrayStruct *pArray = procArray;
3412  int head,
3413  tail;
3414  int compress_index;
3415  int i;
3416 
3417  /* no spinlock required since we hold ProcArrayLock exclusively */
3418  head = pArray->headKnownAssignedXids;
3419  tail = pArray->tailKnownAssignedXids;
3420 
3421  if (!force)
3422  {
3423  /*
3424  * If we can choose how much to compress, use a heuristic to avoid
3425  * compressing too often or not often enough.
3426  *
3427  * Heuristic is if we have a large enough current spread and less than
3428  * 50% of the elements are currently in use, then compress. This
3429  * should ensure we compress fairly infrequently. We could compress
3430  * less often though the virtual array would spread out more and
3431  * snapshots would become more expensive.
3432  */
3433  int nelements = head - tail;
3434 
3435  if (nelements < 4 * PROCARRAY_MAXPROCS ||
3436  nelements < 2 * pArray->numKnownAssignedXids)
3437  return;
3438  }
3439 
3440  /*
3441  * We compress the array by reading the valid values from tail to head,
3442  * re-aligning data to 0th element.
3443  */
3444  compress_index = 0;
3445  for (i = tail; i < head; i++)
3446  {
3447  if (KnownAssignedXidsValid[i])
3448  {
3449  KnownAssignedXids[compress_index] = KnownAssignedXids[i];
3450  KnownAssignedXidsValid[compress_index] = true;
3451  compress_index++;
3452  }
3453  }
3454 
3455  pArray->tailKnownAssignedXids = 0;
3456  pArray->headKnownAssignedXids = compress_index;
3457 }
#define PROCARRAY_MAXPROCS
static bool * KnownAssignedXidsValid
Definition: procarray.c:108
static ProcArrayStruct * procArray
Definition: procarray.c:99
static TransactionId * KnownAssignedXids
Definition: procarray.c:107
int i
int tailKnownAssignedXids
Definition: procarray.c:77
int headKnownAssignedXids
Definition: procarray.c:78

◆ KnownAssignedXidsDisplay()

static void KnownAssignedXidsDisplay ( int  trace_level)
static

Definition at line 3928 of file procarray.c.

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

Referenced by KnownAssignedXidsAdd(), and ProcArrayApplyRecoveryInfo().

3929 {
3930  ProcArrayStruct *pArray = procArray;
3932  int head,
3933  tail,
3934  i;
3935  int nxids = 0;
3936 
3937  tail = pArray->tailKnownAssignedXids;
3938  head = pArray->headKnownAssignedXids;
3939 
3940  initStringInfo(&buf);
3941 
3942  for (i = tail; i < head; i++)
3943  {
3944  if (KnownAssignedXidsValid[i])
3945  {
3946  nxids++;
3947  appendStringInfo(&buf, "[%d]=%u ", i, KnownAssignedXids[i]);
3948  }
3949  }
3950 
3951  elog(trace_level, "%d KnownAssignedXids (num=%d tail=%d head=%d) %s",
3952  nxids,
3953  pArray->numKnownAssignedXids,
3954  pArray->tailKnownAssignedXids,
3955  pArray->headKnownAssignedXids,
3956  buf.data);
3957 
3958  pfree(buf.data);
3959 }
void pfree(void *pointer)
Definition: mcxt.c:1031
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
static char * buf
Definition: pg_test_fsync.c:68
int numKnownAssignedXids
Definition: procarray.c:76
static bool * KnownAssignedXidsValid
Definition: procarray.c:108
void initStringInfo(StringInfo str)
Definition: stringinfo.c:46
static ProcArrayStruct * procArray
Definition: procarray.c:99
static TransactionId * KnownAssignedXids
Definition: procarray.c:107
#define elog(elevel,...)
Definition: elog.h:226
int i
int tailKnownAssignedXids
Definition: procarray.c:77
int headKnownAssignedXids
Definition: procarray.c:78

◆ KnownAssignedXidsGet()

static int KnownAssignedXidsGet ( TransactionId xarray,
TransactionId  xmax 
)
static

Definition at line 3821 of file procarray.c.

References InvalidTransactionId, and KnownAssignedXidsGetAndSetXmin().

Referenced by TransactionIdIsInProgress().

3822 {
3824 
3825  return KnownAssignedXidsGetAndSetXmin(xarray, &xtmp, xmax);
3826 }
uint32 TransactionId
Definition: c.h:507
#define InvalidTransactionId
Definition: transam.h:31
static int KnownAssignedXidsGetAndSetXmin(TransactionId *xarray, TransactionId *xmin, TransactionId xmax)
Definition: procarray.c:3835

◆ KnownAssignedXidsGetAndSetXmin()

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

Definition at line 3835 of file procarray.c.

References ProcArrayStruct::headKnownAssignedXids, i, ProcArrayStruct::known_assigned_xids_lck, KnownAssignedXids, KnownAssignedXidsValid, SpinLockAcquire, SpinLockRelease, ProcArrayStruct::tailKnownAssignedXids, TransactionIdFollowsOrEquals(), TransactionIdIsValid, and TransactionIdPrecedes().

Referenced by GetSnapshotData(), and KnownAssignedXidsGet().

3837 {
3838  int count = 0;
3839  int head,
3840  tail;
3841  int i;
3842 
3843  /*
3844  * Fetch head just once, since it may change while we loop. We can stop
3845  * once we reach the initially seen head, since we are certain that an xid
3846  * cannot enter and then leave the array while we hold ProcArrayLock. We
3847  * might miss newly-added xids, but they should be >= xmax so irrelevant
3848  * anyway.
3849  *
3850  * Must take spinlock to ensure we see up-to-date array contents.
3851  */
3856 
3857  for (i = tail; i < head; i++)
3858  {
3859  /* Skip any gaps in the array */
3860  if (KnownAssignedXidsValid[i])
3861  {
3862  TransactionId knownXid = KnownAssignedXids[i];
3863 
3864  /*
3865  * Update xmin if required. Only the first XID need be checked,
3866  * since the array is sorted.
3867  */
3868  if (count == 0 &&
3869  TransactionIdPrecedes(knownXid, *xmin))
3870  *xmin = knownXid;
3871 
3872  /*
3873  * Filter out anything >= xmax, again relying on sorted property
3874  * of array.
3875  */
3876  if (TransactionIdIsValid(xmax) &&
3877  TransactionIdFollowsOrEquals(knownXid, xmax))
3878  break;
3879 
3880  /* Add knownXid into output array */
3881  xarray[count++] = knownXid;
3882  }
3883  }
3884 
3885  return count;
3886 }
uint32 TransactionId
Definition: c.h:507
bool TransactionIdFollowsOrEquals(TransactionId id1, TransactionId id2)
Definition: transam.c:349
slock_t known_assigned_xids_lck
Definition: procarray.c:79
#define SpinLockAcquire(lock)
Definition: spin.h:62
static bool * KnownAssignedXidsValid
Definition: procarray.c:108
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
static ProcArrayStruct * procArray
Definition: procarray.c:99
#define SpinLockRelease(lock)
Definition: spin.h:64
static TransactionId * KnownAssignedXids
Definition: procarray.c:107
int i
#define TransactionIdIsValid(xid)
Definition: transam.h:41
int tailKnownAssignedXids
Definition: procarray.c:77
int headKnownAssignedXids
Definition: procarray.c:78

◆ KnownAssignedXidsGetOldestXmin()

static TransactionId KnownAssignedXidsGetOldestXmin ( void  )
static

Definition at line 3893 of file procarray.c.

References ProcArrayStruct::headKnownAssignedXids, i, InvalidTransactionId, ProcArrayStruct::known_assigned_xids_lck, KnownAssignedXids, KnownAssignedXidsValid, SpinLockAcquire, SpinLockRelease, and ProcArrayStruct::tailKnownAssignedXids.

Referenced by GetOldestXmin().

3894 {
3895  int head,
3896  tail;
3897  int i;
3898 
3899  /*
3900  * Fetch head just once, since it may change while we loop.
3901  */
3906 
3907  for (i = tail; i < head; i++)
3908  {
3909  /* Skip any gaps in the array */
3910  if (KnownAssignedXidsValid[i])
3911  return KnownAssignedXids[i];
3912  }
3913 
3914  return InvalidTransactionId;
3915 }
slock_t known_assigned_xids_lck
Definition: procarray.c:79
#define SpinLockAcquire(lock)
Definition: spin.h:62
#define InvalidTransactionId
Definition: transam.h:31
static bool * KnownAssignedXidsValid
Definition: procarray.c:108
static ProcArrayStruct * procArray
Definition: procarray.c:99
#define SpinLockRelease(lock)
Definition: spin.h:64
static TransactionId * KnownAssignedXids
Definition: procarray.c:107
int i
int tailKnownAssignedXids
Definition: procarray.c:77
int headKnownAssignedXids
Definition: procarray.c:78

◆ KnownAssignedXidsRemove()

static void KnownAssignedXidsRemove ( TransactionId  xid)
static

Definition at line 3695 of file procarray.c.

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

Referenced by KnownAssignedXidsRemoveTree().

3696 {
3698 
3699  elog(trace_recovery(DEBUG4), "remove KnownAssignedXid %u", xid);
3700 
3701  /*
3702  * Note: we cannot consider it an error to remove an XID that's not
3703  * present. We intentionally remove subxact IDs while processing
3704  * XLOG_XACT_ASSIGNMENT, to avoid array overflow. Then those XIDs will be
3705  * removed again when the top-level xact commits or aborts.
3706  *
3707  * It might be possible to track such XIDs to distinguish this case from
3708  * actual errors, but it would be complicated and probably not worth it.
3709  * So, just ignore the search result.
3710  */
3711  (void) KnownAssignedXidsSearch(xid, true);
3712 }
#define DEBUG4
Definition: elog.h:22
int trace_recovery(int trace_level)
Definition: elog.c:3474
#define Assert(condition)
Definition: c.h:732
static bool KnownAssignedXidsSearch(TransactionId xid, bool remove)
Definition: procarray.c:3589
#define elog(elevel,...)
Definition: elog.h:226
#define TransactionIdIsValid(xid)
Definition: transam.h:41

◆ KnownAssignedXidsRemovePreceding()

static void KnownAssignedXidsRemovePreceding ( TransactionId  xid)
static

Definition at line 3743 of file procarray.c.

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

Referenced by ExpireAllKnownAssignedTransactionIds(), and ExpireOldKnownAssignedTransactionIds().

3744 {
3745  ProcArrayStruct *pArray = procArray;
3746  int count = 0;
3747  int head,
3748  tail,
3749  i;
3750 
3751  if (!TransactionIdIsValid(removeXid))
3752  {
3753  elog(trace_recovery(DEBUG4), "removing all KnownAssignedXids");
3754  pArray->numKnownAssignedXids = 0;
3755  pArray->headKnownAssignedXids = pArray->tailKnownAssignedXids = 0;
3756  return;
3757  }
3758 
3759  elog(trace_recovery(DEBUG4), "prune KnownAssignedXids to %u", removeXid);
3760 
3761  /*
3762  * Mark entries invalid starting at the tail. Since array is sorted, we
3763  * can stop as soon as we reach an entry >= removeXid.
3764  */
3765  tail = pArray->tailKnownAssignedXids;
3766  head = pArray->headKnownAssignedXids;
3767 
3768  for (i = tail; i < head; i++)
3769  {
3770  if (KnownAssignedXidsValid[i])
3771  {
3772  TransactionId knownXid = KnownAssignedXids[i];
3773 
3774  if (TransactionIdFollowsOrEquals(knownXid, removeXid))
3775  break;
3776 
3777  if (!StandbyTransactionIdIsPrepared(knownXid))
3778  {
3779  KnownAssignedXidsValid[i] = false;
3780  count++;
3781  }
3782  }
3783  }
3784 
3785  pArray->numKnownAssignedXids -= count;
3786  Assert(pArray->numKnownAssignedXids >= 0);
3787 
3788  /*
3789  * Advance the tail pointer if we've marked the tail item invalid.
3790  */
3791  for (i = tail; i < head; i++)
3792  {
3793  if (KnownAssignedXidsValid[i])
3794  break;
3795  }
3796  if (i >= head)
3797  {
3798  /* Array is empty, so we can reset both pointers */
3799  pArray->headKnownAssignedXids = 0;
3800  pArray->tailKnownAssignedXids = 0;
3801  }
3802  else
3803  {
3804  pArray->tailKnownAssignedXids = i;
3805  }
3806 
3807  /* Opportunistically compress the array */
3809 }
uint32 TransactionId
Definition: c.h:507
bool TransactionIdFollowsOrEquals(TransactionId id1, TransactionId id2)
Definition: transam.c:349
#define DEBUG4
Definition: elog.h:22
int trace_recovery(int trace_level)
Definition: elog.c:3474
bool StandbyTransactionIdIsPrepared(TransactionId xid)
Definition: twophase.c:1427
int numKnownAssignedXids
Definition: procarray.c:76
static bool * KnownAssignedXidsValid
Definition: procarray.c:108
static ProcArrayStruct * procArray
Definition: procarray.c:99
#define Assert(condition)
Definition: c.h:732
static TransactionId * KnownAssignedXids
Definition: procarray.c:107
static void KnownAssignedXidsCompress(bool force)
Definition: procarray.c:3409
#define elog(elevel,...)
Definition: elog.h:226
int i
#define TransactionIdIsValid(xid)
Definition: transam.h:41
int tailKnownAssignedXids
Definition: procarray.c:77
int headKnownAssignedXids
Definition: procarray.c:78

◆ KnownAssignedXidsRemoveTree()

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

Definition at line 3721 of file procarray.c.

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

Referenced by ExpireTreeKnownAssignedTransactionIds(), and ProcArrayApplyXidAssignment().

3723 {
3724  int i;
3725 
3726  if (TransactionIdIsValid(xid))
3728 
3729  for (i = 0; i < nsubxids; i++)
3730  KnownAssignedXidsRemove(subxids[i]);
3731 
3732  /* Opportunistically compress the array */
3734 }
static void KnownAssignedXidsCompress(bool force)
Definition: procarray.c:3409
static void KnownAssignedXidsRemove(TransactionId xid)
Definition: procarray.c:3695
int i
#define TransactionIdIsValid(xid)
Definition: transam.h:41

◆ KnownAssignedXidsReset()

static void KnownAssignedXidsReset ( void  )
static

Definition at line 3966 of file procarray.c.

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

Referenced by ProcArrayApplyRecoveryInfo().

3967 {
3968  ProcArrayStruct *pArray = procArray;
3969 
3970  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3971 
3972  pArray->numKnownAssignedXids = 0;
3973  pArray->tailKnownAssignedXids = 0;
3974  pArray->headKnownAssignedXids = 0;
3975 
3976  LWLockRelease(ProcArrayLock);
3977 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726
int numKnownAssignedXids
Definition: procarray.c:76
static ProcArrayStruct * procArray
Definition: procarray.c:99
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122
int tailKnownAssignedXids
Definition: procarray.c:77
int headKnownAssignedXids
Definition: procarray.c:78

◆ KnownAssignedXidsSearch()

static bool KnownAssignedXidsSearch ( TransactionId  xid,
bool  remove 
)
static

Definition at line 3589 of file procarray.c.

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

Referenced by KnownAssignedXidExists(), and KnownAssignedXidsRemove().

3590 {
3591  ProcArrayStruct *pArray = procArray;
3592  int first,
3593  last;
3594  int head;
3595  int tail;
3596  int result_index = -1;
3597 
3598  if (remove)
3599  {
3600  /* we hold ProcArrayLock exclusively, so no need for spinlock */
3601  tail = pArray->tailKnownAssignedXids;
3602  head = pArray->headKnownAssignedXids;
3603  }
3604  else
3605  {
3606  /* take spinlock to ensure we see up-to-date array contents */
3608  tail = pArray->tailKnownAssignedXids;
3609  head = pArray->headKnownAssignedXids;
3611  }
3612 
3613  /*
3614  * Standard binary search. Note we can ignore the KnownAssignedXidsValid
3615  * array here, since even invalid entries will contain sorted XIDs.
3616  */
3617  first = tail;
3618  last = head - 1;
3619  while (first <= last)
3620  {
3621  int mid_index;
3622  TransactionId mid_xid;
3623 
3624  mid_index = (first + last) / 2;
3625  mid_xid = KnownAssignedXids[mid_index];
3626 
3627  if (xid == mid_xid)
3628  {
3629  result_index = mid_index;
3630  break;
3631  }
3632  else if (TransactionIdPrecedes(xid, mid_xid))
3633  last = mid_index - 1;
3634  else
3635  first = mid_index + 1;
3636  }
3637 
3638  if (result_index < 0)
3639  return false; /* not in array */
3640 
3641  if (!KnownAssignedXidsValid[result_index])
3642  return false; /* in array, but invalid */
3643 
3644  if (remove)
3645  {
3646  KnownAssignedXidsValid[result_index] = false;
3647 
3648  pArray->numKnownAssignedXids--;
3649  Assert(pArray->numKnownAssignedXids >= 0);
3650 
3651  /*
3652  * If we're removing the tail element then advance tail pointer over
3653  * any invalid elements. This will speed future searches.
3654  */
3655  if (result_index == tail)
3656  {
3657  tail++;
3658  while (tail < head && !KnownAssignedXidsValid[tail])
3659  tail++;
3660  if (tail >= head)
3661  {
3662  /* Array is empty, so we can reset both pointers */
3663  pArray->headKnownAssignedXids = 0;
3664  pArray->tailKnownAssignedXids = 0;
3665  }
3666  else
3667  {
3668  pArray->tailKnownAssignedXids = tail;
3669  }
3670  }
3671  }
3672 
3673  return true;
3674 }
uint32 TransactionId
Definition: c.h:507
slock_t known_assigned_xids_lck
Definition: procarray.c:79
#define SpinLockAcquire(lock)
Definition: spin.h:62
int numKnownAssignedXids
Definition: procarray.c:76
static bool * KnownAssignedXidsValid
Definition: procarray.c:108
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
static ProcArrayStruct * procArray
Definition: procarray.c:99
#define SpinLockRelease(lock)
Definition: spin.h:64
#define Assert(condition)
Definition: c.h:732
static TransactionId * KnownAssignedXids
Definition: procarray.c:107
int tailKnownAssignedXids
Definition: procarray.c:77
int headKnownAssignedXids
Definition: procarray.c:78

◆ MinimumActiveBackends()

bool MinimumActiveBackends ( int  min)

Definition at line 2704 of file procarray.c.

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

Referenced by XLogFlush().

2705 {
2706  ProcArrayStruct *arrayP = procArray;
2707  int count = 0;
2708  int index;
2709 
2710  /* Quick short-circuit if no minimum is specified */
2711  if (min == 0)
2712  return true;
2713 
2714  /*
2715  * Note: for speed, we don't acquire ProcArrayLock. This is a little bit
2716  * bogus, but since we are only testing fields for zero or nonzero, it
2717  * should be OK. The result is only used for heuristic purposes anyway...
2718  */
2719  for (index = 0; index < arrayP->numProcs; index++)
2720  {
2721  int pgprocno = arrayP->pgprocnos[index];
2722  PGPROC *proc = &allProcs[pgprocno];
2723  PGXACT *pgxact = &allPgXact[pgprocno];
2724 
2725  /*
2726  * Since we're not holding a lock, need to be prepared to deal with
2727  * garbage, as someone could have incremented numProcs but not yet
2728  * filled the structure.
2729  *
2730  * If someone just decremented numProcs, 'proc' could also point to a
2731  * PGPROC entry that's no longer in the array. It still points to a
2732  * PGPROC struct, though, because freed PGPROC entries just go to the
2733  * free list and are recycled. Its contents are nonsense in that case,
2734  * but that's acceptable for this function.
2735  */
2736  if (pgprocno == -1)
2737  continue; /* do not count deleted entries */
2738  if (proc == MyProc)
2739  continue; /* do not count myself */
2740  if (pgxact->xid == InvalidTransactionId)
2741  continue; /* do not count if no XID assigned */
2742  if (proc->pid == 0)
2743  continue; /* do not count prepared xacts */
2744  if (proc->waitLock != NULL)
2745  continue; /* do not count if blocked on a lock */
2746  count++;
2747  if (count >= min)
2748  break;
2749  }
2750 
2751  return count >= min;
2752 }
Definition: proc.h:222
PGPROC * MyProc
Definition: proc.c:68
TransactionId xid
Definition: proc.h:224
Definition: type.h:89
#define InvalidTransactionId
Definition: transam.h:31
static PGPROC * allProcs
Definition: procarray.c:101
LOCK * waitLock
Definition: proc.h:139
static ProcArrayStruct * procArray
Definition: procarray.c:99
static PGXACT * allPgXact
Definition: procarray.c:102
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:96
Definition: proc.h:95
int pid
Definition: proc.h:109

◆ ProcArrayAdd()

void ProcArrayAdd ( PGPROC proc)

Definition at line 276 of file procarray.c.

References ereport, errcode(), errmsg(), FATAL, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), ProcArrayStruct::maxProcs, memmove, ProcArrayStruct::numProcs, PGPROC::pgprocno, ProcArrayStruct::pgprocnos, and procArray.

Referenced by InitProcessPhase2(), and MarkAsPrepared().

277 {
278  ProcArrayStruct *arrayP = procArray;
279  int index;
280 
281  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
282 
283  if (arrayP->numProcs >= arrayP->maxProcs)
284  {
285  /*
286  * Oops, no room. (This really shouldn't happen, since there is a
287  * fixed supply of PGPROC structs too, and so we should have failed
288  * earlier.)
289  */
290  LWLockRelease(ProcArrayLock);
291  ereport(FATAL,
292  (errcode(ERRCODE_TOO_MANY_CONNECTIONS),
293  errmsg("sorry, too many clients already")));
294  }
295 
296  /*
297  * Keep the procs array sorted by (PGPROC *) so that we can utilize
298  * locality of references much better. This is useful while traversing the
299  * ProcArray because there is an increased likelihood of finding the next
300  * PGPROC structure in the cache.
301  *
302  * Since the occurrence of adding/removing a proc is much lower than the
303  * access to the ProcArray itself, the overhead should be marginal
304  */
305  for (index = 0; index < arrayP->numProcs; index++)
306  {
307  /*
308  * If we are the first PGPROC or if we have found our right position
309  * in the array, break
310  */
311  if ((arrayP->pgprocnos[index] == -1) || (arrayP->pgprocnos[index] > proc->pgprocno))
312  break;
313  }
314 
315  memmove(&arrayP->pgprocnos[index + 1], &arrayP->pgprocnos[index],
316  (arrayP->numProcs - index) * sizeof(int));
317  arrayP->pgprocnos[index] = proc->pgprocno;
318  arrayP->numProcs++;
319 
320  LWLockRelease(ProcArrayLock);
321 }
int errcode(int sqlerrcode)
Definition: elog.c:570
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726
#define FATAL
Definition: elog.h:52
#define memmove(d, s, c)
Definition: c.h:1224
#define ereport(elevel, rest)
Definition: elog.h:141
static ProcArrayStruct * procArray
Definition: procarray.c:99
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:96
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122
int pgprocno
Definition: proc.h:110
int errmsg(const char *fmt,...)
Definition: elog.c:784

◆ ProcArrayApplyRecoveryInfo()

void ProcArrayApplyRecoveryInfo ( RunningTransactions  running)

Definition at line 663 of file procarray.c.

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

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

664 {
665  TransactionId *xids;
666  int nxids;
667  int i;
668 
673 
674  /*
675  * Remove stale transactions, if any.
676  */
678 
679  /*
680  * Remove stale locks, if any.
681  */
683 
684  /*
685  * If our snapshot is already valid, nothing else to do...
686  */
688  return;
689 
690  /*
691  * If our initial RunningTransactionsData had an overflowed snapshot then
692  * we knew we were missing some subxids from our snapshot. If we continue
693  * to see overflowed snapshots then we might never be able to start up, so
694  * we make another test to see if our snapshot is now valid. We know that
695  * the missing subxids are equal to or earlier than nextXid. After we
696  * initialise we continue to apply changes during recovery, so once the
697  * oldestRunningXid is later than the nextXid from the initial snapshot we
698  * know that we no longer have missing information and can mark the
699  * snapshot as valid.
700  */
702  {
703  /*
704  * If the snapshot isn't overflowed or if its empty we can reset our
705  * pending state and use this snapshot instead.
706  */
707  if (!running->subxid_overflow || running->xcnt == 0)
708  {
709  /*
710  * If we have already collected known assigned xids, we need to
711  * throw them away before we apply the recovery snapshot.
712  */
715  }
716  else
717  {
719  running->oldestRunningXid))
720  {
723  "recovery snapshots are now enabled");
724  }
725  else
727  "recovery snapshot waiting for non-overflowed snapshot or "
728  "until oldest active xid on standby is at least %u (now %u)",
730  running->oldestRunningXid);
731  return;
732  }
733  }
734 
736 
737  /*
738  * OK, we need to initialise from the RunningTransactionsData record.
739  *
740  * NB: this can be reached at least twice, so make sure new code can deal
741  * with that.
742  */
743 
744  /*
745  * Nobody else is running yet, but take locks anyhow
746  */
747  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
748 
749  /*
750  * KnownAssignedXids is sorted so we cannot just add the xids, we have to
751  * sort them first.
752  *
753  * Some of the new xids are top-level xids and some are subtransactions.
754  * We don't call SubtransSetParent because it doesn't matter yet. If we
755  * aren't overflowed then all xids will fit in snapshot and so we don't
756  * need subtrans. If we later overflow, an xid assignment record will add
757  * xids to subtrans. If RunningXacts is overflowed then we don't have
758  * enough information to correctly update subtrans anyway.
759  */
760 
761  /*
762  * Allocate a temporary array to avoid modifying the array passed as
763  * argument.
764  */
765  xids = palloc(sizeof(TransactionId) * (running->xcnt + running->subxcnt));
766 
767  /*
768  * Add to the temp array any xids which have not already completed.
769  */
770  nxids = 0;
771  for (i = 0; i < running->xcnt + running->subxcnt; i++)
772  {
773  TransactionId xid = running->xids[i];
774 
775  /*
776  * The running-xacts snapshot can contain xids that were still visible
777  * in the procarray when the snapshot was taken, but were already
778  * WAL-logged as completed. They're not running anymore, so ignore
779  * them.
780  */
782  continue;
783 
784  xids[nxids++] = xid;
785  }
786 
787  if (nxids > 0)
788  {
790  {
791  LWLockRelease(ProcArrayLock);
792  elog(ERROR, "KnownAssignedXids is not empty");
793  }
794 
795  /*
796  * Sort the array so that we can add them safely into
797  * KnownAssignedXids.
798  */
799  qsort(xids, nxids, sizeof(TransactionId), xidComparator);
800 
801  /*
802  * Add the sorted snapshot into KnownAssignedXids. The running-xacts
803  * snapshot may include duplicated xids because of prepared
804  * transactions, so ignore them.
805  */
806  for (i = 0; i < nxids; i++)
807  {
808  if (i > 0 && TransactionIdEquals(xids[i - 1], xids[i]))
809  {
810  elog(DEBUG1,
811  "found duplicated transaction %u for KnownAssignedXids insertion",
812  xids[i]);
813  continue;
814  }
815  KnownAssignedXidsAdd(xids[i], xids[i], true);
816  }
817 
819  }
820 
821  pfree(xids);
822 
823  /*
824  * latestObservedXid is at least set to the point where SUBTRANS was
825  * started up to (cf. ProcArrayInitRecovery()) or to the biggest xid
826  * RecordKnownAssignedTransactionIds() was called for. Initialize
827  * subtrans from thereon, up to nextXid - 1.
828  *
829  * We need to duplicate parts of RecordKnownAssignedTransactionId() here,
830  * because we've just added xids to the known assigned xids machinery that
831  * haven't gone through RecordKnownAssignedTransactionId().
832  */
836  {
839  }
840  TransactionIdRetreat(latestObservedXid); /* = running->nextXid - 1 */
841 
842  /* ----------
843  * Now we've got the running xids we need to set the global values that
844  * are used to track snapshots as they evolve further.
845  *
846  * - latestCompletedXid which will be the xmax for snapshots
847  * - lastOverflowedXid which shows whether snapshots overflow
848  * - nextXid
849  *
850  * If the snapshot overflowed, then we still initialise with what we know,
851  * but the recovery snapshot isn't fully valid yet because we know there
852  * are some subxids missing. We don't know the specific subxids that are
853  * missing, so conservatively assume the last one is latestObservedXid.
854  * ----------
855  */
856  if (running->subxid_overflow)
857  {
859 
862  }
863  else
864  {
866 
868  }
869 
870  /*
871  * If a transaction wrote a commit record in the gap between taking and
872  * logging the snapshot then latestCompletedXid may already be higher than
873  * the value from the snapshot, so check before we use the incoming value.
874  */
876  running->latestCompletedXid))
878 
880 
881  LWLockRelease(ProcArrayLock);
882 
883  /* ShmemVariableCache->nextFullXid must be beyond any observed xid. */
885 
887 
890  elog(trace_recovery(DEBUG1), "recovery snapshots are now enabled");
891  else
893  "recovery snapshot waiting for non-overflowed snapshot or "
894  "until oldest active xid on standby is at least %u (now %u)",
896  running->oldestRunningXid);
897 }
#define TransactionIdAdvance(dest)
Definition: transam.h:75
static TransactionId latestObservedXid
Definition: procarray.c:109
TransactionId oldestRunningXid
Definition: standby.h:76
#define DEBUG1
Definition: elog.h:25
static void KnownAssignedXidsDisplay(int trace_level)
Definition: procarray.c:3928
#define TransactionIdEquals(id1, id2)
Definition: transam.h:43
uint32 TransactionId
Definition: c.h:507
void AdvanceNextFullTransactionIdPastXid(TransactionId xid)
Definition: varsup.c:262
#define DEBUG3
Definition: elog.h:23
#define FullTransactionIdIsValid(x)
Definition: transam.h:51
TransactionId * xids
Definition: standby.h:79
FullTransactionId nextFullXid
Definition: transam.h:164
bool TransactionIdDidCommit(TransactionId transactionId)
Definition: transam.c:125
#define TransactionIdRetreat(dest)
Definition: transam.h:92
int trace_recovery(int trace_level)
Definition: elog.c:3474
TransactionId latestCompletedXid
Definition: standby.h:77
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726
void pfree(void *pointer)
Definition: mcxt.c:1031
#define ERROR
Definition: elog.h:43
void ExtendSUBTRANS(TransactionId newestXact)
Definition: subtrans.c:326
VariableCache ShmemVariableCache
Definition: varsup.c:34
#define InvalidTransactionId
Definition: transam.h:31
static void KnownAssignedXidsReset(void)
Definition: procarray.c:3966
int numKnownAssignedXids
Definition: procarray.c:76
TransactionId lastOverflowedXid
Definition: procarray.c:88
bool TransactionIdDidAbort(TransactionId transactionId)
Definition: transam.c:181
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
static ProcArrayStruct * procArray
Definition: procarray.c:99
#define Assert(condition)
Definition: c.h:732
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122
static void KnownAssignedXidsAdd(TransactionId from_xid, TransactionId to_xid, bool exclusive_lock)
Definition: procarray.c:3471
TransactionId nextXid
Definition: standby.h:75
void * palloc(Size size)
Definition: mcxt.c:924
#define elog(elevel,...)
Definition: elog.h:226
int i
void ExpireOldKnownAssignedTransactionIds(TransactionId xid)
Definition: procarray.c:3306
#define qsort(a, b, c, d)
Definition: port.h:491
#define TransactionIdIsValid(xid)
Definition: transam.h:41
#define TransactionIdIsNormal(xid)
Definition: transam.h:42
static TransactionId standbySnapshotPendingXmin
Definition: procarray.c:116
HotStandbyState standbyState
Definition: xlog.c:203
void StandbyReleaseOldLocks(TransactionId oldxid)
Definition: standby.c:751
int xidComparator(const void *arg1, const void *arg2)
Definition: xid.c:138
TransactionId latestCompletedXid
Definition: transam.h:182

◆ ProcArrayApplyXidAssignment()

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

Definition at line 904 of file procarray.c.

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

Referenced by xact_redo().

906 {
907  TransactionId max_xid;
908  int i;
909 
911 
912  max_xid = TransactionIdLatest(topxid, nsubxids, subxids);
913 
914  /*
915  * Mark all the subtransactions as observed.
916  *
917  * NOTE: This will fail if the subxid contains too many previously
918  * unobserved xids to fit into known-assigned-xids. That shouldn't happen
919  * as the code stands, because xid-assignment records should never contain
920  * more than PGPROC_MAX_CACHED_SUBXIDS entries.
921  */
923 
924  /*
925  * Notice that we update pg_subtrans with the top-level xid, rather than
926  * the parent xid. This is a difference between normal processing and
927  * recovery, yet is still correct in all cases. The reason is that
928  * subtransaction commit is not marked in clog until commit processing, so
929  * all aborted subtransactions have already been clearly marked in clog.
930  * As a result we are able to refer directly to the top-level
931  * transaction's state rather than skipping through all the intermediate
932  * states in the subtransaction tree. This should be the first time we
933  * have attempted to SubTransSetParent().
934  */
935  for (i = 0; i < nsubxids; i++)
936  SubTransSetParent(subxids[i], topxid);
937 
938  /* KnownAssignedXids isn't maintained yet, so we're done for now */
940  return;
941 
942  /*
943  * Uses same locking as transaction commit
944  */
945  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
946 
947  /*
948  * Remove subxids from known-assigned-xacts.
949  */
951 
952  /*
953  * Advance lastOverflowedXid to be at least the last of these subxids.
954  */
956  procArray->lastOverflowedXid = max_xid;
957 
958  LWLockRelease(ProcArrayLock);
959 }
uint32 TransactionId
Definition: c.h:507
TransactionId TransactionIdLatest(TransactionId mainxid, int nxids, const TransactionId *xids)
Definition: transam.c:365
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726
#define InvalidTransactionId
Definition: transam.h:31
TransactionId lastOverflowedXid
Definition: procarray.c:88
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
static void KnownAssignedXidsRemoveTree(TransactionId xid, int nsubxids, TransactionId *subxids)
Definition: procarray.c:3721
static ProcArrayStruct * procArray
Definition: procarray.c:99
#define Assert(condition)
Definition: c.h:732
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122
int i
void RecordKnownAssignedTransactionIds(TransactionId xid)
Definition: procarray.c:3198
void SubTransSetParent(TransactionId xid, TransactionId parent)
Definition: subtrans.c:74
HotStandbyState standbyState
Definition: xlog.c:203

◆ ProcArrayClearTransaction()

void ProcArrayClearTransaction ( PGPROC proc)

Definition at line 600 of file procarray.c.

References PGXACT::delayChkpt, InvalidLocalTransactionId, InvalidTransactionId, PGPROC::lxid, PGXACT::nxids, PGXACT::overflowed, PGPROC::pgprocno, PROC_VACUUM_STATE_MASK, PGPROC::recoveryConflictPending, PGXACT::vacuumFlags, PGXACT::xid, and PGXACT::xmin.

Referenced by PrepareTransaction().

601 {
602  PGXACT *pgxact = &allPgXact[proc->pgprocno];
603 
604  /*
605  * We can skip locking ProcArrayLock here, because this action does not
606  * actually change anyone's view of the set of running XIDs: our entry is
607  * duplicate with the gxact that has already been inserted into the
608  * ProcArray.
609  */
610  pgxact->xid = InvalidTransactionId;
612  pgxact->xmin = InvalidTransactionId;
613  proc->recoveryConflictPending = false;
614 
615  /* redundant, but just in case */
617  pgxact->delayChkpt = false;
618 
619  /* Clear the subtransaction-XID cache too */
620  pgxact->nxids = 0;
621  pgxact->overflowed = false;
622 }
Definition: proc.h:222
TransactionId xmin
Definition: proc.h:228
TransactionId xid
Definition: proc.h:224
uint8 vacuumFlags
Definition: proc.h:233
#define PROC_VACUUM_STATE_MASK
Definition: proc.h:62
bool recoveryConflictPending
Definition: proc.h:127
uint8 nxids
Definition: proc.h:238
#define InvalidTransactionId
Definition: transam.h:31
bool delayChkpt
Definition: proc.h:235
static PGXACT * allPgXact
Definition: procarray.c:102
bool overflowed
Definition: proc.h:234
int pgprocno
Definition: proc.h:110
#define InvalidLocalTransactionId
Definition: lock.h:69
LocalTransactionId lxid
Definition: proc.h:106

◆ ProcArrayEndTransaction()

void ProcArrayEndTransaction ( PGPROC proc,
TransactionId  latestXid 
)

Definition at line 397 of file procarray.c.

References Assert, PGXACT::delayChkpt, InvalidLocalTransactionId, InvalidTransactionId, LW_EXCLUSIVE, LWLockConditionalAcquire(), LWLockRelease(), PGPROC::lxid, PGXACT::nxids, PGXACT::overflowed, PGPROC::pgprocno, PROC_VACUUM_STATE_MASK, ProcArrayEndTransactionInternal(), ProcArrayGroupClearXid(), PGPROC::recoveryConflictPending, TransactionIdIsValid, PGXACT::vacuumFlags, PGXACT::xid, and PGXACT::xmin.

Referenced by AbortTransaction(), and CommitTransaction().

398 {
399  PGXACT *pgxact = &allPgXact[proc->pgprocno];
400 
401  if (TransactionIdIsValid(latestXid))
402  {
403  /*
404  * We must lock ProcArrayLock while clearing our advertised XID, so
405  * that we do not exit the set of "running" transactions while someone
406  * else is taking a snapshot. See discussion in
407  * src/backend/access/transam/README.
408  */
410 
411  /*
412  * If we can immediately acquire ProcArrayLock, we clear our own XID
413  * and release the lock. If not, use group XID clearing to improve
414  * efficiency.
415  */
416  if (LWLockConditionalAcquire(ProcArrayLock, LW_EXCLUSIVE))
417  {
418  ProcArrayEndTransactionInternal(proc, pgxact, latestXid);
419  LWLockRelease(ProcArrayLock);
420  }
421  else
422  ProcArrayGroupClearXid(proc, latestXid);
423  }
424  else
425  {
426  /*
427  * If we have no XID, we don't need to lock, since we won't affect
428  * anyone else's calculation of a snapshot. We might change their
429  * estimate of global xmin, but that's OK.
430  */
432 
434  pgxact->xmin = InvalidTransactionId;
435  /* must be cleared with xid/xmin: */
437  pgxact->delayChkpt = false; /* be sure this is cleared in abort */
438  proc->recoveryConflictPending = false;
439 
440  Assert(pgxact->nxids == 0);
441  Assert(pgxact->overflowed == false);
442  }
443 }
Definition: proc.h:222
TransactionId xmin
Definition: proc.h:228
TransactionId xid
Definition: proc.h:224
static void ProcArrayGroupClearXid(PGPROC *proc, TransactionId latestXid)
Definition: procarray.c:485
uint8 vacuumFlags
Definition: proc.h:233
#define PROC_VACUUM_STATE_MASK
Definition: proc.h:62
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726
bool LWLockConditionalAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1294
bool recoveryConflictPending
Definition: proc.h:127
uint8 nxids
Definition: proc.h:238
#define InvalidTransactionId
Definition: transam.h:31
bool delayChkpt
Definition: proc.h:235
static PGXACT * allPgXact
Definition: procarray.c:102
bool overflowed
Definition: proc.h:234
static void ProcArrayEndTransactionInternal(PGPROC *proc, PGXACT *pgxact, TransactionId latestXid)
Definition: procarray.c:451
#define Assert(condition)
Definition: c.h:732
int pgprocno
Definition: proc.h:110
#define InvalidLocalTransactionId
Definition: lock.h:69
#define TransactionIdIsValid(xid)
Definition: transam.h:41
LocalTransactionId lxid
Definition: proc.h:106

◆ ProcArrayEndTransactionInternal()

static void ProcArrayEndTransactionInternal ( PGPROC proc,
PGXACT pgxact,
TransactionId  latestXid 
)
inlinestatic

Definition at line 451 of file procarray.c.

References PGXACT::delayChkpt, InvalidLocalTransactionId, InvalidTransactionId, VariableCacheData::latestCompletedXid, PGPROC::lxid, PGXACT::nxids, PGXACT::overflowed, PROC_VACUUM_STATE_MASK, PGPROC::recoveryConflictPending, ShmemVariableCache, TransactionIdPrecedes(), PGXACT::vacuumFlags, PGXACT::xid, and PGXACT::xmin.

Referenced by ProcArrayEndTransaction(), and ProcArrayGroupClearXid().

453 {
454  pgxact->xid = InvalidTransactionId;
456  pgxact->xmin = InvalidTransactionId;
457  /* must be cleared with xid/xmin: */
459  pgxact->delayChkpt = false; /* be sure this is cleared in abort */
460  proc->recoveryConflictPending = false;
461 
462  /* Clear the subtransaction-XID cache too while holding the lock */
463  pgxact->nxids = 0;
464  pgxact->overflowed = false;
465 
466  /* Also advance global latestCompletedXid while holding the lock */
468  latestXid))
470 }
TransactionId xmin
Definition: proc.h:228
TransactionId xid
Definition: proc.h:224
uint8 vacuumFlags
Definition: proc.h:233
#define PROC_VACUUM_STATE_MASK
Definition: proc.h:62
bool recoveryConflictPending
Definition: proc.h:127
uint8 nxids
Definition: proc.h:238
VariableCache ShmemVariableCache
Definition: varsup.c:34
#define InvalidTransactionId
Definition: transam.h:31
bool delayChkpt
Definition: proc.h:235
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
bool overflowed
Definition: proc.h:234
#define InvalidLocalTransactionId
Definition: lock.h:69
LocalTransactionId lxid
Definition: proc.h:106
TransactionId latestCompletedXid
Definition: transam.h:182

◆ ProcArrayGetReplicationSlotXmin()

void ProcArrayGetReplicationSlotXmin ( TransactionId xmin,
TransactionId catalog_xmin 
)

Definition at line 3005 of file procarray.c.

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

Referenced by logical_begin_heap_rewrite(), and XLogWalRcvSendHSFeedback().

3007 {
3008  LWLockAcquire(ProcArrayLock, LW_SHARED);
3009 
3010  if (xmin != NULL)
3012 
3013  if (catalog_xmin != NULL)
3014  *catalog_xmin = procArray->replication_slot_catalog_xmin;
3015 
3016  LWLockRelease(ProcArrayLock);
3017 }
TransactionId replication_slot_catalog_xmin
Definition: procarray.c:93
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726
static ProcArrayStruct * procArray
Definition: procarray.c:99
TransactionId replication_slot_xmin
Definition: procarray.c:91
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122

◆ ProcArrayGroupClearXid()

static void ProcArrayGroupClearXid ( PGPROC proc,
TransactionId  latestXid 
)
static

Definition at line 485 of file procarray.c.

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

Referenced by ProcArrayEndTransaction().

486 {
487  PROC_HDR *procglobal = ProcGlobal;
488  uint32 nextidx;
489  uint32 wakeidx;
490 
491  /* We should definitely have an XID to clear. */
493 
494  /* Add ourselves to the list of processes needing a group XID clear. */
495  proc->procArrayGroupMember = true;
496  proc->procArrayGroupMemberXid = latestXid;
497  while (true)
498  {
499  nextidx = pg_atomic_read_u32(&procglobal->procArrayGroupFirst);
500  pg_atomic_write_u32(&proc->procArrayGroupNext, nextidx);
501 
503  &nextidx,
504  (uint32) proc->pgprocno))
505  break;
506  }
507 
508  /*
509  * If the list was not empty, the leader will clear our XID. It is
510  * impossible to have followers without a leader because the first process
511  * that has added itself to the list will always have nextidx as
512  * INVALID_PGPROCNO.
513  */
514  if (nextidx != INVALID_PGPROCNO)
515  {
516  int extraWaits = 0;
517 
518  /* Sleep until the leader clears our XID. */
520  for (;;)
521  {
522  /* acts as a read barrier */
523  PGSemaphoreLock(proc->sem);
524  if (!proc->procArrayGroupMember)
525  break;
526  extraWaits++;
527  }
529 
531 
532  /* Fix semaphore count for any absorbed wakeups */
533  while (extraWaits-- > 0)
534  PGSemaphoreUnlock(proc->sem);
535  return;
536  }
537 
538  /* We are the leader. Acquire the lock on behalf of everyone. */
539  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
540 
541  /*
542  * Now that we've got the lock, clear the list of processes waiting for
543  * group XID clearing, saving a pointer to the head of the list. Trying
544  * to pop elements one at a time could lead to an ABA problem.
545  */
546  nextidx = pg_atomic_exchange_u32(&procglobal->procArrayGroupFirst,
548 
549  /* Remember head of list so we can perform wakeups after dropping lock. */
550  wakeidx = nextidx;
551 
552  /* Walk the list and clear all XIDs. */
553  while (nextidx != INVALID_PGPROCNO)
554  {
555  PGPROC *proc = &allProcs[nextidx];
556  PGXACT *pgxact = &allPgXact[nextidx];
557 
559 
560  /* Move to next proc in list. */
561  nextidx = pg_atomic_read_u32(&proc->procArrayGroupNext);
562  }
563 
564  /* We're done with the lock now. */
565  LWLockRelease(ProcArrayLock);
566 
567  /*
568  * Now that we've released the lock, go back and wake everybody up. We
569  * don't do this under the lock so as to keep lock hold times to a
570  * minimum. The system calls we need to perform to wake other processes
571  * up are probably much slower than the simple memory writes we did while
572  * holding the lock.
573  */
574  while (wakeidx != INVALID_PGPROCNO)
575  {
576  PGPROC *proc = &allProcs[wakeidx];
577 
578  wakeidx = pg_atomic_read_u32(&proc->procArrayGroupNext);
580 
581  /* ensure all previous writes are visible before follower continues. */
583 
584  proc->procArrayGroupMember = false;
585 
586  if (proc != MyProc)
587  PGSemaphoreUnlock(proc->sem);
588  }
589 }
bool procArrayGroupMember
Definition: proc.h:166
void PGSemaphoreUnlock(PGSemaphore sema)
Definition: posix_sema.c:329
Definition: proc.h:222
static bool pg_atomic_compare_exchange_u32(volatile pg_atomic_uint32 *ptr, uint32 *expected, uint32 newval)
Definition: atomics.h:314
PGPROC * MyProc
Definition: proc.c:68
TransactionId xid
Definition: proc.h:224
PROC_HDR * ProcGlobal
Definition: proc.c:81
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726
static uint32 pg_atomic_exchange_u32(volatile pg_atomic_uint32 *ptr, uint32 newval)
Definition: atomics.h:295
static PGPROC * allProcs
Definition: procarray.c:101
unsigned int uint32
Definition: c.h:358
static void pgstat_report_wait_end(void)
Definition: pgstat.h:1343
#define INVALID_PGPROCNO
Definition: proc.h:77
pg_atomic_uint32 procArrayGroupNext
Definition: proc.h:168
Definition: proc.h:244
static PGXACT * allPgXact
Definition: procarray.c:102
static void ProcArrayEndTransactionInternal(PGPROC *proc, PGXACT *pgxact, TransactionId latestXid)
Definition: procarray.c:451
#define Assert(condition)
Definition: c.h:732
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition: pgstat.h:1319
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122
void PGSemaphoreLock(PGSemaphore sema)
Definition: posix_sema.c:309
int pgprocno
Definition: proc.h:110
pg_atomic_uint32 procArrayGroupFirst
Definition: proc.h:261
#define pg_write_barrier()
Definition: atomics.h:162
#define TransactionIdIsValid(xid)
Definition: transam.h:41
static void pg_atomic_write_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
Definition: atomics.h:261
PGSemaphore sem
Definition: proc.h:101
Definition: proc.h:95
TransactionId procArrayGroupMemberXid
Definition: proc.h:174
static uint32 pg_atomic_read_u32(volatile pg_atomic_uint32 *ptr)
Definition: atomics.h:244

◆ ProcArrayInitRecovery()

void ProcArrayInitRecovery ( TransactionId  initializedUptoXID)

Definition at line 632 of file procarray.c.

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

Referenced by StartupXLOG().

633 {
635  Assert(TransactionIdIsNormal(initializedUptoXID));
636 
637  /*
638  * we set latestObservedXid to the xid SUBTRANS has been initialized up
639  * to, so we can extend it from that point onwards in
640  * RecordKnownAssignedTransactionIds, and when we get consistent in
641  * ProcArrayApplyRecoveryInfo().
642  */
643  latestObservedXid = initializedUptoXID;
645 }
static TransactionId latestObservedXid
Definition: procarray.c:109
#define TransactionIdRetreat(dest)
Definition: transam.h:92
#define Assert(condition)
Definition: c.h:732
#define TransactionIdIsNormal(xid)
Definition: transam.h:42
HotStandbyState standbyState
Definition: xlog.c:203

◆ ProcArrayInstallImportedXmin()

bool ProcArrayInstallImportedXmin ( TransactionId  xmin,
VirtualTransactionId sourcevxid 
)

Definition at line 1796 of file procarray.c.

References Assert, VirtualTransactionId::backendId, PGPROC::backendId, PGPROC::databaseId, VirtualTransactionId::localTransactionId, LW_SHARED, LWLockAcquire(), LWLockRelease(), PGPROC::lxid, MyDatabaseId, MyPgXact, ProcArrayStruct::numProcs, ProcArrayStruct::pgprocnos, PROC_IN_VACUUM, procArray, TransactionIdIsNormal, TransactionIdPrecedesOrEquals(), TransactionXmin, UINT32_ACCESS_ONCE, PGXACT::vacuumFlags, and PGXACT::xmin.

Referenced by GetSerializableTransactionSnapshotInt(), and SetTransactionSnapshot().

1798 {
1799  bool result = false;
1800  ProcArrayStruct *arrayP = procArray;
1801  int index;
1802 
1804  if (!sourcevxid)
1805  return false;
1806 
1807  /* Get lock so source xact can't end while we're doing this */
1808  LWLockAcquire(ProcArrayLock, LW_SHARED);
1809 
1810  for (index = 0; index < arrayP->numProcs; index++)
1811  {
1812  int pgprocno = arrayP->pgprocnos[index];
1813  PGPROC *proc = &allProcs[pgprocno];
1814  PGXACT *pgxact = &allPgXact[pgprocno];
1815  TransactionId xid;
1816 
1817  /* Ignore procs running LAZY VACUUM */
1818  if (pgxact->vacuumFlags & PROC_IN_VACUUM)
1819  continue;
1820 
1821  /* We are only interested in the specific virtual transaction. */
1822  if (proc->backendId != sourcevxid->backendId)
1823  continue;
1824  if (proc->lxid != sourcevxid->localTransactionId)
1825  continue;
1826 
1827  /*
1828  * We check the transaction's database ID for paranoia's sake: if it's
1829  * in another DB then its xmin does not cover us. Caller should have
1830  * detected this already, so we just treat any funny cases as
1831  * "transaction not found".
1832  */
1833  if (proc->databaseId != MyDatabaseId)
1834  continue;
1835 
1836  /*
1837  * Likewise, let's just make real sure its xmin does cover us.
1838  */
1839  xid = UINT32_ACCESS_ONCE(pgxact->xmin);
1840  if (!TransactionIdIsNormal(xid) ||
1841  !TransactionIdPrecedesOrEquals(xid, xmin))
1842  continue;
1843 
1844  /*
1845  * We're good. Install the new xmin. As in GetSnapshotData, set
1846  * TransactionXmin too. (Note that because snapmgr.c called
1847  * GetSnapshotData first, we'll be overwriting a valid xmin here, so
1848  * we don't check that.)
1849  */
1850  MyPgXact->xmin = TransactionXmin = xmin;
1851 
1852  result = true;
1853  break;
1854  }
1855 
1856  LWLockRelease(ProcArrayLock);
1857 
1858  return result;
1859 }
BackendId backendId
Definition: proc.h:113
uint32 TransactionId
Definition: c.h:507
Definition: proc.h:222
TransactionId xmin
Definition: proc.h:228
#define UINT32_ACCESS_ONCE(var)
Definition: procarray.c:64
LocalTransactionId localTransactionId
Definition: lock.h:66
PGXACT * MyPgXact
Definition: proc.c:69
uint8 vacuumFlags
Definition: proc.h:233
TransactionId TransactionXmin
Definition: snapmgr.c:166
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726
#define PROC_IN_VACUUM
Definition: proc.h:54
bool TransactionIdPrecedesOrEquals(TransactionId id1, TransactionId id2)
Definition: transam.c:319
static PGPROC * allProcs
Definition: procarray.c:101
Oid databaseId
Definition: proc.h:114
static ProcArrayStruct * procArray
Definition: procarray.c:99
static PGXACT * allPgXact
Definition: procarray.c:102
Oid MyDatabaseId
Definition: globals.c:85
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:96
#define Assert(condition)
Definition: c.h:732
BackendId backendId
Definition: lock.h:65
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122
#define TransactionIdIsNormal(xid)
Definition: transam.h:42
Definition: proc.h:95
LocalTransactionId lxid
Definition: proc.h:106

◆ ProcArrayInstallRestoredXmin()

bool ProcArrayInstallRestoredXmin ( TransactionId  xmin,
PGPROC proc 
)

Definition at line 1871 of file procarray.c.

References Assert, PGPROC::databaseId, LW_SHARED, LWLockAcquire(), LWLockRelease(), MyDatabaseId, MyPgXact, PGPROC::pgprocno, TransactionIdIsNormal, TransactionIdPrecedesOrEquals(), TransactionXmin, UINT32_ACCESS_ONCE, and PGXACT::xmin.

Referenced by SetTransactionSnapshot().

1872 {
1873  bool result = false;
1874  TransactionId xid;
1875  PGXACT *pgxact;
1876 
1878  Assert(proc != NULL);
1879 
1880  /* Get lock so source xact can't end while we're doing this */
1881  LWLockAcquire(ProcArrayLock, LW_SHARED);
1882 
1883  pgxact = &allPgXact[proc->pgprocno];
1884 
1885  /*
1886  * Be certain that the referenced PGPROC has an advertised xmin which is
1887  * no later than the one we're installing, so that the system-wide xmin
1888  * can't go backwards. Also, make sure it's running in the same database,
1889  * so that the per-database xmin cannot go backwards.
1890  */
1891  xid = UINT32_ACCESS_ONCE(pgxact->xmin);
1892  if (proc->databaseId == MyDatabaseId &&
1893  TransactionIdIsNormal(xid) &&
1894  TransactionIdPrecedesOrEquals(xid, xmin))
1895  {
1896  MyPgXact->xmin = TransactionXmin = xmin;
1897  result = true;
1898  }
1899 
1900  LWLockRelease(ProcArrayLock);
1901 
1902  return result;
1903 }
uint32 TransactionId
Definition: c.h:507
Definition: proc.h:222
TransactionId xmin
Definition: proc.h:228
#define UINT32_ACCESS_ONCE(var)
Definition: procarray.c:64
PGXACT * MyPgXact
Definition: proc.c:69
TransactionId TransactionXmin
Definition: snapmgr.c:166
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726
bool TransactionIdPrecedesOrEquals(TransactionId id1, TransactionId id2)
Definition: transam.c:319
Oid databaseId
Definition: proc.h:114
static PGXACT * allPgXact
Definition: procarray.c:102
Oid MyDatabaseId
Definition: globals.c:85
#define Assert(condition)
Definition: c.h:732
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122
int pgprocno
Definition: proc.h:110
#define TransactionIdIsNormal(xid)
Definition: transam.h:42

◆ ProcArrayRemove()

void ProcArrayRemove ( PGPROC proc,
TransactionId  latestXid 
)

Definition at line 334 of file procarray.c.

References Assert, elog, VariableCacheData::latestCompletedXid, LOG, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), memmove, ProcArrayStruct::numProcs, PGPROC::pgprocno, ProcArrayStruct::pgprocnos, PGPROC::pid, procArray, ShmemVariableCache, TransactionIdIsValid, TransactionIdPrecedes(), and PGXACT::xid.

Referenced by FinishPreparedTransaction(), and RemoveProcFromArray().

335 {
336  ProcArrayStruct *arrayP = procArray;
337  int index;
338 
339 #ifdef XIDCACHE_DEBUG
340  /* dump stats at backend shutdown, but not prepared-xact end */
341  if (proc->pid != 0)
342  DisplayXidCache();
343 #endif
344 
345  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
346 
347  if (TransactionIdIsValid(latestXid))
348  {
350 
351  /* Advance global latestCompletedXid while holding the lock */
353  latestXid))
355  }
356  else
357  {
358  /* Shouldn't be trying to remove a live transaction here */
360  }
361 
362  for (index = 0; index < arrayP->numProcs; index++)
363  {
364  if (arrayP->pgprocnos[index] == proc->pgprocno)
365  {
366  /* Keep the PGPROC array sorted. See notes above */
367  memmove(&arrayP->pgprocnos[index], &arrayP->pgprocnos[index + 1],
368  (arrayP->numProcs - index - 1) * sizeof(int));
369  arrayP->pgprocnos[arrayP->numProcs - 1] = -1; /* for debugging */
370  arrayP->numProcs--;
371  LWLockRelease(ProcArrayLock);
372  return;
373  }
374  }
375 
376  /* Oops */
377  LWLockRelease(ProcArrayLock);
378 
379  elog(LOG, "failed to find proc %p in ProcArray", proc);
380 }
TransactionId xid
Definition: proc.h:224
#define LOG
Definition: elog.h:26
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726
#define memmove(d, s, c)
Definition: c.h:1224
VariableCache ShmemVariableCache
Definition: varsup.c:34
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
static ProcArrayStruct * procArray
Definition: procarray.c:99
static PGXACT * allPgXact
Definition: procarray.c:102
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:96
#define Assert(condition)
Definition: c.h:732
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122
int pgprocno
Definition: proc.h:110
#define elog(elevel,...)
Definition: elog.h:226
#define TransactionIdIsValid(xid)
Definition: transam.h:41
int pid
Definition: proc.h:109
TransactionId latestCompletedXid
Definition: transam.h:182

◆ ProcArraySetReplicationSlotXmin()

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

Definition at line 2983 of file procarray.c.

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

Referenced by ReplicationSlotsComputeRequiredXmin().

2985 {
2986  Assert(!already_locked || LWLockHeldByMe(ProcArrayLock));
2987 
2988  if (!already_locked)
2989  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
2990 
2992  procArray->replication_slot_catalog_xmin = catalog_xmin;
2993 
2994  if (!already_locked)
2995  LWLockRelease(ProcArrayLock);
2996 }
bool LWLockHeldByMe(LWLock *l)
Definition: lwlock.c:1842
TransactionId replication_slot_catalog_xmin
Definition: procarray.c:93
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726
static ProcArrayStruct * procArray
Definition: procarray.c:99
TransactionId replication_slot_xmin
Definition: procarray.c:91
#define Assert(condition)
Definition: c.h:732
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122

◆ ProcArrayShmemSize()

Size ProcArrayShmemSize ( void  )

Definition at line 180 of file procarray.c.

References add_size(), EnableHotStandby, mul_size(), offsetof, ProcArrayStruct::pgprocnos, PROCARRAY_MAXPROCS, and TOTAL_MAX_CACHED_SUBXIDS.

Referenced by CreateSharedMemoryAndSemaphores().

181 {
182  Size size;
183 
184  /* Size of the ProcArray structure itself */
185 #define PROCARRAY_MAXPROCS (MaxBackends + max_prepared_xacts)
186 
187  size = offsetof(ProcArrayStruct, pgprocnos);
188  size = add_size(size, mul_size(sizeof(int), PROCARRAY_MAXPROCS));
189 
190  /*
191  * During Hot Standby processing we have a data structure called
192  * KnownAssignedXids, created in shared memory. Local data structures are
193  * also created in various backends during GetSnapshotData(),
194  * TransactionIdIsInProgress() and GetRunningTransactionData(). All of the
195  * main structures created in those functions must be identically sized,
196  * since we may at times copy the whole of the data structures around. We
197  * refer to this size as TOTAL_MAX_CACHED_SUBXIDS.
198  *
199  * Ideally we'd only create this structure if we were actually doing hot
200  * standby in the current run, but we don't know that yet at the time
201  * shared memory is being set up.
202  */
203 #define TOTAL_MAX_CACHED_SUBXIDS \
204  ((PGPROC_MAX_CACHED_SUBXIDS + 1) * PROCARRAY_MAXPROCS)
205 
206  if (EnableHotStandby)
207  {
208  size = add_size(size,
209  mul_size(sizeof(TransactionId),
211  size = add_size(size,
212  mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS));
213  }
214 
215  return size;
216 }
#define PROCARRAY_MAXPROCS
uint32 TransactionId
Definition: c.h:507
Size mul_size(Size s1, Size s2)
Definition: shmem.c:492
Size add_size(Size s1, Size s2)
Definition: shmem.c:475
#define TOTAL_MAX_CACHED_SUBXIDS
size_t Size
Definition: c.h:466
bool EnableHotStandby
Definition: xlog.c:93
#define offsetof(type, field)
Definition: c.h:655

◆ RecordKnownAssignedTransactionIds()

void RecordKnownAssignedTransactionIds ( TransactionId  xid)

Definition at line 3198 of file procarray.c.

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

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

3199 {
3203 
3204  elog(trace_recovery(DEBUG4), "record known xact %u latestObservedXid %u",
3205  xid, latestObservedXid);
3206 
3207  /*
3208  * When a newly observed xid arrives, it is frequently the case that it is
3209  * *not* the next xid in sequence. When this occurs, we must treat the
3210  * intervening xids as running also.
3211  */
3213  {
3214  TransactionId next_expected_xid;
3215 
3216  /*
3217  * Extend subtrans like we do in GetNewTransactionId() during normal
3218  * operation using individual extend steps. Note that we do not need
3219  * to extend clog since its extensions are WAL logged.
3220  *
3221  * This part has to be done regardless of standbyState since we
3222  * immediately start assigning subtransactions to their toplevel
3223  * transactions.
3224  */
3225  next_expected_xid = latestObservedXid;
3226  while (TransactionIdPrecedes(next_expected_xid, xid))
3227  {
3228  TransactionIdAdvance(next_expected_xid);
3229  ExtendSUBTRANS(next_expected_xid);
3230  }
3231  Assert(next_expected_xid == xid);
3232 
3233  /*
3234  * If the KnownAssignedXids machinery isn't up yet, there's nothing
3235  * more to do since we don't track assigned xids yet.
3236  */
3238  {
3239  latestObservedXid = xid;
3240  return;
3241  }
3242 
3243  /*
3244  * Add (latestObservedXid, xid] onto the KnownAssignedXids array.
3245  */
3246  next_expected_xid = latestObservedXid;
3247  TransactionIdAdvance(next_expected_xid);
3248  KnownAssignedXidsAdd(next_expected_xid, xid, false);
3249 
3250  /*
3251  * Now we can advance latestObservedXid
3252  */
3253  latestObservedXid = xid;
3254 
3255  /* ShmemVariableCache->nextFullXid must be beyond any observed xid */
3257  next_expected_xid = latestObservedXid;
3258  TransactionIdAdvance(next_expected_xid);
3259  }
3260 }
#define TransactionIdAdvance(dest)
Definition: transam.h:75
static TransactionId latestObservedXid
Definition: procarray.c:109
bool TransactionIdFollows(TransactionId id1, TransactionId id2)
Definition: transam.c:334
uint32 TransactionId
Definition: c.h:507
void AdvanceNextFullTransactionIdPastXid(TransactionId xid)
Definition: varsup.c:262
#define DEBUG4
Definition: elog.h:22
int trace_recovery(int trace_level)
Definition: elog.c:3474
void ExtendSUBTRANS(TransactionId newestXact)
Definition: subtrans.c:326
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
#define Assert(condition)
Definition: c.h:732
static void KnownAssignedXidsAdd(TransactionId from_xid, TransactionId to_xid, bool exclusive_lock)
Definition: procarray.c:3471
#define elog(elevel,...)
Definition: elog.h:226
#define TransactionIdIsValid(xid)
Definition: transam.h:41
HotStandbyState standbyState
Definition: xlog.c:203

◆ TransactionIdIsActive()

bool TransactionIdIsActive ( TransactionId  xid)

Definition at line 1208 of file procarray.c.

References i, LW_SHARED, LWLockAcquire(), LWLockRelease(), ProcArrayStruct::numProcs, ProcArrayStruct::pgprocnos, PGPROC::pid, procArray, RecentXmin, TransactionIdEquals, TransactionIdIsValid, TransactionIdPrecedes(), UINT32_ACCESS_ONCE, and PGXACT::xid.

1209 {
1210  bool result = false;
1211  ProcArrayStruct *arrayP = procArray;
1212  int i;
1213 
1214  /*
1215  * Don't bother checking a transaction older than RecentXmin; it could not
1216  * possibly still be running.
1217  */
1219  return false;
1220 
1221  LWLockAcquire(ProcArrayLock, LW_SHARED);
1222 
1223  for (i = 0; i < arrayP->numProcs; i++)
1224  {
1225  int pgprocno = arrayP->pgprocnos[i];
1226  PGPROC *proc = &allProcs[pgprocno];
1227  PGXACT *pgxact = &allPgXact[pgprocno];
1228  TransactionId pxid;
1229 
1230  /* Fetch xid just once - see GetNewTransactionId */
1231  pxid = UINT32_ACCESS_ONCE(pgxact->xid);
1232 
1233  if (!TransactionIdIsValid(pxid))
1234  continue;
1235 
1236  if (proc->pid == 0)
1237  continue; /* ignore prepared transactions */
1238 
1239  if (TransactionIdEquals(pxid, xid))
1240  {
1241  result = true;
1242  break;
1243  }
1244  }
1245 
1246  LWLockRelease(ProcArrayLock);
1247 
1248  return result;
1249 }
#define TransactionIdEquals(id1, id2)
Definition: transam.h:43
uint32 TransactionId
Definition: c.h:507
Definition: proc.h:222
TransactionId xid
Definition: proc.h:224
#define UINT32_ACCESS_ONCE(var)
Definition: procarray.c:64
TransactionId RecentXmin
Definition: snapmgr.c:167
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726
static PGPROC * allProcs
Definition: procarray.c:101
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
static ProcArrayStruct * procArray
Definition: procarray.c:99
static PGXACT * allPgXact
Definition: procarray.c:102
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:96
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122
int i
#define TransactionIdIsValid(xid)
Definition: transam.h:41
Definition: proc.h:95
int pid
Definition: proc.h:109

◆ TransactionIdIsInProgress()

bool TransactionIdIsInProgress ( TransactionId  xid)

Definition at line 988 of file procarray.c.

References Assert, ereport, errcode(), errmsg(), ERROR, i, KnownAssignedXidExists(), KnownAssignedXidsGet(), ProcArrayStruct::lastOverflowedXid, VariableCacheData::latestCompletedXid, LW_SHARED, LWLockAcquire(), LWLockRelease(), malloc, ProcArrayStruct::maxProcs, MyProc, ProcArrayStruct::numProcs, PGXACT::nxids, PGXACT::overflowed, pg_read_barrier, ProcArrayStruct::pgprocnos, procArray, RecentXmin, RecoveryInProgress(), ShmemVariableCache, SubTransGetTopmostTransaction(), PGPROC::subxids, TOTAL_MAX_CACHED_SUBXIDS, TransactionIdDidAbort(), TransactionIdEquals, TransactionIdIsCurrentTransactionId(), TransactionIdIsKnownCompleted(), TransactionIdIsValid, TransactionIdPrecedes(), TransactionIdPrecedesOrEquals(), 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, PGXACT::xid, and XidCache::xids.

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

989 {
990  static TransactionId *xids = NULL;
991  int nxids = 0;
992  ProcArrayStruct *arrayP = procArray;
993  TransactionId topxid;
994  int i,
995  j;
996 
997  /*
998  * Don't bother checking a transaction older than RecentXmin; it could not
999  * possibly still be running. (Note: in particular, this guarantees that
1000  * we reject InvalidTransactionId, FrozenTransactionId, etc as not
1001  * running.)
1002  */
1004  {
1006  return false;
1007  }
1008 
1009  /*
1010  * We may have just checked the status of this transaction, so if it is
1011  * already known to be completed, we can fall out without any access to
1012  * shared memory.
1013  */
1015  {
1017  return false;
1018  }
1019 
1020  /*
1021  * Also, we can handle our own transaction (and subtransactions) without
1022  * any access to shared memory.
1023  */
1025  {
1027  return true;
1028  }
1029 
1030  /*
1031  * If first time through, get workspace to remember main XIDs in. We
1032  * malloc it permanently to avoid repeated palloc/pfree overhead.
1033  */
1034  if (xids == NULL)
1035  {
1036  /*
1037  * In hot standby mode, reserve enough space to hold all xids in the
1038  * known-assigned list. If we later finish recovery, we no longer need
1039  * the bigger array, but we don't bother to shrink it.
1040  */
1041  int maxxids = RecoveryInProgress() ? TOTAL_MAX_CACHED_SUBXIDS : arrayP->maxProcs;
1042 
1043  xids = (TransactionId *) malloc(maxxids * sizeof(TransactionId));
1044  if (xids == NULL)
1045  ereport(ERROR,
1046  (errcode(ERRCODE_OUT_OF_MEMORY),
1047  errmsg("out of memory")));
1048  }
1049 
1050  LWLockAcquire(ProcArrayLock, LW_SHARED);
1051 
1052  /*
1053  * Now that we have the lock, we can check latestCompletedXid; if the
1054  * target Xid is after that, it's surely still running.
1055  */
1057  {
1058  LWLockRelease(ProcArrayLock);
1060  return true;
1061  }
1062 
1063  /* No shortcuts, gotta grovel through the array */
1064  for (i = 0; i < arrayP->numProcs; i++)
1065  {
1066  int pgprocno = arrayP->pgprocnos[i];
1067  PGPROC *proc = &allProcs[pgprocno];
1068  PGXACT *pgxact = &allPgXact[pgprocno];
1069  TransactionId pxid;
1070  int pxids;
1071 
1072  /* Ignore my own proc --- dealt with it above */
1073  if (proc == MyProc)
1074  continue;
1075 
1076  /* Fetch xid just once - see GetNewTransactionId */
1077  pxid = UINT32_ACCESS_ONCE(pgxact->xid);
1078 
1079  if (!TransactionIdIsValid(pxid))
1080  continue;
1081 
1082  /*
1083  * Step 1: check the main Xid
1084  */
1085  if (TransactionIdEquals(pxid, xid))
1086  {
1087  LWLockRelease(ProcArrayLock);
1089  return true;
1090  }
1091 
1092  /*
1093  * We can ignore main Xids that are younger than the target Xid, since
1094  * the target could not possibly be their child.
1095  */
1096  if (TransactionIdPrecedes(xid, pxid))
1097  continue;
1098 
1099  /*
1100  * Step 2: check the cached child-Xids arrays
1101  */
1102  pxids = pgxact->nxids;
1103  pg_read_barrier(); /* pairs with barrier in GetNewTransactionId() */
1104  for (j = pxids - 1; j >= 0; j--)
1105  {
1106  /* Fetch xid just once - see GetNewTransactionId */
1107  TransactionId cxid = UINT32_ACCESS_ONCE(proc->subxids.xids[j]);
1108 
1109  if (TransactionIdEquals(cxid, xid))
1110  {
1111  LWLockRelease(ProcArrayLock);
1113  return true;
1114  }
1115  }
1116 
1117  /*
1118  * Save the main Xid for step 4. We only need to remember main Xids
1119  * that have uncached children. (Note: there is no race condition
1120  * here because the overflowed flag cannot be cleared, only set, while
1121  * we hold ProcArrayLock. So we can't miss an Xid that we need to
1122  * worry about.)
1123  */
1124  if (pgxact->overflowed)
1125  xids[nxids++] = pxid;
1126  }
1127 
1128  /*
1129  * Step 3: in hot standby mode, check the known-assigned-xids list. XIDs
1130  * in the list must be treated as running.
1131  */
1132  if (RecoveryInProgress())
1133  {
1134  /* none of the PGXACT entries should have XIDs in hot standby mode */
1135  Assert(nxids == 0);
1136 
1137  if (KnownAssignedXidExists(xid))
1138  {
1139  LWLockRelease(ProcArrayLock);
1141  return true;
1142  }
1143 
1144  /*
1145  * If the KnownAssignedXids overflowed, we have to check pg_subtrans
1146  * too. Fetch all xids from KnownAssignedXids that are lower than
1147  * xid, since if xid is a subtransaction its parent will always have a
1148  * lower value. Note we will collect both main and subXIDs here, but
1149  * there's no help for it.
1150  */
1152  nxids = KnownAssignedXidsGet(xids, xid);
1153  }
1154 
1155  LWLockRelease(ProcArrayLock);
1156 
1157  /*
1158  * If none of the relevant caches overflowed, we know the Xid is not
1159  * running without even looking at pg_subtrans.
1160  */
1161  if (nxids == 0)
1162  {
1164  return false;
1165  }
1166 
1167  /*
1168  * Step 4: have to check pg_subtrans.
1169  *
1170  * At this point, we know it's either a subtransaction of one of the Xids
1171  * in xids[], or it's not running. If it's an already-failed
1172  * subtransaction, we want to say "not running" even though its parent may
1173  * still be running. So first, check pg_xact to see if it's been aborted.
1174  */
1176 
1177  if (TransactionIdDidAbort(xid))
1178  return false;
1179 
1180  /*
1181  * It isn't aborted, so check whether the transaction tree it belongs to
1182  * is still running (or, more precisely, whether it was running when we
1183  * held ProcArrayLock).
1184  */
1185  topxid = SubTransGetTopmostTransaction(xid);
1186  Assert(TransactionIdIsValid(topxid));
1187  if (!TransactionIdEquals(topxid, xid))
1188  {
1189  for (i = 0; i < nxids; i++)
1190  {
1191  if (TransactionIdEquals(xids[i], topxid))
1192  return true;
1193  }
1194  }
1195 
1196  return false;
1197 }
#define TransactionIdEquals(id1, id2)
Definition: transam.h:43
uint32 TransactionId
Definition: c.h:507
Definition: proc.h:222
bool TransactionIdIsCurrentTransactionId(TransactionId xid)
Definition: xact.c:854
TransactionId SubTransGetTopmostTransaction(TransactionId xid)
Definition: subtrans.c:150
PGPROC * MyProc
Definition: proc.c:68
TransactionId xid
Definition: proc.h:224
#define UINT32_ACCESS_ONCE(var)
Definition: procarray.c:64
#define xc_by_my_xact_inc()
Definition: procarray.c:146
int errcode(int sqlerrcode)
Definition: elog.c:570
TransactionId RecentXmin
Definition: snapmgr.c:167
bool RecoveryInProgress(void)
Definition: xlog.c:7882
#define xc_by_child_xid_inc()
Definition: procarray.c:149
bool TransactionIdIsKnownCompleted(TransactionId transactionId)
Definition: transam.c:238
#define malloc(a)
Definition: header.h:50
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726
#define xc_by_recent_xmin_inc()
Definition: procarray.c:144
#define xc_by_known_xact_inc()
Definition: procarray.c:145
bool TransactionIdPrecedesOrEquals(TransactionId id1, TransactionId id2)
Definition: transam.c:319
#define ERROR
Definition: elog.h:43
#define xc_by_main_xid_inc()
Definition: procarray.c:148
#define xc_by_known_assigned_inc()
Definition: procarray.c:150
uint8 nxids
Definition: proc.h:238
VariableCache ShmemVariableCache
Definition: varsup.c:34
static PGPROC * allProcs
Definition: procarray.c:101
struct XidCache subxids
Definition: proc.h:162
TransactionId lastOverflowedXid
Definition: procarray.c:88
#define ereport(elevel, rest)
Definition: elog.h:141
bool TransactionIdDidAbort(TransactionId transactionId)
Definition: transam.c:181
#define xc_by_latest_xid_inc()
Definition: procarray.c:147
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
static ProcArrayStruct * procArray
Definition: procarray.c:99
static PGXACT * allPgXact
Definition: procarray.c:102
static int KnownAssignedXidsGet(TransactionId *xarray, TransactionId xmax)
Definition: procarray.c:3821
bool overflowed
Definition: proc.h:234
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:96
TransactionId xids[PGPROC_MAX_CACHED_SUBXIDS]
Definition: proc.h:40
#define TOTAL_MAX_CACHED_SUBXIDS
#define Assert(condition)
Definition: c.h:732
#define pg_read_barrier()
Definition: atomics.h:161
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122
#define xc_no_overflow_inc()
Definition: procarray.c:151
static bool KnownAssignedXidExists(TransactionId xid)
Definition: procarray.c:3682
#define xc_slow_answer_inc()
Definition: procarray.c:152
int errmsg(const char *fmt,...)
Definition: elog.c:784
int i
#define TransactionIdIsValid(xid)
Definition: transam.h:41
Definition: proc.h:95
TransactionId latestCompletedXid
Definition: transam.h:182

◆ XidCacheRemoveRunningXids()

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

Definition at line 3036 of file procarray.c.

References Assert, elog, fprintf, i, VariableCacheData::latestCompletedXid, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MyPgXact, MyProc, PGXACT::nxids, ShmemVariableCache, PGPROC::subxids, TransactionIdEquals, TransactionIdIsValid, TransactionIdPrecedes(), WARNING, XidCacheRemove, and XidCache::xids.

Referenced by RecordTransactionAbort().

3039 {
3040  int i,
3041  j;
3042 
3044 
3045  /*
3046  * We must hold ProcArrayLock exclusively in order to remove transactions
3047  * from the PGPROC array. (See src/backend/access/transam/README.) It's
3048  * possible this could be relaxed since we know this routine is only used
3049  * to abort subtransactions, but pending closer analysis we'd best be
3050  * conservative.
3051  *
3052  * Note that we do not have to be careful about memory ordering of our own
3053  * reads wrt. GetNewTransactionId() here - only this process can modify
3054  * relevant fields of MyProc/MyPgXact. But we do have to be careful about
3055  * our own writes being well ordered.
3056  */
3057  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3058 
3059  /*
3060  * Under normal circumstances xid and xids[] will be in increasing order,
3061  * as will be the entries in subxids. Scan backwards to avoid O(N^2)
3062  * behavior when removing a lot of xids.
3063  */
3064  for (i = nxids - 1; i >= 0; i--)
3065  {
3066  TransactionId anxid = xids[i];
3067 
3068  for (j = MyPgXact->nxids - 1; j >= 0; j--)
3069  {
3070  if (TransactionIdEquals(MyProc->subxids.xids[j], anxid))
3071  {
3072  XidCacheRemove(j);
3073  break;
3074  }
3075  }
3076 
3077  /*
3078  * Ordinarily we should have found it, unless the cache has
3079  * overflowed. However it's also possible for this routine to be
3080  * invoked multiple times for the same subtransaction, in case of an
3081  * error during AbortSubTransaction. So instead of Assert, emit a
3082  * debug warning.
3083  */
3084  if (j < 0 && !MyPgXact->overflowed)
3085  elog(WARNING, "did not find subXID %u in MyProc", anxid);
3086  }
3087 
3088  for (j = MyPgXact->nxids - 1; j >= 0; j--)
3089  {
3090  if (TransactionIdEquals(MyProc->subxids.xids[j], xid))
3091  {
3092  XidCacheRemove(j);
3093  break;
3094  }
3095  }
3096  /* Ordinarily we should have found it, unless the cache has overflowed */
3097  if (j < 0 && !MyPgXact->overflowed)
3098  elog(WARNING, "did not find subXID %u in MyProc", xid);
3099 
3100  /* Also advance global latestCompletedXid while holding the lock */
3102  latestXid))
3104 
3105  LWLockRelease(ProcArrayLock);
3106 }
#define XidCacheRemove(i)
Definition: procarray.c:3020
#define TransactionIdEquals(id1, id2)
Definition: transam.h:43
uint32 TransactionId
Definition: c.h:507
PGPROC * MyProc
Definition: proc.c:68
PGXACT * MyPgXact
Definition: proc.c:69
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726
uint8 nxids
Definition: proc.h:238
VariableCache ShmemVariableCache
Definition: varsup.c:34
struct XidCache subxids
Definition: proc.h:162
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
#define WARNING
Definition: elog.h:40
TransactionId xids[PGPROC_MAX_CACHED_SUBXIDS]
Definition: proc.h:40
#define Assert(condition)
Definition: c.h:732
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122
#define elog(elevel,...)
Definition: elog.h:226
int i
#define TransactionIdIsValid(xid)
Definition: transam.h:41
TransactionId latestCompletedXid
Definition: transam.h:182

Variable Documentation

◆ allPgXact

PGXACT* allPgXact
static

Definition at line 102 of file procarray.c.

◆ allProcs

PGPROC* allProcs
static

Definition at line 101 of file procarray.c.

◆ KnownAssignedXids

◆ KnownAssignedXidsValid

◆ latestObservedXid

◆ procArray

◆ standbySnapshotPendingXmin

TransactionId standbySnapshotPendingXmin
static

Definition at line 116 of file procarray.c.

Referenced by ProcArrayApplyRecoveryInfo().