PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
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 "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, bool ignoreVacuum)
 
int GetMaxSnapshotXidCount (void)
 
int GetMaxSnapshotSubxidCount (void)
 
Snapshot GetSnapshotData (Snapshot snapshot)
 
bool ProcArrayInstallImportedXmin (TransactionId xmin, TransactionId sourcexid)
 
bool ProcArrayInstallRestoredXmin (TransactionId xmin, PGPROC *proc)
 
RunningTransactions GetRunningTransactionData (void)
 
TransactionId GetOldestActiveTransactionId (void)
 
TransactionId GetOldestSafeDecodingTransactionId (void)
 
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

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

Referenced by CountOtherDBBackends().

#define xc_by_child_xid_inc ( )    ((void) 0)

Definition at line 147 of file procarray.c.

Referenced by TransactionIdIsInProgress().

#define xc_by_known_assigned_inc ( )    ((void) 0)

Definition at line 148 of file procarray.c.

Referenced by TransactionIdIsInProgress().

#define xc_by_known_xact_inc ( )    ((void) 0)

Definition at line 143 of file procarray.c.

Referenced by TransactionIdIsInProgress().

#define xc_by_latest_xid_inc ( )    ((void) 0)

Definition at line 145 of file procarray.c.

Referenced by TransactionIdIsInProgress().

#define xc_by_main_xid_inc ( )    ((void) 0)

Definition at line 146 of file procarray.c.

Referenced by TransactionIdIsInProgress().

#define xc_by_my_xact_inc ( )    ((void) 0)

Definition at line 144 of file procarray.c.

Referenced by TransactionIdIsInProgress().

#define xc_by_recent_xmin_inc ( )    ((void) 0)

Definition at line 142 of file procarray.c.

Referenced by TransactionIdIsInProgress().

#define xc_no_overflow_inc ( )    ((void) 0)

Definition at line 149 of file procarray.c.

Referenced by TransactionIdIsInProgress().

#define xc_slow_answer_inc ( )    ((void) 0)

Definition at line 150 of file procarray.c.

Referenced by TransactionIdIsInProgress().

#define XidCacheRemove (   i)
Value:
do { \
} while (0)
PGPROC * MyProc
Definition: proc.c:67
PGXACT * MyPgXact
Definition: proc.c:68
uint8 nxids
Definition: proc.h:213
struct XidCache subxids
Definition: proc.h:148
TransactionId xids[PGPROC_MAX_CACHED_SUBXIDS]
Definition: proc.h:39
int i

Definition at line 2984 of file procarray.c.

Referenced by XidCacheRemoveRunningXids().

Typedef Documentation

Function Documentation

PGPROC* BackendPidGetProc ( int  pid)

Definition at line 2329 of file procarray.c.

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

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

2330 {
2331  PGPROC *result;
2332 
2333  if (pid == 0) /* never match dummy PGPROCs */
2334  return NULL;
2335 
2336  LWLockAcquire(ProcArrayLock, LW_SHARED);
2337 
2338  result = BackendPidGetProcWithLock(pid);
2339 
2340  LWLockRelease(ProcArrayLock);
2341 
2342  return result;
2343 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1714
PGPROC * BackendPidGetProcWithLock(int pid)
Definition: procarray.c:2352
#define NULL
Definition: c.h:226
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1110
Definition: proc.h:84
PGPROC* BackendPidGetProcWithLock ( int  pid)

Definition at line 2352 of file procarray.c.

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

Referenced by BackendPidGetProc(), and GetBlockerStatusData().

2353 {
2354  PGPROC *result = NULL;
2355  ProcArrayStruct *arrayP = procArray;
2356  int index;
2357 
2358  if (pid == 0) /* never match dummy PGPROCs */
2359  return NULL;
2360 
2361  for (index = 0; index < arrayP->numProcs; index++)
2362  {
2363  PGPROC *proc = &allProcs[arrayP->pgprocnos[index]];
2364 
2365  if (proc->pid == pid)
2366  {
2367  result = proc;
2368  break;
2369  }
2370  }
2371 
2372  return result;
2373 }
Definition: type.h:90
static PGPROC * allProcs
Definition: procarray.c:99
static ProcArrayStruct * procArray
Definition: procarray.c:97
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:94
#define NULL
Definition: c.h:226
Definition: proc.h:84
int pid
Definition: proc.h:98
int BackendXidGetPid ( TransactionId  xid)

Definition at line 2389 of file procarray.c.

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

Referenced by pgrowlocks().

2390 {
2391  int result = 0;
2392  ProcArrayStruct *arrayP = procArray;
2393  int index;
2394 
2395  if (xid == InvalidTransactionId) /* never match invalid xid */
2396  return 0;
2397 
2398  LWLockAcquire(ProcArrayLock, LW_SHARED);
2399 
2400  for (index = 0; index < arrayP->numProcs; index++)
2401  {
2402  int pgprocno = arrayP->pgprocnos[index];
2403  volatile PGPROC *proc = &allProcs[pgprocno];
2404  volatile PGXACT *pgxact = &allPgXact[pgprocno];
2405 
2406  if (pgxact->xid == xid)
2407  {
2408  result = proc->pid;
2409  break;
2410  }
2411  }
2412 
2413  LWLockRelease(ProcArrayLock);
2414 
2415  return result;
2416 }
Definition: proc.h:197
TransactionId xid
Definition: proc.h:199
Definition: type.h:90
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1714
#define InvalidTransactionId
Definition: transam.h:31
static PGPROC * allProcs
Definition: procarray.c:99
static ProcArrayStruct * procArray
Definition: procarray.c:97
static PGXACT * allPgXact
Definition: procarray.c:100
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:94
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1110
Definition: proc.h:84
int pid
Definition: proc.h:98
void CancelDBBackends ( Oid  databaseid,
ProcSignalReason  sigmode,
bool  conflictPending 
)

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

2784 {
2785  ProcArrayStruct *arrayP = procArray;
2786  int index;
2787  pid_t pid = 0;
2788 
2789  /* tell all backends to die */
2790  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
2791 
2792  for (index = 0; index < arrayP->numProcs; index++)
2793  {
2794  int pgprocno = arrayP->pgprocnos[index];
2795  volatile PGPROC *proc = &allProcs[pgprocno];
2796 
2797  if (databaseid == InvalidOid || proc->databaseId == databaseid)
2798  {
2799  VirtualTransactionId procvxid;
2800 
2801  GET_VXID_FROM_PGPROC(procvxid, *proc);
2802 
2803  proc->recoveryConflictPending = conflictPending;
2804  pid = proc->pid;
2805  if (pid != 0)
2806  {
2807  /*
2808  * Kill the pid if it's still here. If not, that's what we
2809  * wanted so ignore any errors.
2810  */
2811  (void) SendProcSignal(pid, sigmode, procvxid.backendId);
2812  }
2813  }
2814  }
2815 
2816  LWLockRelease(ProcArrayLock);
2817 }
#define GET_VXID_FROM_PGPROC(vxid, proc)
Definition: lock.h:81
Definition: type.h:90
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1714
int SendProcSignal(pid_t pid, ProcSignalReason reason, BackendId backendId)
Definition: procsignal.c:179
bool recoveryConflictPending
Definition: proc.h:113
static PGPROC * allProcs
Definition: procarray.c:99
Oid databaseId
Definition: proc.h:103
static ProcArrayStruct * procArray
Definition: procarray.c:97
#define InvalidOid
Definition: postgres_ext.h:36
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:94
BackendId backendId
Definition: lock.h:65
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1110
Definition: proc.h:84
int pid
Definition: proc.h:98
pid_t CancelVirtualTransaction ( VirtualTransactionId  vxid,
ProcSignalReason  sigmode 
)

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

2621 {
2622  ProcArrayStruct *arrayP = procArray;
2623  int index;
2624  pid_t pid = 0;
2625 
2626  LWLockAcquire(ProcArrayLock, LW_SHARED);
2627 
2628  for (index = 0; index < arrayP->numProcs; index++)
2629  {
2630  int pgprocno = arrayP->pgprocnos[index];
2631  volatile PGPROC *proc = &allProcs[pgprocno];
2632  VirtualTransactionId procvxid;
2633 
2634  GET_VXID_FROM_PGPROC(procvxid, *proc);
2635 
2636  if (procvxid.backendId == vxid.backendId &&
2637  procvxid.localTransactionId == vxid.localTransactionId)
2638  {
2639  proc->recoveryConflictPending = true;
2640  pid = proc->pid;
2641  if (pid != 0)
2642  {
2643  /*
2644  * Kill the pid if it's still here. If not, that's what we
2645  * wanted so ignore any errors.
2646  */
2647  (void) SendProcSignal(pid, sigmode, vxid.backendId);
2648  }
2649  break;
2650  }
2651  }
2652 
2653  LWLockRelease(ProcArrayLock);
2654 
2655  return pid;
2656 }
#define GET_VXID_FROM_PGPROC(vxid, proc)
Definition: lock.h:81
LocalTransactionId localTransactionId
Definition: lock.h:66
Definition: type.h:90
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1714
int SendProcSignal(pid_t pid, ProcSignalReason reason, BackendId backendId)
Definition: procsignal.c:179
bool recoveryConflictPending
Definition: proc.h:113
static PGPROC * allProcs
Definition: procarray.c:99
static ProcArrayStruct * procArray
Definition: procarray.c:97
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:94
BackendId backendId
Definition: lock.h:65
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1110
Definition: proc.h:84
int pid
Definition: proc.h:98
int CountDBBackends ( Oid  databaseid)

Definition at line 2722 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(), and ResolveRecoveryConflictWithDatabase().

2723 {
2724  ProcArrayStruct *arrayP = procArray;
2725  int count = 0;
2726  int index;
2727 
2728  LWLockAcquire(ProcArrayLock, LW_SHARED);
2729 
2730  for (index = 0; index < arrayP->numProcs; index++)
2731  {
2732  int pgprocno = arrayP->pgprocnos[index];
2733  volatile PGPROC *proc = &allProcs[pgprocno];
2734 
2735  if (proc->pid == 0)
2736  continue; /* do not count prepared xacts */
2737  if (!OidIsValid(databaseid) ||
2738  proc->databaseId == databaseid)
2739  count++;
2740  }
2741 
2742  LWLockRelease(ProcArrayLock);
2743 
2744  return count;
2745 }
#define OidIsValid(objectId)
Definition: c.h:534
Definition: type.h:90
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1714
static PGPROC * allProcs
Definition: procarray.c:99
Oid databaseId
Definition: proc.h:103
static ProcArrayStruct * procArray
Definition: procarray.c:97
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:94
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1110
Definition: proc.h:84
int pid
Definition: proc.h:98
int CountDBConnections ( Oid  databaseid)

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

2753 {
2754  ProcArrayStruct *arrayP = procArray;
2755  int count = 0;
2756  int index;
2757 
2758  LWLockAcquire(ProcArrayLock, LW_SHARED);
2759 
2760  for (index = 0; index < arrayP->numProcs; index++)
2761  {
2762  int pgprocno = arrayP->pgprocnos[index];
2763  volatile PGPROC *proc = &allProcs[pgprocno];
2764 
2765  if (proc->pid == 0)
2766  continue; /* do not count prepared xacts */
2767  if (proc->isBackgroundWorker)
2768  continue; /* do not count background workers */
2769  if (!OidIsValid(databaseid) ||
2770  proc->databaseId == databaseid)
2771  count++;
2772  }
2773 
2774  LWLockRelease(ProcArrayLock);
2775 
2776  return count;
2777 }
#define OidIsValid(objectId)
Definition: c.h:534
Definition: type.h:90
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1714
bool isBackgroundWorker
Definition: proc.h:106
static PGPROC * allProcs
Definition: procarray.c:99
Oid databaseId
Definition: proc.h:103
static ProcArrayStruct * procArray
Definition: procarray.c:97
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:94
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1110
Definition: proc.h:84
int pid
Definition: proc.h:98
bool CountOtherDBBackends ( Oid  databaseId,
int *  nbackends,
int *  nprepared 
)

Definition at line 2873 of file procarray.c.

References CHECK_FOR_INTERRUPTS, PGPROC::databaseId, 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().

2874 {
2875  ProcArrayStruct *arrayP = procArray;
2876 
2877 #define MAXAUTOVACPIDS 10 /* max autovacs to SIGTERM per iteration */
2878  int autovac_pids[MAXAUTOVACPIDS];
2879  int tries;
2880 
2881  /* 50 tries with 100ms sleep between tries makes 5 sec total wait */
2882  for (tries = 0; tries < 50; tries++)
2883  {
2884  int nautovacs = 0;
2885  bool found = false;
2886  int index;
2887 
2889 
2890  *nbackends = *nprepared = 0;
2891 
2892  LWLockAcquire(ProcArrayLock, LW_SHARED);
2893 
2894  for (index = 0; index < arrayP->numProcs; index++)
2895  {
2896  int pgprocno = arrayP->pgprocnos[index];
2897  volatile PGPROC *proc = &allProcs[pgprocno];
2898  volatile PGXACT *pgxact = &allPgXact[pgprocno];
2899 
2900  if (proc->databaseId != databaseId)
2901  continue;
2902  if (proc == MyProc)
2903  continue;
2904 
2905  found = true;
2906 
2907  if (proc->pid == 0)
2908  (*nprepared)++;
2909  else
2910  {
2911  (*nbackends)++;
2912  if ((pgxact->vacuumFlags & PROC_IS_AUTOVACUUM) &&
2913  nautovacs < MAXAUTOVACPIDS)
2914  autovac_pids[nautovacs++] = proc->pid;
2915  }
2916  }
2917 
2918  LWLockRelease(ProcArrayLock);
2919 
2920  if (!found)
2921  return false; /* no conflicting backends, so done */
2922 
2923  /*
2924  * Send SIGTERM to any conflicting autovacuums before sleeping. We
2925  * postpone this step until after the loop because we don't want to
2926  * hold ProcArrayLock while issuing kill(). We have no idea what might
2927  * block kill() inside the kernel...
2928  */
2929  for (index = 0; index < nautovacs; index++)
2930  (void) kill(autovac_pids[index], SIGTERM); /* ignore any error */
2931 
2932  /* sleep, then try again */
2933  pg_usleep(100 * 1000L); /* 100ms */
2934  }
2935 
2936  return true; /* timed out, still conflicts */
2937 }
Definition: proc.h:197
PGPROC * MyProc
Definition: proc.c:67
#define MAXAUTOVACPIDS
uint8 vacuumFlags
Definition: proc.h:208
Definition: type.h:90
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1714
void pg_usleep(long microsec)
Definition: signal.c:53
static PGPROC * allProcs
Definition: procarray.c:99
Oid databaseId
Definition: proc.h:103
static ProcArrayStruct * procArray
Definition: procarray.c:97
static PGXACT * allPgXact
Definition: procarray.c:100
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:94
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1110
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:97
Definition: proc.h:84
int pid
Definition: proc.h:98
#define PROC_IS_AUTOVACUUM
Definition: proc.h:43
int CountUserBackends ( Oid  roleid)

Definition at line 2823 of file procarray.c.

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

Referenced by InitializeSessionUserId().

2824 {
2825  ProcArrayStruct *arrayP = procArray;
2826  int count = 0;
2827  int index;
2828 
2829  LWLockAcquire(ProcArrayLock, LW_SHARED);
2830 
2831  for (index = 0; index < arrayP->numProcs; index++)
2832  {
2833  int pgprocno = arrayP->pgprocnos[index];
2834  volatile PGPROC *proc = &allProcs[pgprocno];
2835 
2836  if (proc->pid == 0)
2837  continue; /* do not count prepared xacts */
2838  if (proc->isBackgroundWorker)
2839  continue; /* do not count background workers */
2840  if (proc->roleId == roleid)
2841  count++;
2842  }
2843 
2844  LWLockRelease(ProcArrayLock);
2845 
2846  return count;
2847 }
Oid roleId
Definition: proc.h:104
Definition: type.h:90
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1714
bool isBackgroundWorker
Definition: proc.h:106
static PGPROC * allProcs
Definition: procarray.c:99
static ProcArrayStruct * procArray
Definition: procarray.c:97
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:94
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1110
Definition: proc.h:84
int pid
Definition: proc.h:98
void CreateSharedProcArray ( void  )

Definition at line 220 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, PROCARRAY_MAXPROCS, ProcGlobal, ProcArrayStruct::replication_slot_xmin, ShmemInitStruct(), SpinLockInit, ProcArrayStruct::tailKnownAssignedXids, and TOTAL_MAX_CACHED_SUBXIDS.

Referenced by CreateSharedMemoryAndSemaphores().

221 {
222  bool found;
223 
224  /* Create or attach to the ProcArray shared structure */
226  ShmemInitStruct("Proc Array",
227  add_size(offsetof(ProcArrayStruct, pgprocnos),
228  mul_size(sizeof(int),
230  &found);
231 
232  if (!found)
233  {
234  /*
235  * We're the first - initialize.
236  */
237  procArray->numProcs = 0;
246  }
247 
250 
251  /* Create or attach to the KnownAssignedXids arrays too, if needed */
252  if (EnableHotStandby)
253  {
255  ShmemInitStruct("KnownAssignedXids",
256  mul_size(sizeof(TransactionId),
258  &found);
259  KnownAssignedXidsValid = (bool *)
260  ShmemInitStruct("KnownAssignedXidsValid",
261  mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS),
262  &found);
263  }
264 
265  /* Register and initialize fields of ProcLWLockTranche */
267 }
#define PROCARRAY_MAXPROCS
uint32 TransactionId
Definition: c.h:394
PGXACT * allPgXact
Definition: proc.h:224
#define SpinLockInit(lock)
Definition: spin.h:60
slock_t known_assigned_xids_lck
Definition: procarray.c:77
PROC_HDR * ProcGlobal
Definition: proc.c:80
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition: shmem.c:372
int maxKnownAssignedXids
Definition: procarray.c:73
#define InvalidTransactionId
Definition: transam.h:31
static PGPROC * allProcs
Definition: procarray.c:99
int numKnownAssignedXids
Definition: procarray.c:74
static bool * KnownAssignedXidsValid
Definition: procarray.c:106
TransactionId lastOverflowedXid
Definition: procarray.c:86
static ProcArrayStruct * procArray
Definition: procarray.c:97
TransactionId replication_slot_xmin
Definition: procarray.c:89
Size mul_size(Size s1, Size s2)
Definition: shmem.c:492
static PGXACT * allPgXact
Definition: procarray.c:100
Size add_size(Size s1, Size s2)
Definition: shmem.c:475
#define TOTAL_MAX_CACHED_SUBXIDS
static TransactionId * KnownAssignedXids
Definition: procarray.c:105
void LWLockRegisterTranche(int tranche_id, char *tranche_name)
Definition: lwlock.c:591
bool EnableHotStandby
Definition: xlog.c:95
PGPROC * allProcs
Definition: proc.h:222
int tailKnownAssignedXids
Definition: procarray.c:75
#define offsetof(type, field)
Definition: c.h:551
int headKnownAssignedXids
Definition: procarray.c:76
void ExpireAllKnownAssignedTransactionIds ( void  )

Definition at line 3254 of file procarray.c.

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

Referenced by ShutdownRecoveryTransactionEnvironment().

3255 {
3256  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3258  LWLockRelease(ProcArrayLock);
3259 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1714
static void KnownAssignedXidsRemovePreceding(TransactionId xid)
Definition: procarray.c:3706
#define InvalidTransactionId
Definition: transam.h:31
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1110
void ExpireOldKnownAssignedTransactionIds ( TransactionId  xid)

Definition at line 3266 of file procarray.c.

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

Referenced by ProcArrayApplyRecoveryInfo().

3267 {
3268  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3270  LWLockRelease(ProcArrayLock);
3271 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1714
static void KnownAssignedXidsRemovePreceding(TransactionId xid)
Definition: procarray.c:3706
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1110
void ExpireTreeKnownAssignedTransactionIds ( TransactionId  xid,
int  nsubxids,
TransactionId subxids,
TransactionId  max_xid 
)

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

3231 {
3233 
3234  /*
3235  * Uses same locking as transaction commit
3236  */
3237  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3238 
3239  KnownAssignedXidsRemoveTree(xid, nsubxids, subxids);
3240 
3241  /* As in ProcArrayEndTransaction, advance latestCompletedXid */
3243  max_xid))
3245 
3246  LWLockRelease(ProcArrayLock);
3247 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1714
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:3684
#define Assert(condition)
Definition: c.h:671
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1110
HotStandbyState standbyState
Definition: xlog.c:194
TransactionId latestCompletedXid
Definition: transam.h:135
VirtualTransactionId* GetConflictingVirtualXIDs ( TransactionId  limitXmin,
Oid  dbOid 
)

Definition at line 2545 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, NULL, ProcArrayStruct::numProcs, OidIsValid, ProcArrayStruct::pgprocnos, PGPROC::pid, procArray, TransactionIdFollows(), TransactionIdIsValid, VirtualTransactionIdIsValid, and PGXACT::xmin.

Referenced by ResolveRecoveryConflictWithSnapshot(), and ResolveRecoveryConflictWithTablespace().

2546 {
2547  static VirtualTransactionId *vxids;
2548  ProcArrayStruct *arrayP = procArray;
2549  int count = 0;
2550  int index;
2551 
2552  /*
2553  * If first time through, get workspace to remember main XIDs in. We
2554  * malloc it permanently to avoid repeated palloc/pfree overhead. Allow
2555  * result space, remembering room for a terminator.
2556  */
2557  if (vxids == NULL)
2558  {
2559  vxids = (VirtualTransactionId *)
2560  malloc(sizeof(VirtualTransactionId) * (arrayP->maxProcs + 1));
2561  if (vxids == NULL)
2562  ereport(ERROR,
2563  (errcode(ERRCODE_OUT_OF_MEMORY),
2564  errmsg("out of memory")));
2565  }
2566 
2567  LWLockAcquire(ProcArrayLock, LW_SHARED);
2568 
2569  for (index = 0; index < arrayP->numProcs; index++)
2570  {
2571  int pgprocno = arrayP->pgprocnos[index];
2572  volatile PGPROC *proc = &allProcs[pgprocno];
2573  volatile PGXACT *pgxact = &allPgXact[pgprocno];
2574 
2575  /* Exclude prepared transactions */
2576  if (proc->pid == 0)
2577  continue;
2578 
2579  if (!OidIsValid(dbOid) ||
2580  proc->databaseId == dbOid)
2581  {
2582  /* Fetch xmin just once - can't change on us, but good coding */
2583  TransactionId pxmin = pgxact->xmin;
2584 
2585  /*
2586  * We ignore an invalid pxmin because this means that backend has
2587  * no snapshot currently. We hold a Share lock to avoid contention
2588  * with users taking snapshots. That is not a problem because the
2589  * current xmin is always at least one higher than the latest
2590  * removed xid, so any new snapshot would never conflict with the
2591  * test here.
2592  */
2593  if (!TransactionIdIsValid(limitXmin) ||
2594  (TransactionIdIsValid(pxmin) && !TransactionIdFollows(pxmin, limitXmin)))
2595  {
2596  VirtualTransactionId vxid;
2597 
2598  GET_VXID_FROM_PGPROC(vxid, *proc);
2599  if (VirtualTransactionIdIsValid(vxid))
2600  vxids[count++] = vxid;
2601  }
2602  }
2603  }
2604 
2605  LWLockRelease(ProcArrayLock);
2606 
2607  /* add the terminator */
2608  vxids[count].backendId = InvalidBackendId;
2610 
2611  return vxids;
2612 }
#define GET_VXID_FROM_PGPROC(vxid, proc)
Definition: lock.h:81
bool TransactionIdFollows(TransactionId id1, TransactionId id2)
Definition: transam.c:334
uint32 TransactionId
Definition: c.h:394
Definition: proc.h:197
TransactionId xmin
Definition: proc.h:203
int errcode(int sqlerrcode)
Definition: elog.c:575
LocalTransactionId localTransactionId
Definition: lock.h:66
#define OidIsValid(objectId)
Definition: c.h:534
Definition: type.h:90
#define malloc(a)
Definition: header.h:45
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1714
#define ERROR
Definition: elog.h:43
static PGPROC * allProcs
Definition: procarray.c:99
Oid databaseId
Definition: proc.h:103
#define ereport(elevel, rest)
Definition: elog.h:122
static ProcArrayStruct * procArray
Definition: procarray.c:97
#define VirtualTransactionIdIsValid(vxid)
Definition: lock.h:72
#define InvalidBackendId
Definition: backendid.h:23
static PGXACT * allPgXact
Definition: procarray.c:100
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:94
#define NULL
Definition: c.h:226
BackendId backendId
Definition: lock.h:65
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1110
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define InvalidLocalTransactionId
Definition: lock.h:70
#define TransactionIdIsValid(xid)
Definition: transam.h:41
Definition: proc.h:84
int pid
Definition: proc.h:98
VirtualTransactionId* GetCurrentVirtualXIDs ( TransactionId  limitXmin,
bool  excludeXmin0,
bool  allDbs,
int  excludeVacuum,
int *  nvxids 
)

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

2460 {
2461  VirtualTransactionId *vxids;
2462  ProcArrayStruct *arrayP = procArray;
2463  int count = 0;
2464  int index;
2465 
2466  /* allocate what's certainly enough result space */
2467  vxids = (VirtualTransactionId *)
2468  palloc(sizeof(VirtualTransactionId) * arrayP->maxProcs);
2469 
2470  LWLockAcquire(ProcArrayLock, LW_SHARED);
2471 
2472  for (index = 0; index < arrayP->numProcs; index++)
2473  {
2474  int pgprocno = arrayP->pgprocnos[index];
2475  volatile PGPROC *proc = &allProcs[pgprocno];
2476  volatile PGXACT *pgxact = &allPgXact[pgprocno];
2477 
2478  if (proc == MyProc)
2479  continue;
2480 
2481  if (excludeVacuum & pgxact->vacuumFlags)
2482  continue;
2483 
2484  if (allDbs || proc->databaseId == MyDatabaseId)
2485  {
2486  /* Fetch xmin just once - might change on us */
2487  TransactionId pxmin = pgxact->xmin;
2488 
2489  if (excludeXmin0 && !TransactionIdIsValid(pxmin))
2490  continue;
2491 
2492  /*
2493  * InvalidTransactionId precedes all other XIDs, so a proc that
2494  * hasn't set xmin yet will not be rejected by this test.
2495  */
2496  if (!TransactionIdIsValid(limitXmin) ||
2497  TransactionIdPrecedesOrEquals(pxmin, limitXmin))
2498  {
2499  VirtualTransactionId vxid;
2500 
2501  GET_VXID_FROM_PGPROC(vxid, *proc);
2502  if (VirtualTransactionIdIsValid(vxid))
2503  vxids[count++] = vxid;
2504  }
2505  }
2506  }
2507 
2508  LWLockRelease(ProcArrayLock);
2509 
2510  *nvxids = count;
2511  return vxids;
2512 }
#define GET_VXID_FROM_PGPROC(vxid, proc)
Definition: lock.h:81
uint32 TransactionId
Definition: c.h:394
Definition: proc.h:197
TransactionId xmin
Definition: proc.h:203
PGPROC * MyProc
Definition: proc.c:67
uint8 vacuumFlags
Definition: proc.h:208
Definition: type.h:90
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1714
bool TransactionIdPrecedesOrEquals(TransactionId id1, TransactionId id2)
Definition: transam.c:319
static PGPROC * allProcs
Definition: procarray.c:99
Oid databaseId
Definition: proc.h:103
static ProcArrayStruct * procArray
Definition: procarray.c:97
#define VirtualTransactionIdIsValid(vxid)
Definition: lock.h:72
static PGXACT * allPgXact
Definition: procarray.c:100
Oid MyDatabaseId
Definition: globals.c:76
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:94
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1110
void * palloc(Size size)
Definition: mcxt.c:891
#define TransactionIdIsValid(xid)
Definition: transam.h:41
Definition: proc.h:84
int GetMaxSnapshotSubxidCount ( void  )

Definition at line 1462 of file procarray.c.

References TOTAL_MAX_CACHED_SUBXIDS.

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

1463 {
1464  return TOTAL_MAX_CACHED_SUBXIDS;
1465 }
#define TOTAL_MAX_CACHED_SUBXIDS
int GetMaxSnapshotXidCount ( void  )

Definition at line 1451 of file procarray.c.

References ProcArrayStruct::maxProcs.

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

1452 {
1453  return procArray->maxProcs;
1454 }
static ProcArrayStruct * procArray
Definition: procarray.c:97
TransactionId GetOldestActiveTransactionId ( void  )

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

2084 {
2085  ProcArrayStruct *arrayP = procArray;
2086  TransactionId oldestRunningXid;
2087  int index;
2088 
2090 
2091  LWLockAcquire(ProcArrayLock, LW_SHARED);
2092 
2093  /*
2094  * It's okay to read nextXid without acquiring XidGenLock because (1) we
2095  * assume TransactionIds can be read atomically and (2) we don't care if
2096  * we get a slightly stale value. It can't be very stale anyway, because
2097  * the LWLockAcquire above will have done any necessary memory
2098  * interlocking.
2099  */
2100  oldestRunningXid = ShmemVariableCache->nextXid;
2101 
2102  /*
2103  * Spin over procArray collecting all xids and subxids.
2104  */
2105  for (index = 0; index < arrayP->numProcs; index++)
2106  {
2107  int pgprocno = arrayP->pgprocnos[index];
2108  volatile PGXACT *pgxact = &allPgXact[pgprocno];
2109  TransactionId xid;
2110 
2111  /* Fetch xid just once - see GetNewTransactionId */
2112  xid = pgxact->xid;
2113 
2114  if (!TransactionIdIsNormal(xid))
2115  continue;
2116 
2117  if (TransactionIdPrecedes(xid, oldestRunningXid))
2118  oldestRunningXid = xid;
2119 
2120  /*
2121  * Top-level XID of a transaction is always less than any of its
2122  * subxids, so we don't need to check if any of the subxids are
2123  * smaller than oldestRunningXid
2124  */
2125  }
2126 
2127  LWLockRelease(ProcArrayLock);
2128 
2129  return oldestRunningXid;
2130 }
uint32 TransactionId
Definition: c.h:394
Definition: proc.h:197
TransactionId xid
Definition: proc.h:199
bool RecoveryInProgress(void)
Definition: xlog.c:7805
Definition: type.h:90
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1714
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:97
static PGXACT * allPgXact
Definition: procarray.c:100
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:94
#define Assert(condition)
Definition: c.h:671
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1110
#define TransactionIdIsNormal(xid)
Definition: transam.h:42
TransactionId GetOldestSafeDecodingTransactionId ( void  )

Definition at line 2149 of file procarray.c.

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

Referenced by CreateInitDecodingContext().

2150 {
2151  ProcArrayStruct *arrayP = procArray;
2152  TransactionId oldestSafeXid;
2153  int index;
2154  bool recovery_in_progress = RecoveryInProgress();
2155 
2156  Assert(LWLockHeldByMe(ProcArrayLock));
2157 
2158  /*
2159  * Acquire XidGenLock, so no transactions can acquire an xid while we're
2160  * running. If no transaction with xid were running concurrently a new xid
2161  * could influence the RecentXmin et al.
2162  *
2163  * We initialize the computation to nextXid since that's guaranteed to be
2164  * a safe, albeit pessimal, value.
2165  */
2166  LWLockAcquire(XidGenLock, LW_SHARED);
2167  oldestSafeXid = ShmemVariableCache->nextXid;
2168 
2169  /*
2170  * If there's already a slot pegging the xmin horizon, we can start with
2171  * that value, it's guaranteed to be safe since it's computed by this
2172  * routine initially and has been enforced since.
2173  */
2176  oldestSafeXid))
2177  oldestSafeXid = procArray->replication_slot_catalog_xmin;
2178 
2179  /*
2180  * If we're not in recovery, we walk over the procarray and collect the
2181  * lowest xid. Since we're called with ProcArrayLock held and have
2182  * acquired XidGenLock, no entries can vanish concurrently, since
2183  * PGXACT->xid is only set with XidGenLock held and only cleared with
2184  * ProcArrayLock held.
2185  *
2186  * In recovery we can't lower the safe value besides what we've computed
2187  * above, so we'll have to wait a bit longer there. We unfortunately can
2188  * *not* use KnownAssignedXidsGetOldestXmin() since the KnownAssignedXids
2189  * machinery can miss values and return an older value than is safe.
2190  */
2191  if (!recovery_in_progress)
2192  {
2193  /*
2194  * Spin over procArray collecting all min(PGXACT->xid)
2195  */
2196  for (index = 0; index < arrayP->numProcs; index++)
2197  {
2198  int pgprocno = arrayP->pgprocnos[index];
2199  volatile PGXACT *pgxact = &allPgXact[pgprocno];
2200  TransactionId xid;
2201 
2202  /* Fetch xid just once - see GetNewTransactionId */
2203  xid = pgxact->xid;
2204 
2205  if (!TransactionIdIsNormal(xid))
2206  continue;
2207 
2208  if (TransactionIdPrecedes(xid, oldestSafeXid))
2209  oldestSafeXid = xid;
2210  }
2211  }
2212 
2213  LWLockRelease(XidGenLock);
2214 
2215  return oldestSafeXid;
2216 }
uint32 TransactionId
Definition: c.h:394
Definition: proc.h:197
bool LWLockHeldByMe(LWLock *l)
Definition: lwlock.c:1830
TransactionId xid
Definition: proc.h:199
TransactionId replication_slot_catalog_xmin
Definition: procarray.c:91
bool RecoveryInProgress(void)
Definition: xlog.c:7805
Definition: type.h:90
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1714
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:97
static PGXACT * allPgXact
Definition: procarray.c:100
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:94
#define Assert(condition)
Definition: c.h:671
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1110
#define TransactionIdIsValid(xid)
Definition: transam.h:41
#define TransactionIdIsNormal(xid)
Definition: transam.h:42
TransactionId GetOldestXmin ( Relation  rel,
bool  ignoreVacuum 
)

Definition at line 1305 of file procarray.c.

References Assert, PGPROC::databaseId, FirstNormalTransactionId, InvalidTransactionId, KnownAssignedXidsGetOldestXmin(), VariableCacheData::latestCompletedXid, LW_SHARED, LWLockAcquire(), LWLockRelease(), MyDatabaseId, NormalTransactionIdPrecedes, NULL, ProcArrayStruct::numProcs, ProcArrayStruct::pgprocnos, PROC_IN_LOGICAL_DECODING, PROC_IN_VACUUM, procArray, 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().

1306 {
1307  ProcArrayStruct *arrayP = procArray;
1308  TransactionId result;
1309  int index;
1310  bool allDbs;
1311 
1312  volatile TransactionId replication_slot_xmin = InvalidTransactionId;
1313  volatile TransactionId replication_slot_catalog_xmin = InvalidTransactionId;
1314 
1315  /*
1316  * If we're not computing a relation specific limit, or if a shared
1317  * relation has been passed in, backends in all databases have to be
1318  * considered.
1319  */
1320  allDbs = rel == NULL || rel->rd_rel->relisshared;
1321 
1322  /* Cannot look for individual databases during recovery */
1323  Assert(allDbs || !RecoveryInProgress());
1324 
1325  LWLockAcquire(ProcArrayLock, LW_SHARED);
1326 
1327  /*
1328  * We initialize the MIN() calculation with latestCompletedXid + 1. This
1329  * is a lower bound for the XIDs that might appear in the ProcArray later,
1330  * and so protects us against overestimating the result due to future
1331  * additions.
1332  */
1334  Assert(TransactionIdIsNormal(result));
1335  TransactionIdAdvance(result);
1336 
1337  for (index = 0; index < arrayP->numProcs; index++)
1338  {
1339  int pgprocno = arrayP->pgprocnos[index];
1340  volatile PGPROC *proc = &allProcs[pgprocno];
1341  volatile PGXACT *pgxact = &allPgXact[pgprocno];
1342 
1343  /*
1344  * Backend is doing logical decoding which manages xmin separately,
1345  * check below.
1346  */
1347  if (pgxact->vacuumFlags & PROC_IN_LOGICAL_DECODING)
1348  continue;
1349 
1350  if (ignoreVacuum && (pgxact->vacuumFlags & PROC_IN_VACUUM))
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 slave servers. This is quick and
1410  * 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 (TransactionIdIsValid(replication_slot_xmin) &&
1427  NormalTransactionIdPrecedes(replication_slot_xmin, result))
1428  result = replication_slot_xmin;
1429 
1430  /*
1431  * After locks have been released and defer_cleanup_age has been applied,
1432  * check whether we need to back up further to make logical decoding
1433  * possible. We need to do so if we're computing the global limit (rel =
1434  * NULL) or if the passed relation is a catalog relation of some kind.
1435  */
1436  if ((rel == NULL ||
1438  TransactionIdIsValid(replication_slot_catalog_xmin) &&
1439  NormalTransactionIdPrecedes(replication_slot_catalog_xmin, result))
1440  result = replication_slot_catalog_xmin;
1441 
1442  return result;
1443 }
#define TransactionIdAdvance(dest)
Definition: transam.h:48
#define PROC_IN_LOGICAL_DECODING
Definition: proc.h:47
uint32 TransactionId
Definition: c.h:394
Definition: proc.h:197
TransactionId xmin
Definition: proc.h:203
TransactionId xid
Definition: proc.h:199
int vacuum_defer_cleanup_age
Definition: standby.c:37
TransactionId replication_slot_catalog_xmin
Definition: procarray.c:91
Form_pg_class rd_rel
Definition: rel.h:113
bool RecoveryInProgress(void)
Definition: xlog.c:7805
uint8 vacuumFlags
Definition: proc.h:208
Definition: type.h:90
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1714
#define PROC_IN_VACUUM
Definition: proc.h:44
#define FirstNormalTransactionId
Definition: transam.h:34
VariableCache ShmemVariableCache
Definition: varsup.c:34
#define InvalidTransactionId
Definition: transam.h:31
static PGPROC * allProcs
Definition: procarray.c:99
Oid databaseId
Definition: proc.h:103
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
static ProcArrayStruct * procArray
Definition: procarray.c:97
TransactionId replication_slot_xmin
Definition: procarray.c:89
static PGXACT * allPgXact
Definition: procarray.c:100
#define RelationIsAccessibleInLogicalDecoding(relation)
Definition: rel.h:556
Oid MyDatabaseId
Definition: globals.c:76
static TransactionId KnownAssignedXidsGetOldestXmin(void)
Definition: procarray.c:3857
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:94
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1110
#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:84
TransactionId latestCompletedXid
Definition: transam.h:135
RunningTransactions GetRunningTransactionData ( void  )

Definition at line 1925 of file procarray.c.

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

1926 {
1927  /* result workspace */
1928  static RunningTransactionsData CurrentRunningXactsData;
1929 
1930  ProcArrayStruct *arrayP = procArray;
1931  RunningTransactions CurrentRunningXacts = &CurrentRunningXactsData;
1932  TransactionId latestCompletedXid;
1933  TransactionId oldestRunningXid;
1934  TransactionId *xids;
1935  int index;
1936  int count;
1937  int subcount;
1938  bool suboverflowed;
1939 
1941 
1942  /*
1943  * Allocating space for maxProcs xids is usually overkill; numProcs would
1944  * be sufficient. But it seems better to do the malloc while not holding
1945  * the lock, so we can't look at numProcs. Likewise, we allocate much
1946  * more subxip storage than is probably needed.
1947  *
1948  * Should only be allocated in bgwriter, since only ever executed during
1949  * checkpoints.
1950  */
1951  if (CurrentRunningXacts->xids == NULL)
1952  {
1953  /*
1954  * First call
1955  */
1956  CurrentRunningXacts->xids = (TransactionId *)
1958  if (CurrentRunningXacts->xids == NULL)
1959  ereport(ERROR,
1960  (errcode(ERRCODE_OUT_OF_MEMORY),
1961  errmsg("out of memory")));
1962  }
1963 
1964  xids = CurrentRunningXacts->xids;
1965 
1966  count = subcount = 0;
1967  suboverflowed = false;
1968 
1969  /*
1970  * Ensure that no xids enter or leave the procarray while we obtain
1971  * snapshot.
1972  */
1973  LWLockAcquire(ProcArrayLock, LW_SHARED);
1974  LWLockAcquire(XidGenLock, LW_SHARED);
1975 
1976  latestCompletedXid = ShmemVariableCache->latestCompletedXid;
1977 
1978  oldestRunningXid = ShmemVariableCache->nextXid;
1979 
1980  /*
1981  * Spin over procArray collecting all xids
1982  */
1983  for (index = 0; index < arrayP->numProcs; index++)
1984  {
1985  int pgprocno = arrayP->pgprocnos[index];
1986  volatile PGXACT *pgxact = &allPgXact[pgprocno];
1987  TransactionId xid;
1988 
1989  /* Fetch xid just once - see GetNewTransactionId */
1990  xid = pgxact->xid;
1991 
1992  /*
1993  * We don't need to store transactions that don't have a TransactionId
1994  * yet because they will not show as running on a standby server.
1995  */
1996  if (!TransactionIdIsValid(xid))
1997  continue;
1998 
1999  xids[count++] = xid;
2000 
2001  if (TransactionIdPrecedes(xid, oldestRunningXid))
2002  oldestRunningXid = xid;
2003 
2004  if (pgxact->overflowed)
2005  suboverflowed = true;
2006  }
2007 
2008  /*
2009  * Spin over procArray collecting all subxids, but only if there hasn't
2010  * been a suboverflow.
2011  */
2012  if (!suboverflowed)
2013  {
2014  for (index = 0; index < arrayP->numProcs; index++)
2015  {
2016  int pgprocno = arrayP->pgprocnos[index];
2017  volatile PGPROC *proc = &allProcs[pgprocno];
2018  volatile PGXACT *pgxact = &allPgXact[pgprocno];
2019  int nxids;
2020 
2021  /*
2022  * Save subtransaction XIDs. Other backends can't add or remove
2023  * entries while we're holding XidGenLock.
2024  */
2025  nxids = pgxact->nxids;
2026  if (nxids > 0)
2027  {
2028  memcpy(&xids[count], (void *) proc->subxids.xids,
2029  nxids * sizeof(TransactionId));
2030  count += nxids;
2031  subcount += nxids;
2032 
2033  /*
2034  * Top-level XID of a transaction is always less than any of
2035  * its subxids, so we don't need to check if any of the
2036  * subxids are smaller than oldestRunningXid
2037  */
2038  }
2039  }
2040  }
2041 
2042  /*
2043  * It's important *not* to include the limits set by slots here because
2044  * snapbuild.c uses oldestRunningXid to manage its xmin horizon. If those
2045  * were to be included here the initial value could never increase because
2046  * of a circular dependency where slots only increase their limits when
2047  * running xacts increases oldestRunningXid and running xacts only
2048  * increases if slots do.
2049  */
2050 
2051  CurrentRunningXacts->xcnt = count - subcount;
2052  CurrentRunningXacts->subxcnt = subcount;
2053  CurrentRunningXacts->subxid_overflow = suboverflowed;
2054  CurrentRunningXacts->nextXid = ShmemVariableCache->nextXid;
2055  CurrentRunningXacts->oldestRunningXid = oldestRunningXid;
2056  CurrentRunningXacts->latestCompletedXid = latestCompletedXid;
2057 
2058  Assert(TransactionIdIsValid(CurrentRunningXacts->nextXid));
2059  Assert(TransactionIdIsValid(CurrentRunningXacts->oldestRunningXid));
2060  Assert(TransactionIdIsNormal(CurrentRunningXacts->latestCompletedXid));
2061 
2062  /* We don't release the locks here, the caller is responsible for that */
2063 
2064  return CurrentRunningXacts;
2065 }
TransactionId oldestRunningXid
Definition: standby.h:76
uint32 TransactionId
Definition: c.h:394
Definition: proc.h:197
TransactionId xid
Definition: proc.h:199
int errcode(int sqlerrcode)
Definition: elog.c:575
TransactionId * xids
Definition: standby.h:79
bool RecoveryInProgress(void)
Definition: xlog.c:7805
TransactionId latestCompletedXid
Definition: standby.h:77
Definition: type.h:90
#define malloc(a)
Definition: header.h:45
#define ERROR
Definition: elog.h:43
TransactionId nextXid
Definition: transam.h:117
uint8 nxids
Definition: proc.h:213
VariableCache ShmemVariableCache
Definition: varsup.c:34
static PGPROC * allProcs
Definition: procarray.c:99
struct XidCache subxids
Definition: proc.h:148
#define ereport(elevel, rest)
Definition: elog.h:122
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
static ProcArrayStruct * procArray
Definition: procarray.c:97
static PGXACT * allPgXact
Definition: procarray.c:100
bool overflowed
Definition: proc.h:209
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:94
TransactionId xids[PGPROC_MAX_CACHED_SUBXIDS]
Definition: proc.h:39
#define TOTAL_MAX_CACHED_SUBXIDS
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1110
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:84
TransactionId latestCompletedXid
Definition: transam.h:135
Snapshot GetSnapshotData ( Snapshot  snapshot)

Definition at line 1503 of file procarray.c.

References SnapshotData::active_count, Assert, SnapshotData::copied, SnapshotData::curcid, ereport, errcode(), errmsg(), ERROR, FirstNormalTransactionId, GetCurrentCommandId(), GetMaxSnapshotSubxidCount(), GetMaxSnapshotXidCount(), GetSnapshotCurrentTimestamp(), GetXLogInsertRecPtr(), InvalidTransactionId, InvalidXLogRecPtr, KnownAssignedXidsGetAndSetXmin(), ProcArrayStruct::lastOverflowedXid, VariableCacheData::latestCompletedXid, SnapshotData::lsn, LW_SHARED, LWLockAcquire(), LWLockRelease(), MaintainOldSnapshotTimeMapping(), malloc, MyPgXact, NormalTransactionIdPrecedes, NULL, 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().

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

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

2238 {
2239  VirtualTransactionId *vxids;
2240  ProcArrayStruct *arrayP = procArray;
2241  int count = 0;
2242  int index;
2243 
2244  /* allocate what's certainly enough result space */
2245  vxids = (VirtualTransactionId *)
2246  palloc(sizeof(VirtualTransactionId) * arrayP->maxProcs);
2247 
2248  LWLockAcquire(ProcArrayLock, LW_SHARED);
2249 
2250  for (index = 0; index < arrayP->numProcs; index++)
2251  {
2252  int pgprocno = arrayP->pgprocnos[index];
2253  volatile PGPROC *proc = &allProcs[pgprocno];
2254  volatile PGXACT *pgxact = &allPgXact[pgprocno];
2255 
2256  if (pgxact->delayChkpt)
2257  {
2258  VirtualTransactionId vxid;
2259 
2260  GET_VXID_FROM_PGPROC(vxid, *proc);
2261  if (VirtualTransactionIdIsValid(vxid))
2262  vxids[count++] = vxid;
2263  }
2264  }
2265 
2266  LWLockRelease(ProcArrayLock);
2267 
2268  *nvxids = count;
2269  return vxids;
2270 }
#define GET_VXID_FROM_PGPROC(vxid, proc)
Definition: lock.h:81
Definition: proc.h:197
Definition: type.h:90
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1714
static PGPROC * allProcs
Definition: procarray.c:99
bool delayChkpt
Definition: proc.h:210
static ProcArrayStruct * procArray
Definition: procarray.c:97
#define VirtualTransactionIdIsValid(vxid)
Definition: lock.h:72
static PGXACT * allPgXact
Definition: procarray.c:100
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:94
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1110
void * palloc(Size size)
Definition: mcxt.c:891
Definition: proc.h:84
bool HaveVirtualXIDsDelayingChkpt ( VirtualTransactionId vxids,
int  nvxids 
)

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

2283 {
2284  bool result = false;
2285  ProcArrayStruct *arrayP = procArray;
2286  int index;
2287 
2288  LWLockAcquire(ProcArrayLock, LW_SHARED);
2289 
2290  for (index = 0; index < arrayP->numProcs; index++)
2291  {
2292  int pgprocno = arrayP->pgprocnos[index];
2293  volatile PGPROC *proc = &allProcs[pgprocno];
2294  volatile PGXACT *pgxact = &allPgXact[pgprocno];
2295  VirtualTransactionId vxid;
2296 
2297  GET_VXID_FROM_PGPROC(vxid, *proc);
2298 
2299  if (pgxact->delayChkpt && VirtualTransactionIdIsValid(vxid))
2300  {
2301  int i;
2302 
2303  for (i = 0; i < nvxids; i++)
2304  {
2305  if (VirtualTransactionIdEquals(vxid, vxids[i]))
2306  {
2307  result = true;
2308  break;
2309  }
2310  }
2311  if (result)
2312  break;
2313  }
2314  }
2315 
2316  LWLockRelease(ProcArrayLock);
2317 
2318  return result;
2319 }
#define GET_VXID_FROM_PGPROC(vxid, proc)
Definition: lock.h:81
Definition: proc.h:197
Definition: type.h:90
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1714
#define VirtualTransactionIdEquals(vxid1, vxid2)
Definition: lock.h:75
static PGPROC * allProcs
Definition: procarray.c:99
bool delayChkpt
Definition: proc.h:210
static ProcArrayStruct * procArray
Definition: procarray.c:97
#define VirtualTransactionIdIsValid(vxid)
Definition: lock.h:72
static PGXACT * allPgXact
Definition: procarray.c:100
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:94
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1110
int i
Definition: proc.h:84
bool IsBackendPid ( int  pid)

Definition at line 2424 of file procarray.c.

References BackendPidGetProc(), and NULL.

Referenced by ApplyLauncherWakeup(), logicalrep_worker_find(), and pg_stat_get_subscription().

2425 {
2426  return (BackendPidGetProc(pid) != NULL);
2427 }
PGPROC * BackendPidGetProc(int pid)
Definition: procarray.c:2329
#define NULL
Definition: c.h:226
static bool KnownAssignedXidExists ( TransactionId  xid)
static

Definition at line 3645 of file procarray.c.

References Assert, KnownAssignedXidsSearch(), and TransactionIdIsValid.

Referenced by TransactionIdIsInProgress().

3646 {
3648 
3649  return KnownAssignedXidsSearch(xid, false);
3650 }
#define Assert(condition)
Definition: c.h:671
static bool KnownAssignedXidsSearch(TransactionId xid, bool remove)
Definition: procarray.c:3551
#define TransactionIdIsValid(xid)
Definition: transam.h:41
static void KnownAssignedXidsAdd ( TransactionId  from_xid,
TransactionId  to_xid,
bool  exclusive_lock 
)
static

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

3434 {
3435  /* use volatile pointer to prevent code rearrangement */
3436  volatile ProcArrayStruct *pArray = procArray;
3437  TransactionId next_xid;
3438  int head,
3439  tail;
3440  int nxids;
3441  int i;
3442 
3443  Assert(TransactionIdPrecedesOrEquals(from_xid, to_xid));
3444 
3445  /*
3446  * Calculate how many array slots we'll need. Normally this is cheap; in
3447  * the unusual case where the XIDs cross the wrap point, we do it the hard
3448  * way.
3449  */
3450  if (to_xid >= from_xid)
3451  nxids = to_xid - from_xid + 1;
3452  else
3453  {
3454  nxids = 1;
3455  next_xid = from_xid;
3456  while (TransactionIdPrecedes(next_xid, to_xid))
3457  {
3458  nxids++;
3459  TransactionIdAdvance(next_xid);
3460  }
3461  }
3462 
3463  /*
3464  * Since only the startup process modifies the head/tail pointers, we
3465  * don't need a lock to read them here.
3466  */
3467  head = pArray->headKnownAssignedXids;
3468  tail = pArray->tailKnownAssignedXids;
3469 
3470  Assert(head >= 0 && head <= pArray->maxKnownAssignedXids);
3471  Assert(tail >= 0 && tail < pArray->maxKnownAssignedXids);
3472 
3473  /*
3474  * Verify that insertions occur in TransactionId sequence. Note that even
3475  * if the last existing element is marked invalid, it must still have a
3476  * correctly sequenced XID value.
3477  */
3478  if (head > tail &&
3479  TransactionIdFollowsOrEquals(KnownAssignedXids[head - 1], from_xid))
3480  {
3482  elog(ERROR, "out-of-order XID insertion in KnownAssignedXids");
3483  }
3484 
3485  /*
3486  * If our xids won't fit in the remaining space, compress out free space
3487  */
3488  if (head + nxids > pArray->maxKnownAssignedXids)
3489  {
3490  /* must hold lock to compress */
3491  if (!exclusive_lock)
3492  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3493 
3495 
3496  head = pArray->headKnownAssignedXids;
3497  /* note: we no longer care about the tail pointer */
3498 
3499  if (!exclusive_lock)
3500  LWLockRelease(ProcArrayLock);
3501 
3502  /*
3503  * If it still won't fit then we're out of memory
3504  */
3505  if (head + nxids > pArray->maxKnownAssignedXids)
3506  elog(ERROR, "too many KnownAssignedXids");
3507  }
3508 
3509  /* Now we can insert the xids into the space starting at head */
3510  next_xid = from_xid;
3511  for (i = 0; i < nxids; i++)
3512  {
3513  KnownAssignedXids[head] = next_xid;
3514  KnownAssignedXidsValid[head] = true;
3515  TransactionIdAdvance(next_xid);
3516  head++;
3517  }
3518 
3519  /* Adjust count of number of valid entries */
3520  pArray->numKnownAssignedXids += nxids;
3521 
3522  /*
3523  * Now update the head pointer. We use a spinlock to protect this
3524  * pointer, not because the update is likely to be non-atomic, but to
3525  * ensure that other processors see the above array updates before they
3526  * see the head pointer change.
3527  *
3528  * If we're holding ProcArrayLock exclusively, there's no need to take the
3529  * spinlock.
3530  */
3531  if (exclusive_lock)
3532  pArray->headKnownAssignedXids = head;
3533  else
3534  {
3536  pArray->headKnownAssignedXids = head;
3538  }
3539 }
#define TransactionIdAdvance(dest)
Definition: transam.h:48
static void KnownAssignedXidsDisplay(int trace_level)
Definition: procarray.c:3892
uint32 TransactionId
Definition: c.h:394
bool TransactionIdFollowsOrEquals(TransactionId id1, TransactionId id2)
Definition: transam.c:349
slock_t known_assigned_xids_lck
Definition: procarray.c:77
#define LOG
Definition: elog.h:26
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1714
#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:73
int numKnownAssignedXids
Definition: procarray.c:74
static bool * KnownAssignedXidsValid
Definition: procarray.c:106
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
static ProcArrayStruct * procArray
Definition: procarray.c:97
#define SpinLockRelease(lock)
Definition: spin.h:64
#define Assert(condition)
Definition: c.h:671
static TransactionId * KnownAssignedXids
Definition: procarray.c:105
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1110
static void KnownAssignedXidsCompress(bool force)
Definition: procarray.c:3369
int i
#define elog
Definition: elog.h:219
int tailKnownAssignedXids
Definition: procarray.c:75
int headKnownAssignedXids
Definition: procarray.c:76
static void KnownAssignedXidsCompress ( bool  force)
static

Definition at line 3369 of file procarray.c.

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

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

3370 {
3371  /* use volatile pointer to prevent code rearrangement */
3372  volatile ProcArrayStruct *pArray = procArray;
3373  int head,
3374  tail;
3375  int compress_index;
3376  int i;
3377 
3378  /* no spinlock required since we hold ProcArrayLock exclusively */
3379  head = pArray->headKnownAssignedXids;
3380  tail = pArray->tailKnownAssignedXids;
3381 
3382  if (!force)
3383  {
3384  /*
3385  * If we can choose how much to compress, use a heuristic to avoid
3386  * compressing too often or not often enough.
3387  *
3388  * Heuristic is if we have a large enough current spread and less than
3389  * 50% of the elements are currently in use, then compress. This
3390  * should ensure we compress fairly infrequently. We could compress
3391  * less often though the virtual array would spread out more and
3392  * snapshots would become more expensive.
3393  */
3394  int nelements = head - tail;
3395 
3396  if (nelements < 4 * PROCARRAY_MAXPROCS ||
3397  nelements < 2 * pArray->numKnownAssignedXids)
3398  return;
3399  }
3400 
3401  /*
3402  * We compress the array by reading the valid values from tail to head,
3403  * re-aligning data to 0th element.
3404  */
3405  compress_index = 0;
3406  for (i = tail; i < head; i++)
3407  {
3408  if (KnownAssignedXidsValid[i])
3409  {
3410  KnownAssignedXids[compress_index] = KnownAssignedXids[i];
3411  KnownAssignedXidsValid[compress_index] = true;
3412  compress_index++;
3413  }
3414  }
3415 
3416  pArray->tailKnownAssignedXids = 0;
3417  pArray->headKnownAssignedXids = compress_index;
3418 }
#define PROCARRAY_MAXPROCS
static bool * KnownAssignedXidsValid
Definition: procarray.c:106
static ProcArrayStruct * procArray
Definition: procarray.c:97
static TransactionId * KnownAssignedXids
Definition: procarray.c:105
int i
int tailKnownAssignedXids
Definition: procarray.c:75
int headKnownAssignedXids
Definition: procarray.c:76
static void KnownAssignedXidsDisplay ( int  trace_level)
static

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

3893 {
3894  /* use volatile pointer to prevent code rearrangement */
3895  volatile ProcArrayStruct *pArray = procArray;
3897  int head,
3898  tail,
3899  i;
3900  int nxids = 0;
3901 
3902  tail = pArray->tailKnownAssignedXids;
3903  head = pArray->headKnownAssignedXids;
3904 
3905  initStringInfo(&buf);
3906 
3907  for (i = tail; i < head; i++)
3908  {
3909  if (KnownAssignedXidsValid[i])
3910  {
3911  nxids++;
3912  appendStringInfo(&buf, "[%d]=%u ", i, KnownAssignedXids[i]);
3913  }
3914  }
3915 
3916  elog(trace_level, "%d KnownAssignedXids (num=%d tail=%d head=%d) %s",
3917  nxids,
3918  pArray->numKnownAssignedXids,
3919  pArray->tailKnownAssignedXids,
3920  pArray->headKnownAssignedXids,
3921  buf.data);
3922 
3923  pfree(buf.data);
3924 }
void pfree(void *pointer)
Definition: mcxt.c:992
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:110
static char * buf
Definition: pg_test_fsync.c:65
int numKnownAssignedXids
Definition: procarray.c:74
static bool * KnownAssignedXidsValid
Definition: procarray.c:106
void initStringInfo(StringInfo str)
Definition: stringinfo.c:65
static ProcArrayStruct * procArray
Definition: procarray.c:97
static TransactionId * KnownAssignedXids
Definition: procarray.c:105
int i
#define elog
Definition: elog.h:219
int tailKnownAssignedXids
Definition: procarray.c:75
int headKnownAssignedXids
Definition: procarray.c:76
static int KnownAssignedXidsGet ( TransactionId xarray,
TransactionId  xmax 
)
static

Definition at line 3785 of file procarray.c.

References InvalidTransactionId, and KnownAssignedXidsGetAndSetXmin().

Referenced by TransactionIdIsInProgress().

3786 {
3788 
3789  return KnownAssignedXidsGetAndSetXmin(xarray, &xtmp, xmax);
3790 }
uint32 TransactionId
Definition: c.h:394
#define InvalidTransactionId
Definition: transam.h:31
static int KnownAssignedXidsGetAndSetXmin(TransactionId *xarray, TransactionId *xmin, TransactionId xmax)
Definition: procarray.c:3799
static int KnownAssignedXidsGetAndSetXmin ( TransactionId xarray,
TransactionId xmin,
TransactionId  xmax 
)
static

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

3801 {
3802  int count = 0;
3803  int head,
3804  tail;
3805  int i;
3806 
3807  /*
3808  * Fetch head just once, since it may change while we loop. We can stop
3809  * once we reach the initially seen head, since we are certain that an xid
3810  * cannot enter and then leave the array while we hold ProcArrayLock. We
3811  * might miss newly-added xids, but they should be >= xmax so irrelevant
3812  * anyway.
3813  *
3814  * Must take spinlock to ensure we see up-to-date array contents.
3815  */
3820 
3821  for (i = tail; i < head; i++)
3822  {
3823  /* Skip any gaps in the array */
3824  if (KnownAssignedXidsValid[i])
3825  {
3826  TransactionId knownXid = KnownAssignedXids[i];
3827 
3828  /*
3829  * Update xmin if required. Only the first XID need be checked,
3830  * since the array is sorted.
3831  */
3832  if (count == 0 &&
3833  TransactionIdPrecedes(knownXid, *xmin))
3834  *xmin = knownXid;
3835 
3836  /*
3837  * Filter out anything >= xmax, again relying on sorted property
3838  * of array.
3839  */
3840  if (TransactionIdIsValid(xmax) &&
3841  TransactionIdFollowsOrEquals(knownXid, xmax))
3842  break;
3843 
3844  /* Add knownXid into output array */
3845  xarray[count++] = knownXid;
3846  }
3847  }
3848 
3849  return count;
3850 }
uint32 TransactionId
Definition: c.h:394
bool TransactionIdFollowsOrEquals(TransactionId id1, TransactionId id2)
Definition: transam.c:349
slock_t known_assigned_xids_lck
Definition: procarray.c:77
#define SpinLockAcquire(lock)
Definition: spin.h:62
static bool * KnownAssignedXidsValid
Definition: procarray.c:106
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
static ProcArrayStruct * procArray
Definition: procarray.c:97
#define SpinLockRelease(lock)
Definition: spin.h:64
static TransactionId * KnownAssignedXids
Definition: procarray.c:105
int i
#define TransactionIdIsValid(xid)
Definition: transam.h:41
int tailKnownAssignedXids
Definition: procarray.c:75
int headKnownAssignedXids
Definition: procarray.c:76
static TransactionId KnownAssignedXidsGetOldestXmin ( void  )
static

Definition at line 3857 of file procarray.c.

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

Referenced by GetOldestXmin().

3858 {
3859  int head,
3860  tail;
3861  int i;
3862 
3863  /*
3864  * Fetch head just once, since it may change while we loop.
3865  */
3870 
3871  for (i = tail; i < head; i++)
3872  {
3873  /* Skip any gaps in the array */
3874  if (KnownAssignedXidsValid[i])
3875  return KnownAssignedXids[i];
3876  }
3877 
3878  return InvalidTransactionId;
3879 }
slock_t known_assigned_xids_lck
Definition: procarray.c:77
#define SpinLockAcquire(lock)
Definition: spin.h:62
#define InvalidTransactionId
Definition: transam.h:31
static bool * KnownAssignedXidsValid
Definition: procarray.c:106
static ProcArrayStruct * procArray
Definition: procarray.c:97
#define SpinLockRelease(lock)
Definition: spin.h:64
static TransactionId * KnownAssignedXids
Definition: procarray.c:105
int i
int tailKnownAssignedXids
Definition: procarray.c:75
int headKnownAssignedXids
Definition: procarray.c:76
static void KnownAssignedXidsRemove ( TransactionId  xid)
static

Definition at line 3658 of file procarray.c.

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

Referenced by KnownAssignedXidsRemoveTree().

3659 {
3661 
3662  elog(trace_recovery(DEBUG4), "remove KnownAssignedXid %u", xid);
3663 
3664  /*
3665  * Note: we cannot consider it an error to remove an XID that's not
3666  * present. We intentionally remove subxact IDs while processing
3667  * XLOG_XACT_ASSIGNMENT, to avoid array overflow. Then those XIDs will be
3668  * removed again when the top-level xact commits or aborts.
3669  *
3670  * It might be possible to track such XIDs to distinguish this case from
3671  * actual errors, but it would be complicated and probably not worth it.
3672  * So, just ignore the search result.
3673  */
3674  (void) KnownAssignedXidsSearch(xid, true);
3675 }
#define DEBUG4
Definition: elog.h:22
int trace_recovery(int trace_level)
Definition: elog.c:3753
#define Assert(condition)
Definition: c.h:671
static bool KnownAssignedXidsSearch(TransactionId xid, bool remove)
Definition: procarray.c:3551
#define elog
Definition: elog.h:219
#define TransactionIdIsValid(xid)
Definition: transam.h:41
static void KnownAssignedXidsRemovePreceding ( TransactionId  xid)
static

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

3707 {
3708  /* use volatile pointer to prevent code rearrangement */
3709  volatile ProcArrayStruct *pArray = procArray;
3710  int count = 0;
3711  int head,
3712  tail,
3713  i;
3714 
3715  if (!TransactionIdIsValid(removeXid))
3716  {
3717  elog(trace_recovery(DEBUG4), "removing all KnownAssignedXids");
3718  pArray->numKnownAssignedXids = 0;
3719  pArray->headKnownAssignedXids = pArray->tailKnownAssignedXids = 0;
3720  return;
3721  }
3722 
3723  elog(trace_recovery(DEBUG4), "prune KnownAssignedXids to %u", removeXid);
3724 
3725  /*
3726  * Mark entries invalid starting at the tail. Since array is sorted, we
3727  * can stop as soon as we reach an entry >= removeXid.
3728  */
3729  tail = pArray->tailKnownAssignedXids;
3730  head = pArray->headKnownAssignedXids;
3731 
3732  for (i = tail; i < head; i++)
3733  {
3734  if (KnownAssignedXidsValid[i])
3735  {
3736  TransactionId knownXid = KnownAssignedXids[i];
3737 
3738  if (TransactionIdFollowsOrEquals(knownXid, removeXid))
3739  break;
3740 
3741  if (!StandbyTransactionIdIsPrepared(knownXid))
3742  {
3743  KnownAssignedXidsValid[i] = false;
3744  count++;
3745  }
3746  }
3747  }
3748 
3749  pArray->numKnownAssignedXids -= count;
3750  Assert(pArray->numKnownAssignedXids >= 0);
3751 
3752  /*
3753  * Advance the tail pointer if we've marked the tail item invalid.
3754  */
3755  for (i = tail; i < head; i++)
3756  {
3757  if (KnownAssignedXidsValid[i])
3758  break;
3759  }
3760  if (i >= head)
3761  {
3762  /* Array is empty, so we can reset both pointers */
3763  pArray->headKnownAssignedXids = 0;
3764  pArray->tailKnownAssignedXids = 0;
3765  }
3766  else
3767  {
3768  pArray->tailKnownAssignedXids = i;
3769  }
3770 
3771  /* Opportunistically compress the array */
3773 }
uint32 TransactionId
Definition: c.h:394
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:3753
bool StandbyTransactionIdIsPrepared(TransactionId xid)
Definition: twophase.c:1295
int numKnownAssignedXids
Definition: procarray.c:74
static bool * KnownAssignedXidsValid
Definition: procarray.c:106
static ProcArrayStruct * procArray
Definition: procarray.c:97
#define Assert(condition)
Definition: c.h:671
static TransactionId * KnownAssignedXids
Definition: procarray.c:105
static void KnownAssignedXidsCompress(bool force)
Definition: procarray.c:3369
int i
#define elog
Definition: elog.h:219
#define TransactionIdIsValid(xid)
Definition: transam.h:41
int tailKnownAssignedXids
Definition: procarray.c:75
int headKnownAssignedXids
Definition: procarray.c:76
static void KnownAssignedXidsRemoveTree ( TransactionId  xid,
int  nsubxids,
TransactionId subxids 
)
static

Definition at line 3684 of file procarray.c.

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

Referenced by ExpireTreeKnownAssignedTransactionIds(), and ProcArrayApplyXidAssignment().

3686 {
3687  int i;
3688 
3689  if (TransactionIdIsValid(xid))
3691 
3692  for (i = 0; i < nsubxids; i++)
3693  KnownAssignedXidsRemove(subxids[i]);
3694 
3695  /* Opportunistically compress the array */
3697 }
static void KnownAssignedXidsCompress(bool force)
Definition: procarray.c:3369
static void KnownAssignedXidsRemove(TransactionId xid)
Definition: procarray.c:3658
int i
#define TransactionIdIsValid(xid)
Definition: transam.h:41
static void KnownAssignedXidsReset ( void  )
static

Definition at line 3931 of file procarray.c.

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

Referenced by ProcArrayApplyRecoveryInfo().

3932 {
3933  /* use volatile pointer to prevent code rearrangement */
3934  volatile ProcArrayStruct *pArray = procArray;
3935 
3936  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3937 
3938  pArray->numKnownAssignedXids = 0;
3939  pArray->tailKnownAssignedXids = 0;
3940  pArray->headKnownAssignedXids = 0;
3941 
3942  LWLockRelease(ProcArrayLock);
3943 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1714
int numKnownAssignedXids
Definition: procarray.c:74
static ProcArrayStruct * procArray
Definition: procarray.c:97
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1110
int tailKnownAssignedXids
Definition: procarray.c:75
int headKnownAssignedXids
Definition: procarray.c:76
static bool KnownAssignedXidsSearch ( TransactionId  xid,
bool  remove 
)
static

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

3552 {
3553  /* use volatile pointer to prevent code rearrangement */
3554  volatile ProcArrayStruct *pArray = procArray;
3555  int first,
3556  last;
3557  int head;
3558  int tail;
3559  int result_index = -1;
3560 
3561  if (remove)
3562  {
3563  /* we hold ProcArrayLock exclusively, so no need for spinlock */
3564  tail = pArray->tailKnownAssignedXids;
3565  head = pArray->headKnownAssignedXids;
3566  }
3567  else
3568  {
3569  /* take spinlock to ensure we see up-to-date array contents */
3571  tail = pArray->tailKnownAssignedXids;
3572  head = pArray->headKnownAssignedXids;
3574  }
3575 
3576  /*
3577  * Standard binary search. Note we can ignore the KnownAssignedXidsValid
3578  * array here, since even invalid entries will contain sorted XIDs.
3579  */
3580  first = tail;
3581  last = head - 1;
3582  while (first <= last)
3583  {
3584  int mid_index;
3585  TransactionId mid_xid;
3586 
3587  mid_index = (first + last) / 2;
3588  mid_xid = KnownAssignedXids[mid_index];
3589 
3590  if (xid == mid_xid)
3591  {
3592  result_index = mid_index;
3593  break;
3594  }
3595  else if (TransactionIdPrecedes(xid, mid_xid))
3596  last = mid_index - 1;
3597  else
3598  first = mid_index + 1;
3599  }
3600 
3601  if (result_index < 0)
3602  return false; /* not in array */
3603 
3604  if (!KnownAssignedXidsValid[result_index])
3605  return false; /* in array, but invalid */
3606 
3607  if (remove)
3608  {
3609  KnownAssignedXidsValid[result_index] = false;
3610 
3611  pArray->numKnownAssignedXids--;
3612  Assert(pArray->numKnownAssignedXids >= 0);
3613 
3614  /*
3615  * If we're removing the tail element then advance tail pointer over
3616  * any invalid elements. This will speed future searches.
3617  */
3618  if (result_index == tail)
3619  {
3620  tail++;
3621  while (tail < head && !KnownAssignedXidsValid[tail])
3622  tail++;
3623  if (tail >= head)
3624  {
3625  /* Array is empty, so we can reset both pointers */
3626  pArray->headKnownAssignedXids = 0;
3627  pArray->tailKnownAssignedXids = 0;
3628  }
3629  else
3630  {
3631  pArray->tailKnownAssignedXids = tail;
3632  }
3633  }
3634  }
3635 
3636  return true;
3637 }
uint32 TransactionId
Definition: c.h:394
slock_t known_assigned_xids_lck
Definition: procarray.c:77
#define SpinLockAcquire(lock)
Definition: spin.h:62
int numKnownAssignedXids
Definition: procarray.c:74
static bool * KnownAssignedXidsValid
Definition: procarray.c:106
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
static ProcArrayStruct * procArray
Definition: procarray.c:97
#define SpinLockRelease(lock)
Definition: spin.h:64
#define Assert(condition)
Definition: c.h:671
static TransactionId * KnownAssignedXids
Definition: procarray.c:105
int tailKnownAssignedXids
Definition: procarray.c:75
int headKnownAssignedXids
Definition: procarray.c:76
bool MinimumActiveBackends ( int  min)

Definition at line 2668 of file procarray.c.

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

Referenced by XLogFlush().

2669 {
2670  ProcArrayStruct *arrayP = procArray;
2671  int count = 0;
2672  int index;
2673 
2674  /* Quick short-circuit if no minimum is specified */
2675  if (min == 0)
2676  return true;
2677 
2678  /*
2679  * Note: for speed, we don't acquire ProcArrayLock. This is a little bit
2680  * bogus, but since we are only testing fields for zero or nonzero, it
2681  * should be OK. The result is only used for heuristic purposes anyway...
2682  */
2683  for (index = 0; index < arrayP->numProcs; index++)
2684  {
2685  int pgprocno = arrayP->pgprocnos[index];
2686  volatile PGPROC *proc = &allProcs[pgprocno];
2687  volatile PGXACT *pgxact = &allPgXact[pgprocno];
2688 
2689  /*
2690  * Since we're not holding a lock, need to be prepared to deal with
2691  * garbage, as someone could have incremented numProcs but not yet
2692  * filled the structure.
2693  *
2694  * If someone just decremented numProcs, 'proc' could also point to a
2695  * PGPROC entry that's no longer in the array. It still points to a
2696  * PGPROC struct, though, because freed PGPROC entries just go to the
2697  * free list and are recycled. Its contents are nonsense in that case,
2698  * but that's acceptable for this function.
2699  */
2700  if (pgprocno == -1)
2701  continue; /* do not count deleted entries */
2702  if (proc == MyProc)
2703  continue; /* do not count myself */
2704  if (pgxact->xid == InvalidTransactionId)
2705  continue; /* do not count if no XID assigned */
2706  if (proc->pid == 0)
2707  continue; /* do not count prepared xacts */
2708  if (proc->waitLock != NULL)
2709  continue; /* do not count if blocked on a lock */
2710  count++;
2711  if (count >= min)
2712  break;
2713  }
2714 
2715  return count >= min;
2716 }
Definition: proc.h:197
PGPROC * MyProc
Definition: proc.c:67
TransactionId xid
Definition: proc.h:199
Definition: type.h:90
#define InvalidTransactionId
Definition: transam.h:31
static PGPROC * allProcs
Definition: procarray.c:99
LOCK * waitLock
Definition: proc.h:125
static ProcArrayStruct * procArray
Definition: procarray.c:97
static PGXACT * allPgXact
Definition: procarray.c:100
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:94
#define NULL
Definition: c.h:226
Definition: proc.h:84
int pid
Definition: proc.h:98
void ProcArrayAdd ( PGPROC proc)

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

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

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

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

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

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

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

602 {
603  PGXACT *pgxact = &allPgXact[proc->pgprocno];
604 
605  /*
606  * We can skip locking ProcArrayLock here, because this action does not
607  * actually change anyone's view of the set of running XIDs: our entry is
608  * duplicate with the gxact that has already been inserted into the
609  * ProcArray.
610  */
611  pgxact->xid = InvalidTransactionId;
613  pgxact->xmin = InvalidTransactionId;
614  proc->recoveryConflictPending = false;
615 
616  /* redundant, but just in case */
618  pgxact->delayChkpt = false;
619 
620  /* Clear the subtransaction-XID cache too */
621  pgxact->nxids = 0;
622  pgxact->overflowed = false;
623 }
Definition: proc.h:197
TransactionId xmin
Definition: proc.h:203
TransactionId xid
Definition: proc.h:199
uint8 vacuumFlags
Definition: proc.h:208
#define PROC_VACUUM_STATE_MASK
Definition: proc.h:51
bool recoveryConflictPending
Definition: proc.h:113
uint8 nxids
Definition: proc.h:213
#define InvalidTransactionId
Definition: transam.h:31
bool delayChkpt
Definition: proc.h:210
static PGXACT * allPgXact
Definition: procarray.c:100
bool overflowed
Definition: proc.h:209
int pgprocno
Definition: proc.h:99
#define InvalidLocalTransactionId
Definition: lock.h:70
LocalTransactionId lxid
Definition: proc.h:95
void ProcArrayEndTransaction ( PGPROC proc,
TransactionId  latestXid 
)

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

395 {
396  PGXACT *pgxact = &allPgXact[proc->pgprocno];
397 
398  if (TransactionIdIsValid(latestXid))
399  {
400  /*
401  * We must lock ProcArrayLock while clearing our advertised XID, so
402  * that we do not exit the set of "running" transactions while someone
403  * else is taking a snapshot. See discussion in
404  * src/backend/access/transam/README.
405  */
407 
408  /*
409  * If we can immediately acquire ProcArrayLock, we clear our own XID
410  * and release the lock. If not, use group XID clearing to improve
411  * efficiency.
412  */
413  if (LWLockConditionalAcquire(ProcArrayLock, LW_EXCLUSIVE))
414  {
415  ProcArrayEndTransactionInternal(proc, pgxact, latestXid);
416  LWLockRelease(ProcArrayLock);
417  }
418  else
419  ProcArrayGroupClearXid(proc, latestXid);
420  }
421  else
422  {
423  /*
424  * If we have no XID, we don't need to lock, since we won't affect
425  * anyone else's calculation of a snapshot. We might change their
426  * estimate of global xmin, but that's OK.
427  */
429 
431  pgxact->xmin = InvalidTransactionId;
432  /* must be cleared with xid/xmin: */
434  pgxact->delayChkpt = false; /* be sure this is cleared in abort */
435  proc->recoveryConflictPending = false;
436 
437  Assert(pgxact->nxids == 0);
438  Assert(pgxact->overflowed == false);
439  }
440 }
Definition: proc.h:197
TransactionId xmin
Definition: proc.h:203
TransactionId xid
Definition: proc.h:199
static void ProcArrayGroupClearXid(PGPROC *proc, TransactionId latestXid)
Definition: procarray.c:482
uint8 vacuumFlags
Definition: proc.h:208
#define PROC_VACUUM_STATE_MASK
Definition: proc.h:51
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1714
bool LWLockConditionalAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1282
bool recoveryConflictPending
Definition: proc.h:113
uint8 nxids
Definition: proc.h:213
#define InvalidTransactionId
Definition: transam.h:31
bool delayChkpt
Definition: proc.h:210
static PGXACT * allPgXact
Definition: procarray.c:100
bool overflowed
Definition: proc.h:209
static void ProcArrayEndTransactionInternal(PGPROC *proc, PGXACT *pgxact, TransactionId latestXid)
Definition: procarray.c:448
#define Assert(condition)
Definition: c.h:671
int pgprocno
Definition: proc.h:99
#define InvalidLocalTransactionId
Definition: lock.h:70
#define TransactionIdIsValid(xid)
Definition: transam.h:41
LocalTransactionId lxid
Definition: proc.h:95
static void ProcArrayEndTransactionInternal ( PGPROC proc,
PGXACT pgxact,
TransactionId  latestXid 
)
inlinestatic

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

450 {
451  pgxact->xid = InvalidTransactionId;
453  pgxact->xmin = InvalidTransactionId;
454  /* must be cleared with xid/xmin: */
456  pgxact->delayChkpt = false; /* be sure this is cleared in abort */
457  proc->recoveryConflictPending = false;
458 
459  /* Clear the subtransaction-XID cache too while holding the lock */
460  pgxact->nxids = 0;
461  pgxact->overflowed = false;
462 
463  /* Also advance global latestCompletedXid while holding the lock */
465  latestXid))
467 }
TransactionId xmin
Definition: proc.h:203
TransactionId xid
Definition: proc.h:199
uint8 vacuumFlags
Definition: proc.h:208
#define PROC_VACUUM_STATE_MASK
Definition: proc.h:51
bool recoveryConflictPending
Definition: proc.h:113
uint8 nxids
Definition: proc.h:213
VariableCache ShmemVariableCache
Definition: varsup.c:34
#define InvalidTransactionId
Definition: transam.h:31
bool delayChkpt
Definition: proc.h:210
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
bool overflowed
Definition: proc.h:209
#define InvalidLocalTransactionId
Definition: lock.h:70
LocalTransactionId lxid
Definition: proc.h:95
TransactionId latestCompletedXid
Definition: transam.h:135
void ProcArrayGetReplicationSlotXmin ( TransactionId xmin,
TransactionId catalog_xmin 
)

Definition at line 2969 of file procarray.c.

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

Referenced by logical_begin_heap_rewrite().

2971 {
2972  LWLockAcquire(ProcArrayLock, LW_SHARED);
2973 
2974  if (xmin != NULL)
2976 
2977  if (catalog_xmin != NULL)
2978  *catalog_xmin = procArray->replication_slot_catalog_xmin;
2979 
2980  LWLockRelease(ProcArrayLock);
2981 }
TransactionId replication_slot_catalog_xmin
Definition: procarray.c:91
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1714
static ProcArrayStruct * procArray
Definition: procarray.c:97
TransactionId replication_slot_xmin
Definition: procarray.c:89
#define NULL
Definition: c.h:226
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1110
static void ProcArrayGroupClearXid ( PGPROC proc,
TransactionId  latestXid 
)
static

Definition at line 482 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(), ProcArrayEndTransactionInternal(), PROC_HDR::procArrayGroupFirst, PGPROC::procArrayGroupMember, PGPROC::procArrayGroupMemberXid, PGPROC::procArrayGroupNext, ProcGlobal, PGPROC::sem, TransactionIdIsValid, and PGXACT::xid.

Referenced by ProcArrayEndTransaction().

483 {
484  volatile PROC_HDR *procglobal = ProcGlobal;
485  uint32 nextidx;
486  uint32 wakeidx;
487 
488  /* We should definitely have an XID to clear. */
490 
491  /* Add ourselves to the list of processes needing a group XID clear. */
492  proc->procArrayGroupMember = true;
493  proc->procArrayGroupMemberXid = latestXid;
494  while (true)
495  {
496  nextidx = pg_atomic_read_u32(&procglobal->procArrayGroupFirst);
497  pg_atomic_write_u32(&proc->procArrayGroupNext, nextidx);
498 
500  &nextidx,
501  (uint32) proc->pgprocno))
502  break;
503  }
504 
505  /*
506  * If the list was not empty, the leader will clear our XID. It is
507  * impossible to have followers without a leader because the first process
508  * that has added itself to the list will always have nextidx as
509  * INVALID_PGPROCNO.
510  */
511  if (nextidx != INVALID_PGPROCNO)
512  {
513  int extraWaits = 0;
514 
515  /* Sleep until the leader clears our XID. */
516  for (;;)
517  {
518  /* acts as a read barrier */
519  PGSemaphoreLock(proc->sem);
520  if (!proc->procArrayGroupMember)
521  break;
522  extraWaits++;
523  }
524 
526 
527  /* Fix semaphore count for any absorbed wakeups */
528  while (extraWaits-- > 0)
529  PGSemaphoreUnlock(proc->sem);
530  return;
531  }
532 
533  /* We are the leader. Acquire the lock on behalf of everyone. */
534  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
535 
536  /*
537  * Now that we've got the lock, clear the list of processes waiting for
538  * group XID clearing, saving a pointer to the head of the list. Trying
539  * to pop elements one at a time could lead to an ABA problem.
540  */
541  while (true)
542  {
543  nextidx = pg_atomic_read_u32(&procglobal->procArrayGroupFirst);
545  &nextidx,
547  break;
548  }
549 
550  /* Remember head of list so we can perform wakeups after dropping lock. */
551  wakeidx = nextidx;
552 
553  /* Walk the list and clear all XIDs. */
554  while (nextidx != INVALID_PGPROCNO)
555  {
556  PGPROC *proc = &allProcs[nextidx];
557  PGXACT *pgxact = &allPgXact[nextidx];
558 
560 
561  /* Move to next proc in list. */
562  nextidx = pg_atomic_read_u32(&proc->procArrayGroupNext);
563  }
564 
565  /* We're done with the lock now. */
566  LWLockRelease(ProcArrayLock);
567 
568  /*
569  * Now that we've released the lock, go back and wake everybody up. We
570  * don't do this under the lock so as to keep lock hold times to a
571  * minimum. The system calls we need to perform to wake other processes
572  * up are probably much slower than the simple memory writes we did while
573  * holding the lock.
574  */
575  while (wakeidx != INVALID_PGPROCNO)
576  {
577  PGPROC *proc = &allProcs[wakeidx];
578 
579  wakeidx = pg_atomic_read_u32(&proc->procArrayGroupNext);
581 
582  /* ensure all previous writes are visible before follower continues. */
584 
585  proc->procArrayGroupMember = false;
586 
587  if (proc != MyProc)
588  PGSemaphoreUnlock(proc->sem);
589  }
590 }
bool procArrayGroupMember
Definition: proc.h:152
void PGSemaphoreUnlock(PGSemaphore sema)
Definition: posix_sema.c:323
Definition: proc.h:197
static bool pg_atomic_compare_exchange_u32(volatile pg_atomic_uint32 *ptr, uint32 *expected, uint32 newval)
Definition: atomics.h:321
PGPROC * MyProc
Definition: proc.c:67
TransactionId xid
Definition: proc.h:199
PROC_HDR * ProcGlobal
Definition: proc.c:80
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1714
static PGPROC * allProcs
Definition: procarray.c:99
unsigned int uint32
Definition: c.h:265
#define INVALID_PGPROCNO
Definition: proc.h:66
pg_atomic_uint32 procArrayGroupNext
Definition: proc.h:154
Definition: proc.h:219
static PGXACT * allPgXact
Definition: procarray.c:100
static void ProcArrayEndTransactionInternal(PGPROC *proc, PGXACT *pgxact, TransactionId latestXid)
Definition: procarray.c:448
#define Assert(condition)
Definition: c.h:671
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1110
void PGSemaphoreLock(PGSemaphore sema)
Definition: posix_sema.c:303
int pgprocno
Definition: proc.h:99
pg_atomic_uint32 procArrayGroupFirst
Definition: proc.h:234
#define pg_write_barrier()
Definition: atomics.h:161
#define TransactionIdIsValid(xid)
Definition: transam.h:41
static void pg_atomic_write_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
Definition: atomics.h:268
PGSemaphore sem
Definition: proc.h:90
Definition: proc.h:84
TransactionId procArrayGroupMemberXid
Definition: proc.h:160
static uint32 pg_atomic_read_u32(volatile pg_atomic_uint32 *ptr)
Definition: atomics.h:251
void ProcArrayInitRecovery ( TransactionId  initializedUptoXID)

Definition at line 633 of file procarray.c.

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

Referenced by StartupXLOG().

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

Definition at line 1791 of file procarray.c.

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

Referenced by GetSerializableTransactionSnapshotInt(), and SetTransactionSnapshot().

1792 {
1793  bool result = false;
1794  ProcArrayStruct *arrayP = procArray;
1795  int index;
1796 
1798  if (!TransactionIdIsNormal(sourcexid))
1799  return false;
1800 
1801  /* Get lock so source xact can't end while we're doing this */
1802  LWLockAcquire(ProcArrayLock, LW_SHARED);
1803 
1804  for (index = 0; index < arrayP->numProcs; index++)
1805  {
1806  int pgprocno = arrayP->pgprocnos[index];
1807  volatile PGPROC *proc = &allProcs[pgprocno];
1808  volatile PGXACT *pgxact = &allPgXact[pgprocno];
1809  TransactionId xid;
1810 
1811  /* Ignore procs running LAZY VACUUM */
1812  if (pgxact->vacuumFlags & PROC_IN_VACUUM)
1813  continue;
1814 
1815  xid = pgxact->xid; /* fetch just once */
1816  if (xid != sourcexid)
1817  continue;
1818 
1819  /*
1820  * We check the transaction's database ID for paranoia's sake: if it's
1821  * in another DB then its xmin does not cover us. Caller should have
1822  * detected this already, so we just treat any funny cases as
1823  * "transaction not found".
1824  */
1825  if (proc->databaseId != MyDatabaseId)
1826  continue;
1827 
1828  /*
1829  * Likewise, let's just make real sure its xmin does cover us.
1830  */
1831  xid = pgxact->xmin; /* fetch just once */
1832  if (!TransactionIdIsNormal(xid) ||
1833  !TransactionIdPrecedesOrEquals(xid, xmin))
1834  continue;
1835 
1836  /*
1837  * We're good. Install the new xmin. As in GetSnapshotData, set
1838  * TransactionXmin too. (Note that because snapmgr.c called
1839  * GetSnapshotData first, we'll be overwriting a valid xmin here, so
1840  * we don't check that.)
1841  */
1842  MyPgXact->xmin = TransactionXmin = xmin;
1843 
1844  result = true;
1845  break;
1846  }
1847 
1848  LWLockRelease(ProcArrayLock);
1849 
1850  return result;
1851 }
uint32 TransactionId
Definition: c.h:394
Definition: proc.h:197
TransactionId xmin
Definition: proc.h:203
TransactionId xid
Definition: proc.h:199
PGXACT * MyPgXact
Definition: proc.c:68
uint8 vacuumFlags
Definition: proc.h:208
TransactionId TransactionXmin
Definition: snapmgr.c:164
Definition: type.h:90
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1714
#define PROC_IN_VACUUM
Definition: proc.h:44
bool TransactionIdPrecedesOrEquals(TransactionId id1, TransactionId id2)
Definition: transam.c:319
static PGPROC * allProcs
Definition: procarray.c:99
Oid databaseId
Definition: proc.h:103
static ProcArrayStruct * procArray
Definition: procarray.c:97
static PGXACT * allPgXact
Definition: procarray.c:100
Oid MyDatabaseId
Definition: globals.c:76
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:94
#define Assert(condition)
Definition: c.h:671
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1110
#define TransactionIdIsNormal(xid)
Definition: transam.h:42
Definition: proc.h:84
bool ProcArrayInstallRestoredXmin ( TransactionId  xmin,
PGPROC proc 
)

Definition at line 1863 of file procarray.c.

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

Referenced by SetTransactionSnapshot().

1864 {
1865  bool result = false;
1866  TransactionId xid;
1867  volatile PGXACT *pgxact;
1868 
1870  Assert(proc != NULL);
1871 
1872  /* Get lock so source xact can't end while we're doing this */
1873  LWLockAcquire(ProcArrayLock, LW_SHARED);
1874 
1875  pgxact = &allPgXact[proc->pgprocno];
1876 
1877  /*
1878  * Be certain that the referenced PGPROC has an advertised xmin which is
1879  * no later than the one we're installing, so that the system-wide xmin
1880  * can't go backwards. Also, make sure it's running in the same database,
1881  * so that the per-database xmin cannot go backwards.
1882  */
1883  xid = pgxact->xmin; /* fetch just once */
1884  if (proc->databaseId == MyDatabaseId &&
1885  TransactionIdIsNormal(xid) &&
1886  TransactionIdPrecedesOrEquals(xid, xmin))
1887  {
1888  MyPgXact->xmin = TransactionXmin = xmin;
1889  result = true;
1890  }
1891 
1892  LWLockRelease(ProcArrayLock);
1893 
1894  return result;
1895 }
uint32 TransactionId
Definition: c.h:394
Definition: proc.h:197
TransactionId xmin
Definition: proc.h:203
PGXACT * MyPgXact
Definition: proc.c:68
TransactionId TransactionXmin
Definition: snapmgr.c:164
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1714
bool TransactionIdPrecedesOrEquals(TransactionId id1, TransactionId id2)
Definition: transam.c:319
Oid databaseId
Definition: proc.h:103
static PGXACT * allPgXact
Definition: procarray.c:100
Oid MyDatabaseId
Definition: globals.c:76
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1110
int pgprocno
Definition: proc.h:99
#define TransactionIdIsNormal(xid)
Definition: transam.h:42
void ProcArrayRemove ( PGPROC proc,
TransactionId  latestXid 
)

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

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

Definition at line 2947 of file procarray.c.

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

Referenced by ReplicationSlotsComputeRequiredXmin().

2949 {
2950  Assert(!already_locked || LWLockHeldByMe(ProcArrayLock));
2951 
2952  if (!already_locked)
2953  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
2954 
2956  procArray->replication_slot_catalog_xmin = catalog_xmin;
2957 
2958  if (!already_locked)
2959  LWLockRelease(ProcArrayLock);
2960 }
bool LWLockHeldByMe(LWLock *l)
Definition: lwlock.c:1830
TransactionId replication_slot_catalog_xmin
Definition: procarray.c:91
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1714
static ProcArrayStruct * procArray
Definition: procarray.c:97
TransactionId replication_slot_xmin
Definition: procarray.c:89
#define Assert(condition)
Definition: c.h:671
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1110
Size ProcArrayShmemSize ( void  )

Definition at line 178 of file procarray.c.

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

Referenced by CreateSharedMemoryAndSemaphores().

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

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

3157 {
3161 
3162  elog(trace_recovery(DEBUG4), "record known xact %u latestObservedXid %u",
3163  xid, latestObservedXid);
3164 
3165  /*
3166  * When a newly observed xid arrives, it is frequently the case that it is
3167  * *not* the next xid in sequence. When this occurs, we must treat the
3168  * intervening xids as running also.
3169  */
3171  {
3172  TransactionId next_expected_xid;
3173 
3174  /*
3175  * Extend subtrans like we do in GetNewTransactionId() during normal
3176  * operation using individual extend steps. Note that we do not need
3177  * to extend clog since its extensions are WAL logged.
3178  *
3179  * This part has to be done regardless of standbyState since we
3180  * immediately start assigning subtransactions to their toplevel
3181  * transactions.
3182  */
3183  next_expected_xid = latestObservedXid;
3184  while (TransactionIdPrecedes(next_expected_xid, xid))
3185  {
3186  TransactionIdAdvance(next_expected_xid);
3187  ExtendSUBTRANS(next_expected_xid);
3188  }
3189  Assert(next_expected_xid == xid);
3190 
3191  /*
3192  * If the KnownAssignedXids machinery isn't up yet, there's nothing
3193  * more to do since we don't track assigned xids yet.
3194  */
3196  {
3197  latestObservedXid = xid;
3198  return;
3199  }
3200 
3201  /*
3202  * Add (latestObservedXid, xid] onto the KnownAssignedXids array.
3203  */
3204  next_expected_xid = latestObservedXid;
3205  TransactionIdAdvance(next_expected_xid);
3206  KnownAssignedXidsAdd(next_expected_xid, xid, false);
3207 
3208  /*
3209  * Now we can advance latestObservedXid
3210  */
3211  latestObservedXid = xid;
3212 
3213  /* ShmemVariableCache->nextXid must be beyond any observed xid */
3214  next_expected_xid = latestObservedXid;
3215  TransactionIdAdvance(next_expected_xid);
3216  LWLockAcquire(XidGenLock, LW_EXCLUSIVE);
3217  ShmemVariableCache->nextXid = next_expected_xid;
3218  LWLockRelease(XidGenLock);
3219  }
3220 }
#define TransactionIdAdvance(dest)
Definition: transam.h:48
static TransactionId latestObservedXid
Definition: procarray.c:107
bool TransactionIdFollows(TransactionId id1, TransactionId id2)
Definition: transam.c:334
uint32 TransactionId
Definition: c.h:394
#define DEBUG4
Definition: elog.h:22
int trace_recovery(int trace_level)
Definition: elog.c:3753
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1714
void ExtendSUBTRANS(TransactionId newestXact)
Definition: subtrans.c:312
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:671
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1110
static void KnownAssignedXidsAdd(TransactionId from_xid, TransactionId to_xid, bool exclusive_lock)
Definition: procarray.c:3432
#define elog
Definition: elog.h:219
#define TransactionIdIsValid(xid)
Definition: transam.h:41
HotStandbyState standbyState
Definition: xlog.c:194
bool TransactionIdIsActive ( TransactionId  xid)

Definition at line 1212 of file procarray.c.

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

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

Definition at line 995 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, NULL, 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 asyncQueueProcessPageEntries(), check_safe_enum_use(), compute_new_xmax_infomask(), ConditionalXactLockTableWait(), Do_MultiXactIdWait(), DoesMultiXactIdConflict(), FreezeMultiXactId(), HeapTupleHeaderIsOnlyLocked(), HeapTupleSatisfiesDirty(), HeapTupleSatisfiesSelf(), HeapTupleSatisfiesToast(), HeapTupleSatisfiesUpdate(), HeapTupleSatisfiesVacuum(), MultiXactIdExpand(), MultiXactIdIsRunning(), test_lockmode_for_conflict(), and XactLockTableWait().

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

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

3002 {
3003  int i,
3004  j;
3005 
3007 
3008  /*
3009  * We must hold ProcArrayLock exclusively in order to remove transactions
3010  * from the PGPROC array. (See src/backend/access/transam/README.) It's
3011  * possible this could be relaxed since we know this routine is only used
3012  * to abort subtransactions, but pending closer analysis we'd best be
3013  * conservative.
3014  */
3015  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3016 
3017  /*
3018  * Under normal circumstances xid and xids[] will be in increasing order,
3019  * as will be the entries in subxids. Scan backwards to avoid O(N^2)
3020  * behavior when removing a lot of xids.
3021  */
3022  for (i = nxids - 1; i >= 0; i--)
3023  {
3024  TransactionId anxid = xids[i];
3025 
3026  for (j = MyPgXact->nxids - 1; j >= 0; j--)
3027  {
3028  if (TransactionIdEquals(MyProc->subxids.xids[j], anxid))
3029  {
3030  XidCacheRemove(j);
3031  break;
3032  }
3033  }
3034 
3035  /*
3036  * Ordinarily we should have found it, unless the cache has
3037  * overflowed. However it's also possible for this routine to be
3038  * invoked multiple times for the same subtransaction, in case of an
3039  * error during AbortSubTransaction. So instead of Assert, emit a
3040  * debug warning.
3041  */
3042  if (j < 0 && !MyPgXact->overflowed)
3043  elog(WARNING, "did not find subXID %u in MyProc", anxid);
3044  }
3045 
3046  for (j = MyPgXact->nxids - 1; j >= 0; j--)
3047  {
3048  if (TransactionIdEquals(MyProc->subxids.xids[j], xid))
3049  {
3050  XidCacheRemove(j);
3051  break;
3052  }
3053  }
3054  /* Ordinarily we should have found it, unless the cache has overflowed */
3055  if (j < 0 && !MyPgXact->overflowed)
3056  elog(WARNING, "did not find subXID %u in MyProc", xid);
3057 
3058  /* Also advance global latestCompletedXid while holding the lock */
3060  latestXid))
3062 
3063  LWLockRelease(ProcArrayLock);
3064 }
#define XidCacheRemove(i)
Definition: procarray.c:2984
#define TransactionIdEquals(id1, id2)
Definition: transam.h:43
uint32 TransactionId
Definition: c.h:394
PGPROC * MyProc
Definition: proc.c:67
PGXACT * MyPgXact
Definition: proc.c:68
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1714
uint8 nxids
Definition: proc.h:213
VariableCache ShmemVariableCache
Definition: varsup.c:34
struct XidCache subxids
Definition: proc.h:148
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:39
#define Assert(condition)
Definition: c.h:671
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1110
int i
#define elog
Definition: elog.h:219
#define TransactionIdIsValid(xid)
Definition: transam.h:41
TransactionId latestCompletedXid
Definition: transam.h:135

Variable Documentation

PGXACT* allPgXact
static

Definition at line 100 of file procarray.c.

PGPROC* allProcs
static

Definition at line 99 of file procarray.c.

TransactionId standbySnapshotPendingXmin
static

Definition at line 114 of file procarray.c.

Referenced by ProcArrayApplyRecoveryInfo().