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 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

◆ xc_by_child_xid_inc

#define xc_by_child_xid_inc ( )    ((void) 0)

Definition at line 148 of file procarray.c.

Referenced by TransactionIdIsInProgress().

◆ xc_by_known_assigned_inc

#define xc_by_known_assigned_inc ( )    ((void) 0)

Definition at line 149 of file procarray.c.

Referenced by TransactionIdIsInProgress().

◆ xc_by_known_xact_inc

#define xc_by_known_xact_inc ( )    ((void) 0)

Definition at line 144 of file procarray.c.

Referenced by TransactionIdIsInProgress().

◆ xc_by_latest_xid_inc

#define xc_by_latest_xid_inc ( )    ((void) 0)

Definition at line 146 of file procarray.c.

Referenced by TransactionIdIsInProgress().

◆ xc_by_main_xid_inc

#define xc_by_main_xid_inc ( )    ((void) 0)

Definition at line 147 of file procarray.c.

Referenced by TransactionIdIsInProgress().

◆ xc_by_my_xact_inc

#define xc_by_my_xact_inc ( )    ((void) 0)

Definition at line 145 of file procarray.c.

Referenced by TransactionIdIsInProgress().

◆ xc_by_recent_xmin_inc

#define xc_by_recent_xmin_inc ( )    ((void) 0)

Definition at line 143 of file procarray.c.

Referenced by TransactionIdIsInProgress().

◆ xc_no_overflow_inc

#define xc_no_overflow_inc ( )    ((void) 0)

Definition at line 150 of file procarray.c.

Referenced by TransactionIdIsInProgress().

◆ xc_slow_answer_inc

#define xc_slow_answer_inc ( )    ((void) 0)

Definition at line 151 of file procarray.c.

Referenced by TransactionIdIsInProgress().

◆ XidCacheRemove

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

Definition at line 3009 of file procarray.c.

Referenced by XidCacheRemoveRunningXids().

Typedef Documentation

◆ ProcArrayStruct

Function Documentation

◆ BackendPidGetProc()

PGPROC* BackendPidGetProc ( int  pid)

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

2355 {
2356  PGPROC *result;
2357 
2358  if (pid == 0) /* never match dummy PGPROCs */
2359  return NULL;
2360 
2361  LWLockAcquire(ProcArrayLock, LW_SHARED);
2362 
2363  result = BackendPidGetProcWithLock(pid);
2364 
2365  LWLockRelease(ProcArrayLock);
2366 
2367  return result;
2368 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
PGPROC * BackendPidGetProcWithLock(int pid)
Definition: procarray.c:2377
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121
Definition: proc.h:95

◆ BackendPidGetProcWithLock()

PGPROC* BackendPidGetProcWithLock ( int  pid)

Definition at line 2377 of file procarray.c.

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

Referenced by BackendPidGetProc(), and GetBlockerStatusData().

2378 {
2379  PGPROC *result = NULL;
2380  ProcArrayStruct *arrayP = procArray;
2381  int index;
2382 
2383  if (pid == 0) /* never match dummy PGPROCs */
2384  return NULL;
2385 
2386  for (index = 0; index < arrayP->numProcs; index++)
2387  {
2388  PGPROC *proc = &allProcs[arrayP->pgprocnos[index]];
2389 
2390  if (proc->pid == pid)
2391  {
2392  result = proc;
2393  break;
2394  }
2395  }
2396 
2397  return result;
2398 }
Definition: type.h:89
static PGPROC * allProcs
Definition: procarray.c:100
static ProcArrayStruct * procArray
Definition: procarray.c:98
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:95
Definition: proc.h:95
int pid
Definition: proc.h:109

◆ BackendXidGetPid()

int BackendXidGetPid ( TransactionId  xid)

Definition at line 2414 of file procarray.c.

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

Referenced by pgrowlocks().

2415 {
2416  int result = 0;
2417  ProcArrayStruct *arrayP = procArray;
2418  int index;
2419 
2420  if (xid == InvalidTransactionId) /* never match invalid xid */
2421  return 0;
2422 
2423  LWLockAcquire(ProcArrayLock, LW_SHARED);
2424 
2425  for (index = 0; index < arrayP->numProcs; index++)
2426  {
2427  int pgprocno = arrayP->pgprocnos[index];
2428  volatile PGPROC *proc = &allProcs[pgprocno];
2429  volatile PGXACT *pgxact = &allPgXact[pgprocno];
2430 
2431  if (pgxact->xid == xid)
2432  {
2433  result = proc->pid;
2434  break;
2435  }
2436  }
2437 
2438  LWLockRelease(ProcArrayLock);
2439 
2440  return result;
2441 }
Definition: proc.h:222
TransactionId xid
Definition: proc.h:224
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
#define InvalidTransactionId
Definition: transam.h:31
static PGPROC * allProcs
Definition: procarray.c:100
static ProcArrayStruct * procArray
Definition: procarray.c:98
static PGXACT * allPgXact
Definition: procarray.c:101
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:95
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121
Definition: proc.h:95
int pid
Definition: proc.h:109

◆ CancelDBBackends()

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

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

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

◆ CancelVirtualTransaction()

pid_t CancelVirtualTransaction ( VirtualTransactionId  vxid,
ProcSignalReason  sigmode 
)

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

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

◆ CountDBBackends()

int CountDBBackends ( Oid  databaseid)

Definition at line 2747 of file procarray.c.

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

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

2748 {
2749  ProcArrayStruct *arrayP = procArray;
2750  int count = 0;
2751  int index;
2752 
2753  LWLockAcquire(ProcArrayLock, LW_SHARED);
2754 
2755  for (index = 0; index < arrayP->numProcs; index++)
2756  {
2757  int pgprocno = arrayP->pgprocnos[index];
2758  volatile PGPROC *proc = &allProcs[pgprocno];
2759 
2760  if (proc->pid == 0)
2761  continue; /* do not count prepared xacts */
2762  if (!OidIsValid(databaseid) ||
2763  proc->databaseId == databaseid)
2764  count++;
2765  }
2766 
2767  LWLockRelease(ProcArrayLock);
2768 
2769  return count;
2770 }
#define OidIsValid(objectId)
Definition: c.h:605
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
static PGPROC * allProcs
Definition: procarray.c:100
Oid databaseId
Definition: proc.h:114
static ProcArrayStruct * procArray
Definition: procarray.c:98
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:95
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121
Definition: proc.h:95
int pid
Definition: proc.h:109

◆ CountDBConnections()

int CountDBConnections ( Oid  databaseid)

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

2778 {
2779  ProcArrayStruct *arrayP = procArray;
2780  int count = 0;
2781  int index;
2782 
2783  LWLockAcquire(ProcArrayLock, LW_SHARED);
2784 
2785  for (index = 0; index < arrayP->numProcs; index++)
2786  {
2787  int pgprocno = arrayP->pgprocnos[index];
2788  volatile PGPROC *proc = &allProcs[pgprocno];
2789 
2790  if (proc->pid == 0)
2791  continue; /* do not count prepared xacts */
2792  if (proc->isBackgroundWorker)
2793  continue; /* do not count background workers */
2794  if (!OidIsValid(databaseid) ||
2795  proc->databaseId == databaseid)
2796  count++;
2797  }
2798 
2799  LWLockRelease(ProcArrayLock);
2800 
2801  return count;
2802 }
#define OidIsValid(objectId)
Definition: c.h:605
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
bool isBackgroundWorker
Definition: proc.h:120
static PGPROC * allProcs
Definition: procarray.c:100
Oid databaseId
Definition: proc.h:114
static ProcArrayStruct * procArray
Definition: procarray.c:98
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:95
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121
Definition: proc.h:95
int pid
Definition: proc.h:109

◆ CountOtherDBBackends()

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

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

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

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

Referenced by InitializeSessionUserId().

2849 {
2850  ProcArrayStruct *arrayP = procArray;
2851  int count = 0;
2852  int index;
2853 
2854  LWLockAcquire(ProcArrayLock, LW_SHARED);
2855 
2856  for (index = 0; index < arrayP->numProcs; index++)
2857  {
2858  int pgprocno = arrayP->pgprocnos[index];
2859  volatile PGPROC *proc = &allProcs[pgprocno];
2860 
2861  if (proc->pid == 0)
2862  continue; /* do not count prepared xacts */
2863  if (proc->isBackgroundWorker)
2864  continue; /* do not count background workers */
2865  if (proc->roleId == roleid)
2866  count++;
2867  }
2868 
2869  LWLockRelease(ProcArrayLock);
2870 
2871  return count;
2872 }
Oid roleId
Definition: proc.h:115
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
bool isBackgroundWorker
Definition: proc.h:120
static PGPROC * allProcs
Definition: procarray.c:100
static ProcArrayStruct * procArray
Definition: procarray.c:98
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:95
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121
Definition: proc.h:95
int pid
Definition: proc.h:109

◆ CreateSharedProcArray()

void CreateSharedProcArray ( void  )

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

222 {
223  bool found;
224 
225  /* Create or attach to the ProcArray shared structure */
227  ShmemInitStruct("Proc Array",
228  add_size(offsetof(ProcArrayStruct, pgprocnos),
229  mul_size(sizeof(int),
231  &found);
232 
233  if (!found)
234  {
235  /*
236  * We're the first - initialize.
237  */
238  procArray->numProcs = 0;
248  }
249 
252 
253  /* Create or attach to the KnownAssignedXids arrays too, if needed */
254  if (EnableHotStandby)
255  {
257  ShmemInitStruct("KnownAssignedXids",
258  mul_size(sizeof(TransactionId),
260  &found);
261  KnownAssignedXidsValid = (bool *)
262  ShmemInitStruct("KnownAssignedXidsValid",
263  mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS),
264  &found);
265  }
266 
267  /* Register and initialize fields of ProcLWLockTranche */
269 }
#define PROCARRAY_MAXPROCS
uint32 TransactionId
Definition: c.h:474
PGXACT * allPgXact
Definition: proc.h:249
#define SpinLockInit(lock)
Definition: spin.h:60
TransactionId replication_slot_catalog_xmin
Definition: procarray.c:92
slock_t known_assigned_xids_lck
Definition: procarray.c:78
PROC_HDR * ProcGlobal
Definition: proc.c:80
void LWLockRegisterTranche(int tranche_id, const char *tranche_name)
Definition: lwlock.c:602
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition: shmem.c:372
int maxKnownAssignedXids
Definition: procarray.c:74
#define InvalidTransactionId
Definition: transam.h:31
static PGPROC * allProcs
Definition: procarray.c:100
int numKnownAssignedXids
Definition: procarray.c:75
static bool * KnownAssignedXidsValid
Definition: procarray.c:107
TransactionId lastOverflowedXid
Definition: procarray.c:87
static ProcArrayStruct * procArray
Definition: procarray.c:98
TransactionId replication_slot_xmin
Definition: procarray.c:90
Size mul_size(Size s1, Size s2)
Definition: shmem.c:492
static PGXACT * allPgXact
Definition: procarray.c:101
Size add_size(Size s1, Size s2)
Definition: shmem.c:475
#define TOTAL_MAX_CACHED_SUBXIDS
static TransactionId * KnownAssignedXids
Definition: procarray.c:106
bool EnableHotStandby
Definition: xlog.c:96
PGPROC * allProcs
Definition: proc.h:247
int tailKnownAssignedXids
Definition: procarray.c:76
#define offsetof(type, field)
Definition: c.h:622
int headKnownAssignedXids
Definition: procarray.c:77

◆ ExpireAllKnownAssignedTransactionIds()

void ExpireAllKnownAssignedTransactionIds ( void  )

Definition at line 3279 of file procarray.c.

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

Referenced by ShutdownRecoveryTransactionEnvironment().

3280 {
3281  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3283  LWLockRelease(ProcArrayLock);
3284 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
static void KnownAssignedXidsRemovePreceding(TransactionId xid)
Definition: procarray.c:3731
#define InvalidTransactionId
Definition: transam.h:31
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121

◆ ExpireOldKnownAssignedTransactionIds()

void ExpireOldKnownAssignedTransactionIds ( TransactionId  xid)

Definition at line 3291 of file procarray.c.

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

Referenced by ProcArrayApplyRecoveryInfo().

3292 {
3293  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3295  LWLockRelease(ProcArrayLock);
3296 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
static void KnownAssignedXidsRemovePreceding(TransactionId xid)
Definition: procarray.c:3731
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121

◆ ExpireTreeKnownAssignedTransactionIds()

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

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

3256 {
3258 
3259  /*
3260  * Uses same locking as transaction commit
3261  */
3262  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3263 
3264  KnownAssignedXidsRemoveTree(xid, nsubxids, subxids);
3265 
3266  /* As in ProcArrayEndTransaction, advance latestCompletedXid */
3268  max_xid))
3270 
3271  LWLockRelease(ProcArrayLock);
3272 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
VariableCache ShmemVariableCache
Definition: varsup.c:34
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
static void KnownAssignedXidsRemoveTree(TransactionId xid, int nsubxids, TransactionId *subxids)
Definition: procarray.c:3709
#define Assert(condition)
Definition: c.h:699
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121
HotStandbyState standbyState
Definition: xlog.c:197
TransactionId latestCompletedXid
Definition: transam.h:135

◆ GetConflictingVirtualXIDs()

VirtualTransactionId* GetConflictingVirtualXIDs ( TransactionId  limitXmin,
Oid  dbOid 
)

Definition at line 2570 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, VirtualTransactionIdIsValid, and PGXACT::xmin.

Referenced by ResolveRecoveryConflictWithSnapshot(), and ResolveRecoveryConflictWithTablespace().

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

Referenced by DefineIndex().

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

◆ GetMaxSnapshotSubxidCount()

int GetMaxSnapshotSubxidCount ( void  )

Definition at line 1464 of file procarray.c.

References TOTAL_MAX_CACHED_SUBXIDS.

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

1465 {
1466  return TOTAL_MAX_CACHED_SUBXIDS;
1467 }
#define TOTAL_MAX_CACHED_SUBXIDS

◆ GetMaxSnapshotXidCount()

int GetMaxSnapshotXidCount ( void  )

Definition at line 1453 of file procarray.c.

References ProcArrayStruct::maxProcs.

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

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

◆ GetOldestActiveTransactionId()

TransactionId GetOldestActiveTransactionId ( void  )

Definition at line 2100 of file procarray.c.

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

Referenced by CreateCheckPoint().

2101 {
2102  ProcArrayStruct *arrayP = procArray;
2103  TransactionId oldestRunningXid;
2104  int index;
2105 
2107 
2108  /*
2109  * Read nextXid, as the upper bound of what's still active.
2110  *
2111  * Reading a TransactionId is atomic, but we must grab the lock to make
2112  * sure that all XIDs < nextXid are already present in the proc array (or
2113  * have already completed), when we spin over it.
2114  */
2115  LWLockAcquire(XidGenLock, LW_SHARED);
2116  oldestRunningXid = ShmemVariableCache->nextXid;
2117  LWLockRelease(XidGenLock);
2118 
2119  /*
2120  * Spin over procArray collecting all xids and subxids.
2121  */
2122  LWLockAcquire(ProcArrayLock, LW_SHARED);
2123  for (index = 0; index < arrayP->numProcs; index++)
2124  {
2125  int pgprocno = arrayP->pgprocnos[index];
2126  volatile PGXACT *pgxact = &allPgXact[pgprocno];
2127  TransactionId xid;
2128 
2129  /* Fetch xid just once - see GetNewTransactionId */
2130  xid = pgxact->xid;
2131 
2132  if (!TransactionIdIsNormal(xid))
2133  continue;
2134 
2135  if (TransactionIdPrecedes(xid, oldestRunningXid))
2136  oldestRunningXid = xid;
2137 
2138  /*
2139  * Top-level XID of a transaction is always less than any of its
2140  * subxids, so we don't need to check if any of the subxids are
2141  * smaller than oldestRunningXid
2142  */
2143  }
2144  LWLockRelease(ProcArrayLock);
2145 
2146  return oldestRunningXid;
2147 }
uint32 TransactionId
Definition: c.h:474
Definition: proc.h:222
TransactionId xid
Definition: proc.h:224
bool RecoveryInProgress(void)
Definition: xlog.c:8057
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
TransactionId nextXid
Definition: transam.h:117
VariableCache ShmemVariableCache
Definition: varsup.c:34
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
static ProcArrayStruct * procArray
Definition: procarray.c:98
static PGXACT * allPgXact
Definition: procarray.c:101
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:95
#define Assert(condition)
Definition: c.h:699
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121
#define TransactionIdIsNormal(xid)
Definition: transam.h:42

◆ GetOldestSafeDecodingTransactionId()

TransactionId GetOldestSafeDecodingTransactionId ( bool  catalogOnly)

Definition at line 2166 of file procarray.c.

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

Referenced by CreateInitDecodingContext(), and SnapBuildInitialSnapshot().

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

◆ GetOldestXmin()

TransactionId GetOldestXmin ( Relation  rel,
int  flags 
)

Definition at line 1312 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(), vacuum_defer_cleanup_age, PGXACT::vacuumFlags, PGXACT::xid, and PGXACT::xmin.

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

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

◆ GetRunningTransactionData()

RunningTransactions GetRunningTransactionData ( void  )

Definition at line 1929 of file procarray.c.

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

Referenced by LogStandbySnapshot().

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

◆ GetSnapshotData()

Snapshot GetSnapshotData ( Snapshot  snapshot)

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

1507 {
1508  ProcArrayStruct *arrayP = procArray;
1509  TransactionId xmin;
1510  TransactionId xmax;
1511  TransactionId globalxmin;
1512  int index;
1513  int count = 0;
1514  int subcount = 0;
1515  bool suboverflowed = false;
1516  volatile TransactionId replication_slot_xmin = InvalidTransactionId;
1517  volatile TransactionId replication_slot_catalog_xmin = InvalidTransactionId;
1518 
1519  Assert(snapshot != NULL);
1520 
1521  /*
1522  * Allocating space for maxProcs xids is usually overkill; numProcs would
1523  * be sufficient. But it seems better to do the malloc while not holding
1524  * the lock, so we can't look at numProcs. Likewise, we allocate much
1525  * more subxip storage than is probably needed.
1526  *
1527  * This does open a possibility for avoiding repeated malloc/free: since
1528  * maxProcs does not change at runtime, we can simply reuse the previous
1529  * xip arrays if any. (This relies on the fact that all callers pass
1530  * static SnapshotData structs.)
1531  */
1532  if (snapshot->xip == NULL)
1533  {
1534  /*
1535  * First call for this snapshot. Snapshot is same size whether or not
1536  * we are in recovery, see later comments.
1537  */
1538  snapshot->xip = (TransactionId *)
1540  if (snapshot->xip == NULL)
1541  ereport(ERROR,
1542  (errcode(ERRCODE_OUT_OF_MEMORY),
1543  errmsg("out of memory")));
1544  Assert(snapshot->subxip == NULL);
1545  snapshot->subxip = (TransactionId *)
1547  if (snapshot->subxip == NULL)
1548  ereport(ERROR,
1549  (errcode(ERRCODE_OUT_OF_MEMORY),
1550  errmsg("out of memory")));
1551  }
1552 
1553  /*
1554  * It is sufficient to get shared lock on ProcArrayLock, even if we are
1555  * going to set MyPgXact->xmin.
1556  */
1557  LWLockAcquire(ProcArrayLock, LW_SHARED);
1558 
1559  /* xmax is always latestCompletedXid + 1 */
1562  TransactionIdAdvance(xmax);
1563 
1564  /* initialize xmin calculation with xmax */
1565  globalxmin = xmin = xmax;
1566 
1568 
1569  if (!snapshot->takenDuringRecovery)
1570  {
1571  int *pgprocnos = arrayP->pgprocnos;
1572  int numProcs;
1573 
1574  /*
1575  * Spin over procArray checking xid, xmin, and subxids. The goal is
1576  * to gather all active xids, find the lowest xmin, and try to record
1577  * subxids.
1578  */
1579  numProcs = arrayP->numProcs;
1580  for (index = 0; index < numProcs; index++)
1581  {
1582  int pgprocno = pgprocnos[index];
1583  volatile PGXACT *pgxact = &allPgXact[pgprocno];
1584  TransactionId xid;
1585 
1586  /*
1587  * Backend is doing logical decoding which manages xmin
1588  * separately, check below.
1589  */
1590  if (pgxact->vacuumFlags & PROC_IN_LOGICAL_DECODING)
1591  continue;
1592 
1593  /* Ignore procs running LAZY VACUUM */
1594  if (pgxact->vacuumFlags & PROC_IN_VACUUM)
1595  continue;
1596 
1597  /* Update globalxmin to be the smallest valid xmin */
1598  xid = pgxact->xmin; /* fetch just once */
1599  if (TransactionIdIsNormal(xid) &&
1600  NormalTransactionIdPrecedes(xid, globalxmin))
1601  globalxmin = xid;
1602 
1603  /* Fetch xid just once - see GetNewTransactionId */
1604  xid = pgxact->xid;
1605 
1606  /*
1607  * If the transaction has no XID assigned, we can skip it; it
1608  * won't have sub-XIDs either. If the XID is >= xmax, we can also
1609  * skip it; such transactions will be treated as running anyway
1610  * (and any sub-XIDs will also be >= xmax).
1611  */
1612  if (!TransactionIdIsNormal(xid)
1613  || !NormalTransactionIdPrecedes(xid, xmax))
1614  continue;
1615 
1616  /*
1617  * We don't include our own XIDs (if any) in the snapshot, but we
1618  * must include them in xmin.
1619  */
1620  if (NormalTransactionIdPrecedes(xid, xmin))
1621  xmin = xid;
1622  if (pgxact == MyPgXact)
1623  continue;
1624 
1625  /* Add XID to snapshot. */
1626  snapshot->xip[count++] = xid;
1627 
1628  /*
1629  * Save subtransaction XIDs if possible (if we've already
1630  * overflowed, there's no point). Note that the subxact XIDs must
1631  * be later than their parent, so no need to check them against
1632  * xmin. We could filter against xmax, but it seems better not to
1633  * do that much work while holding the ProcArrayLock.
1634  *
1635  * The other backend can add more subxids concurrently, but cannot
1636  * remove any. Hence it's important to fetch nxids just once.
1637  * Should be safe to use memcpy, though. (We needn't worry about
1638  * missing any xids added concurrently, because they must postdate
1639  * xmax.)
1640  *
1641  * Again, our own XIDs are not included in the snapshot.
1642  */
1643  if (!suboverflowed)
1644  {
1645  if (pgxact->overflowed)
1646  suboverflowed = true;
1647  else
1648  {
1649  int nxids = pgxact->nxids;
1650 
1651  if (nxids > 0)
1652  {
1653  volatile PGPROC *proc = &allProcs[pgprocno];
1654 
1655  memcpy(snapshot->subxip + subcount,
1656  (void *) proc->subxids.xids,
1657  nxids * sizeof(TransactionId));
1658  subcount += nxids;
1659  }
1660  }
1661  }
1662  }
1663  }
1664  else
1665  {
1666  /*
1667  * We're in hot standby, so get XIDs from KnownAssignedXids.
1668  *
1669  * We store all xids directly into subxip[]. Here's why:
1670  *
1671  * In recovery we don't know which xids are top-level and which are
1672  * subxacts, a design choice that greatly simplifies xid processing.
1673  *
1674  * It seems like we would want to try to put xids into xip[] only, but
1675  * that is fairly small. We would either need to make that bigger or
1676  * to increase the rate at which we WAL-log xid assignment; neither is
1677  * an appealing choice.
1678  *
1679  * We could try to store xids into xip[] first and then into subxip[]
1680  * if there are too many xids. That only works if the snapshot doesn't
1681  * overflow because we do not search subxip[] in that case. A simpler
1682  * way is to just store all xids in the subxact array because this is
1683  * by far the bigger array. We just leave the xip array empty.
1684  *
1685  * Either way we need to change the way XidInMVCCSnapshot() works
1686  * depending upon when the snapshot was taken, or change normal
1687  * snapshot processing so it matches.
1688  *
1689  * Note: It is possible for recovery to end before we finish taking
1690  * the snapshot, and for newly assigned transaction ids to be added to
1691  * the ProcArray. xmax cannot change while we hold ProcArrayLock, so
1692  * those newly added transaction ids would be filtered away, so we
1693  * need not be concerned about them.
1694  */
1695  subcount = KnownAssignedXidsGetAndSetXmin(snapshot->subxip, &xmin,
1696  xmax);
1697 
1699  suboverflowed = true;
1700  }
1701 
1702 
1703  /* fetch into volatile var while ProcArrayLock is held */
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:48
#define InvalidXLogRecPtr
Definition: xlogdefs.h:28
#define PROC_IN_LOGICAL_DECODING
Definition: proc.h:57
uint32 TransactionId
Definition: c.h:474
bool copied
Definition: snapshot.h:96
Definition: proc.h:222
TransactionId xmin
Definition: proc.h:228
TransactionId xid
Definition: proc.h:224
int vacuum_defer_cleanup_age
Definition: standby.c:39
TransactionId replication_slot_catalog_xmin
Definition: procarray.c:92
XLogRecPtr lsn
Definition: snapshot.h:114
int errcode(int sqlerrcode)
Definition: elog.c:575
TransactionId RecentXmin
Definition: snapmgr.c:165
bool suboverflowed
Definition: snapshot.h:93
bool RecoveryInProgress(void)
Definition: xlog.c:8057
uint32 regd_count
Definition: snapshot.h:110
PGXACT * MyPgXact
Definition: proc.c:68
uint8 vacuumFlags
Definition: proc.h:233
TransactionId TransactionXmin
Definition: snapmgr.c:164
Definition: type.h:89
#define malloc(a)
Definition: header.h:50
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
#define PROC_IN_VACUUM
Definition: proc.h:54
bool TransactionIdPrecedesOrEquals(TransactionId id1, TransactionId id2)
Definition: transam.c:319
#define FirstNormalTransactionId
Definition: transam.h:34
#define ERROR
Definition: elog.h:43
TimestampTz GetSnapshotCurrentTimestamp(void)
Definition: snapmgr.c:1686
XLogRecPtr GetXLogInsertRecPtr(void)
Definition: xlog.c:11334
TransactionId RecentGlobalXmin
Definition: snapmgr.c:166
uint8 nxids
Definition: proc.h:238
VariableCache ShmemVariableCache
Definition: varsup.c:34
#define InvalidTransactionId
Definition: transam.h:31
static PGPROC * allProcs
Definition: procarray.c:100
TransactionId xmax
Definition: snapshot.h:69
TransactionId xmin
Definition: snapshot.h:68
TransactionId RecentGlobalDataXmin
Definition: snapmgr.c:167
struct XidCache subxids
Definition: proc.h:162
TransactionId lastOverflowedXid
Definition: procarray.c:87
#define ereport(elevel, rest)
Definition: elog.h:141
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
TransactionId * xip
Definition: snapshot.h:79
static ProcArrayStruct * procArray
Definition: procarray.c:98
TransactionId replication_slot_xmin
Definition: procarray.c:90
static PGXACT * allPgXact
Definition: procarray.c:101
bool overflowed
Definition: proc.h:234
CommandId curcid
Definition: snapshot.h:98
int GetMaxSnapshotXidCount(void)
Definition: procarray.c:1453
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:95
TransactionId xids[PGPROC_MAX_CACHED_SUBXIDS]
Definition: proc.h:40
#define Assert(condition)
Definition: c.h:699
bool takenDuringRecovery
Definition: snapshot.h:95
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121
static int KnownAssignedXidsGetAndSetXmin(TransactionId *xarray, TransactionId *xmin, TransactionId xmax)
Definition: procarray.c:3824
#define NormalTransactionIdPrecedes(id1, id2)
Definition: transam.h:62
uint32 xcnt
Definition: snapshot.h:80
int errmsg(const char *fmt,...)
Definition: elog.c:797
int old_snapshot_threshold
Definition: snapmgr.c:75
int GetMaxSnapshotSubxidCount(void)
Definition: procarray.c:1464
TimestampTz whenTaken
Definition: snapshot.h:113
CommandId GetCurrentCommandId(bool used)
Definition: xact.c:679
#define TransactionIdIsValid(xid)
Definition: transam.h:41
void MaintainOldSnapshotTimeMapping(TimestampTz whenTaken, TransactionId xmin)
Definition: snapmgr.c:1848
#define TransactionIdIsNormal(xid)
Definition: transam.h:42
Definition: proc.h:95
TransactionId * subxip
Definition: snapshot.h:91
uint32 active_count
Definition: snapshot.h:109
int32 subxcnt
Definition: snapshot.h:92
TransactionId latestCompletedXid
Definition: transam.h:135

◆ GetVirtualXIDsDelayingChkpt()

VirtualTransactionId* GetVirtualXIDsDelayingChkpt ( int *  nvxids)

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

2263 {
2264  VirtualTransactionId *vxids;
2265  ProcArrayStruct *arrayP = procArray;
2266  int count = 0;
2267  int index;
2268 
2269  /* allocate what's certainly enough result space */
2270  vxids = (VirtualTransactionId *)
2271  palloc(sizeof(VirtualTransactionId) * arrayP->maxProcs);
2272 
2273  LWLockAcquire(ProcArrayLock, LW_SHARED);
2274 
2275  for (index = 0; index < arrayP->numProcs; index++)
2276  {
2277  int pgprocno = arrayP->pgprocnos[index];
2278  volatile PGPROC *proc = &allProcs[pgprocno];
2279  volatile PGXACT *pgxact = &allPgXact[pgprocno];
2280 
2281  if (pgxact->delayChkpt)
2282  {
2283  VirtualTransactionId vxid;
2284 
2285  GET_VXID_FROM_PGPROC(vxid, *proc);
2286  if (VirtualTransactionIdIsValid(vxid))
2287  vxids[count++] = vxid;
2288  }
2289  }
2290 
2291  LWLockRelease(ProcArrayLock);
2292 
2293  *nvxids = count;
2294  return vxids;
2295 }
#define GET_VXID_FROM_PGPROC(vxid, proc)
Definition: lock.h:80
Definition: proc.h:222
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
static PGPROC * allProcs
Definition: procarray.c:100
bool delayChkpt
Definition: proc.h:235
static ProcArrayStruct * procArray
Definition: procarray.c:98
#define VirtualTransactionIdIsValid(vxid)
Definition: lock.h:71
static PGXACT * allPgXact
Definition: procarray.c:101
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:95
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121
void * palloc(Size size)
Definition: mcxt.c:924
Definition: proc.h:95

◆ HaveVirtualXIDsDelayingChkpt()

bool HaveVirtualXIDsDelayingChkpt ( VirtualTransactionId vxids,
int  nvxids 
)

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

2308 {
2309  bool result = false;
2310  ProcArrayStruct *arrayP = procArray;
2311  int index;
2312 
2313  LWLockAcquire(ProcArrayLock, LW_SHARED);
2314 
2315  for (index = 0; index < arrayP->numProcs; index++)
2316  {
2317  int pgprocno = arrayP->pgprocnos[index];
2318  volatile PGPROC *proc = &allProcs[pgprocno];
2319  volatile PGXACT *pgxact = &allPgXact[pgprocno];
2320  VirtualTransactionId vxid;
2321 
2322  GET_VXID_FROM_PGPROC(vxid, *proc);
2323 
2324  if (pgxact->delayChkpt && VirtualTransactionIdIsValid(vxid))
2325  {
2326  int i;
2327 
2328  for (i = 0; i < nvxids; i++)
2329  {
2330  if (VirtualTransactionIdEquals(vxid, vxids[i]))
2331  {
2332  result = true;
2333  break;
2334  }
2335  }
2336  if (result)
2337  break;
2338  }
2339  }
2340 
2341  LWLockRelease(ProcArrayLock);
2342 
2343  return result;
2344 }
#define GET_VXID_FROM_PGPROC(vxid, proc)
Definition: lock.h:80
Definition: proc.h:222
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
#define VirtualTransactionIdEquals(vxid1, vxid2)
Definition: lock.h:74
static PGPROC * allProcs
Definition: procarray.c:100
bool delayChkpt
Definition: proc.h:235
static ProcArrayStruct * procArray
Definition: procarray.c:98
#define VirtualTransactionIdIsValid(vxid)
Definition: lock.h:71
static PGXACT * allPgXact
Definition: procarray.c:101
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:95
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121
int i
Definition: proc.h:95

◆ IsBackendPid()

bool IsBackendPid ( int  pid)

Definition at line 2449 of file procarray.c.

References BackendPidGetProc().

Referenced by pg_stat_get_subscription().

2450 {
2451  return (BackendPidGetProc(pid) != NULL);
2452 }
PGPROC * BackendPidGetProc(int pid)
Definition: procarray.c:2354

◆ KnownAssignedXidExists()

static bool KnownAssignedXidExists ( TransactionId  xid)
static

Definition at line 3670 of file procarray.c.

References Assert, KnownAssignedXidsSearch(), and TransactionIdIsValid.

Referenced by TransactionIdIsInProgress().

3671 {
3673 
3674  return KnownAssignedXidsSearch(xid, false);
3675 }
#define Assert(condition)
Definition: c.h:699
static bool KnownAssignedXidsSearch(TransactionId xid, bool remove)
Definition: procarray.c:3576
#define TransactionIdIsValid(xid)
Definition: transam.h:41

◆ KnownAssignedXidsAdd()

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

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

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

◆ KnownAssignedXidsCompress()

static void KnownAssignedXidsCompress ( bool  force)
static

Definition at line 3394 of file procarray.c.

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

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

3395 {
3396  /* use volatile pointer to prevent code rearrangement */
3397  volatile ProcArrayStruct *pArray = procArray;
3398  int head,
3399  tail;
3400  int compress_index;
3401  int i;
3402 
3403  /* no spinlock required since we hold ProcArrayLock exclusively */
3404  head = pArray->headKnownAssignedXids;
3405  tail = pArray->tailKnownAssignedXids;
3406 
3407  if (!force)
3408  {
3409  /*
3410  * If we can choose how much to compress, use a heuristic to avoid
3411  * compressing too often or not often enough.
3412  *
3413  * Heuristic is if we have a large enough current spread and less than
3414  * 50% of the elements are currently in use, then compress. This
3415  * should ensure we compress fairly infrequently. We could compress
3416  * less often though the virtual array would spread out more and
3417  * snapshots would become more expensive.
3418  */
3419  int nelements = head - tail;
3420 
3421  if (nelements < 4 * PROCARRAY_MAXPROCS ||
3422  nelements < 2 * pArray->numKnownAssignedXids)
3423  return;
3424  }
3425 
3426  /*
3427  * We compress the array by reading the valid values from tail to head,
3428  * re-aligning data to 0th element.
3429  */
3430  compress_index = 0;
3431  for (i = tail; i < head; i++)
3432  {
3433  if (KnownAssignedXidsValid[i])
3434  {
3435  KnownAssignedXids[compress_index] = KnownAssignedXids[i];
3436  KnownAssignedXidsValid[compress_index] = true;
3437  compress_index++;
3438  }
3439  }
3440 
3441  pArray->tailKnownAssignedXids = 0;
3442  pArray->headKnownAssignedXids = compress_index;
3443 }
#define PROCARRAY_MAXPROCS
static bool * KnownAssignedXidsValid
Definition: procarray.c:107
static ProcArrayStruct * procArray
Definition: procarray.c:98
static TransactionId * KnownAssignedXids
Definition: procarray.c:106
int i
int tailKnownAssignedXids
Definition: procarray.c:76
int headKnownAssignedXids
Definition: procarray.c:77

◆ KnownAssignedXidsDisplay()

static void KnownAssignedXidsDisplay ( int  trace_level)
static

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

3918 {
3919  /* use volatile pointer to prevent code rearrangement */
3920  volatile ProcArrayStruct *pArray = procArray;
3922  int head,
3923  tail,
3924  i;
3925  int nxids = 0;
3926 
3927  tail = pArray->tailKnownAssignedXids;
3928  head = pArray->headKnownAssignedXids;
3929 
3930  initStringInfo(&buf);
3931 
3932  for (i = tail; i < head; i++)
3933  {
3934  if (KnownAssignedXidsValid[i])
3935  {
3936  nxids++;
3937  appendStringInfo(&buf, "[%d]=%u ", i, KnownAssignedXids[i]);
3938  }
3939  }
3940 
3941  elog(trace_level, "%d KnownAssignedXids (num=%d tail=%d head=%d) %s",
3942  nxids,
3943  pArray->numKnownAssignedXids,
3944  pArray->tailKnownAssignedXids,
3945  pArray->headKnownAssignedXids,
3946  buf.data);
3947 
3948  pfree(buf.data);
3949 }
void pfree(void *pointer)
Definition: mcxt.c:1031
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
static char * buf
Definition: pg_test_fsync.c:67
int numKnownAssignedXids
Definition: procarray.c:75
static bool * KnownAssignedXidsValid
Definition: procarray.c:107
void initStringInfo(StringInfo str)
Definition: stringinfo.c:46
static ProcArrayStruct * procArray
Definition: procarray.c:98
static TransactionId * KnownAssignedXids
Definition: procarray.c:106
int i
#define elog
Definition: elog.h:240
int tailKnownAssignedXids
Definition: procarray.c:76
int headKnownAssignedXids
Definition: procarray.c:77

◆ KnownAssignedXidsGet()

static int KnownAssignedXidsGet ( TransactionId xarray,
TransactionId  xmax 
)
static

Definition at line 3810 of file procarray.c.

References InvalidTransactionId, and KnownAssignedXidsGetAndSetXmin().

Referenced by TransactionIdIsInProgress().

3811 {
3813 
3814  return KnownAssignedXidsGetAndSetXmin(xarray, &xtmp, xmax);
3815 }
uint32 TransactionId
Definition: c.h:474
#define InvalidTransactionId
Definition: transam.h:31
static int KnownAssignedXidsGetAndSetXmin(TransactionId *xarray, TransactionId *xmin, TransactionId xmax)
Definition: procarray.c:3824

◆ KnownAssignedXidsGetAndSetXmin()

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

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

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

◆ KnownAssignedXidsGetOldestXmin()

static TransactionId KnownAssignedXidsGetOldestXmin ( void  )
static

Definition at line 3882 of file procarray.c.

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

Referenced by GetOldestXmin().

3883 {
3884  int head,
3885  tail;
3886  int i;
3887 
3888  /*
3889  * Fetch head just once, since it may change while we loop.
3890  */
3895 
3896  for (i = tail; i < head; i++)
3897  {
3898  /* Skip any gaps in the array */
3899  if (KnownAssignedXidsValid[i])
3900  return KnownAssignedXids[i];
3901  }
3902 
3903  return InvalidTransactionId;
3904 }
slock_t known_assigned_xids_lck
Definition: procarray.c:78
#define SpinLockAcquire(lock)
Definition: spin.h:62
#define InvalidTransactionId
Definition: transam.h:31
static bool * KnownAssignedXidsValid
Definition: procarray.c:107
static ProcArrayStruct * procArray
Definition: procarray.c:98
#define SpinLockRelease(lock)
Definition: spin.h:64
static TransactionId * KnownAssignedXids
Definition: procarray.c:106
int i
int tailKnownAssignedXids
Definition: procarray.c:76
int headKnownAssignedXids
Definition: procarray.c:77

◆ KnownAssignedXidsRemove()

static void KnownAssignedXidsRemove ( TransactionId  xid)
static

Definition at line 3683 of file procarray.c.

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

Referenced by KnownAssignedXidsRemoveTree().

3684 {
3686 
3687  elog(trace_recovery(DEBUG4), "remove KnownAssignedXid %u", xid);
3688 
3689  /*
3690  * Note: we cannot consider it an error to remove an XID that's not
3691  * present. We intentionally remove subxact IDs while processing
3692  * XLOG_XACT_ASSIGNMENT, to avoid array overflow. Then those XIDs will be
3693  * removed again when the top-level xact commits or aborts.
3694  *
3695  * It might be possible to track such XIDs to distinguish this case from
3696  * actual errors, but it would be complicated and probably not worth it.
3697  * So, just ignore the search result.
3698  */
3699  (void) KnownAssignedXidsSearch(xid, true);
3700 }
#define DEBUG4
Definition: elog.h:22
int trace_recovery(int trace_level)
Definition: elog.c:3758
#define Assert(condition)
Definition: c.h:699
static bool KnownAssignedXidsSearch(TransactionId xid, bool remove)
Definition: procarray.c:3576
#define elog
Definition: elog.h:240
#define TransactionIdIsValid(xid)
Definition: transam.h:41

◆ KnownAssignedXidsRemovePreceding()

static void KnownAssignedXidsRemovePreceding ( TransactionId  xid)
static

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

3732 {
3733  /* use volatile pointer to prevent code rearrangement */
3734  volatile ProcArrayStruct *pArray = procArray;
3735  int count = 0;
3736  int head,
3737  tail,
3738  i;
3739 
3740  if (!TransactionIdIsValid(removeXid))
3741  {
3742  elog(trace_recovery(DEBUG4), "removing all KnownAssignedXids");
3743  pArray->numKnownAssignedXids = 0;
3744  pArray->headKnownAssignedXids = pArray->tailKnownAssignedXids = 0;
3745  return;
3746  }
3747 
3748  elog(trace_recovery(DEBUG4), "prune KnownAssignedXids to %u", removeXid);
3749 
3750  /*
3751  * Mark entries invalid starting at the tail. Since array is sorted, we
3752  * can stop as soon as we reach an entry >= removeXid.
3753  */
3754  tail = pArray->tailKnownAssignedXids;
3755  head = pArray->headKnownAssignedXids;
3756 
3757  for (i = tail; i < head; i++)
3758  {
3759  if (KnownAssignedXidsValid[i])
3760  {
3761  TransactionId knownXid = KnownAssignedXids[i];
3762 
3763  if (TransactionIdFollowsOrEquals(knownXid, removeXid))
3764  break;
3765 
3766  if (!StandbyTransactionIdIsPrepared(knownXid))
3767  {
3768  KnownAssignedXidsValid[i] = false;
3769  count++;
3770  }
3771  }
3772  }
3773 
3774  pArray->numKnownAssignedXids -= count;
3775  Assert(pArray->numKnownAssignedXids >= 0);
3776 
3777  /*
3778  * Advance the tail pointer if we've marked the tail item invalid.
3779  */
3780  for (i = tail; i < head; i++)
3781  {
3782  if (KnownAssignedXidsValid[i])
3783  break;
3784  }
3785  if (i >= head)
3786  {
3787  /* Array is empty, so we can reset both pointers */
3788  pArray->headKnownAssignedXids = 0;
3789  pArray->tailKnownAssignedXids = 0;
3790  }
3791  else
3792  {
3793  pArray->tailKnownAssignedXids = i;
3794  }
3795 
3796  /* Opportunistically compress the array */
3798 }
uint32 TransactionId
Definition: c.h:474
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:3758
bool StandbyTransactionIdIsPrepared(TransactionId xid)
Definition: twophase.c:1422
int numKnownAssignedXids
Definition: procarray.c:75
static bool * KnownAssignedXidsValid
Definition: procarray.c:107
static ProcArrayStruct * procArray
Definition: procarray.c:98
#define Assert(condition)
Definition: c.h:699
static TransactionId * KnownAssignedXids
Definition: procarray.c:106
static void KnownAssignedXidsCompress(bool force)
Definition: procarray.c:3394
int i
#define elog
Definition: elog.h:240
#define TransactionIdIsValid(xid)
Definition: transam.h:41
int tailKnownAssignedXids
Definition: procarray.c:76
int headKnownAssignedXids
Definition: procarray.c:77

◆ KnownAssignedXidsRemoveTree()

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

Definition at line 3709 of file procarray.c.

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

Referenced by ExpireTreeKnownAssignedTransactionIds(), and ProcArrayApplyXidAssignment().

3711 {
3712  int i;
3713 
3714  if (TransactionIdIsValid(xid))
3716 
3717  for (i = 0; i < nsubxids; i++)
3718  KnownAssignedXidsRemove(subxids[i]);
3719 
3720  /* Opportunistically compress the array */
3722 }
static void KnownAssignedXidsCompress(bool force)
Definition: procarray.c:3394
static void KnownAssignedXidsRemove(TransactionId xid)
Definition: procarray.c:3683
int i
#define TransactionIdIsValid(xid)
Definition: transam.h:41

◆ KnownAssignedXidsReset()

static void KnownAssignedXidsReset ( void  )
static

Definition at line 3956 of file procarray.c.

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

Referenced by ProcArrayApplyRecoveryInfo().

3957 {
3958  /* use volatile pointer to prevent code rearrangement */
3959  volatile ProcArrayStruct *pArray = procArray;
3960 
3961  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3962 
3963  pArray->numKnownAssignedXids = 0;
3964  pArray->tailKnownAssignedXids = 0;
3965  pArray->headKnownAssignedXids = 0;
3966 
3967  LWLockRelease(ProcArrayLock);
3968 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
int numKnownAssignedXids
Definition: procarray.c:75
static ProcArrayStruct * procArray
Definition: procarray.c:98
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121
int tailKnownAssignedXids
Definition: procarray.c:76
int headKnownAssignedXids
Definition: procarray.c:77

◆ KnownAssignedXidsSearch()

static bool KnownAssignedXidsSearch ( TransactionId  xid,
bool  remove 
)
static

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

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

◆ MinimumActiveBackends()

bool MinimumActiveBackends ( int  min)

Definition at line 2693 of file procarray.c.

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

Referenced by XLogFlush().

2694 {
2695  ProcArrayStruct *arrayP = procArray;
2696  int count = 0;
2697  int index;
2698 
2699  /* Quick short-circuit if no minimum is specified */
2700  if (min == 0)
2701  return true;
2702 
2703  /*
2704  * Note: for speed, we don't acquire ProcArrayLock. This is a little bit
2705  * bogus, but since we are only testing fields for zero or nonzero, it
2706  * should be OK. The result is only used for heuristic purposes anyway...
2707  */
2708  for (index = 0; index < arrayP->numProcs; index++)
2709  {
2710  int pgprocno = arrayP->pgprocnos[index];
2711  volatile PGPROC *proc = &allProcs[pgprocno];
2712  volatile PGXACT *pgxact = &allPgXact[pgprocno];
2713 
2714  /*
2715  * Since we're not holding a lock, need to be prepared to deal with
2716  * garbage, as someone could have incremented numProcs but not yet
2717  * filled the structure.
2718  *
2719  * If someone just decremented numProcs, 'proc' could also point to a
2720  * PGPROC entry that's no longer in the array. It still points to a
2721  * PGPROC struct, though, because freed PGPROC entries just go to the
2722  * free list and are recycled. Its contents are nonsense in that case,
2723  * but that's acceptable for this function.
2724  */
2725  if (pgprocno == -1)
2726  continue; /* do not count deleted entries */
2727  if (proc == MyProc)
2728  continue; /* do not count myself */
2729  if (pgxact->xid == InvalidTransactionId)
2730  continue; /* do not count if no XID assigned */
2731  if (proc->pid == 0)
2732  continue; /* do not count prepared xacts */
2733  if (proc->waitLock != NULL)
2734  continue; /* do not count if blocked on a lock */
2735  count++;
2736  if (count >= min)
2737  break;
2738  }
2739 
2740  return count >= min;
2741 }
Definition: proc.h:222
PGPROC * MyProc
Definition: proc.c:67
TransactionId xid
Definition: proc.h:224
Definition: type.h:89
#define InvalidTransactionId
Definition: transam.h:31
static PGPROC * allProcs
Definition: procarray.c:100
LOCK * waitLock
Definition: proc.h:139
static ProcArrayStruct * procArray
Definition: procarray.c:98
static PGXACT * allPgXact
Definition: procarray.c:101
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:95
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:575
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
#define FATAL
Definition: elog.h:52
#define memmove(d, s, c)
Definition: c.h:1135
#define ereport(elevel, rest)
Definition: elog.h:141
static ProcArrayStruct * procArray
Definition: procarray.c:98
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:95
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121
int pgprocno
Definition: proc.h:110
int errmsg(const char *fmt,...)
Definition: elog.c:797

◆ ProcArrayApplyRecoveryInfo()

void ProcArrayApplyRecoveryInfo ( RunningTransactions  running)

Definition at line 668 of file procarray.c.

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

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

669 {
670  TransactionId *xids;
671  int nxids;
672  TransactionId nextXid;
673  int i;
674 
679 
680  /*
681  * Remove stale transactions, if any.
682  */
684 
685  /*
686  * Remove stale locks, if any.
687  */
689 
690  /*
691  * If our snapshot is already valid, nothing else to do...
692  */
694  return;
695 
696  /*
697  * If our initial RunningTransactionsData had an overflowed snapshot then
698  * we knew we were missing some subxids from our snapshot. If we continue
699  * to see overflowed snapshots then we might never be able to start up, so
700  * we make another test to see if our snapshot is now valid. We know that
701  * the missing subxids are equal to or earlier than nextXid. After we
702  * initialise we continue to apply changes during recovery, so once the
703  * oldestRunningXid is later than the nextXid from the initial snapshot we
704  * know that we no longer have missing information and can mark the
705  * snapshot as valid.
706  */
708  {
709  /*
710  * If the snapshot isn't overflowed or if its empty we can reset our
711  * pending state and use this snapshot instead.
712  */
713  if (!running->subxid_overflow || running->xcnt == 0)
714  {
715  /*
716  * If we have already collected known assigned xids, we need to
717  * throw them away before we apply the recovery snapshot.
718  */
721  }
722  else
723  {
725  running->oldestRunningXid))
726  {
729  "recovery snapshots are now enabled");
730  }
731  else
733  "recovery snapshot waiting for non-overflowed snapshot or "
734  "until oldest active xid on standby is at least %u (now %u)",
736  running->oldestRunningXid);
737  return;
738  }
739  }
740 
742 
743  /*
744  * OK, we need to initialise from the RunningTransactionsData record.
745  *
746  * NB: this can be reached at least twice, so make sure new code can deal
747  * with that.
748  */
749 
750  /*
751  * Nobody else is running yet, but take locks anyhow
752  */
753  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
754 
755  /*
756  * KnownAssignedXids is sorted so we cannot just add the xids, we have to
757  * sort them first.
758  *
759  * Some of the new xids are top-level xids and some are subtransactions.
760  * We don't call SubtransSetParent because it doesn't matter yet. If we
761  * aren't overflowed then all xids will fit in snapshot and so we don't
762  * need subtrans. If we later overflow, an xid assignment record will add
763  * xids to subtrans. If RunningXacts is overflowed then we don't have
764  * enough information to correctly update subtrans anyway.
765  */
766 
767  /*
768  * Allocate a temporary array to avoid modifying the array passed as
769  * argument.
770  */
771  xids = palloc(sizeof(TransactionId) * (running->xcnt + running->subxcnt));
772 
773  /*
774  * Add to the temp array any xids which have not already completed.
775  */
776  nxids = 0;
777  for (i = 0; i < running->xcnt + running->subxcnt; i++)
778  {
779  TransactionId xid = running->xids[i];
780 
781  /*
782  * The running-xacts snapshot can contain xids that were still visible
783  * in the procarray when the snapshot was taken, but were already
784  * WAL-logged as completed. They're not running anymore, so ignore
785  * them.
786  */
788  continue;
789 
790  xids[nxids++] = xid;
791  }
792 
793  if (nxids > 0)
794  {
796  {
797  LWLockRelease(ProcArrayLock);
798  elog(ERROR, "KnownAssignedXids is not empty");
799  }
800 
801  /*
802  * Sort the array so that we can add them safely into
803  * KnownAssignedXids.
804  */
805  qsort(xids, nxids, sizeof(TransactionId), xidComparator);
806 
807  /*
808  * Add the sorted snapshot into KnownAssignedXids
809  */
810  for (i = 0; i < nxids; i++)
811  KnownAssignedXidsAdd(xids[i], xids[i], true);
812 
814  }
815 
816  pfree(xids);
817 
818  /*
819  * latestObservedXid is at least set to the point where SUBTRANS was
820  * started up to (cf. ProcArrayInitRecovery()) or to the biggest xid
821  * RecordKnownAssignedTransactionIds() was called for. Initialize
822  * subtrans from thereon, up to nextXid - 1.
823  *
824  * We need to duplicate parts of RecordKnownAssignedTransactionId() here,
825  * because we've just added xids to the known assigned xids machinery that
826  * haven't gone through RecordKnownAssignedTransactionId().
827  */
831  {
834  }
835  TransactionIdRetreat(latestObservedXid); /* = running->nextXid - 1 */
836 
837  /* ----------
838  * Now we've got the running xids we need to set the global values that
839  * are used to track snapshots as they evolve further.
840  *
841  * - latestCompletedXid which will be the xmax for snapshots
842  * - lastOverflowedXid which shows whether snapshots overflow
843  * - nextXid
844  *
845  * If the snapshot overflowed, then we still initialise with what we know,
846  * but the recovery snapshot isn't fully valid yet because we know there
847  * are some subxids missing. We don't know the specific subxids that are
848  * missing, so conservatively assume the last one is latestObservedXid.
849  * ----------
850  */
851  if (running->subxid_overflow)
852  {
854 
857  }
858  else
859  {
861 
863  }
864 
865  /*
866  * If a transaction wrote a commit record in the gap between taking and
867  * logging the snapshot then latestCompletedXid may already be higher than
868  * the value from the snapshot, so check before we use the incoming value.
869  */
871  running->latestCompletedXid))
873 
875 
876  LWLockRelease(ProcArrayLock);
877 
878  /*
879  * ShmemVariableCache->nextXid must be beyond any observed xid.
880  *
881  * We don't expect anyone else to modify nextXid, hence we don't need to
882  * hold a lock while examining it. We still acquire the lock to modify
883  * it, though.
884  */
885  nextXid = latestObservedXid;
886  TransactionIdAdvance(nextXid);
888  {
889  LWLockAcquire(XidGenLock, LW_EXCLUSIVE);
890  ShmemVariableCache->nextXid = nextXid;
891  LWLockRelease(XidGenLock);
892  }
893 
895 
898  elog(trace_recovery(DEBUG1), "recovery snapshots are now enabled");
899  else
901  "recovery snapshot waiting for non-overflowed snapshot or "
902  "until oldest active xid on standby is at least %u (now %u)",
904  running->oldestRunningXid);
905 }
#define TransactionIdAdvance(dest)
Definition: transam.h:48
static TransactionId latestObservedXid
Definition: procarray.c:108
TransactionId oldestRunningXid
Definition: standby.h:76
#define DEBUG1
Definition: elog.h:25
static void KnownAssignedXidsDisplay(int trace_level)
Definition: procarray.c:3917
bool TransactionIdFollows(TransactionId id1, TransactionId id2)
Definition: transam.c:334
uint32 TransactionId
Definition: c.h:474
#define DEBUG3
Definition: elog.h:23
TransactionId * xids
Definition: standby.h:79
bool TransactionIdDidCommit(TransactionId transactionId)
Definition: transam.c:125
#define TransactionIdRetreat(dest)
Definition: transam.h:56
int trace_recovery(int trace_level)
Definition: elog.c:3758
TransactionId latestCompletedXid
Definition: standby.h:77
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
void pfree(void *pointer)
Definition: mcxt.c:1031
#define ERROR
Definition: elog.h:43
void ExtendSUBTRANS(TransactionId newestXact)
Definition: subtrans.c:324
TransactionId nextXid
Definition: transam.h:117
VariableCache ShmemVariableCache
Definition: varsup.c:34
#define InvalidTransactionId
Definition: transam.h:31
static void KnownAssignedXidsReset(void)
Definition: procarray.c:3956
int numKnownAssignedXids
Definition: procarray.c:75
TransactionId lastOverflowedXid
Definition: procarray.c:87
bool TransactionIdDidAbort(TransactionId transactionId)
Definition: transam.c:181
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
static ProcArrayStruct * procArray
Definition: procarray.c:98
#define Assert(condition)
Definition: c.h:699
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121
static void KnownAssignedXidsAdd(TransactionId from_xid, TransactionId to_xid, bool exclusive_lock)
Definition: procarray.c:3457
TransactionId nextXid
Definition: standby.h:75
void * palloc(Size size)
Definition: mcxt.c:924
int i
void ExpireOldKnownAssignedTransactionIds(TransactionId xid)
Definition: procarray.c:3291
#define elog
Definition: elog.h:240
#define qsort(a, b, c, d)
Definition: port.h:421
#define TransactionIdIsValid(xid)
Definition: transam.h:41
#define TransactionIdIsNormal(xid)
Definition: transam.h:42
static TransactionId standbySnapshotPendingXmin
Definition: procarray.c:115
HotStandbyState standbyState
Definition: xlog.c:197
void StandbyReleaseOldLocks(TransactionId oldxid)
Definition: standby.c:751
int xidComparator(const void *arg1, const void *arg2)
Definition: xid.c:138
TransactionId latestCompletedXid
Definition: transam.h:135

◆ ProcArrayApplyXidAssignment()

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

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

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

◆ ProcArrayClearTransaction()

void ProcArrayClearTransaction ( PGPROC proc)

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

606 {
607  PGXACT *pgxact = &allPgXact[proc->pgprocno];
608 
609  /*
610  * We can skip locking ProcArrayLock here, because this action does not
611  * actually change anyone's view of the set of running XIDs: our entry is
612  * duplicate with the gxact that has already been inserted into the
613  * ProcArray.
614  */
615  pgxact->xid = InvalidTransactionId;
617  pgxact->xmin = InvalidTransactionId;
618  proc->recoveryConflictPending = false;
619 
620  /* redundant, but just in case */
622  pgxact->delayChkpt = false;
623 
624  /* Clear the subtransaction-XID cache too */
625  pgxact->nxids = 0;
626  pgxact->overflowed = false;
627 }
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:101
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:1725
bool LWLockConditionalAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1293
bool recoveryConflictPending
Definition: proc.h:127
uint8 nxids
Definition: proc.h:238
#define InvalidTransactionId
Definition: transam.h:31
bool delayChkpt
Definition: proc.h:235
static PGXACT * allPgXact
Definition: procarray.c:101
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:699
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:135

◆ ProcArrayGetReplicationSlotXmin()

void ProcArrayGetReplicationSlotXmin ( TransactionId xmin,
TransactionId catalog_xmin 
)

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

2996 {
2997  LWLockAcquire(ProcArrayLock, LW_SHARED);
2998 
2999  if (xmin != NULL)
3001 
3002  if (catalog_xmin != NULL)
3003  *catalog_xmin = procArray->replication_slot_catalog_xmin;
3004 
3005  LWLockRelease(ProcArrayLock);
3006 }
TransactionId replication_slot_catalog_xmin
Definition: procarray.c:92
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
static ProcArrayStruct * procArray
Definition: procarray.c:98
TransactionId replication_slot_xmin
Definition: procarray.c:90
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121

◆ 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_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  volatile 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  while (true)
497  {
498  nextidx = pg_atomic_read_u32(&procglobal->procArrayGroupFirst);
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  while (true)
546  {
547  nextidx = pg_atomic_read_u32(&procglobal->procArrayGroupFirst);
549  &nextidx,
551  break;
552  }
553 
554  /* Remember head of list so we can perform wakeups after dropping lock. */
555  wakeidx = nextidx;
556 
557  /* Walk the list and clear all XIDs. */
558  while (nextidx != INVALID_PGPROCNO)
559  {
560  PGPROC *proc = &allProcs[nextidx];
561  PGXACT *pgxact = &allPgXact[nextidx];
562 
564 
565  /* Move to next proc in list. */
566  nextidx = pg_atomic_read_u32(&proc->procArrayGroupNext);
567  }
568 
569  /* We're done with the lock now. */
570  LWLockRelease(ProcArrayLock);
571 
572  /*
573  * Now that we've released the lock, go back and wake everybody up. We
574  * don't do this under the lock so as to keep lock hold times to a
575  * minimum. The system calls we need to perform to wake other processes
576  * up are probably much slower than the simple memory writes we did while
577  * holding the lock.
578  */
579  while (wakeidx != INVALID_PGPROCNO)
580  {
581  PGPROC *proc = &allProcs[wakeidx];
582 
583  wakeidx = pg_atomic_read_u32(&proc->procArrayGroupNext);
585 
586  /* ensure all previous writes are visible before follower continues. */
588 
589  proc->procArrayGroupMember = false;
590 
591  if (proc != MyProc)
592  PGSemaphoreUnlock(proc->sem);
593  }
594 }
bool procArrayGroupMember
Definition: proc.h:166
void PGSemaphoreUnlock(PGSemaphore sema)
Definition: posix_sema.c:329
Definition: proc.h:222
static bool pg_atomic_compare_exchange_u32(volatile pg_atomic_uint32 *ptr, uint32 *expected, uint32 newval)
Definition: atomics.h:314
PGPROC * MyProc
Definition: proc.c:67
TransactionId xid
Definition: proc.h:224
PROC_HDR * ProcGlobal
Definition: proc.c:80
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
static PGPROC * allProcs
Definition: procarray.c:100
unsigned int uint32
Definition: c.h:325
static void pgstat_report_wait_end(void)
Definition: pgstat.h:1261
#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:101
static void ProcArrayEndTransactionInternal(PGPROC *proc, PGXACT *pgxact, TransactionId latestXid)
Definition: procarray.c:450
#define Assert(condition)
Definition: c.h:699
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition: pgstat.h:1237
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121
void PGSemaphoreLock(PGSemaphore sema)
Definition: posix_sema.c:309
int pgprocno
Definition: proc.h:110
pg_atomic_uint32 procArrayGroupFirst
Definition: proc.h:259
#define pg_write_barrier()
Definition: atomics.h:162
#define TransactionIdIsValid(xid)
Definition: transam.h:41
static void pg_atomic_write_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
Definition: atomics.h:261
PGSemaphore sem
Definition: proc.h:101
Definition: proc.h:95
TransactionId procArrayGroupMemberXid
Definition: proc.h:174
static uint32 pg_atomic_read_u32(volatile pg_atomic_uint32 *ptr)
Definition: atomics.h:244

◆ ProcArrayInitRecovery()

void ProcArrayInitRecovery ( TransactionId  initializedUptoXID)

Definition at line 637 of file procarray.c.

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

Referenced by StartupXLOG().

638 {
640  Assert(TransactionIdIsNormal(initializedUptoXID));
641 
642  /*
643  * we set latestObservedXid to the xid SUBTRANS has been initialized up
644  * to, so we can extend it from that point onwards in
645  * RecordKnownAssignedTransactionIds, and when we get consistent in
646  * ProcArrayApplyRecoveryInfo().
647  */
648  latestObservedXid = initializedUptoXID;
650 }
static TransactionId latestObservedXid
Definition: procarray.c:108
#define TransactionIdRetreat(dest)
Definition: transam.h:56
#define Assert(condition)
Definition: c.h:699
#define TransactionIdIsNormal(xid)
Definition: transam.h:42
HotStandbyState standbyState
Definition: xlog.c:197

◆ 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, 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  volatile PGPROC *proc = &allProcs[pgprocno];
1812  volatile 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 = pgxact->xmin; /* fetch just once */
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:474
Definition: proc.h:222
TransactionId xmin
Definition: proc.h:228
LocalTransactionId localTransactionId
Definition: lock.h:66
PGXACT * MyPgXact
Definition: proc.c:68
uint8 vacuumFlags
Definition: proc.h:233
TransactionId TransactionXmin
Definition: snapmgr.c:164
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
#define PROC_IN_VACUUM
Definition: proc.h:54
bool TransactionIdPrecedesOrEquals(TransactionId id1, TransactionId id2)
Definition: transam.c:319
static PGPROC * allProcs
Definition: procarray.c:100
Oid databaseId
Definition: proc.h:114
static ProcArrayStruct * procArray
Definition: procarray.c:98
static PGXACT * allPgXact
Definition: procarray.c:101
Oid MyDatabaseId
Definition: globals.c:84
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:95
#define Assert(condition)
Definition: c.h:699
BackendId backendId
Definition: lock.h:65
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121
#define TransactionIdIsNormal(xid)
Definition: transam.h:42
Definition: proc.h:95
LocalTransactionId lxid
Definition: proc.h:106

◆ ProcArrayInstallRestoredXmin()

bool ProcArrayInstallRestoredXmin ( TransactionId  xmin,
PGPROC proc 
)

Definition at line 1869 of file procarray.c.

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

Referenced by SetTransactionSnapshot().

1870 {
1871  bool result = false;
1872  TransactionId xid;
1873  volatile 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 = pgxact->xmin; /* fetch just once */
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:474
Definition: proc.h:222
TransactionId xmin
Definition: proc.h:228
PGXACT * MyPgXact
Definition: proc.c:68
TransactionId TransactionXmin
Definition: snapmgr.c:164
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
bool TransactionIdPrecedesOrEquals(TransactionId id1, TransactionId id2)
Definition: transam.c:319
Oid databaseId
Definition: proc.h:114
static PGXACT * allPgXact
Definition: procarray.c:101
Oid MyDatabaseId
Definition: globals.c:84
#define Assert(condition)
Definition: c.h:699
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121
int pgprocno
Definition: proc.h:110
#define TransactionIdIsNormal(xid)
Definition: transam.h:42

◆ ProcArrayRemove()

void ProcArrayRemove ( PGPROC proc,
TransactionId  latestXid 
)

Definition at line 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:1725
#define memmove(d, s, c)
Definition: c.h:1135
VariableCache ShmemVariableCache
Definition: varsup.c:34
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
static ProcArrayStruct * procArray
Definition: procarray.c:98
static PGXACT * allPgXact
Definition: procarray.c:101
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:95
#define Assert(condition)
Definition: c.h:699
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121
int pgprocno
Definition: proc.h:110
#define elog
Definition: elog.h:240
#define TransactionIdIsValid(xid)
Definition: transam.h:41
int pid
Definition: proc.h:109
TransactionId latestCompletedXid
Definition: transam.h:135

◆ ProcArraySetReplicationSlotXmin()

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

Definition at line 2972 of file procarray.c.

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

Referenced by ReplicationSlotsComputeRequiredXmin().

2974 {
2975  Assert(!already_locked || LWLockHeldByMe(ProcArrayLock));
2976 
2977  if (!already_locked)
2978  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
2979 
2981  procArray->replication_slot_catalog_xmin = catalog_xmin;
2982 
2983  if (!already_locked)
2984  LWLockRelease(ProcArrayLock);
2985 }
bool LWLockHeldByMe(LWLock *l)
Definition: lwlock.c:1841
TransactionId replication_slot_catalog_xmin
Definition: procarray.c:92
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
static ProcArrayStruct * procArray
Definition: procarray.c:98
TransactionId replication_slot_xmin
Definition: procarray.c:90
#define Assert(condition)
Definition: c.h:699
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121

◆ ProcArrayShmemSize()

Size ProcArrayShmemSize ( void  )

Definition at line 179 of file procarray.c.

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

Referenced by CreateSharedMemoryAndSemaphores().

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

◆ RecordKnownAssignedTransactionIds()

void RecordKnownAssignedTransactionIds ( TransactionId  xid)

Definition at line 3181 of file procarray.c.

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

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

3182 {
3186 
3187  elog(trace_recovery(DEBUG4), "record known xact %u latestObservedXid %u",
3188  xid, latestObservedXid);
3189 
3190  /*
3191  * When a newly observed xid arrives, it is frequently the case that it is
3192  * *not* the next xid in sequence. When this occurs, we must treat the
3193  * intervening xids as running also.
3194  */
3196  {
3197  TransactionId next_expected_xid;
3198 
3199  /*
3200  * Extend subtrans like we do in GetNewTransactionId() during normal
3201  * operation using individual extend steps. Note that we do not need
3202  * to extend clog since its extensions are WAL logged.
3203  *
3204  * This part has to be done regardless of standbyState since we
3205  * immediately start assigning subtransactions to their toplevel
3206  * transactions.
3207  */
3208  next_expected_xid = latestObservedXid;
3209  while (TransactionIdPrecedes(next_expected_xid, xid))
3210  {
3211  TransactionIdAdvance(next_expected_xid);
3212  ExtendSUBTRANS(next_expected_xid);
3213  }
3214  Assert(next_expected_xid == xid);
3215 
3216  /*
3217  * If the KnownAssignedXids machinery isn't up yet, there's nothing
3218  * more to do since we don't track assigned xids yet.
3219  */
3221  {
3222  latestObservedXid = xid;
3223  return;
3224  }
3225 
3226  /*
3227  * Add (latestObservedXid, xid] onto the KnownAssignedXids array.
3228  */
3229  next_expected_xid = latestObservedXid;
3230  TransactionIdAdvance(next_expected_xid);
3231  KnownAssignedXidsAdd(next_expected_xid, xid, false);
3232 
3233  /*
3234  * Now we can advance latestObservedXid
3235  */
3236  latestObservedXid = xid;
3237 
3238  /* ShmemVariableCache->nextXid must be beyond any observed xid */
3239  next_expected_xid = latestObservedXid;
3240  TransactionIdAdvance(next_expected_xid);
3241  LWLockAcquire(XidGenLock, LW_EXCLUSIVE);
3242  ShmemVariableCache->nextXid = next_expected_xid;
3243  LWLockRelease(XidGenLock);
3244  }
3245 }
#define TransactionIdAdvance(dest)
Definition: transam.h:48
static TransactionId latestObservedXid
Definition: procarray.c:108
bool TransactionIdFollows(TransactionId id1, TransactionId id2)
Definition: transam.c:334
uint32 TransactionId
Definition: c.h:474
#define DEBUG4
Definition: elog.h:22
int trace_recovery(int trace_level)
Definition: elog.c:3758
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
void ExtendSUBTRANS(TransactionId newestXact)
Definition: subtrans.c:324
TransactionId nextXid
Definition: transam.h:117
VariableCache ShmemVariableCache
Definition: varsup.c:34
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
#define Assert(condition)
Definition: c.h:699
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121
static void KnownAssignedXidsAdd(TransactionId from_xid, TransactionId to_xid, bool exclusive_lock)
Definition: procarray.c:3457
#define elog
Definition: elog.h:240
#define TransactionIdIsValid(xid)
Definition: transam.h:41
HotStandbyState standbyState
Definition: xlog.c:197

◆ TransactionIdIsActive()

bool TransactionIdIsActive ( TransactionId  xid)

Definition at line 1213 of file procarray.c.

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

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

◆ TransactionIdIsInProgress()

bool TransactionIdIsInProgress ( TransactionId  xid)

Definition at line 996 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, ProcArrayStruct::pgprocnos, procArray, RecentXmin, RecoveryInProgress(), ShmemVariableCache, SubTransGetTopmostTransaction(), PGPROC::subxids, TOTAL_MAX_CACHED_SUBXIDS, TransactionIdDidAbort(), TransactionIdEquals, TransactionIdIsCurrentTransactionId(), TransactionIdIsKnownCompleted(), TransactionIdIsValid, TransactionIdPrecedes(), TransactionIdPrecedesOrEquals(), 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 compute_new_xmax_infomask(), ConditionalXactLockTableWait(), Do_MultiXactIdWait(), DoesMultiXactIdConflict(), FreezeMultiXactId(), HeapTupleHeaderIsOnlyLocked(), HeapTupleSatisfiesDirty(), HeapTupleSatisfiesSelf(), HeapTupleSatisfiesToast(), HeapTupleSatisfiesUpdate(), HeapTupleSatisfiesVacuum(), MultiXactIdExpand(), MultiXactIdIsRunning(), test_lockmode_for_conflict(), and XactLockTableWait().

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

◆ XidCacheRemoveRunningXids()

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

Definition at line 3024 of file procarray.c.

References Assert, elog, 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().

3027 {
3028  int i,
3029  j;
3030 
3032 
3033  /*
3034  * We must hold ProcArrayLock exclusively in order to remove transactions
3035  * from the PGPROC array. (See src/backend/access/transam/README.) It's
3036  * possible this could be relaxed since we know this routine is only used
3037  * to abort subtransactions, but pending closer analysis we'd best be
3038  * conservative.
3039  */
3040  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3041 
3042  /*
3043  * Under normal circumstances xid and xids[] will be in increasing order,
3044  * as will be the entries in subxids. Scan backwards to avoid O(N^2)
3045  * behavior when removing a lot of xids.
3046  */
3047  for (i = nxids - 1; i >= 0; i--)
3048  {
3049  TransactionId anxid = xids[i];
3050 
3051  for (j = MyPgXact->nxids - 1; j >= 0; j--)
3052  {
3053  if (TransactionIdEquals(MyProc->subxids.xids[j], anxid))
3054  {
3055  XidCacheRemove(j);
3056  break;
3057  }
3058  }
3059 
3060  /*
3061  * Ordinarily we should have found it, unless the cache has
3062  * overflowed. However it's also possible for this routine to be
3063  * invoked multiple times for the same subtransaction, in case of an
3064  * error during AbortSubTransaction. So instead of Assert, emit a
3065  * debug warning.
3066  */
3067  if (j < 0 && !MyPgXact->overflowed)
3068  elog(WARNING, "did not find subXID %u in MyProc", anxid);
3069  }
3070 
3071  for (j = MyPgXact->nxids - 1; j >= 0; j--)
3072  {
3073  if (TransactionIdEquals(MyProc->subxids.xids[j], xid))
3074  {
3075  XidCacheRemove(j);
3076  break;
3077  }
3078  }
3079  /* Ordinarily we should have found it, unless the cache has overflowed */
3080  if (j < 0 && !MyPgXact->overflowed)
3081  elog(WARNING, "did not find subXID %u in MyProc", xid);
3082 
3083  /* Also advance global latestCompletedXid while holding the lock */
3085  latestXid))
3087 
3088  LWLockRelease(ProcArrayLock);
3089 }
#define XidCacheRemove(i)
Definition: procarray.c:3009
#define TransactionIdEquals(id1, id2)
Definition: transam.h:43
uint32 TransactionId
Definition: c.h:474
PGPROC * MyProc
Definition: proc.c:67
PGXACT * MyPgXact
Definition: proc.c:68
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
uint8 nxids
Definition: proc.h:238
VariableCache ShmemVariableCache
Definition: varsup.c:34
struct XidCache subxids
Definition: proc.h:162
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
#define WARNING
Definition: elog.h:40
TransactionId xids[PGPROC_MAX_CACHED_SUBXIDS]
Definition: proc.h:40
#define Assert(condition)
Definition: c.h:699
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121
int i
#define elog
Definition: elog.h:240
#define TransactionIdIsValid(xid)
Definition: transam.h:41
TransactionId latestCompletedXid
Definition: transam.h:135

Variable Documentation

◆ allPgXact

PGXACT* allPgXact
static

Definition at line 101 of file procarray.c.

◆ allProcs

PGPROC* allProcs
static

Definition at line 100 of file procarray.c.

◆ KnownAssignedXids

◆ KnownAssignedXidsValid

◆ latestObservedXid

◆ procArray

◆ standbySnapshotPendingXmin

TransactionId standbySnapshotPendingXmin
static

Definition at line 115 of file procarray.c.

Referenced by ProcArrayApplyRecoveryInfo().