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:67
PGXACT * MyPgXact
Definition: proc.c:68
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 3034 of file procarray.c.

Referenced by XidCacheRemoveRunningXids().

Typedef Documentation

◆ ProcArrayStruct

Function Documentation

◆ BackendPidGetProc()

PGPROC* BackendPidGetProc ( int  pid)

Definition at line 2379 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().

2380 {
2381  PGPROC *result;
2382 
2383  if (pid == 0) /* never match dummy PGPROCs */
2384  return NULL;
2385 
2386  LWLockAcquire(ProcArrayLock, LW_SHARED);
2387 
2388  result = BackendPidGetProcWithLock(pid);
2389 
2390  LWLockRelease(ProcArrayLock);
2391 
2392  return result;
2393 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
PGPROC * BackendPidGetProcWithLock(int pid)
Definition: procarray.c:2402
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121
Definition: proc.h:95

◆ BackendPidGetProcWithLock()

PGPROC* BackendPidGetProcWithLock ( int  pid)

Definition at line 2402 of file procarray.c.

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

Referenced by BackendPidGetProc(), and GetBlockerStatusData().

2403 {
2404  PGPROC *result = NULL;
2405  ProcArrayStruct *arrayP = procArray;
2406  int index;
2407 
2408  if (pid == 0) /* never match dummy PGPROCs */
2409  return NULL;
2410 
2411  for (index = 0; index < arrayP->numProcs; index++)
2412  {
2413  PGPROC *proc = &allProcs[arrayP->pgprocnos[index]];
2414 
2415  if (proc->pid == pid)
2416  {
2417  result = proc;
2418  break;
2419  }
2420  }
2421 
2422  return result;
2423 }
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 2439 of file procarray.c.

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

Referenced by pgrowlocks().

2440 {
2441  int result = 0;
2442  ProcArrayStruct *arrayP = procArray;
2443  int index;
2444 
2445  if (xid == InvalidTransactionId) /* never match invalid xid */
2446  return 0;
2447 
2448  LWLockAcquire(ProcArrayLock, LW_SHARED);
2449 
2450  for (index = 0; index < arrayP->numProcs; index++)
2451  {
2452  int pgprocno = arrayP->pgprocnos[index];
2453  PGPROC *proc = &allProcs[pgprocno];
2454  PGXACT *pgxact = &allPgXact[pgprocno];
2455 
2456  if (pgxact->xid == xid)
2457  {
2458  result = proc->pid;
2459  break;
2460  }
2461  }
2462 
2463  LWLockRelease(ProcArrayLock);
2464 
2465  return result;
2466 }
Definition: proc.h:222
TransactionId xid
Definition: proc.h:224
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
#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:1121
Definition: proc.h:95
int pid
Definition: proc.h:109

◆ CancelDBBackends()

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

Definition at line 2833 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().

2834 {
2835  ProcArrayStruct *arrayP = procArray;
2836  int index;
2837  pid_t pid = 0;
2838 
2839  /* tell all backends to die */
2840  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
2841 
2842  for (index = 0; index < arrayP->numProcs; index++)
2843  {
2844  int pgprocno = arrayP->pgprocnos[index];
2845  PGPROC *proc = &allProcs[pgprocno];
2846 
2847  if (databaseid == InvalidOid || proc->databaseId == databaseid)
2848  {
2849  VirtualTransactionId procvxid;
2850 
2851  GET_VXID_FROM_PGPROC(procvxid, *proc);
2852 
2853  proc->recoveryConflictPending = conflictPending;
2854  pid = proc->pid;
2855  if (pid != 0)
2856  {
2857  /*
2858  * Kill the pid if it's still here. If not, that's what we
2859  * wanted so ignore any errors.
2860  */
2861  (void) SendProcSignal(pid, sigmode, procvxid.backendId);
2862  }
2863  }
2864  }
2865 
2866  LWLockRelease(ProcArrayLock);
2867 }
#define GET_VXID_FROM_PGPROC(vxid, proc)
Definition: lock.h:80
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
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:1121
Definition: proc.h:95
int pid
Definition: proc.h:109

◆ CancelVirtualTransaction()

pid_t CancelVirtualTransaction ( VirtualTransactionId  vxid,
ProcSignalReason  sigmode 
)

Definition at line 2670 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().

2671 {
2672  ProcArrayStruct *arrayP = procArray;
2673  int index;
2674  pid_t pid = 0;
2675 
2676  LWLockAcquire(ProcArrayLock, LW_SHARED);
2677 
2678  for (index = 0; index < arrayP->numProcs; index++)
2679  {
2680  int pgprocno = arrayP->pgprocnos[index];
2681  PGPROC *proc = &allProcs[pgprocno];
2682  VirtualTransactionId procvxid;
2683 
2684  GET_VXID_FROM_PGPROC(procvxid, *proc);
2685 
2686  if (procvxid.backendId == vxid.backendId &&
2687  procvxid.localTransactionId == vxid.localTransactionId)
2688  {
2689  proc->recoveryConflictPending = true;
2690  pid = proc->pid;
2691  if (pid != 0)
2692  {
2693  /*
2694  * Kill the pid if it's still here. If not, that's what we
2695  * wanted so ignore any errors.
2696  */
2697  (void) SendProcSignal(pid, sigmode, vxid.backendId);
2698  }
2699  break;
2700  }
2701  }
2702 
2703  LWLockRelease(ProcArrayLock);
2704 
2705  return pid;
2706 }
#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:1725
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:1121
Definition: proc.h:95
int pid
Definition: proc.h:109

◆ CountDBBackends()

int CountDBBackends ( Oid  databaseid)

Definition at line 2772 of file procarray.c.

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

Referenced by btree_xlog_delete_get_latestRemovedXid(), hash_xlog_vacuum_get_latestRemovedXid(), and ResolveRecoveryConflictWithDatabase().

2773 {
2774  ProcArrayStruct *arrayP = procArray;
2775  int count = 0;
2776  int index;
2777 
2778  LWLockAcquire(ProcArrayLock, LW_SHARED);
2779 
2780  for (index = 0; index < arrayP->numProcs; index++)
2781  {
2782  int pgprocno = arrayP->pgprocnos[index];
2783  PGPROC *proc = &allProcs[pgprocno];
2784 
2785  if (proc->pid == 0)
2786  continue; /* do not count prepared xacts */
2787  if (!OidIsValid(databaseid) ||
2788  proc->databaseId == databaseid)
2789  count++;
2790  }
2791 
2792  LWLockRelease(ProcArrayLock);
2793 
2794  return count;
2795 }
#define OidIsValid(objectId)
Definition: c.h:638
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
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:1121
Definition: proc.h:95
int pid
Definition: proc.h:109

◆ CountDBConnections()

int CountDBConnections ( Oid  databaseid)

Definition at line 2802 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().

2803 {
2804  ProcArrayStruct *arrayP = procArray;
2805  int count = 0;
2806  int index;
2807 
2808  LWLockAcquire(ProcArrayLock, LW_SHARED);
2809 
2810  for (index = 0; index < arrayP->numProcs; index++)
2811  {
2812  int pgprocno = arrayP->pgprocnos[index];
2813  PGPROC *proc = &allProcs[pgprocno];
2814 
2815  if (proc->pid == 0)
2816  continue; /* do not count prepared xacts */
2817  if (proc->isBackgroundWorker)
2818  continue; /* do not count background workers */
2819  if (!OidIsValid(databaseid) ||
2820  proc->databaseId == databaseid)
2821  count++;
2822  }
2823 
2824  LWLockRelease(ProcArrayLock);
2825 
2826  return count;
2827 }
#define OidIsValid(objectId)
Definition: c.h:638
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
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:1121
Definition: proc.h:95
int pid
Definition: proc.h:109

◆ CountOtherDBBackends()

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

Definition at line 2923 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().

2924 {
2925  ProcArrayStruct *arrayP = procArray;
2926 
2927 #define MAXAUTOVACPIDS 10 /* max autovacs to SIGTERM per iteration */
2928  int autovac_pids[MAXAUTOVACPIDS];
2929  int tries;
2930 
2931  /* 50 tries with 100ms sleep between tries makes 5 sec total wait */
2932  for (tries = 0; tries < 50; tries++)
2933  {
2934  int nautovacs = 0;
2935  bool found = false;
2936  int index;
2937 
2939 
2940  *nbackends = *nprepared = 0;
2941 
2942  LWLockAcquire(ProcArrayLock, LW_SHARED);
2943 
2944  for (index = 0; index < arrayP->numProcs; index++)
2945  {
2946  int pgprocno = arrayP->pgprocnos[index];
2947  PGPROC *proc = &allProcs[pgprocno];
2948  PGXACT *pgxact = &allPgXact[pgprocno];
2949 
2950  if (proc->databaseId != databaseId)
2951  continue;
2952  if (proc == MyProc)
2953  continue;
2954 
2955  found = true;
2956 
2957  if (proc->pid == 0)
2958  (*nprepared)++;
2959  else
2960  {
2961  (*nbackends)++;
2962  if ((pgxact->vacuumFlags & PROC_IS_AUTOVACUUM) &&
2963  nautovacs < MAXAUTOVACPIDS)
2964  autovac_pids[nautovacs++] = proc->pid;
2965  }
2966  }
2967 
2968  LWLockRelease(ProcArrayLock);
2969 
2970  if (!found)
2971  return false; /* no conflicting backends, so done */
2972 
2973  /*
2974  * Send SIGTERM to any conflicting autovacuums before sleeping. We
2975  * postpone this step until after the loop because we don't want to
2976  * hold ProcArrayLock while issuing kill(). We have no idea what might
2977  * block kill() inside the kernel...
2978  */
2979  for (index = 0; index < nautovacs; index++)
2980  (void) kill(autovac_pids[index], SIGTERM); /* ignore any error */
2981 
2982  /* sleep, then try again */
2983  pg_usleep(100 * 1000L); /* 100ms */
2984  }
2985 
2986  return true; /* timed out, still conflicts */
2987 }
Definition: proc.h:222
PGPROC * MyProc
Definition: proc.c:67
#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:1725
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:1121
#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 2873 of file procarray.c.

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

Referenced by InitializeSessionUserId().

2874 {
2875  ProcArrayStruct *arrayP = procArray;
2876  int count = 0;
2877  int index;
2878 
2879  LWLockAcquire(ProcArrayLock, LW_SHARED);
2880 
2881  for (index = 0; index < arrayP->numProcs; index++)
2882  {
2883  int pgprocno = arrayP->pgprocnos[index];
2884  PGPROC *proc = &allProcs[pgprocno];
2885 
2886  if (proc->pid == 0)
2887  continue; /* do not count prepared xacts */
2888  if (proc->isBackgroundWorker)
2889  continue; /* do not count background workers */
2890  if (proc->roleId == roleid)
2891  count++;
2892  }
2893 
2894  LWLockRelease(ProcArrayLock);
2895 
2896  return count;
2897 }
Oid roleId
Definition: proc.h:115
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
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:1121
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:80
void LWLockRegisterTranche(int tranche_id, const char *tranche_name)
Definition: lwlock.c:602
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:92
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 3310 of file procarray.c.

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

Referenced by ShutdownRecoveryTransactionEnvironment().

3311 {
3312  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3314  LWLockRelease(ProcArrayLock);
3315 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
static void KnownAssignedXidsRemovePreceding(TransactionId xid)
Definition: procarray.c:3759
#define InvalidTransactionId
Definition: transam.h:31
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121

◆ ExpireOldKnownAssignedTransactionIds()

void ExpireOldKnownAssignedTransactionIds ( TransactionId  xid)

Definition at line 3322 of file procarray.c.

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

Referenced by ProcArrayApplyRecoveryInfo().

3323 {
3324  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3326  LWLockRelease(ProcArrayLock);
3327 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
static void KnownAssignedXidsRemovePreceding(TransactionId xid)
Definition: procarray.c:3759
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121

◆ ExpireTreeKnownAssignedTransactionIds()

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

Definition at line 3285 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().

3287 {
3289 
3290  /*
3291  * Uses same locking as transaction commit
3292  */
3293  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3294 
3295  KnownAssignedXidsRemoveTree(xid, nsubxids, subxids);
3296 
3297  /* As in ProcArrayEndTransaction, advance latestCompletedXid */
3299  max_xid))
3301 
3302  LWLockRelease(ProcArrayLock);
3303 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
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:3737
#define Assert(condition)
Definition: c.h:732
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121
HotStandbyState standbyState
Definition: xlog.c:200
TransactionId latestCompletedXid
Definition: transam.h:135

◆ GetConflictingVirtualXIDs()

VirtualTransactionId* GetConflictingVirtualXIDs ( TransactionId  limitXmin,
Oid  dbOid 
)

Definition at line 2595 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().

2596 {
2597  static VirtualTransactionId *vxids;
2598  ProcArrayStruct *arrayP = procArray;
2599  int count = 0;
2600  int index;
2601 
2602  /*
2603  * If first time through, get workspace to remember main XIDs in. We
2604  * malloc it permanently to avoid repeated palloc/pfree overhead. Allow
2605  * result space, remembering room for a terminator.
2606  */
2607  if (vxids == NULL)
2608  {
2609  vxids = (VirtualTransactionId *)
2610  malloc(sizeof(VirtualTransactionId) * (arrayP->maxProcs + 1));
2611  if (vxids == NULL)
2612  ereport(ERROR,
2613  (errcode(ERRCODE_OUT_OF_MEMORY),
2614  errmsg("out of memory")));
2615  }
2616 
2617  LWLockAcquire(ProcArrayLock, LW_SHARED);
2618 
2619  for (index = 0; index < arrayP->numProcs; index++)
2620  {
2621  int pgprocno = arrayP->pgprocnos[index];
2622  PGPROC *proc = &allProcs[pgprocno];
2623  PGXACT *pgxact = &allPgXact[pgprocno];
2624 
2625  /* Exclude prepared transactions */
2626  if (proc->pid == 0)
2627  continue;
2628 
2629  if (!OidIsValid(dbOid) ||
2630  proc->databaseId == dbOid)
2631  {
2632  /* Fetch xmin just once - can't change on us, but good coding */
2633  TransactionId pxmin = UINT32_ACCESS_ONCE(pgxact->xmin);
2634 
2635  /*
2636  * We ignore an invalid pxmin because this means that backend has
2637  * no snapshot currently. We hold a Share lock to avoid contention
2638  * with users taking snapshots. That is not a problem because the
2639  * current xmin is always at least one higher than the latest
2640  * removed xid, so any new snapshot would never conflict with the
2641  * test here.
2642  */
2643  if (!TransactionIdIsValid(limitXmin) ||
2644  (TransactionIdIsValid(pxmin) && !TransactionIdFollows(pxmin, limitXmin)))
2645  {
2646  VirtualTransactionId vxid;
2647 
2648  GET_VXID_FROM_PGPROC(vxid, *proc);
2649  if (VirtualTransactionIdIsValid(vxid))
2650  vxids[count++] = vxid;
2651  }
2652  }
2653  }
2654 
2655  LWLockRelease(ProcArrayLock);
2656 
2657  /* add the terminator */
2658  vxids[count].backendId = InvalidBackendId;
2660 
2661  return vxids;
2662 }
#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:1725
#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:1121
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 2507 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 DefineIndex().

2510 {
2511  VirtualTransactionId *vxids;
2512  ProcArrayStruct *arrayP = procArray;
2513  int count = 0;
2514  int index;
2515 
2516  /* allocate what's certainly enough result space */
2517  vxids = (VirtualTransactionId *)
2518  palloc(sizeof(VirtualTransactionId) * arrayP->maxProcs);
2519 
2520  LWLockAcquire(ProcArrayLock, LW_SHARED);
2521 
2522  for (index = 0; index < arrayP->numProcs; index++)
2523  {
2524  int pgprocno = arrayP->pgprocnos[index];
2525  PGPROC *proc = &allProcs[pgprocno];
2526  PGXACT *pgxact = &allPgXact[pgprocno];
2527 
2528  if (proc == MyProc)
2529  continue;
2530 
2531  if (excludeVacuum & pgxact->vacuumFlags)
2532  continue;
2533 
2534  if (allDbs || proc->databaseId == MyDatabaseId)
2535  {
2536  /* Fetch xmin just once - might change on us */
2537  TransactionId pxmin = UINT32_ACCESS_ONCE(pgxact->xmin);
2538 
2539  if (excludeXmin0 && !TransactionIdIsValid(pxmin))
2540  continue;
2541 
2542  /*
2543  * InvalidTransactionId precedes all other XIDs, so a proc that
2544  * hasn't set xmin yet will not be rejected by this test.
2545  */
2546  if (!TransactionIdIsValid(limitXmin) ||
2547  TransactionIdPrecedesOrEquals(pxmin, limitXmin))
2548  {
2549  VirtualTransactionId vxid;
2550 
2551  GET_VXID_FROM_PGPROC(vxid, *proc);
2552  if (VirtualTransactionIdIsValid(vxid))
2553  vxids[count++] = vxid;
2554  }
2555  }
2556  }
2557 
2558  LWLockRelease(ProcArrayLock);
2559 
2560  *nvxids = count;
2561  return vxids;
2562 }
#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:67
#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:1725
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:1121
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 1477 of file procarray.c.

References TOTAL_MAX_CACHED_SUBXIDS.

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

1478 {
1479  return TOTAL_MAX_CACHED_SUBXIDS;
1480 }
#define TOTAL_MAX_CACHED_SUBXIDS

◆ GetMaxSnapshotXidCount()

int GetMaxSnapshotXidCount ( void  )

Definition at line 1466 of file procarray.c.

References ProcArrayStruct::maxProcs.

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

1467 {
1468  return procArray->maxProcs;
1469 }
static ProcArrayStruct * procArray
Definition: procarray.c:99

◆ GetOldestActiveTransactionId()

TransactionId GetOldestActiveTransactionId ( void  )

Definition at line 2125 of file procarray.c.

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

Referenced by CreateCheckPoint().

2126 {
2127  ProcArrayStruct *arrayP = procArray;
2128  TransactionId oldestRunningXid;
2129  int index;
2130 
2132 
2133  /*
2134  * Read nextXid, as the upper bound of what's still active.
2135  *
2136  * Reading a TransactionId is atomic, but we must grab the lock to make
2137  * sure that all XIDs < nextXid are already present in the proc array (or
2138  * have already completed), when we spin over it.
2139  */
2140  LWLockAcquire(XidGenLock, LW_SHARED);
2141  oldestRunningXid = ShmemVariableCache->nextXid;
2142  LWLockRelease(XidGenLock);
2143 
2144  /*
2145  * Spin over procArray collecting all xids and subxids.
2146  */
2147  LWLockAcquire(ProcArrayLock, LW_SHARED);
2148  for (index = 0; index < arrayP->numProcs; index++)
2149  {
2150  int pgprocno = arrayP->pgprocnos[index];
2151  PGXACT *pgxact = &allPgXact[pgprocno];
2152  TransactionId xid;
2153 
2154  /* Fetch xid just once - see GetNewTransactionId */
2155  xid = UINT32_ACCESS_ONCE(pgxact->xid);
2156 
2157  if (!TransactionIdIsNormal(xid))
2158  continue;
2159 
2160  if (TransactionIdPrecedes(xid, oldestRunningXid))
2161  oldestRunningXid = xid;
2162 
2163  /*
2164  * Top-level XID of a transaction is always less than any of its
2165  * subxids, so we don't need to check if any of the subxids are
2166  * smaller than oldestRunningXid
2167  */
2168  }
2169  LWLockRelease(ProcArrayLock);
2170 
2171  return oldestRunningXid;
2172 }
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
bool RecoveryInProgress(void)
Definition: xlog.c:7888
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
TransactionId nextXid
Definition: transam.h:117
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:1121
#define TransactionIdIsNormal(xid)
Definition: transam.h:42

◆ GetOldestSafeDecodingTransactionId()

TransactionId GetOldestSafeDecodingTransactionId ( bool  catalogOnly)

Definition at line 2191 of file procarray.c.

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

Referenced by CreateInitDecodingContext(), and SnapBuildInitialSnapshot().

2192 {
2193  ProcArrayStruct *arrayP = procArray;
2194  TransactionId oldestSafeXid;
2195  int index;
2196  bool recovery_in_progress = RecoveryInProgress();
2197 
2198  Assert(LWLockHeldByMe(ProcArrayLock));
2199 
2200  /*
2201  * Acquire XidGenLock, so no transactions can acquire an xid while we're
2202  * running. If no transaction with xid were running concurrently a new xid
2203  * could influence the RecentXmin et al.
2204  *
2205  * We initialize the computation to nextXid since that's guaranteed to be
2206  * a safe, albeit pessimal, value.
2207  */
2208  LWLockAcquire(XidGenLock, LW_SHARED);
2209  oldestSafeXid = ShmemVariableCache->nextXid;
2210 
2211  /*
2212  * If there's already a slot pegging the xmin horizon, we can start with
2213  * that value, it's guaranteed to be safe since it's computed by this
2214  * routine initially and has been enforced since. We can always use the
2215  * slot's general xmin horizon, but the catalog horizon is only usable
2216  * when only catalog data is going to be looked at.
2217  */
2220  oldestSafeXid))
2221  oldestSafeXid = procArray->replication_slot_xmin;
2222 
2223  if (catalogOnly &&
2226  oldestSafeXid))
2227  oldestSafeXid = procArray->replication_slot_catalog_xmin;
2228 
2229  /*
2230  * If we're not in recovery, we walk over the procarray and collect the
2231  * lowest xid. Since we're called with ProcArrayLock held and have
2232  * acquired XidGenLock, no entries can vanish concurrently, since
2233  * PGXACT->xid is only set with XidGenLock held and only cleared with
2234  * ProcArrayLock held.
2235  *
2236  * In recovery we can't lower the safe value besides what we've computed
2237  * above, so we'll have to wait a bit longer there. We unfortunately can
2238  * *not* use KnownAssignedXidsGetOldestXmin() since the KnownAssignedXids
2239  * machinery can miss values and return an older value than is safe.
2240  */
2241  if (!recovery_in_progress)
2242  {
2243  /*
2244  * Spin over procArray collecting all min(PGXACT->xid)
2245  */
2246  for (index = 0; index < arrayP->numProcs; index++)
2247  {
2248  int pgprocno = arrayP->pgprocnos[index];
2249  PGXACT *pgxact = &allPgXact[pgprocno];
2250  TransactionId xid;
2251 
2252  /* Fetch xid just once - see GetNewTransactionId */
2253  xid = UINT32_ACCESS_ONCE(pgxact->xid);
2254 
2255  if (!TransactionIdIsNormal(xid))
2256  continue;
2257 
2258  if (TransactionIdPrecedes(xid, oldestSafeXid))
2259  oldestSafeXid = xid;
2260  }
2261  }
2262 
2263  LWLockRelease(XidGenLock);
2264 
2265  return oldestSafeXid;
2266 }
uint32 TransactionId
Definition: c.h:507
Definition: proc.h:222
bool LWLockHeldByMe(LWLock *l)
Definition: lwlock.c:1841
TransactionId xid
Definition: proc.h:224
#define UINT32_ACCESS_ONCE(var)
Definition: procarray.c:64
TransactionId replication_slot_catalog_xmin
Definition: procarray.c:93
bool RecoveryInProgress(void)
Definition: xlog.c:7888
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
TransactionId nextXid
Definition: transam.h:117
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:1121
#define TransactionIdIsValid(xid)
Definition: transam.h:41
#define TransactionIdIsNormal(xid)
Definition: transam.h:42

◆ GetOldestXmin()

TransactionId GetOldestXmin ( Relation  rel,
int  flags 
)

Definition at line 1321 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(), IndexBuildHeapRangeScan(), statapprox_heap(), vac_update_datfrozenxid(), vacuum_set_xid_limits(), and XLogWalRcvSendHSFeedback().

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

◆ GetRunningTransactionData()

RunningTransactions GetRunningTransactionData ( void  )

Definition at line 1951 of file procarray.c.

References Assert, ereport, errcode(), errmsg(), ERROR, RunningTransactionsData::latestCompletedXid, VariableCacheData::latestCompletedXid, LW_SHARED, LWLockAcquire(), malloc, RunningTransactionsData::nextXid, VariableCacheData::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, XidCache::xids, and RunningTransactionsData::xids.

Referenced by LogStandbySnapshot().

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

◆ GetSnapshotData()

Snapshot GetSnapshotData ( Snapshot  snapshot)

Definition at line 1519 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().

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

◆ GetVirtualXIDsDelayingChkpt()

VirtualTransactionId* GetVirtualXIDsDelayingChkpt ( int *  nvxids)

Definition at line 2287 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().

2288 {
2289  VirtualTransactionId *vxids;
2290  ProcArrayStruct *arrayP = procArray;
2291  int count = 0;
2292  int index;
2293 
2294  /* allocate what's certainly enough result space */
2295  vxids = (VirtualTransactionId *)
2296  palloc(sizeof(VirtualTransactionId) * arrayP->maxProcs);
2297 
2298  LWLockAcquire(ProcArrayLock, LW_SHARED);
2299 
2300  for (index = 0; index < arrayP->numProcs; index++)
2301  {
2302  int pgprocno = arrayP->pgprocnos[index];
2303  PGPROC *proc = &allProcs[pgprocno];
2304  PGXACT *pgxact = &allPgXact[pgprocno];
2305 
2306  if (pgxact->delayChkpt)
2307  {
2308  VirtualTransactionId vxid;
2309 
2310  GET_VXID_FROM_PGPROC(vxid, *proc);
2311  if (VirtualTransactionIdIsValid(vxid))
2312  vxids[count++] = vxid;
2313  }
2314  }
2315 
2316  LWLockRelease(ProcArrayLock);
2317 
2318  *nvxids = count;
2319  return vxids;
2320 }
#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:1725
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:1121
void * palloc(Size size)
Definition: mcxt.c:924
Definition: proc.h:95

◆ HaveVirtualXIDsDelayingChkpt()

bool HaveVirtualXIDsDelayingChkpt ( VirtualTransactionId vxids,
int  nvxids 
)

Definition at line 2332 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().

2333 {
2334  bool result = false;
2335  ProcArrayStruct *arrayP = procArray;
2336  int index;
2337 
2338  LWLockAcquire(ProcArrayLock, LW_SHARED);
2339 
2340  for (index = 0; index < arrayP->numProcs; index++)
2341  {
2342  int pgprocno = arrayP->pgprocnos[index];
2343  PGPROC *proc = &allProcs[pgprocno];
2344  PGXACT *pgxact = &allPgXact[pgprocno];
2345  VirtualTransactionId vxid;
2346 
2347  GET_VXID_FROM_PGPROC(vxid, *proc);
2348 
2349  if (pgxact->delayChkpt && VirtualTransactionIdIsValid(vxid))
2350  {
2351  int i;
2352 
2353  for (i = 0; i < nvxids; i++)
2354  {
2355  if (VirtualTransactionIdEquals(vxid, vxids[i]))
2356  {
2357  result = true;
2358  break;
2359  }
2360  }
2361  if (result)
2362  break;
2363  }
2364  }
2365 
2366  LWLockRelease(ProcArrayLock);
2367 
2368  return result;
2369 }
#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:1725
#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:1121
int i
Definition: proc.h:95

◆ IsBackendPid()

bool IsBackendPid ( int  pid)

Definition at line 2474 of file procarray.c.

References BackendPidGetProc().

Referenced by pg_stat_get_subscription().

2475 {
2476  return (BackendPidGetProc(pid) != NULL);
2477 }
PGPROC * BackendPidGetProc(int pid)
Definition: procarray.c:2379

◆ KnownAssignedXidExists()

static bool KnownAssignedXidExists ( TransactionId  xid)
static

Definition at line 3698 of file procarray.c.

References Assert, KnownAssignedXidsSearch(), and TransactionIdIsValid.

Referenced by TransactionIdIsInProgress().

3699 {
3701 
3702  return KnownAssignedXidsSearch(xid, false);
3703 }
#define Assert(condition)
Definition: c.h:732
static bool KnownAssignedXidsSearch(TransactionId xid, bool remove)
Definition: procarray.c:3605
#define TransactionIdIsValid(xid)
Definition: transam.h:41

◆ KnownAssignedXidsAdd()

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

Definition at line 3487 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().

3489 {
3490  ProcArrayStruct *pArray = procArray;
3491  TransactionId next_xid;
3492  int head,
3493  tail;
3494  int nxids;
3495  int i;
3496 
3497  Assert(TransactionIdPrecedesOrEquals(from_xid, to_xid));
3498 
3499  /*
3500  * Calculate how many array slots we'll need. Normally this is cheap; in
3501  * the unusual case where the XIDs cross the wrap point, we do it the hard
3502  * way.
3503  */
3504  if (to_xid >= from_xid)
3505  nxids = to_xid - from_xid + 1;
3506  else
3507  {
3508  nxids = 1;
3509  next_xid = from_xid;
3510  while (TransactionIdPrecedes(next_xid, to_xid))
3511  {
3512  nxids++;
3513  TransactionIdAdvance(next_xid);
3514  }
3515  }
3516 
3517  /*
3518  * Since only the startup process modifies the head/tail pointers, we
3519  * don't need a lock to read them here.
3520  */
3521  head = pArray->headKnownAssignedXids;
3522  tail = pArray->tailKnownAssignedXids;
3523 
3524  Assert(head >= 0 && head <= pArray->maxKnownAssignedXids);
3525  Assert(tail >= 0 && tail < pArray->maxKnownAssignedXids);
3526 
3527  /*
3528  * Verify that insertions occur in TransactionId sequence. Note that even
3529  * if the last existing element is marked invalid, it must still have a
3530  * correctly sequenced XID value.
3531  */
3532  if (head > tail &&
3533  TransactionIdFollowsOrEquals(KnownAssignedXids[head - 1], from_xid))
3534  {
3536  elog(ERROR, "out-of-order XID insertion in KnownAssignedXids");
3537  }
3538 
3539  /*
3540  * If our xids won't fit in the remaining space, compress out free space
3541  */
3542  if (head + nxids > pArray->maxKnownAssignedXids)
3543  {
3544  /* must hold lock to compress */
3545  if (!exclusive_lock)
3546  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3547 
3549 
3550  head = pArray->headKnownAssignedXids;
3551  /* note: we no longer care about the tail pointer */
3552 
3553  if (!exclusive_lock)
3554  LWLockRelease(ProcArrayLock);
3555 
3556  /*
3557  * If it still won't fit then we're out of memory
3558  */
3559  if (head + nxids > pArray->maxKnownAssignedXids)
3560  elog(ERROR, "too many KnownAssignedXids");
3561  }
3562 
3563  /* Now we can insert the xids into the space starting at head */
3564  next_xid = from_xid;
3565  for (i = 0; i < nxids; i++)
3566  {
3567  KnownAssignedXids[head] = next_xid;
3568  KnownAssignedXidsValid[head] = true;
3569  TransactionIdAdvance(next_xid);
3570  head++;
3571  }
3572 
3573  /* Adjust count of number of valid entries */
3574  pArray->numKnownAssignedXids += nxids;
3575 
3576  /*
3577  * Now update the head pointer. We use a spinlock to protect this
3578  * pointer, not because the update is likely to be non-atomic, but to
3579  * ensure that other processors see the above array updates before they
3580  * see the head pointer change.
3581  *
3582  * If we're holding ProcArrayLock exclusively, there's no need to take the
3583  * spinlock.
3584  */
3585  if (exclusive_lock)
3586  pArray->headKnownAssignedXids = head;
3587  else
3588  {
3590  pArray->headKnownAssignedXids = head;
3592  }
3593 }
#define TransactionIdAdvance(dest)
Definition: transam.h:48
static void KnownAssignedXidsDisplay(int trace_level)
Definition: procarray.c:3944
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:1725
#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:1121
static void KnownAssignedXidsCompress(bool force)
Definition: procarray.c:3425
#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 3425 of file procarray.c.

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

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

3426 {
3427  ProcArrayStruct *pArray = procArray;
3428  int head,
3429  tail;
3430  int compress_index;
3431  int i;
3432 
3433  /* no spinlock required since we hold ProcArrayLock exclusively */
3434  head = pArray->headKnownAssignedXids;
3435  tail = pArray->tailKnownAssignedXids;
3436 
3437  if (!force)
3438  {
3439  /*
3440  * If we can choose how much to compress, use a heuristic to avoid
3441  * compressing too often or not often enough.
3442  *
3443  * Heuristic is if we have a large enough current spread and less than
3444  * 50% of the elements are currently in use, then compress. This
3445  * should ensure we compress fairly infrequently. We could compress
3446  * less often though the virtual array would spread out more and
3447  * snapshots would become more expensive.
3448  */
3449  int nelements = head - tail;
3450 
3451  if (nelements < 4 * PROCARRAY_MAXPROCS ||
3452  nelements < 2 * pArray->numKnownAssignedXids)
3453  return;
3454  }
3455 
3456  /*
3457  * We compress the array by reading the valid values from tail to head,
3458  * re-aligning data to 0th element.
3459  */
3460  compress_index = 0;
3461  for (i = tail; i < head; i++)
3462  {
3463  if (KnownAssignedXidsValid[i])
3464  {
3465  KnownAssignedXids[compress_index] = KnownAssignedXids[i];
3466  KnownAssignedXidsValid[compress_index] = true;
3467  compress_index++;
3468  }
3469  }
3470 
3471  pArray->tailKnownAssignedXids = 0;
3472  pArray->headKnownAssignedXids = compress_index;
3473 }
#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 3944 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().

3945 {
3946  ProcArrayStruct *pArray = procArray;
3948  int head,
3949  tail,
3950  i;
3951  int nxids = 0;
3952 
3953  tail = pArray->tailKnownAssignedXids;
3954  head = pArray->headKnownAssignedXids;
3955 
3956  initStringInfo(&buf);
3957 
3958  for (i = tail; i < head; i++)
3959  {
3960  if (KnownAssignedXidsValid[i])
3961  {
3962  nxids++;
3963  appendStringInfo(&buf, "[%d]=%u ", i, KnownAssignedXids[i]);
3964  }
3965  }
3966 
3967  elog(trace_level, "%d KnownAssignedXids (num=%d tail=%d head=%d) %s",
3968  nxids,
3969  pArray->numKnownAssignedXids,
3970  pArray->tailKnownAssignedXids,
3971  pArray->headKnownAssignedXids,
3972  buf.data);
3973 
3974  pfree(buf.data);
3975 }
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:67
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 3837 of file procarray.c.

References InvalidTransactionId, and KnownAssignedXidsGetAndSetXmin().

Referenced by TransactionIdIsInProgress().

3838 {
3840 
3841  return KnownAssignedXidsGetAndSetXmin(xarray, &xtmp, xmax);
3842 }
uint32 TransactionId
Definition: c.h:507
#define InvalidTransactionId
Definition: transam.h:31
static int KnownAssignedXidsGetAndSetXmin(TransactionId *xarray, TransactionId *xmin, TransactionId xmax)
Definition: procarray.c:3851

◆ KnownAssignedXidsGetAndSetXmin()

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

Definition at line 3851 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().

3853 {
3854  int count = 0;
3855  int head,
3856  tail;
3857  int i;
3858 
3859  /*
3860  * Fetch head just once, since it may change while we loop. We can stop
3861  * once we reach the initially seen head, since we are certain that an xid
3862  * cannot enter and then leave the array while we hold ProcArrayLock. We
3863  * might miss newly-added xids, but they should be >= xmax so irrelevant
3864  * anyway.
3865  *
3866  * Must take spinlock to ensure we see up-to-date array contents.
3867  */
3872 
3873  for (i = tail; i < head; i++)
3874  {
3875  /* Skip any gaps in the array */
3876  if (KnownAssignedXidsValid[i])
3877  {
3878  TransactionId knownXid = KnownAssignedXids[i];
3879 
3880  /*
3881  * Update xmin if required. Only the first XID need be checked,
3882  * since the array is sorted.
3883  */
3884  if (count == 0 &&
3885  TransactionIdPrecedes(knownXid, *xmin))
3886  *xmin = knownXid;
3887 
3888  /*
3889  * Filter out anything >= xmax, again relying on sorted property
3890  * of array.
3891  */
3892  if (TransactionIdIsValid(xmax) &&
3893  TransactionIdFollowsOrEquals(knownXid, xmax))
3894  break;
3895 
3896  /* Add knownXid into output array */
3897  xarray[count++] = knownXid;
3898  }
3899  }
3900 
3901  return count;
3902 }
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 3909 of file procarray.c.

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

Referenced by GetOldestXmin().

3910 {
3911  int head,
3912  tail;
3913  int i;
3914 
3915  /*
3916  * Fetch head just once, since it may change while we loop.
3917  */
3922 
3923  for (i = tail; i < head; i++)
3924  {
3925  /* Skip any gaps in the array */
3926  if (KnownAssignedXidsValid[i])
3927  return KnownAssignedXids[i];
3928  }
3929 
3930  return InvalidTransactionId;
3931 }
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 3711 of file procarray.c.

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

Referenced by KnownAssignedXidsRemoveTree().

3712 {
3714 
3715  elog(trace_recovery(DEBUG4), "remove KnownAssignedXid %u", xid);
3716 
3717  /*
3718  * Note: we cannot consider it an error to remove an XID that's not
3719  * present. We intentionally remove subxact IDs while processing
3720  * XLOG_XACT_ASSIGNMENT, to avoid array overflow. Then those XIDs will be
3721  * removed again when the top-level xact commits or aborts.
3722  *
3723  * It might be possible to track such XIDs to distinguish this case from
3724  * actual errors, but it would be complicated and probably not worth it.
3725  * So, just ignore the search result.
3726  */
3727  (void) KnownAssignedXidsSearch(xid, true);
3728 }
#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:3605
#define elog(elevel,...)
Definition: elog.h:226
#define TransactionIdIsValid(xid)
Definition: transam.h:41

◆ KnownAssignedXidsRemovePreceding()

static void KnownAssignedXidsRemovePreceding ( TransactionId  xid)
static

Definition at line 3759 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().

3760 {
3761  ProcArrayStruct *pArray = procArray;
3762  int count = 0;
3763  int head,
3764  tail,
3765  i;
3766 
3767  if (!TransactionIdIsValid(removeXid))
3768  {
3769  elog(trace_recovery(DEBUG4), "removing all KnownAssignedXids");
3770  pArray->numKnownAssignedXids = 0;
3771  pArray->headKnownAssignedXids = pArray->tailKnownAssignedXids = 0;
3772  return;
3773  }
3774 
3775  elog(trace_recovery(DEBUG4), "prune KnownAssignedXids to %u", removeXid);
3776 
3777  /*
3778  * Mark entries invalid starting at the tail. Since array is sorted, we
3779  * can stop as soon as we reach an entry >= removeXid.
3780  */
3781  tail = pArray->tailKnownAssignedXids;
3782  head = pArray->headKnownAssignedXids;
3783 
3784  for (i = tail; i < head; i++)
3785  {
3786  if (KnownAssignedXidsValid[i])
3787  {
3788  TransactionId knownXid = KnownAssignedXids[i];
3789 
3790  if (TransactionIdFollowsOrEquals(knownXid, removeXid))
3791  break;
3792 
3793  if (!StandbyTransactionIdIsPrepared(knownXid))
3794  {
3795  KnownAssignedXidsValid[i] = false;
3796  count++;
3797  }
3798  }
3799  }
3800 
3801  pArray->numKnownAssignedXids -= count;
3802  Assert(pArray->numKnownAssignedXids >= 0);
3803 
3804  /*
3805  * Advance the tail pointer if we've marked the tail item invalid.
3806  */
3807  for (i = tail; i < head; i++)
3808  {
3809  if (KnownAssignedXidsValid[i])
3810  break;
3811  }
3812  if (i >= head)
3813  {
3814  /* Array is empty, so we can reset both pointers */
3815  pArray->headKnownAssignedXids = 0;
3816  pArray->tailKnownAssignedXids = 0;
3817  }
3818  else
3819  {
3820  pArray->tailKnownAssignedXids = i;
3821  }
3822 
3823  /* Opportunistically compress the array */
3825 }
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:1411
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:3425
#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 3737 of file procarray.c.

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

Referenced by ExpireTreeKnownAssignedTransactionIds(), and ProcArrayApplyXidAssignment().

3739 {
3740  int i;
3741 
3742  if (TransactionIdIsValid(xid))
3744 
3745  for (i = 0; i < nsubxids; i++)
3746  KnownAssignedXidsRemove(subxids[i]);
3747 
3748  /* Opportunistically compress the array */
3750 }
static void KnownAssignedXidsCompress(bool force)
Definition: procarray.c:3425
static void KnownAssignedXidsRemove(TransactionId xid)
Definition: procarray.c:3711
int i
#define TransactionIdIsValid(xid)
Definition: transam.h:41

◆ KnownAssignedXidsReset()

static void KnownAssignedXidsReset ( void  )
static

Definition at line 3982 of file procarray.c.

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

Referenced by ProcArrayApplyRecoveryInfo().

3983 {
3984  ProcArrayStruct *pArray = procArray;
3985 
3986  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3987 
3988  pArray->numKnownAssignedXids = 0;
3989  pArray->tailKnownAssignedXids = 0;
3990  pArray->headKnownAssignedXids = 0;
3991 
3992  LWLockRelease(ProcArrayLock);
3993 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
int numKnownAssignedXids
Definition: procarray.c:76
static ProcArrayStruct * procArray
Definition: procarray.c:99
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121
int tailKnownAssignedXids
Definition: procarray.c:77
int headKnownAssignedXids
Definition: procarray.c:78

◆ KnownAssignedXidsSearch()

static bool KnownAssignedXidsSearch ( TransactionId  xid,
bool  remove 
)
static

Definition at line 3605 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().

3606 {
3607  ProcArrayStruct *pArray = procArray;
3608  int first,
3609  last;
3610  int head;
3611  int tail;
3612  int result_index = -1;
3613 
3614  if (remove)
3615  {
3616  /* we hold ProcArrayLock exclusively, so no need for spinlock */
3617  tail = pArray->tailKnownAssignedXids;
3618  head = pArray->headKnownAssignedXids;
3619  }
3620  else
3621  {
3622  /* take spinlock to ensure we see up-to-date array contents */
3624  tail = pArray->tailKnownAssignedXids;
3625  head = pArray->headKnownAssignedXids;
3627  }
3628 
3629  /*
3630  * Standard binary search. Note we can ignore the KnownAssignedXidsValid
3631  * array here, since even invalid entries will contain sorted XIDs.
3632  */
3633  first = tail;
3634  last = head - 1;
3635  while (first <= last)
3636  {
3637  int mid_index;
3638  TransactionId mid_xid;
3639 
3640  mid_index = (first + last) / 2;
3641  mid_xid = KnownAssignedXids[mid_index];
3642 
3643  if (xid == mid_xid)
3644  {
3645  result_index = mid_index;
3646  break;
3647  }
3648  else if (TransactionIdPrecedes(xid, mid_xid))
3649  last = mid_index - 1;
3650  else
3651  first = mid_index + 1;
3652  }
3653 
3654  if (result_index < 0)
3655  return false; /* not in array */
3656 
3657  if (!KnownAssignedXidsValid[result_index])
3658  return false; /* in array, but invalid */
3659 
3660  if (remove)
3661  {
3662  KnownAssignedXidsValid[result_index] = false;
3663 
3664  pArray->numKnownAssignedXids--;
3665  Assert(pArray->numKnownAssignedXids >= 0);
3666 
3667  /*
3668  * If we're removing the tail element then advance tail pointer over
3669  * any invalid elements. This will speed future searches.
3670  */
3671  if (result_index == tail)
3672  {
3673  tail++;
3674  while (tail < head && !KnownAssignedXidsValid[tail])
3675  tail++;
3676  if (tail >= head)
3677  {
3678  /* Array is empty, so we can reset both pointers */
3679  pArray->headKnownAssignedXids = 0;
3680  pArray->tailKnownAssignedXids = 0;
3681  }
3682  else
3683  {
3684  pArray->tailKnownAssignedXids = tail;
3685  }
3686  }
3687  }
3688 
3689  return true;
3690 }
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 2718 of file procarray.c.

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

Referenced by XLogFlush().

2719 {
2720  ProcArrayStruct *arrayP = procArray;
2721  int count = 0;
2722  int index;
2723 
2724  /* Quick short-circuit if no minimum is specified */
2725  if (min == 0)
2726  return true;
2727 
2728  /*
2729  * Note: for speed, we don't acquire ProcArrayLock. This is a little bit
2730  * bogus, but since we are only testing fields for zero or nonzero, it
2731  * should be OK. The result is only used for heuristic purposes anyway...
2732  */
2733  for (index = 0; index < arrayP->numProcs; index++)
2734  {
2735  int pgprocno = arrayP->pgprocnos[index];
2736  PGPROC *proc = &allProcs[pgprocno];
2737  PGXACT *pgxact = &allPgXact[pgprocno];
2738 
2739  /*
2740  * Since we're not holding a lock, need to be prepared to deal with
2741  * garbage, as someone could have incremented numProcs but not yet
2742  * filled the structure.
2743  *
2744  * If someone just decremented numProcs, 'proc' could also point to a
2745  * PGPROC entry that's no longer in the array. It still points to a
2746  * PGPROC struct, though, because freed PGPROC entries just go to the
2747  * free list and are recycled. Its contents are nonsense in that case,
2748  * but that's acceptable for this function.
2749  */
2750  if (pgprocno == -1)
2751  continue; /* do not count deleted entries */
2752  if (proc == MyProc)
2753  continue; /* do not count myself */
2754  if (pgxact->xid == InvalidTransactionId)
2755  continue; /* do not count if no XID assigned */
2756  if (proc->pid == 0)
2757  continue; /* do not count prepared xacts */
2758  if (proc->waitLock != NULL)
2759  continue; /* do not count if blocked on a lock */
2760  count++;
2761  if (count >= min)
2762  break;
2763  }
2764 
2765  return count >= min;
2766 }
Definition: proc.h:222
PGPROC * MyProc
Definition: proc.c:67
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:1725
#define FATAL
Definition: elog.h:52
#define memmove(d, s, c)
Definition: c.h:1218
#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:1121
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 Assert, DEBUG1, DEBUG3, elog, ERROR, ExpireOldKnownAssignedTransactionIds(), ExtendSUBTRANS(), i, InvalidTransactionId, KnownAssignedXidsAdd(), KnownAssignedXidsDisplay(), KnownAssignedXidsReset(), ProcArrayStruct::lastOverflowedXid, RunningTransactionsData::latestCompletedXid, VariableCacheData::latestCompletedXid, latestObservedXid, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), RunningTransactionsData::nextXid, VariableCacheData::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, TransactionIdFollows(), 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  TransactionId nextXid;
668  int i;
669 
674 
675  /*
676  * Remove stale transactions, if any.
677  */
679 
680  /*
681  * Remove stale locks, if any.
682  */
684 
685  /*
686  * If our snapshot is already valid, nothing else to do...
687  */
689  return;
690 
691  /*
692  * If our initial RunningTransactionsData had an overflowed snapshot then
693  * we knew we were missing some subxids from our snapshot. If we continue
694  * to see overflowed snapshots then we might never be able to start up, so
695  * we make another test to see if our snapshot is now valid. We know that
696  * the missing subxids are equal to or earlier than nextXid. After we
697  * initialise we continue to apply changes during recovery, so once the
698  * oldestRunningXid is later than the nextXid from the initial snapshot we
699  * know that we no longer have missing information and can mark the
700  * snapshot as valid.
701  */
703  {
704  /*
705  * If the snapshot isn't overflowed or if its empty we can reset our
706  * pending state and use this snapshot instead.
707  */
708  if (!running->subxid_overflow || running->xcnt == 0)
709  {
710  /*
711  * If we have already collected known assigned xids, we need to
712  * throw them away before we apply the recovery snapshot.
713  */
716  }
717  else
718  {
720  running->oldestRunningXid))
721  {
724  "recovery snapshots are now enabled");
725  }
726  else
728  "recovery snapshot waiting for non-overflowed snapshot or "
729  "until oldest active xid on standby is at least %u (now %u)",
731  running->oldestRunningXid);
732  return;
733  }
734  }
735 
737 
738  /*
739  * OK, we need to initialise from the RunningTransactionsData record.
740  *
741  * NB: this can be reached at least twice, so make sure new code can deal
742  * with that.
743  */
744 
745  /*
746  * Nobody else is running yet, but take locks anyhow
747  */
748  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
749 
750  /*
751  * KnownAssignedXids is sorted so we cannot just add the xids, we have to
752  * sort them first.
753  *
754  * Some of the new xids are top-level xids and some are subtransactions.
755  * We don't call SubtransSetParent because it doesn't matter yet. If we
756  * aren't overflowed then all xids will fit in snapshot and so we don't
757  * need subtrans. If we later overflow, an xid assignment record will add
758  * xids to subtrans. If RunningXacts is overflowed then we don't have
759  * enough information to correctly update subtrans anyway.
760  */
761 
762  /*
763  * Allocate a temporary array to avoid modifying the array passed as
764  * argument.
765  */
766  xids = palloc(sizeof(TransactionId) * (running->xcnt + running->subxcnt));
767 
768  /*
769  * Add to the temp array any xids which have not already completed.
770  */
771  nxids = 0;
772  for (i = 0; i < running->xcnt + running->subxcnt; i++)
773  {
774  TransactionId xid = running->xids[i];
775 
776  /*
777  * The running-xacts snapshot can contain xids that were still visible
778  * in the procarray when the snapshot was taken, but were already
779  * WAL-logged as completed. They're not running anymore, so ignore
780  * them.
781  */
783  continue;
784 
785  xids[nxids++] = xid;
786  }
787 
788  if (nxids > 0)
789  {
791  {
792  LWLockRelease(ProcArrayLock);
793  elog(ERROR, "KnownAssignedXids is not empty");
794  }
795 
796  /*
797  * Sort the array so that we can add them safely into
798  * KnownAssignedXids.
799  */
800  qsort(xids, nxids, sizeof(TransactionId), xidComparator);
801 
802  /*
803  * Add the sorted snapshot into KnownAssignedXids. The running-xacts
804  * snapshot may include duplicated xids because of prepared
805  * transactions, so ignore them.
806  */
807  for (i = 0; i < nxids; i++)
808  {
809  if (i > 0 && TransactionIdEquals(xids[i - 1], xids[i]))
810  {
811  elog(DEBUG1,
812  "found duplicated transaction %u for KnownAssignedXids insertion",
813  xids[i]);
814  continue;
815  }
816  KnownAssignedXidsAdd(xids[i], xids[i], true);
817  }
818 
820  }
821 
822  pfree(xids);
823 
824  /*
825  * latestObservedXid is at least set to the point where SUBTRANS was
826  * started up to (cf. ProcArrayInitRecovery()) or to the biggest xid
827  * RecordKnownAssignedTransactionIds() was called for. Initialize
828  * subtrans from thereon, up to nextXid - 1.
829  *
830  * We need to duplicate parts of RecordKnownAssignedTransactionId() here,
831  * because we've just added xids to the known assigned xids machinery that
832  * haven't gone through RecordKnownAssignedTransactionId().
833  */
837  {
840  }
841  TransactionIdRetreat(latestObservedXid); /* = running->nextXid - 1 */
842 
843  /* ----------
844  * Now we've got the running xids we need to set the global values that
845  * are used to track snapshots as they evolve further.
846  *
847  * - latestCompletedXid which will be the xmax for snapshots
848  * - lastOverflowedXid which shows whether snapshots overflow
849  * - nextXid
850  *
851  * If the snapshot overflowed, then we still initialise with what we know,
852  * but the recovery snapshot isn't fully valid yet because we know there
853  * are some subxids missing. We don't know the specific subxids that are
854  * missing, so conservatively assume the last one is latestObservedXid.
855  * ----------
856  */
857  if (running->subxid_overflow)
858  {
860 
863  }
864  else
865  {
867 
869  }
870 
871  /*
872  * If a transaction wrote a commit record in the gap between taking and
873  * logging the snapshot then latestCompletedXid may already be higher than
874  * the value from the snapshot, so check before we use the incoming value.
875  */
877  running->latestCompletedXid))
879 
881 
882  LWLockRelease(ProcArrayLock);
883 
884  /*
885  * ShmemVariableCache->nextXid must be beyond any observed xid.
886  *
887  * We don't expect anyone else to modify nextXid, hence we don't need to
888  * hold a lock while examining it. We still acquire the lock to modify
889  * it, though.
890  */
891  nextXid = latestObservedXid;
892  TransactionIdAdvance(nextXid);
894  {
895  LWLockAcquire(XidGenLock, LW_EXCLUSIVE);
896  ShmemVariableCache->nextXid = nextXid;
897  LWLockRelease(XidGenLock);
898  }
899 
901 
904  elog(trace_recovery(DEBUG1), "recovery snapshots are now enabled");
905  else
907  "recovery snapshot waiting for non-overflowed snapshot or "
908  "until oldest active xid on standby is at least %u (now %u)",
910  running->oldestRunningXid);
911 }
#define TransactionIdAdvance(dest)
Definition: transam.h:48
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:3944
#define TransactionIdEquals(id1, id2)
Definition: transam.h:43
bool TransactionIdFollows(TransactionId id1, TransactionId id2)
Definition: transam.c:334
uint32 TransactionId
Definition: c.h:507
#define DEBUG3
Definition: elog.h:23
TransactionId * xids
Definition: standby.h:79
bool TransactionIdDidCommit(TransactionId transactionId)
Definition: transam.c:125
#define TransactionIdRetreat(dest)
Definition: transam.h:56
int trace_recovery(int trace_level)
Definition: elog.c:3474
TransactionId latestCompletedXid
Definition: standby.h:77
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
void pfree(void *pointer)
Definition: mcxt.c:1031
#define ERROR
Definition: elog.h:43
void ExtendSUBTRANS(TransactionId newestXact)
Definition: subtrans.c:324
TransactionId nextXid
Definition: transam.h:117
VariableCache ShmemVariableCache
Definition: varsup.c:34
#define InvalidTransactionId
Definition: transam.h:31
static void KnownAssignedXidsReset(void)
Definition: procarray.c:3982
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:1121
static void KnownAssignedXidsAdd(TransactionId from_xid, TransactionId to_xid, bool exclusive_lock)
Definition: procarray.c:3487
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:3322
#define qsort(a, b, c, d)
Definition: port.h:479
#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:200
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:135

◆ ProcArrayApplyXidAssignment()

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

Definition at line 918 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().

920 {
921  TransactionId max_xid;
922  int i;
923 
925 
926  max_xid = TransactionIdLatest(topxid, nsubxids, subxids);
927 
928  /*
929  * Mark all the subtransactions as observed.
930  *
931  * NOTE: This will fail if the subxid contains too many previously
932  * unobserved xids to fit into known-assigned-xids. That shouldn't happen
933  * as the code stands, because xid-assignment records should never contain
934  * more than PGPROC_MAX_CACHED_SUBXIDS entries.
935  */
937 
938  /*
939  * Notice that we update pg_subtrans with the top-level xid, rather than
940  * the parent xid. This is a difference between normal processing and
941  * recovery, yet is still correct in all cases. The reason is that
942  * subtransaction commit is not marked in clog until commit processing, so
943  * all aborted subtransactions have already been clearly marked in clog.
944  * As a result we are able to refer directly to the top-level
945  * transaction's state rather than skipping through all the intermediate
946  * states in the subtransaction tree. This should be the first time we
947  * have attempted to SubTransSetParent().
948  */
949  for (i = 0; i < nsubxids; i++)
950  SubTransSetParent(subxids[i], topxid);
951 
952  /* KnownAssignedXids isn't maintained yet, so we're done for now */
954  return;
955 
956  /*
957  * Uses same locking as transaction commit
958  */
959  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
960 
961  /*
962  * Remove subxids from known-assigned-xacts.
963  */
965 
966  /*
967  * Advance lastOverflowedXid to be at least the last of these subxids.
968  */
970  procArray->lastOverflowedXid = max_xid;
971 
972  LWLockRelease(ProcArrayLock);
973 }
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:1725
#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:3737
static ProcArrayStruct * procArray
Definition: procarray.c:99
#define Assert(condition)
Definition: c.h:732
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121
int i
void RecordKnownAssignedTransactionIds(TransactionId xid)
Definition: procarray.c:3212
void SubTransSetParent(TransactionId xid, TransactionId parent)
Definition: subtrans.c:74
HotStandbyState standbyState
Definition: xlog.c:200

◆ 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:1725
bool LWLockConditionalAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1293
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:135

◆ ProcArrayGetReplicationSlotXmin()

void ProcArrayGetReplicationSlotXmin ( TransactionId xmin,
TransactionId catalog_xmin 
)

Definition at line 3019 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().

3021 {
3022  LWLockAcquire(ProcArrayLock, LW_SHARED);
3023 
3024  if (xmin != NULL)
3026 
3027  if (catalog_xmin != NULL)
3028  *catalog_xmin = procArray->replication_slot_catalog_xmin;
3029 
3030  LWLockRelease(ProcArrayLock);
3031 }
TransactionId replication_slot_catalog_xmin
Definition: procarray.c:93
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
static ProcArrayStruct * procArray
Definition: procarray.c:99
TransactionId replication_slot_xmin
Definition: procarray.c:91
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121

◆ 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:67
TransactionId xid
Definition: proc.h:224
PROC_HDR * ProcGlobal
Definition: proc.c:80
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
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:1262
#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:1238
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121
void PGSemaphoreLock(PGSemaphore sema)
Definition: posix_sema.c:309
int pgprocno
Definition: proc.h:110
pg_atomic_uint32 procArrayGroupFirst
Definition: proc.h:259
#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:56
#define Assert(condition)
Definition: c.h:732
#define TransactionIdIsNormal(xid)
Definition: transam.h:42
HotStandbyState standbyState
Definition: xlog.c:200

◆ ProcArrayInstallImportedXmin()

bool ProcArrayInstallImportedXmin ( TransactionId  xmin,
VirtualTransactionId sourcevxid 
)

Definition at line 1810 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().

1812 {
1813  bool result = false;
1814  ProcArrayStruct *arrayP = procArray;
1815  int index;
1816 
1818  if (!sourcevxid)
1819  return false;
1820 
1821  /* Get lock so source xact can't end while we're doing this */
1822  LWLockAcquire(ProcArrayLock, LW_SHARED);
1823 
1824  for (index = 0; index < arrayP->numProcs; index++)
1825  {
1826  int pgprocno = arrayP->pgprocnos[index];
1827  PGPROC *proc = &allProcs[pgprocno];
1828  PGXACT *pgxact = &allPgXact[pgprocno];
1829  TransactionId xid;
1830 
1831  /* Ignore procs running LAZY VACUUM */
1832  if (pgxact->vacuumFlags & PROC_IN_VACUUM)
1833  continue;
1834 
1835  /* We are only interested in the specific virtual transaction. */
1836  if (proc->backendId != sourcevxid->backendId)
1837  continue;
1838  if (proc->lxid != sourcevxid->localTransactionId)
1839  continue;
1840 
1841  /*
1842  * We check the transaction's database ID for paranoia's sake: if it's
1843  * in another DB then its xmin does not cover us. Caller should have
1844  * detected this already, so we just treat any funny cases as
1845  * "transaction not found".
1846  */
1847  if (proc->databaseId != MyDatabaseId)
1848  continue;
1849 
1850  /*
1851  * Likewise, let's just make real sure its xmin does cover us.
1852  */
1853  xid = UINT32_ACCESS_ONCE(pgxact->xmin);
1854  if (!TransactionIdIsNormal(xid) ||
1855  !TransactionIdPrecedesOrEquals(xid, xmin))
1856  continue;
1857 
1858  /*
1859  * We're good. Install the new xmin. As in GetSnapshotData, set
1860  * TransactionXmin too. (Note that because snapmgr.c called
1861  * GetSnapshotData first, we'll be overwriting a valid xmin here, so
1862  * we don't check that.)
1863  */
1864  MyPgXact->xmin = TransactionXmin = xmin;
1865 
1866  result = true;
1867  break;
1868  }
1869 
1870  LWLockRelease(ProcArrayLock);
1871 
1872  return result;
1873 }
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:68
uint8 vacuumFlags
Definition: proc.h:233
TransactionId TransactionXmin
Definition: snapmgr.c:164
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
#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:1121
#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 1885 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().

1886 {
1887  bool result = false;
1888  TransactionId xid;
1889  PGXACT *pgxact;
1890 
1892  Assert(proc != NULL);
1893 
1894  /* Get lock so source xact can't end while we're doing this */
1895  LWLockAcquire(ProcArrayLock, LW_SHARED);
1896 
1897  pgxact = &allPgXact[proc->pgprocno];
1898 
1899  /*
1900  * Be certain that the referenced PGPROC has an advertised xmin which is
1901  * no later than the one we're installing, so that the system-wide xmin
1902  * can't go backwards. Also, make sure it's running in the same database,
1903  * so that the per-database xmin cannot go backwards.
1904  */
1905  xid = UINT32_ACCESS_ONCE(pgxact->xmin);
1906  if (proc->databaseId == MyDatabaseId &&
1907  TransactionIdIsNormal(xid) &&
1908  TransactionIdPrecedesOrEquals(xid, xmin))
1909  {
1910  MyPgXact->xmin = TransactionXmin = xmin;
1911  result = true;
1912  }
1913 
1914  LWLockRelease(ProcArrayLock);
1915 
1916  return result;
1917 }
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:68
TransactionId TransactionXmin
Definition: snapmgr.c:164
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
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:1121
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:1725
#define memmove(d, s, c)
Definition: c.h:1218
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:1121
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:135

◆ ProcArraySetReplicationSlotXmin()

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

Definition at line 2997 of file procarray.c.

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

Referenced by ReplicationSlotsComputeRequiredXmin().

2999 {
3000  Assert(!already_locked || LWLockHeldByMe(ProcArrayLock));
3001 
3002  if (!already_locked)
3003  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3004 
3006  procArray->replication_slot_catalog_xmin = catalog_xmin;
3007 
3008  if (!already_locked)
3009  LWLockRelease(ProcArrayLock);
3010 }
bool LWLockHeldByMe(LWLock *l)
Definition: lwlock.c:1841
TransactionId replication_slot_catalog_xmin
Definition: procarray.c:93
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
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:1121

◆ 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:92
#define offsetof(type, field)
Definition: c.h:655

◆ RecordKnownAssignedTransactionIds()

void RecordKnownAssignedTransactionIds ( TransactionId  xid)

Definition at line 3212 of file procarray.c.

References Assert, DEBUG4, elog, ExtendSUBTRANS(), KnownAssignedXidsAdd(), latestObservedXid, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), VariableCacheData::nextXid, ShmemVariableCache, STANDBY_INITIALIZED, standbyState, trace_recovery(), TransactionIdAdvance, TransactionIdFollows(), TransactionIdIsValid, and TransactionIdPrecedes().

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

3213 {
3217 
3218  elog(trace_recovery(DEBUG4), "record known xact %u latestObservedXid %u",
3219  xid, latestObservedXid);
3220 
3221  /*
3222  * When a newly observed xid arrives, it is frequently the case that it is
3223  * *not* the next xid in sequence. When this occurs, we must treat the
3224  * intervening xids as running also.
3225  */
3227  {
3228  TransactionId next_expected_xid;
3229 
3230  /*
3231  * Extend subtrans like we do in GetNewTransactionId() during normal
3232  * operation using individual extend steps. Note that we do not need
3233  * to extend clog since its extensions are WAL logged.
3234  *
3235  * This part has to be done regardless of standbyState since we
3236  * immediately start assigning subtransactions to their toplevel
3237  * transactions.
3238  */
3239  next_expected_xid = latestObservedXid;
3240  while (TransactionIdPrecedes(next_expected_xid, xid))
3241  {
3242  TransactionIdAdvance(next_expected_xid);
3243  ExtendSUBTRANS(next_expected_xid);
3244  }
3245  Assert(next_expected_xid == xid);
3246 
3247  /*
3248  * If the KnownAssignedXids machinery isn't up yet, there's nothing
3249  * more to do since we don't track assigned xids yet.
3250  */
3252  {
3253  latestObservedXid = xid;
3254  return;
3255  }
3256 
3257  /*
3258  * Add (latestObservedXid, xid] onto the KnownAssignedXids array.
3259  */
3260  next_expected_xid = latestObservedXid;
3261  TransactionIdAdvance(next_expected_xid);
3262  KnownAssignedXidsAdd(next_expected_xid, xid, false);
3263 
3264  /*
3265  * Now we can advance latestObservedXid
3266  */
3267  latestObservedXid = xid;
3268 
3269  /* ShmemVariableCache->nextXid must be beyond any observed xid */
3270  next_expected_xid = latestObservedXid;
3271  TransactionIdAdvance(next_expected_xid);
3272  LWLockAcquire(XidGenLock, LW_EXCLUSIVE);
3273  ShmemVariableCache->nextXid = next_expected_xid;
3274  LWLockRelease(XidGenLock);
3275  }
3276 }
#define TransactionIdAdvance(dest)
Definition: transam.h:48
static TransactionId latestObservedXid
Definition: procarray.c:109
bool TransactionIdFollows(TransactionId id1, TransactionId id2)
Definition: transam.c:334
uint32 TransactionId
Definition: c.h:507
#define DEBUG4
Definition: elog.h:22
int trace_recovery(int trace_level)
Definition: elog.c:3474
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
void ExtendSUBTRANS(TransactionId newestXact)
Definition: subtrans.c:324
TransactionId nextXid
Definition: transam.h:117
VariableCache ShmemVariableCache
Definition: varsup.c:34
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
#define Assert(condition)
Definition: c.h:732
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121
static void KnownAssignedXidsAdd(TransactionId from_xid, TransactionId to_xid, bool exclusive_lock)
Definition: procarray.c:3487
#define elog(elevel,...)
Definition: elog.h:226
#define TransactionIdIsValid(xid)
Definition: transam.h:41
HotStandbyState standbyState
Definition: xlog.c:200

◆ TransactionIdIsActive()

bool TransactionIdIsActive ( TransactionId  xid)

Definition at line 1222 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.

1223 {
1224  bool result = false;
1225  ProcArrayStruct *arrayP = procArray;
1226  int i;
1227 
1228  /*
1229  * Don't bother checking a transaction older than RecentXmin; it could not
1230  * possibly still be running.
1231  */
1233  return false;
1234 
1235  LWLockAcquire(ProcArrayLock, LW_SHARED);
1236 
1237  for (i = 0; i < arrayP->numProcs; i++)
1238  {
1239  int pgprocno = arrayP->pgprocnos[i];
1240  PGPROC *proc = &allProcs[pgprocno];
1241  PGXACT *pgxact = &allPgXact[pgprocno];
1242  TransactionId pxid;
1243 
1244  /* Fetch xid just once - see GetNewTransactionId */
1245  pxid = UINT32_ACCESS_ONCE(pgxact->xid);
1246 
1247  if (!TransactionIdIsValid(pxid))
1248  continue;
1249 
1250  if (proc->pid == 0)
1251  continue; /* ignore prepared transactions */
1252 
1253  if (TransactionIdEquals(pxid, xid))
1254  {
1255  result = true;
1256  break;
1257  }
1258  }
1259 
1260  LWLockRelease(ProcArrayLock);
1261 
1262  return result;
1263 }
#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:165
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
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:1121
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 1002 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().

1003 {
1004  static TransactionId *xids = NULL;
1005  int nxids = 0;
1006  ProcArrayStruct *arrayP = procArray;
1007  TransactionId topxid;
1008  int i,
1009  j;
1010 
1011  /*
1012  * Don't bother checking a transaction older than RecentXmin; it could not
1013  * possibly still be running. (Note: in particular, this guarantees that
1014  * we reject InvalidTransactionId, FrozenTransactionId, etc as not
1015  * running.)
1016  */
1018  {
1020  return false;
1021  }
1022 
1023  /*
1024  * We may have just checked the status of this transaction, so if it is
1025  * already known to be completed, we can fall out without any access to
1026  * shared memory.
1027  */
1029  {
1031  return false;
1032  }
1033 
1034  /*
1035  * Also, we can handle our own transaction (and subtransactions) without
1036  * any access to shared memory.
1037  */
1039  {
1041  return true;
1042  }
1043 
1044  /*
1045  * If first time through, get workspace to remember main XIDs in. We
1046  * malloc it permanently to avoid repeated palloc/pfree overhead.
1047  */
1048  if (xids == NULL)
1049  {
1050  /*
1051  * In hot standby mode, reserve enough space to hold all xids in the
1052  * known-assigned list. If we later finish recovery, we no longer need
1053  * the bigger array, but we don't bother to shrink it.
1054  */
1055  int maxxids = RecoveryInProgress() ? TOTAL_MAX_CACHED_SUBXIDS : arrayP->maxProcs;
1056 
1057  xids = (TransactionId *) malloc(maxxids * sizeof(TransactionId));
1058  if (xids == NULL)
1059  ereport(ERROR,
1060  (errcode(ERRCODE_OUT_OF_MEMORY),
1061  errmsg("out of memory")));
1062  }
1063 
1064  LWLockAcquire(ProcArrayLock, LW_SHARED);
1065 
1066  /*
1067  * Now that we have the lock, we can check latestCompletedXid; if the
1068  * target Xid is after that, it's surely still running.
1069  */
1071  {
1072  LWLockRelease(ProcArrayLock);
1074  return true;
1075  }
1076 
1077  /* No shortcuts, gotta grovel through the array */
1078  for (i = 0; i < arrayP->numProcs; i++)
1079  {
1080  int pgprocno = arrayP->pgprocnos[i];
1081  PGPROC *proc = &allProcs[pgprocno];
1082  PGXACT *pgxact = &allPgXact[pgprocno];
1083  TransactionId pxid;
1084  int pxids;
1085 
1086  /* Ignore my own proc --- dealt with it above */
1087  if (proc == MyProc)
1088  continue;
1089 
1090  /* Fetch xid just once - see GetNewTransactionId */
1091  pxid = UINT32_ACCESS_ONCE(pgxact->xid);
1092 
1093  if (!TransactionIdIsValid(pxid))
1094  continue;
1095 
1096  /*
1097  * Step 1: check the main Xid
1098  */
1099  if (TransactionIdEquals(pxid, xid))
1100  {
1101  LWLockRelease(ProcArrayLock);
1103  return true;
1104  }
1105 
1106  /*
1107  * We can ignore main Xids that are younger than the target Xid, since
1108  * the target could not possibly be their child.
1109  */
1110  if (TransactionIdPrecedes(xid, pxid))
1111  continue;
1112 
1113  /*
1114  * Step 2: check the cached child-Xids arrays
1115  */
1116  pxids = pgxact->nxids;
1117  pg_read_barrier(); /* pairs with barrier in GetNewTransactionId() */
1118  for (j = pxids - 1; j >= 0; j--)
1119  {
1120  /* Fetch xid just once - see GetNewTransactionId */
1121  TransactionId cxid = UINT32_ACCESS_ONCE(proc->subxids.xids[j]);
1122 
1123  if (TransactionIdEquals(cxid, xid))
1124  {
1125  LWLockRelease(ProcArrayLock);
1127  return true;
1128  }
1129  }
1130 
1131  /*
1132  * Save the main Xid for step 4. We only need to remember main Xids
1133  * that have uncached children. (Note: there is no race condition
1134  * here because the overflowed flag cannot be cleared, only set, while
1135  * we hold ProcArrayLock. So we can't miss an Xid that we need to
1136  * worry about.)
1137  */
1138  if (pgxact->overflowed)
1139  xids[nxids++] = pxid;
1140  }
1141 
1142  /*
1143  * Step 3: in hot standby mode, check the known-assigned-xids list. XIDs
1144  * in the list must be treated as running.
1145  */
1146  if (RecoveryInProgress())
1147  {
1148  /* none of the PGXACT entries should have XIDs in hot standby mode */
1149  Assert(nxids == 0);
1150 
1151  if (KnownAssignedXidExists(xid))
1152  {
1153  LWLockRelease(ProcArrayLock);
1155  return true;
1156  }
1157 
1158  /*
1159  * If the KnownAssignedXids overflowed, we have to check pg_subtrans
1160  * too. Fetch all xids from KnownAssignedXids that are lower than
1161  * xid, since if xid is a subtransaction its parent will always have a
1162  * lower value. Note we will collect both main and subXIDs here, but
1163  * there's no help for it.
1164  */
1166  nxids = KnownAssignedXidsGet(xids, xid);
1167  }
1168 
1169  LWLockRelease(ProcArrayLock);
1170 
1171  /*
1172  * If none of the relevant caches overflowed, we know the Xid is not
1173  * running without even looking at pg_subtrans.
1174  */
1175  if (nxids == 0)
1176  {
1178  return false;
1179  }
1180 
1181  /*
1182  * Step 4: have to check pg_subtrans.
1183  *
1184  * At this point, we know it's either a subtransaction of one of the Xids
1185  * in xids[], or it's not running. If it's an already-failed
1186  * subtransaction, we want to say "not running" even though its parent may
1187  * still be running. So first, check pg_xact to see if it's been aborted.
1188  */
1190 
1191  if (TransactionIdDidAbort(xid))
1192  return false;
1193 
1194  /*
1195  * It isn't aborted, so check whether the transaction tree it belongs to
1196  * is still running (or, more precisely, whether it was running when we
1197  * held ProcArrayLock).
1198  */
1199  topxid = SubTransGetTopmostTransaction(xid);
1200  Assert(TransactionIdIsValid(topxid));
1201  if (!TransactionIdEquals(topxid, xid))
1202  {
1203  for (i = 0; i < nxids; i++)
1204  {
1205  if (TransactionIdEquals(xids[i], topxid))
1206  return true;
1207  }
1208  }
1209 
1210  return false;
1211 }
#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:769
TransactionId SubTransGetTopmostTransaction(TransactionId xid)
Definition: subtrans.c:150
PGPROC * MyProc
Definition: proc.c:67
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:165
bool RecoveryInProgress(void)
Definition: xlog.c:7888
#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:1725
#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:3837
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:1121
#define xc_no_overflow_inc()
Definition: procarray.c:151
static bool KnownAssignedXidExists(TransactionId xid)
Definition: procarray.c:3698
#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:135

◆ XidCacheRemoveRunningXids()

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

Definition at line 3050 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().

3053 {
3054  int i,
3055  j;
3056 
3058 
3059  /*
3060  * We must hold ProcArrayLock exclusively in order to remove transactions
3061  * from the PGPROC array. (See src/backend/access/transam/README.) It's
3062  * possible this could be relaxed since we know this routine is only used
3063  * to abort subtransactions, but pending closer analysis we'd best be
3064  * conservative.
3065  *
3066  * Note that we do not have to be careful about memory ordering of our own
3067  * reads wrt. GetNewTransactionId() here - only this process can modify
3068  * relevant fields of MyProc/MyPgXact. But we do have to be careful about
3069  * our own writes being well ordered.
3070  */
3071  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3072 
3073  /*
3074  * Under normal circumstances xid and xids[] will be in increasing order,
3075  * as will be the entries in subxids. Scan backwards to avoid O(N^2)
3076  * behavior when removing a lot of xids.
3077  */
3078  for (i = nxids - 1; i >= 0; i--)
3079  {
3080  TransactionId anxid = xids[i];
3081 
3082  for (j = MyPgXact->nxids - 1; j >= 0; j--)
3083  {
3084  if (TransactionIdEquals(MyProc->subxids.xids[j], anxid))
3085  {
3086  XidCacheRemove(j);
3087  break;
3088  }
3089  }
3090 
3091  /*
3092  * Ordinarily we should have found it, unless the cache has
3093  * overflowed. However it's also possible for this routine to be
3094  * invoked multiple times for the same subtransaction, in case of an
3095  * error during AbortSubTransaction. So instead of Assert, emit a
3096  * debug warning.
3097  */
3098  if (j < 0 && !MyPgXact->overflowed)
3099  elog(WARNING, "did not find subXID %u in MyProc", anxid);
3100  }
3101 
3102  for (j = MyPgXact->nxids - 1; j >= 0; j--)
3103  {
3104  if (TransactionIdEquals(MyProc->subxids.xids[j], xid))
3105  {
3106  XidCacheRemove(j);
3107  break;
3108  }
3109  }
3110  /* Ordinarily we should have found it, unless the cache has overflowed */
3111  if (j < 0 && !MyPgXact->overflowed)
3112  elog(WARNING, "did not find subXID %u in MyProc", xid);
3113 
3114  /* Also advance global latestCompletedXid while holding the lock */
3116  latestXid))
3118 
3119  LWLockRelease(ProcArrayLock);
3120 }
#define XidCacheRemove(i)
Definition: procarray.c:3034
#define TransactionIdEquals(id1, id2)
Definition: transam.h:43
uint32 TransactionId
Definition: c.h:507
PGPROC * MyProc
Definition: proc.c:67
PGXACT * MyPgXact
Definition: proc.c:68
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
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:1121
#define elog(elevel,...)
Definition: elog.h:226
int i
#define TransactionIdIsValid(xid)
Definition: transam.h:41
TransactionId latestCompletedXid
Definition: transam.h:135

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