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

Go to the source code of this file.

Data Structures

struct  ProcArrayStruct
 

Macros

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

Typedefs

typedef struct ProcArrayStruct ProcArrayStruct
 

Functions

static void KnownAssignedXidsCompress (bool force)
 
static void KnownAssignedXidsAdd (TransactionId from_xid, TransactionId to_xid, bool exclusive_lock)
 
static bool KnownAssignedXidsSearch (TransactionId xid, bool remove)
 
static bool KnownAssignedXidExists (TransactionId xid)
 
static void KnownAssignedXidsRemove (TransactionId xid)
 
static void KnownAssignedXidsRemoveTree (TransactionId xid, int nsubxids, TransactionId *subxids)
 
static void KnownAssignedXidsRemovePreceding (TransactionId xid)
 
static int KnownAssignedXidsGet (TransactionId *xarray, TransactionId xmax)
 
static int KnownAssignedXidsGetAndSetXmin (TransactionId *xarray, TransactionId *xmin, TransactionId xmax)
 
static TransactionId KnownAssignedXidsGetOldestXmin (void)
 
static void KnownAssignedXidsDisplay (int trace_level)
 
static void KnownAssignedXidsReset (void)
 
static void ProcArrayEndTransactionInternal (PGPROC *proc, PGXACT *pgxact, TransactionId latestXid)
 
static void ProcArrayGroupClearXid (PGPROC *proc, TransactionId latestXid)
 
Size ProcArrayShmemSize (void)
 
void CreateSharedProcArray (void)
 
void ProcArrayAdd (PGPROC *proc)
 
void ProcArrayRemove (PGPROC *proc, TransactionId latestXid)
 
void ProcArrayEndTransaction (PGPROC *proc, TransactionId latestXid)
 
void ProcArrayClearTransaction (PGPROC *proc)
 
void ProcArrayInitRecovery (TransactionId initializedUptoXID)
 
void ProcArrayApplyRecoveryInfo (RunningTransactions running)
 
void ProcArrayApplyXidAssignment (TransactionId topxid, int nsubxids, TransactionId *subxids)
 
bool TransactionIdIsInProgress (TransactionId xid)
 
bool TransactionIdIsActive (TransactionId xid)
 
TransactionId GetOldestXmin (Relation rel, int flags)
 
int GetMaxSnapshotXidCount (void)
 
int GetMaxSnapshotSubxidCount (void)
 
Snapshot GetSnapshotData (Snapshot snapshot)
 
bool ProcArrayInstallImportedXmin (TransactionId xmin, VirtualTransactionId *sourcevxid)
 
bool ProcArrayInstallRestoredXmin (TransactionId xmin, PGPROC *proc)
 
RunningTransactions GetRunningTransactionData (void)
 
TransactionId GetOldestActiveTransactionId (void)
 
TransactionId GetOldestSafeDecodingTransactionId (bool catalogOnly)
 
VirtualTransactionIdGetVirtualXIDsDelayingChkpt (int *nvxids)
 
bool HaveVirtualXIDsDelayingChkpt (VirtualTransactionId *vxids, int nvxids)
 
PGPROCBackendPidGetProc (int pid)
 
PGPROCBackendPidGetProcWithLock (int pid)
 
int BackendXidGetPid (TransactionId xid)
 
bool IsBackendPid (int pid)
 
VirtualTransactionIdGetCurrentVirtualXIDs (TransactionId limitXmin, bool excludeXmin0, bool allDbs, int excludeVacuum, int *nvxids)
 
VirtualTransactionIdGetConflictingVirtualXIDs (TransactionId limitXmin, Oid dbOid)
 
pid_t CancelVirtualTransaction (VirtualTransactionId vxid, ProcSignalReason sigmode)
 
bool MinimumActiveBackends (int min)
 
int CountDBBackends (Oid databaseid)
 
int CountDBConnections (Oid databaseid)
 
void CancelDBBackends (Oid databaseid, ProcSignalReason sigmode, bool conflictPending)
 
int CountUserBackends (Oid roleid)
 
bool CountOtherDBBackends (Oid databaseId, int *nbackends, int *nprepared)
 
void ProcArraySetReplicationSlotXmin (TransactionId xmin, TransactionId catalog_xmin, bool already_locked)
 
void ProcArrayGetReplicationSlotXmin (TransactionId *xmin, TransactionId *catalog_xmin)
 
void XidCacheRemoveRunningXids (TransactionId xid, int nxids, const TransactionId *xids, TransactionId latestXid)
 
void RecordKnownAssignedTransactionIds (TransactionId xid)
 
void ExpireTreeKnownAssignedTransactionIds (TransactionId xid, int nsubxids, TransactionId *subxids, TransactionId max_xid)
 
void ExpireAllKnownAssignedTransactionIds (void)
 
void ExpireOldKnownAssignedTransactionIds (TransactionId xid)
 

Variables

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

Macro Definition Documentation

◆ MAXAUTOVACPIDS

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

Referenced by CountOtherDBBackends().

◆ PROCARRAY_MAXPROCS

◆ TOTAL_MAX_CACHED_SUBXIDS

◆ UINT32_ACCESS_ONCE

◆ xc_by_child_xid_inc

#define xc_by_child_xid_inc ( )    ((void) 0)

Definition at line 149 of file procarray.c.

Referenced by TransactionIdIsInProgress().

◆ xc_by_known_assigned_inc

#define xc_by_known_assigned_inc ( )    ((void) 0)

Definition at line 150 of file procarray.c.

Referenced by TransactionIdIsInProgress().

◆ xc_by_known_xact_inc

#define xc_by_known_xact_inc ( )    ((void) 0)

Definition at line 145 of file procarray.c.

Referenced by TransactionIdIsInProgress().

◆ xc_by_latest_xid_inc

#define xc_by_latest_xid_inc ( )    ((void) 0)

Definition at line 147 of file procarray.c.

Referenced by TransactionIdIsInProgress().

◆ xc_by_main_xid_inc

#define xc_by_main_xid_inc ( )    ((void) 0)

Definition at line 148 of file procarray.c.

Referenced by TransactionIdIsInProgress().

◆ xc_by_my_xact_inc

#define xc_by_my_xact_inc ( )    ((void) 0)

Definition at line 146 of file procarray.c.

Referenced by TransactionIdIsInProgress().

◆ xc_by_recent_xmin_inc

#define xc_by_recent_xmin_inc ( )    ((void) 0)

Definition at line 144 of file procarray.c.

Referenced by TransactionIdIsInProgress().

◆ xc_no_overflow_inc

#define xc_no_overflow_inc ( )    ((void) 0)

Definition at line 151 of file procarray.c.

Referenced by TransactionIdIsInProgress().

◆ xc_slow_answer_inc

#define xc_slow_answer_inc ( )    ((void) 0)

Definition at line 152 of file procarray.c.

Referenced by TransactionIdIsInProgress().

◆ XidCacheRemove

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

Definition at line 3018 of file procarray.c.

Referenced by XidCacheRemoveRunningXids().

Typedef Documentation

◆ ProcArrayStruct

Function Documentation

◆ BackendPidGetProc()

PGPROC* BackendPidGetProc ( int  pid)

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

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

◆ BackendPidGetProcWithLock()

PGPROC* BackendPidGetProcWithLock ( int  pid)

Definition at line 2386 of file procarray.c.

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

Referenced by BackendPidGetProc(), and GetBlockerStatusData().

2387 {
2388  PGPROC *result = NULL;
2389  ProcArrayStruct *arrayP = procArray;
2390  int index;
2391 
2392  if (pid == 0) /* never match dummy PGPROCs */
2393  return NULL;
2394 
2395  for (index = 0; index < arrayP->numProcs; index++)
2396  {
2397  PGPROC *proc = &allProcs[arrayP->pgprocnos[index]];
2398 
2399  if (proc->pid == pid)
2400  {
2401  result = proc;
2402  break;
2403  }
2404  }
2405 
2406  return result;
2407 }
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 2423 of file procarray.c.

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

Referenced by pgrowlocks().

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

◆ CancelDBBackends()

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

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

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

◆ CancelVirtualTransaction()

pid_t CancelVirtualTransaction ( VirtualTransactionId  vxid,
ProcSignalReason  sigmode 
)

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

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

◆ CountDBBackends()

int CountDBBackends ( Oid  databaseid)

Definition at line 2756 of file procarray.c.

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

Referenced by ResolveRecoveryConflictWithDatabase().

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

◆ CountDBConnections()

int CountDBConnections ( Oid  databaseid)

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

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

◆ CountOtherDBBackends()

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

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

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

◆ CountUserBackends()

int CountUserBackends ( Oid  roleid)

Definition at line 2857 of file procarray.c.

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

Referenced by InitializeSessionUserId().

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

◆ CreateSharedProcArray()

void CreateSharedProcArray ( void  )

Definition at line 222 of file procarray.c.

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

Referenced by CreateSharedMemoryAndSemaphores().

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

◆ ExpireAllKnownAssignedTransactionIds()

void ExpireAllKnownAssignedTransactionIds ( void  )

Definition at line 3292 of file procarray.c.

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

Referenced by ShutdownRecoveryTransactionEnvironment().

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

◆ ExpireOldKnownAssignedTransactionIds()

void ExpireOldKnownAssignedTransactionIds ( TransactionId  xid)

Definition at line 3304 of file procarray.c.

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

Referenced by ProcArrayApplyRecoveryInfo().

3305 {
3306  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3308  LWLockRelease(ProcArrayLock);
3309 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726
static void KnownAssignedXidsRemovePreceding(TransactionId xid)
Definition: procarray.c:3741
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122

◆ ExpireTreeKnownAssignedTransactionIds()

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

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

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

◆ GetConflictingVirtualXIDs()

VirtualTransactionId* GetConflictingVirtualXIDs ( TransactionId  limitXmin,
Oid  dbOid 
)

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

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

◆ GetCurrentVirtualXIDs()

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

Definition at line 2491 of file procarray.c.

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

Referenced by WaitForOlderSnapshots().

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

◆ GetMaxSnapshotSubxidCount()

int GetMaxSnapshotSubxidCount ( void  )

Definition at line 1461 of file procarray.c.

References TOTAL_MAX_CACHED_SUBXIDS.

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

1462 {
1463  return TOTAL_MAX_CACHED_SUBXIDS;
1464 }
#define TOTAL_MAX_CACHED_SUBXIDS

◆ GetMaxSnapshotXidCount()

int GetMaxSnapshotXidCount ( void  )

Definition at line 1450 of file procarray.c.

References ProcArrayStruct::maxProcs.

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

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

◆ GetOldestActiveTransactionId()

TransactionId GetOldestActiveTransactionId ( void  )

Definition at line 2109 of file procarray.c.

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

Referenced by CreateCheckPoint().

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

◆ GetOldestSafeDecodingTransactionId()

TransactionId GetOldestSafeDecodingTransactionId ( bool  catalogOnly)

Definition at line 2175 of file procarray.c.

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

Referenced by CreateInitDecodingContext(), and SnapBuildInitialSnapshot().

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

◆ GetOldestXmin()

TransactionId GetOldestXmin ( Relation  rel,
int  flags 
)

Definition at line 1304 of file procarray.c.

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

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

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

◆ GetRunningTransactionData()

RunningTransactions GetRunningTransactionData ( void  )

Definition at line 1935 of file procarray.c.

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

Referenced by LogStandbySnapshot().

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

◆ GetSnapshotData()

Snapshot GetSnapshotData ( Snapshot  snapshot)

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

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

◆ GetVirtualXIDsDelayingChkpt()

VirtualTransactionId* GetVirtualXIDsDelayingChkpt ( int *  nvxids)

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

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

◆ HaveVirtualXIDsDelayingChkpt()

bool HaveVirtualXIDsDelayingChkpt ( VirtualTransactionId vxids,
int  nvxids 
)

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

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

◆ IsBackendPid()

bool IsBackendPid ( int  pid)

Definition at line 2458 of file procarray.c.

References BackendPidGetProc().

Referenced by pg_stat_get_subscription().

2459 {
2460  return (BackendPidGetProc(pid) != NULL);
2461 }
PGPROC * BackendPidGetProc(int pid)
Definition: procarray.c:2363

◆ KnownAssignedXidExists()

static bool KnownAssignedXidExists ( TransactionId  xid)
static

Definition at line 3680 of file procarray.c.

References Assert, KnownAssignedXidsSearch(), and TransactionIdIsValid.

Referenced by TransactionIdIsInProgress().

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

◆ KnownAssignedXidsAdd()

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

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

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

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

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

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

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

◆ KnownAssignedXidsGet()

static int KnownAssignedXidsGet ( TransactionId xarray,
TransactionId  xmax 
)
static

Definition at line 3819 of file procarray.c.

References InvalidTransactionId, and KnownAssignedXidsGetAndSetXmin().

Referenced by TransactionIdIsInProgress().

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

◆ KnownAssignedXidsGetAndSetXmin()

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

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

3835 {
3836  int count = 0;
3837  int head,
3838  tail;
3839  int i;
3840 
3841  /*
3842  * Fetch head just once, since it may change while we loop. We can stop
3843  * once we reach the initially seen head, since we are certain that an xid
3844  * cannot enter and then leave the array while we hold ProcArrayLock. We
3845  * might miss newly-added xids, but they should be >= xmax so irrelevant
3846  * anyway.
3847  *
3848  * Must take spinlock to ensure we see up-to-date array contents.
3849  */
3854 
3855  for (i = tail; i < head; i++)
3856  {
3857  /* Skip any gaps in the array */
3858  if (KnownAssignedXidsValid[i])
3859  {
3860  TransactionId knownXid = KnownAssignedXids[i];
3861 
3862  /*
3863  * Update xmin if required. Only the first XID need be checked,
3864  * since the array is sorted.
3865  */
3866  if (count == 0 &&
3867  TransactionIdPrecedes(knownXid, *xmin))
3868  *xmin = knownXid;
3869 
3870  /*
3871  * Filter out anything >= xmax, again relying on sorted property
3872  * of array.
3873  */
3874  if (TransactionIdIsValid(xmax) &&
3875  TransactionIdFollowsOrEquals(knownXid, xmax))
3876  break;
3877 
3878  /* Add knownXid into output array */
3879  xarray[count++] = knownXid;
3880  }
3881  }
3882 
3883  return count;
3884 }
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 3891 of file procarray.c.

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

Referenced by GetOldestXmin().

3892 {
3893  int head,
3894  tail;
3895  int i;
3896 
3897  /*
3898  * Fetch head just once, since it may change while we loop.
3899  */
3904 
3905  for (i = tail; i < head; i++)
3906  {
3907  /* Skip any gaps in the array */
3908  if (KnownAssignedXidsValid[i])
3909  return KnownAssignedXids[i];
3910  }
3911 
3912  return InvalidTransactionId;
3913 }
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 3693 of file procarray.c.

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

Referenced by KnownAssignedXidsRemoveTree().

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

◆ KnownAssignedXidsRemovePreceding()

static void KnownAssignedXidsRemovePreceding ( TransactionId  xid)
static

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

3742 {
3743  ProcArrayStruct *pArray = procArray;
3744  int count = 0;
3745  int head,
3746  tail,
3747  i;
3748 
3749  if (!TransactionIdIsValid(removeXid))
3750  {
3751  elog(trace_recovery(DEBUG4), "removing all KnownAssignedXids");
3752  pArray->numKnownAssignedXids = 0;
3753  pArray->headKnownAssignedXids = pArray->tailKnownAssignedXids = 0;
3754  return;
3755  }
3756 
3757  elog(trace_recovery(DEBUG4), "prune KnownAssignedXids to %u", removeXid);
3758 
3759  /*
3760  * Mark entries invalid starting at the tail. Since array is sorted, we
3761  * can stop as soon as we reach an entry >= removeXid.
3762  */
3763  tail = pArray->tailKnownAssignedXids;
3764  head = pArray->headKnownAssignedXids;
3765 
3766  for (i = tail; i < head; i++)
3767  {
3768  if (KnownAssignedXidsValid[i])
3769  {
3770  TransactionId knownXid = KnownAssignedXids[i];
3771 
3772  if (TransactionIdFollowsOrEquals(knownXid, removeXid))
3773  break;
3774 
3775  if (!StandbyTransactionIdIsPrepared(knownXid))
3776  {
3777  KnownAssignedXidsValid[i] = false;
3778  count++;
3779  }
3780  }
3781  }
3782 
3783  pArray->numKnownAssignedXids -= count;
3784  Assert(pArray->numKnownAssignedXids >= 0);
3785 
3786  /*
3787  * Advance the tail pointer if we've marked the tail item invalid.
3788  */
3789  for (i = tail; i < head; i++)
3790  {
3791  if (KnownAssignedXidsValid[i])
3792  break;
3793  }
3794  if (i >= head)
3795  {
3796  /* Array is empty, so we can reset both pointers */
3797  pArray->headKnownAssignedXids = 0;
3798  pArray->tailKnownAssignedXids = 0;
3799  }
3800  else
3801  {
3802  pArray->tailKnownAssignedXids = i;
3803  }
3804 
3805  /* Opportunistically compress the array */
3807 }
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:1426
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:3407
#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 3719 of file procarray.c.

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

Referenced by ExpireTreeKnownAssignedTransactionIds(), and ProcArrayApplyXidAssignment().

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

◆ KnownAssignedXidsReset()

static void KnownAssignedXidsReset ( void  )
static

Definition at line 3964 of file procarray.c.

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

Referenced by ProcArrayApplyRecoveryInfo().

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

◆ KnownAssignedXidsSearch()

static bool KnownAssignedXidsSearch ( TransactionId  xid,
bool  remove 
)
static

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

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

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

Referenced by XLogFlush().

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

◆ ProcArrayAdd()

void ProcArrayAdd ( PGPROC proc)

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

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

◆ ProcArrayApplyRecoveryInfo()

void ProcArrayApplyRecoveryInfo ( RunningTransactions  running)

Definition at line 662 of file procarray.c.

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

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

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

◆ ProcArrayApplyXidAssignment()

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

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

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

◆ ProcArrayClearTransaction()

void ProcArrayClearTransaction ( PGPROC proc)

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

600 {
601  PGXACT *pgxact = &allPgXact[proc->pgprocno];
602 
603  /*
604  * We can skip locking ProcArrayLock here, because this action does not
605  * actually change anyone's view of the set of running XIDs: our entry is
606  * duplicate with the gxact that has already been inserted into the
607  * ProcArray.
608  */
609  pgxact->xid = InvalidTransactionId;
611  pgxact->xmin = InvalidTransactionId;
612  proc->recoveryConflictPending = false;
613 
614  /* redundant, but just in case */
616  pgxact->delayChkpt = false;
617 
618  /* Clear the subtransaction-XID cache too */
619  pgxact->nxids = 0;
620  pgxact->overflowed = false;
621 }
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 396 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().

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

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

◆ ProcArrayGetReplicationSlotXmin()

void ProcArrayGetReplicationSlotXmin ( TransactionId xmin,
TransactionId catalog_xmin 
)

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

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

◆ ProcArrayGroupClearXid()

static void ProcArrayGroupClearXid ( PGPROC proc,
TransactionId  latestXid 
)
static

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

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

◆ ProcArrayInitRecovery()

void ProcArrayInitRecovery ( TransactionId  initializedUptoXID)

Definition at line 631 of file procarray.c.

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

Referenced by StartupXLOG().

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

◆ ProcArrayInstallImportedXmin()

bool ProcArrayInstallImportedXmin ( TransactionId  xmin,
VirtualTransactionId sourcevxid 
)

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

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

◆ ProcArrayInstallRestoredXmin()

bool ProcArrayInstallRestoredXmin ( TransactionId  xmin,
PGPROC proc 
)

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

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

◆ ProcArrayRemove()

void ProcArrayRemove ( PGPROC proc,
TransactionId  latestXid 
)

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

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

◆ ProcArraySetReplicationSlotXmin()

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

Definition at line 2981 of file procarray.c.

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

Referenced by ReplicationSlotsComputeRequiredXmin().

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

◆ ProcArrayShmemSize()

Size ProcArrayShmemSize ( void  )

Definition at line 180 of file procarray.c.

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

Referenced by CreateSharedMemoryAndSemaphores().

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

◆ RecordKnownAssignedTransactionIds()

void RecordKnownAssignedTransactionIds ( TransactionId  xid)

Definition at line 3196 of file procarray.c.

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

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

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

◆ TransactionIdIsActive()

bool TransactionIdIsActive ( TransactionId  xid)

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

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

◆ TransactionIdIsInProgress()

bool TransactionIdIsInProgress ( TransactionId  xid)

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

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

◆ XidCacheRemoveRunningXids()

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

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

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

Variable Documentation

◆ allPgXact

PGXACT* allPgXact
static

Definition at line 102 of file procarray.c.

◆ allProcs

PGPROC* allProcs
static

Definition at line 101 of file procarray.c.

◆ KnownAssignedXids

◆ KnownAssignedXidsValid

◆ latestObservedXid

◆ procArray

◆ standbySnapshotPendingXmin

TransactionId standbySnapshotPendingXmin
static

Definition at line 116 of file procarray.c.

Referenced by ProcArrayApplyRecoveryInfo().