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 "pgstat.h"
#include "storage/proc.h"
#include "storage/procarray.h"
#include "storage/spin.h"
#include "utils/builtins.h"
#include "utils/rel.h"
#include "utils/snapmgr.h"
Include dependency graph for procarray.c:

Go to the source code of this file.

Data Structures

struct  ProcArrayStruct
 

Macros

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

Typedefs

typedef struct ProcArrayStruct ProcArrayStruct
 

Functions

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

Variables

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

Macro Definition Documentation

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

Referenced by CountOtherDBBackends().

#define xc_by_child_xid_inc ( )    ((void) 0)

Definition at line 148 of file procarray.c.

Referenced by TransactionIdIsInProgress().

#define xc_by_known_assigned_inc ( )    ((void) 0)

Definition at line 149 of file procarray.c.

Referenced by TransactionIdIsInProgress().

#define xc_by_known_xact_inc ( )    ((void) 0)

Definition at line 144 of file procarray.c.

Referenced by TransactionIdIsInProgress().

#define xc_by_latest_xid_inc ( )    ((void) 0)

Definition at line 146 of file procarray.c.

Referenced by TransactionIdIsInProgress().

#define xc_by_main_xid_inc ( )    ((void) 0)

Definition at line 147 of file procarray.c.

Referenced by TransactionIdIsInProgress().

#define xc_by_my_xact_inc ( )    ((void) 0)

Definition at line 145 of file procarray.c.

Referenced by TransactionIdIsInProgress().

#define xc_by_recent_xmin_inc ( )    ((void) 0)

Definition at line 143 of file procarray.c.

Referenced by TransactionIdIsInProgress().

#define xc_no_overflow_inc ( )    ((void) 0)

Definition at line 150 of file procarray.c.

Referenced by TransactionIdIsInProgress().

#define xc_slow_answer_inc ( )    ((void) 0)

Definition at line 151 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:223
struct XidCache subxids
Definition: proc.h:158
TransactionId xids[PGPROC_MAX_CACHED_SUBXIDS]
Definition: proc.h:39
int i

Definition at line 2997 of file procarray.c.

Referenced by XidCacheRemoveRunningXids().

Typedef Documentation

Function Documentation

PGPROC* BackendPidGetProc ( int  pid)

Definition at line 2342 of file procarray.c.

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

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

2343 {
2344  PGPROC *result;
2345 
2346  if (pid == 0) /* never match dummy PGPROCs */
2347  return NULL;
2348 
2349  LWLockAcquire(ProcArrayLock, LW_SHARED);
2350 
2351  result = BackendPidGetProcWithLock(pid);
2352 
2353  LWLockRelease(ProcArrayLock);
2354 
2355  return result;
2356 }
return result
Definition: formatting.c:1618
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
PGPROC * BackendPidGetProcWithLock(int pid)
Definition: procarray.c:2365
#define NULL
Definition: c.h:229
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
Definition: proc.h:94
PGPROC* BackendPidGetProcWithLock ( int  pid)

Definition at line 2365 of file procarray.c.

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

Referenced by BackendPidGetProc(), and GetBlockerStatusData().

2366 {
2367  PGPROC *result = NULL;
2368  ProcArrayStruct *arrayP = procArray;
2369  int index;
2370 
2371  if (pid == 0) /* never match dummy PGPROCs */
2372  return NULL;
2373 
2374  for (index = 0; index < arrayP->numProcs; index++)
2375  {
2376  PGPROC *proc = &allProcs[arrayP->pgprocnos[index]];
2377 
2378  if (proc->pid == pid)
2379  {
2380  result = proc;
2381  break;
2382  }
2383  }
2384 
2385  return result;
2386 }
return result
Definition: formatting.c:1618
Definition: type.h:90
static PGPROC * allProcs
Definition: procarray.c:100
static ProcArrayStruct * procArray
Definition: procarray.c:98
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:95
#define NULL
Definition: c.h:229
Definition: proc.h:94
int pid
Definition: proc.h:108
int BackendXidGetPid ( TransactionId  xid)

Definition at line 2402 of file procarray.c.

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

Referenced by pgrowlocks().

2403 {
2404  int result = 0;
2405  ProcArrayStruct *arrayP = procArray;
2406  int index;
2407 
2408  if (xid == InvalidTransactionId) /* never match invalid xid */
2409  return 0;
2410 
2411  LWLockAcquire(ProcArrayLock, LW_SHARED);
2412 
2413  for (index = 0; index < arrayP->numProcs; index++)
2414  {
2415  int pgprocno = arrayP->pgprocnos[index];
2416  volatile PGPROC *proc = &allProcs[pgprocno];
2417  volatile PGXACT *pgxact = &allPgXact[pgprocno];
2418 
2419  if (pgxact->xid == xid)
2420  {
2421  result = proc->pid;
2422  break;
2423  }
2424  }
2425 
2426  LWLockRelease(ProcArrayLock);
2427 
2428  return result;
2429 }
Definition: proc.h:207
TransactionId xid
Definition: proc.h:209
return result
Definition: formatting.c:1618
Definition: type.h:90
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
#define InvalidTransactionId
Definition: transam.h:31
static PGPROC * allProcs
Definition: procarray.c:100
static ProcArrayStruct * procArray
Definition: procarray.c:98
static PGXACT * allPgXact
Definition: procarray.c:101
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:95
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
Definition: proc.h:94
int pid
Definition: proc.h:108
void CancelDBBackends ( Oid  databaseid,
ProcSignalReason  sigmode,
bool  conflictPending 
)

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

2797 {
2798  ProcArrayStruct *arrayP = procArray;
2799  int index;
2800  pid_t pid = 0;
2801 
2802  /* tell all backends to die */
2803  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
2804 
2805  for (index = 0; index < arrayP->numProcs; index++)
2806  {
2807  int pgprocno = arrayP->pgprocnos[index];
2808  volatile PGPROC *proc = &allProcs[pgprocno];
2809 
2810  if (databaseid == InvalidOid || proc->databaseId == databaseid)
2811  {
2812  VirtualTransactionId procvxid;
2813 
2814  GET_VXID_FROM_PGPROC(procvxid, *proc);
2815 
2816  proc->recoveryConflictPending = conflictPending;
2817  pid = proc->pid;
2818  if (pid != 0)
2819  {
2820  /*
2821  * Kill the pid if it's still here. If not, that's what we
2822  * wanted so ignore any errors.
2823  */
2824  (void) SendProcSignal(pid, sigmode, procvxid.backendId);
2825  }
2826  }
2827  }
2828 
2829  LWLockRelease(ProcArrayLock);
2830 }
#define GET_VXID_FROM_PGPROC(vxid, proc)
Definition: lock.h:81
Definition: type.h:90
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
int SendProcSignal(pid_t pid, ProcSignalReason reason, BackendId backendId)
Definition: procsignal.c:179
bool recoveryConflictPending
Definition: proc.h:123
static PGPROC * allProcs
Definition: procarray.c:100
Oid databaseId
Definition: proc.h:113
static ProcArrayStruct * procArray
Definition: procarray.c:98
#define InvalidOid
Definition: postgres_ext.h:36
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:95
BackendId backendId
Definition: lock.h:65
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
Definition: proc.h:94
int pid
Definition: proc.h:108
pid_t CancelVirtualTransaction ( VirtualTransactionId  vxid,
ProcSignalReason  sigmode 
)

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

2634 {
2635  ProcArrayStruct *arrayP = procArray;
2636  int index;
2637  pid_t pid = 0;
2638 
2639  LWLockAcquire(ProcArrayLock, LW_SHARED);
2640 
2641  for (index = 0; index < arrayP->numProcs; index++)
2642  {
2643  int pgprocno = arrayP->pgprocnos[index];
2644  volatile PGPROC *proc = &allProcs[pgprocno];
2645  VirtualTransactionId procvxid;
2646 
2647  GET_VXID_FROM_PGPROC(procvxid, *proc);
2648 
2649  if (procvxid.backendId == vxid.backendId &&
2650  procvxid.localTransactionId == vxid.localTransactionId)
2651  {
2652  proc->recoveryConflictPending = true;
2653  pid = proc->pid;
2654  if (pid != 0)
2655  {
2656  /*
2657  * Kill the pid if it's still here. If not, that's what we
2658  * wanted so ignore any errors.
2659  */
2660  (void) SendProcSignal(pid, sigmode, vxid.backendId);
2661  }
2662  break;
2663  }
2664  }
2665 
2666  LWLockRelease(ProcArrayLock);
2667 
2668  return pid;
2669 }
#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:1715
int SendProcSignal(pid_t pid, ProcSignalReason reason, BackendId backendId)
Definition: procsignal.c:179
bool recoveryConflictPending
Definition: proc.h:123
static PGPROC * allProcs
Definition: procarray.c:100
static ProcArrayStruct * procArray
Definition: procarray.c:98
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:95
BackendId backendId
Definition: lock.h:65
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
Definition: proc.h:94
int pid
Definition: proc.h:108
int CountDBBackends ( Oid  databaseid)

Definition at line 2735 of file procarray.c.

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

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

2736 {
2737  ProcArrayStruct *arrayP = procArray;
2738  int count = 0;
2739  int index;
2740 
2741  LWLockAcquire(ProcArrayLock, LW_SHARED);
2742 
2743  for (index = 0; index < arrayP->numProcs; index++)
2744  {
2745  int pgprocno = arrayP->pgprocnos[index];
2746  volatile PGPROC *proc = &allProcs[pgprocno];
2747 
2748  if (proc->pid == 0)
2749  continue; /* do not count prepared xacts */
2750  if (!OidIsValid(databaseid) ||
2751  proc->databaseId == databaseid)
2752  count++;
2753  }
2754 
2755  LWLockRelease(ProcArrayLock);
2756 
2757  return count;
2758 }
#define OidIsValid(objectId)
Definition: c.h:538
Definition: type.h:90
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
static PGPROC * allProcs
Definition: procarray.c:100
Oid databaseId
Definition: proc.h:113
static ProcArrayStruct * procArray
Definition: procarray.c:98
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:95
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
Definition: proc.h:94
int pid
Definition: proc.h:108
int CountDBConnections ( Oid  databaseid)

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

2766 {
2767  ProcArrayStruct *arrayP = procArray;
2768  int count = 0;
2769  int index;
2770 
2771  LWLockAcquire(ProcArrayLock, LW_SHARED);
2772 
2773  for (index = 0; index < arrayP->numProcs; index++)
2774  {
2775  int pgprocno = arrayP->pgprocnos[index];
2776  volatile PGPROC *proc = &allProcs[pgprocno];
2777 
2778  if (proc->pid == 0)
2779  continue; /* do not count prepared xacts */
2780  if (proc->isBackgroundWorker)
2781  continue; /* do not count background workers */
2782  if (!OidIsValid(databaseid) ||
2783  proc->databaseId == databaseid)
2784  count++;
2785  }
2786 
2787  LWLockRelease(ProcArrayLock);
2788 
2789  return count;
2790 }
#define OidIsValid(objectId)
Definition: c.h:538
Definition: type.h:90
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
bool isBackgroundWorker
Definition: proc.h:116
static PGPROC * allProcs
Definition: procarray.c:100
Oid databaseId
Definition: proc.h:113
static ProcArrayStruct * procArray
Definition: procarray.c:98
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:95
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
Definition: proc.h:94
int pid
Definition: proc.h:108
bool CountOtherDBBackends ( Oid  databaseId,
int *  nbackends,
int *  nprepared 
)

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

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

Definition at line 2836 of file procarray.c.

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

Referenced by InitializeSessionUserId().

2837 {
2838  ProcArrayStruct *arrayP = procArray;
2839  int count = 0;
2840  int index;
2841 
2842  LWLockAcquire(ProcArrayLock, LW_SHARED);
2843 
2844  for (index = 0; index < arrayP->numProcs; index++)
2845  {
2846  int pgprocno = arrayP->pgprocnos[index];
2847  volatile PGPROC *proc = &allProcs[pgprocno];
2848 
2849  if (proc->pid == 0)
2850  continue; /* do not count prepared xacts */
2851  if (proc->isBackgroundWorker)
2852  continue; /* do not count background workers */
2853  if (proc->roleId == roleid)
2854  count++;
2855  }
2856 
2857  LWLockRelease(ProcArrayLock);
2858 
2859  return count;
2860 }
Oid roleId
Definition: proc.h:114
Definition: type.h:90
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
bool isBackgroundWorker
Definition: proc.h:116
static PGPROC * allProcs
Definition: procarray.c:100
static ProcArrayStruct * procArray
Definition: procarray.c:98
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:95
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
Definition: proc.h:94
int pid
Definition: proc.h:108
void CreateSharedProcArray ( void  )

Definition at line 221 of file procarray.c.

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

Referenced by CreateSharedMemoryAndSemaphores().

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

Definition at line 3267 of file procarray.c.

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

Referenced by ShutdownRecoveryTransactionEnvironment().

3268 {
3269  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3271  LWLockRelease(ProcArrayLock);
3272 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
static void KnownAssignedXidsRemovePreceding(TransactionId xid)
Definition: procarray.c:3719
#define InvalidTransactionId
Definition: transam.h:31
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
void ExpireOldKnownAssignedTransactionIds ( TransactionId  xid)

Definition at line 3279 of file procarray.c.

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

Referenced by ProcArrayApplyRecoveryInfo().

3280 {
3281  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3283  LWLockRelease(ProcArrayLock);
3284 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
static void KnownAssignedXidsRemovePreceding(TransactionId xid)
Definition: procarray.c:3719
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
void ExpireTreeKnownAssignedTransactionIds ( TransactionId  xid,
int  nsubxids,
TransactionId subxids,
TransactionId  max_xid 
)

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

3244 {
3246 
3247  /*
3248  * Uses same locking as transaction commit
3249  */
3250  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3251 
3252  KnownAssignedXidsRemoveTree(xid, nsubxids, subxids);
3253 
3254  /* As in ProcArrayEndTransaction, advance latestCompletedXid */
3256  max_xid))
3258 
3259  LWLockRelease(ProcArrayLock);
3260 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
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:3697
#define Assert(condition)
Definition: c.h:675
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
HotStandbyState standbyState
Definition: xlog.c:195
TransactionId latestCompletedXid
Definition: transam.h:135
VirtualTransactionId* GetConflictingVirtualXIDs ( TransactionId  limitXmin,
Oid  dbOid 
)

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

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

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

2473 {
2474  VirtualTransactionId *vxids;
2475  ProcArrayStruct *arrayP = procArray;
2476  int count = 0;
2477  int index;
2478 
2479  /* allocate what's certainly enough result space */
2480  vxids = (VirtualTransactionId *)
2481  palloc(sizeof(VirtualTransactionId) * arrayP->maxProcs);
2482 
2483  LWLockAcquire(ProcArrayLock, LW_SHARED);
2484 
2485  for (index = 0; index < arrayP->numProcs; index++)
2486  {
2487  int pgprocno = arrayP->pgprocnos[index];
2488  volatile PGPROC *proc = &allProcs[pgprocno];
2489  volatile PGXACT *pgxact = &allPgXact[pgprocno];
2490 
2491  if (proc == MyProc)
2492  continue;
2493 
2494  if (excludeVacuum & pgxact->vacuumFlags)
2495  continue;
2496 
2497  if (allDbs || proc->databaseId == MyDatabaseId)
2498  {
2499  /* Fetch xmin just once - might change on us */
2500  TransactionId pxmin = pgxact->xmin;
2501 
2502  if (excludeXmin0 && !TransactionIdIsValid(pxmin))
2503  continue;
2504 
2505  /*
2506  * InvalidTransactionId precedes all other XIDs, so a proc that
2507  * hasn't set xmin yet will not be rejected by this test.
2508  */
2509  if (!TransactionIdIsValid(limitXmin) ||
2510  TransactionIdPrecedesOrEquals(pxmin, limitXmin))
2511  {
2512  VirtualTransactionId vxid;
2513 
2514  GET_VXID_FROM_PGPROC(vxid, *proc);
2515  if (VirtualTransactionIdIsValid(vxid))
2516  vxids[count++] = vxid;
2517  }
2518  }
2519  }
2520 
2521  LWLockRelease(ProcArrayLock);
2522 
2523  *nvxids = count;
2524  return vxids;
2525 }
#define GET_VXID_FROM_PGPROC(vxid, proc)
Definition: lock.h:81
uint32 TransactionId
Definition: c.h:397
Definition: proc.h:207
TransactionId xmin
Definition: proc.h:213
PGPROC * MyProc
Definition: proc.c:67
uint8 vacuumFlags
Definition: proc.h:218
Definition: type.h:90
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
bool TransactionIdPrecedesOrEquals(TransactionId id1, TransactionId id2)
Definition: transam.c:319
static PGPROC * allProcs
Definition: procarray.c:100
Oid databaseId
Definition: proc.h:113
static ProcArrayStruct * procArray
Definition: procarray.c:98
#define VirtualTransactionIdIsValid(vxid)
Definition: lock.h:72
static PGXACT * allPgXact
Definition: procarray.c:101
Oid MyDatabaseId
Definition: globals.c:76
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:95
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
void * palloc(Size size)
Definition: mcxt.c:849
#define TransactionIdIsValid(xid)
Definition: transam.h:41
Definition: proc.h:94
int GetMaxSnapshotSubxidCount ( void  )

Definition at line 1466 of file procarray.c.

References TOTAL_MAX_CACHED_SUBXIDS.

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

1467 {
1468  return TOTAL_MAX_CACHED_SUBXIDS;
1469 }
#define TOTAL_MAX_CACHED_SUBXIDS
int GetMaxSnapshotXidCount ( void  )

Definition at line 1455 of file procarray.c.

References ProcArrayStruct::maxProcs.

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

1456 {
1457  return procArray->maxProcs;
1458 }
static ProcArrayStruct * procArray
Definition: procarray.c:98
TransactionId GetOldestActiveTransactionId ( void  )

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

2089 {
2090  ProcArrayStruct *arrayP = procArray;
2091  TransactionId oldestRunningXid;
2092  int index;
2093 
2095 
2096  LWLockAcquire(ProcArrayLock, LW_SHARED);
2097 
2098  /*
2099  * It's okay to read nextXid without acquiring XidGenLock because (1) we
2100  * assume TransactionIds can be read atomically and (2) we don't care if
2101  * we get a slightly stale value. It can't be very stale anyway, because
2102  * the LWLockAcquire above will have done any necessary memory
2103  * interlocking.
2104  */
2105  oldestRunningXid = ShmemVariableCache->nextXid;
2106 
2107  /*
2108  * Spin over procArray collecting all xids and subxids.
2109  */
2110  for (index = 0; index < arrayP->numProcs; index++)
2111  {
2112  int pgprocno = arrayP->pgprocnos[index];
2113  volatile PGXACT *pgxact = &allPgXact[pgprocno];
2114  TransactionId xid;
2115 
2116  /* Fetch xid just once - see GetNewTransactionId */
2117  xid = pgxact->xid;
2118 
2119  if (!TransactionIdIsNormal(xid))
2120  continue;
2121 
2122  if (TransactionIdPrecedes(xid, oldestRunningXid))
2123  oldestRunningXid = xid;
2124 
2125  /*
2126  * Top-level XID of a transaction is always less than any of its
2127  * subxids, so we don't need to check if any of the subxids are
2128  * smaller than oldestRunningXid
2129  */
2130  }
2131 
2132  LWLockRelease(ProcArrayLock);
2133 
2134  return oldestRunningXid;
2135 }
uint32 TransactionId
Definition: c.h:397
Definition: proc.h:207
TransactionId xid
Definition: proc.h:209
bool RecoveryInProgress(void)
Definition: xlog.c:7874
Definition: type.h:90
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
TransactionId nextXid
Definition: transam.h:117
VariableCache ShmemVariableCache
Definition: varsup.c:34
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
static ProcArrayStruct * procArray
Definition: procarray.c:98
static PGXACT * allPgXact
Definition: procarray.c:101
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:95
#define Assert(condition)
Definition: c.h:675
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
#define TransactionIdIsNormal(xid)
Definition: transam.h:42
TransactionId GetOldestSafeDecodingTransactionId ( bool  catalogOnly)

Definition at line 2154 of file procarray.c.

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

Referenced by CreateInitDecodingContext(), and SnapBuildInitialSnapshot().

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

Definition at line 1314 of file procarray.c.

References Assert, PGPROC::databaseId, FirstNormalTransactionId, InvalidTransactionId, KnownAssignedXidsGetOldestXmin(), VariableCacheData::latestCompletedXid, LW_SHARED, LWLockAcquire(), LWLockRelease(), MyDatabaseId, NormalTransactionIdPrecedes, NULL, ProcArrayStruct::numProcs, ProcArrayStruct::pgprocnos, procArray, PROCARRAY_PROC_FLAGS_MASK, PROCARRAY_SLOTS_XMIN, RelationData::rd_rel, RecoveryInProgress(), RelationIsAccessibleInLogicalDecoding, ProcArrayStruct::replication_slot_catalog_xmin, ProcArrayStruct::replication_slot_xmin, result, 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().

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

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

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

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

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

2251 {
2252  VirtualTransactionId *vxids;
2253  ProcArrayStruct *arrayP = procArray;
2254  int count = 0;
2255  int index;
2256 
2257  /* allocate what's certainly enough result space */
2258  vxids = (VirtualTransactionId *)
2259  palloc(sizeof(VirtualTransactionId) * arrayP->maxProcs);
2260 
2261  LWLockAcquire(ProcArrayLock, LW_SHARED);
2262 
2263  for (index = 0; index < arrayP->numProcs; index++)
2264  {
2265  int pgprocno = arrayP->pgprocnos[index];
2266  volatile PGPROC *proc = &allProcs[pgprocno];
2267  volatile PGXACT *pgxact = &allPgXact[pgprocno];
2268 
2269  if (pgxact->delayChkpt)
2270  {
2271  VirtualTransactionId vxid;
2272 
2273  GET_VXID_FROM_PGPROC(vxid, *proc);
2274  if (VirtualTransactionIdIsValid(vxid))
2275  vxids[count++] = vxid;
2276  }
2277  }
2278 
2279  LWLockRelease(ProcArrayLock);
2280 
2281  *nvxids = count;
2282  return vxids;
2283 }
#define GET_VXID_FROM_PGPROC(vxid, proc)
Definition: lock.h:81
Definition: proc.h:207
Definition: type.h:90
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
static PGPROC * allProcs
Definition: procarray.c:100
bool delayChkpt
Definition: proc.h:220
static ProcArrayStruct * procArray
Definition: procarray.c:98
#define VirtualTransactionIdIsValid(vxid)
Definition: lock.h:72
static PGXACT * allPgXact
Definition: procarray.c:101
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:95
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
void * palloc(Size size)
Definition: mcxt.c:849
Definition: proc.h:94
bool HaveVirtualXIDsDelayingChkpt ( VirtualTransactionId vxids,
int  nvxids 
)

Definition at line 2295 of file procarray.c.

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

Referenced by CreateCheckPoint().

2296 {
2297  bool result = false;
2298  ProcArrayStruct *arrayP = procArray;
2299  int index;
2300 
2301  LWLockAcquire(ProcArrayLock, LW_SHARED);
2302 
2303  for (index = 0; index < arrayP->numProcs; index++)
2304  {
2305  int pgprocno = arrayP->pgprocnos[index];
2306  volatile PGPROC *proc = &allProcs[pgprocno];
2307  volatile PGXACT *pgxact = &allPgXact[pgprocno];
2308  VirtualTransactionId vxid;
2309 
2310  GET_VXID_FROM_PGPROC(vxid, *proc);
2311 
2312  if (pgxact->delayChkpt && VirtualTransactionIdIsValid(vxid))
2313  {
2314  int i;
2315 
2316  for (i = 0; i < nvxids; i++)
2317  {
2318  if (VirtualTransactionIdEquals(vxid, vxids[i]))
2319  {
2320  result = true;
2321  break;
2322  }
2323  }
2324  if (result)
2325  break;
2326  }
2327  }
2328 
2329  LWLockRelease(ProcArrayLock);
2330 
2331  return result;
2332 }
#define GET_VXID_FROM_PGPROC(vxid, proc)
Definition: lock.h:81
Definition: proc.h:207
return result
Definition: formatting.c:1618
Definition: type.h:90
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
#define VirtualTransactionIdEquals(vxid1, vxid2)
Definition: lock.h:75
static PGPROC * allProcs
Definition: procarray.c:100
bool delayChkpt
Definition: proc.h:220
static ProcArrayStruct * procArray
Definition: procarray.c:98
#define VirtualTransactionIdIsValid(vxid)
Definition: lock.h:72
static PGXACT * allPgXact
Definition: procarray.c:101
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:95
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
int i
Definition: proc.h:94
bool IsBackendPid ( int  pid)

Definition at line 2437 of file procarray.c.

References BackendPidGetProc(), and NULL.

Referenced by pg_stat_get_subscription().

2438 {
2439  return (BackendPidGetProc(pid) != NULL);
2440 }
PGPROC * BackendPidGetProc(int pid)
Definition: procarray.c:2342
#define NULL
Definition: c.h:229
static bool KnownAssignedXidExists ( TransactionId  xid)
static

Definition at line 3658 of file procarray.c.

References Assert, KnownAssignedXidsSearch(), and TransactionIdIsValid.

Referenced by TransactionIdIsInProgress().

3659 {
3661 
3662  return KnownAssignedXidsSearch(xid, false);
3663 }
#define Assert(condition)
Definition: c.h:675
static bool KnownAssignedXidsSearch(TransactionId xid, bool remove)
Definition: procarray.c:3564
#define TransactionIdIsValid(xid)
Definition: transam.h:41
static void KnownAssignedXidsAdd ( TransactionId  from_xid,
TransactionId  to_xid,
bool  exclusive_lock 
)
static

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

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

Definition at line 3382 of file procarray.c.

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

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

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

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

3906 {
3907  /* use volatile pointer to prevent code rearrangement */
3908  volatile ProcArrayStruct *pArray = procArray;
3910  int head,
3911  tail,
3912  i;
3913  int nxids = 0;
3914 
3915  tail = pArray->tailKnownAssignedXids;
3916  head = pArray->headKnownAssignedXids;
3917 
3918  initStringInfo(&buf);
3919 
3920  for (i = tail; i < head; i++)
3921  {
3922  if (KnownAssignedXidsValid[i])
3923  {
3924  nxids++;
3925  appendStringInfo(&buf, "[%d]=%u ", i, KnownAssignedXids[i]);
3926  }
3927  }
3928 
3929  elog(trace_level, "%d KnownAssignedXids (num=%d tail=%d head=%d) %s",
3930  nxids,
3931  pArray->numKnownAssignedXids,
3932  pArray->tailKnownAssignedXids,
3933  pArray->headKnownAssignedXids,
3934  buf.data);
3935 
3936  pfree(buf.data);
3937 }
void pfree(void *pointer)
Definition: mcxt.c:950
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:110
static char * buf
Definition: pg_test_fsync.c:66
int numKnownAssignedXids
Definition: procarray.c:75
static bool * KnownAssignedXidsValid
Definition: procarray.c:107
void initStringInfo(StringInfo str)
Definition: stringinfo.c:65
static ProcArrayStruct * procArray
Definition: procarray.c:98
static TransactionId * KnownAssignedXids
Definition: procarray.c:106
int i
#define elog
Definition: elog.h:219
int tailKnownAssignedXids
Definition: procarray.c:76
int headKnownAssignedXids
Definition: procarray.c:77
static int KnownAssignedXidsGet ( TransactionId xarray,
TransactionId  xmax 
)
static

Definition at line 3798 of file procarray.c.

References InvalidTransactionId, and KnownAssignedXidsGetAndSetXmin().

Referenced by TransactionIdIsInProgress().

3799 {
3801 
3802  return KnownAssignedXidsGetAndSetXmin(xarray, &xtmp, xmax);
3803 }
uint32 TransactionId
Definition: c.h:397
#define InvalidTransactionId
Definition: transam.h:31
static int KnownAssignedXidsGetAndSetXmin(TransactionId *xarray, TransactionId *xmin, TransactionId xmax)
Definition: procarray.c:3812
static int KnownAssignedXidsGetAndSetXmin ( TransactionId xarray,
TransactionId xmin,
TransactionId  xmax 
)
static

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

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

Definition at line 3870 of file procarray.c.

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

Referenced by GetOldestXmin().

3871 {
3872  int head,
3873  tail;
3874  int i;
3875 
3876  /*
3877  * Fetch head just once, since it may change while we loop.
3878  */
3883 
3884  for (i = tail; i < head; i++)
3885  {
3886  /* Skip any gaps in the array */
3887  if (KnownAssignedXidsValid[i])
3888  return KnownAssignedXids[i];
3889  }
3890 
3891  return InvalidTransactionId;
3892 }
slock_t known_assigned_xids_lck
Definition: procarray.c:78
#define SpinLockAcquire(lock)
Definition: spin.h:62
#define InvalidTransactionId
Definition: transam.h:31
static bool * KnownAssignedXidsValid
Definition: procarray.c:107
static ProcArrayStruct * procArray
Definition: procarray.c:98
#define SpinLockRelease(lock)
Definition: spin.h:64
static TransactionId * KnownAssignedXids
Definition: procarray.c:106
int i
int tailKnownAssignedXids
Definition: procarray.c:76
int headKnownAssignedXids
Definition: procarray.c:77
static void KnownAssignedXidsRemove ( TransactionId  xid)
static

Definition at line 3671 of file procarray.c.

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

Referenced by KnownAssignedXidsRemoveTree().

3672 {
3674 
3675  elog(trace_recovery(DEBUG4), "remove KnownAssignedXid %u", xid);
3676 
3677  /*
3678  * Note: we cannot consider it an error to remove an XID that's not
3679  * present. We intentionally remove subxact IDs while processing
3680  * XLOG_XACT_ASSIGNMENT, to avoid array overflow. Then those XIDs will be
3681  * removed again when the top-level xact commits or aborts.
3682  *
3683  * It might be possible to track such XIDs to distinguish this case from
3684  * actual errors, but it would be complicated and probably not worth it.
3685  * So, just ignore the search result.
3686  */
3687  (void) KnownAssignedXidsSearch(xid, true);
3688 }
#define DEBUG4
Definition: elog.h:22
int trace_recovery(int trace_level)
Definition: elog.c:3753
#define Assert(condition)
Definition: c.h:675
static bool KnownAssignedXidsSearch(TransactionId xid, bool remove)
Definition: procarray.c:3564
#define elog
Definition: elog.h:219
#define TransactionIdIsValid(xid)
Definition: transam.h:41
static void KnownAssignedXidsRemovePreceding ( TransactionId  xid)
static

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

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

Definition at line 3697 of file procarray.c.

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

Referenced by ExpireTreeKnownAssignedTransactionIds(), and ProcArrayApplyXidAssignment().

3699 {
3700  int i;
3701 
3702  if (TransactionIdIsValid(xid))
3704 
3705  for (i = 0; i < nsubxids; i++)
3706  KnownAssignedXidsRemove(subxids[i]);
3707 
3708  /* Opportunistically compress the array */
3710 }
static void KnownAssignedXidsCompress(bool force)
Definition: procarray.c:3382
static void KnownAssignedXidsRemove(TransactionId xid)
Definition: procarray.c:3671
int i
#define TransactionIdIsValid(xid)
Definition: transam.h:41
static void KnownAssignedXidsReset ( void  )
static

Definition at line 3944 of file procarray.c.

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

Referenced by ProcArrayApplyRecoveryInfo().

3945 {
3946  /* use volatile pointer to prevent code rearrangement */
3947  volatile ProcArrayStruct *pArray = procArray;
3948 
3949  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3950 
3951  pArray->numKnownAssignedXids = 0;
3952  pArray->tailKnownAssignedXids = 0;
3953  pArray->headKnownAssignedXids = 0;
3954 
3955  LWLockRelease(ProcArrayLock);
3956 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
int numKnownAssignedXids
Definition: procarray.c:75
static ProcArrayStruct * procArray
Definition: procarray.c:98
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
int tailKnownAssignedXids
Definition: procarray.c:76
int headKnownAssignedXids
Definition: procarray.c:77
static bool KnownAssignedXidsSearch ( TransactionId  xid,
bool  remove 
)
static

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

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

Definition at line 2681 of file procarray.c.

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

Referenced by XLogFlush().

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

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

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

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

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

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

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

605 {
606  PGXACT *pgxact = &allPgXact[proc->pgprocno];
607 
608  /*
609  * We can skip locking ProcArrayLock here, because this action does not
610  * actually change anyone's view of the set of running XIDs: our entry is
611  * duplicate with the gxact that has already been inserted into the
612  * ProcArray.
613  */
614  pgxact->xid = InvalidTransactionId;
616  pgxact->xmin = InvalidTransactionId;
617  proc->recoveryConflictPending = false;
618 
619  /* redundant, but just in case */
621  pgxact->delayChkpt = false;
622 
623  /* Clear the subtransaction-XID cache too */
624  pgxact->nxids = 0;
625  pgxact->overflowed = false;
626 }
Definition: proc.h:207
TransactionId xmin
Definition: proc.h:213
TransactionId xid
Definition: proc.h:209
uint8 vacuumFlags
Definition: proc.h:218
#define PROC_VACUUM_STATE_MASK
Definition: proc.h:61
bool recoveryConflictPending
Definition: proc.h:123
uint8 nxids
Definition: proc.h:223
#define InvalidTransactionId
Definition: transam.h:31
bool delayChkpt
Definition: proc.h:220
static PGXACT * allPgXact
Definition: procarray.c:101
bool overflowed
Definition: proc.h:219
int pgprocno
Definition: proc.h:109
#define InvalidLocalTransactionId
Definition: lock.h:70
LocalTransactionId lxid
Definition: proc.h:105
void ProcArrayEndTransaction ( PGPROC proc,
TransactionId  latestXid 
)

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

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

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

451 {
452  pgxact->xid = InvalidTransactionId;
454  pgxact->xmin = InvalidTransactionId;
455  /* must be cleared with xid/xmin: */
457  pgxact->delayChkpt = false; /* be sure this is cleared in abort */
458  proc->recoveryConflictPending = false;
459 
460  /* Clear the subtransaction-XID cache too while holding the lock */
461  pgxact->nxids = 0;
462  pgxact->overflowed = false;
463 
464  /* Also advance global latestCompletedXid while holding the lock */
466  latestXid))
468 }
TransactionId xmin
Definition: proc.h:213
TransactionId xid
Definition: proc.h:209
uint8 vacuumFlags
Definition: proc.h:218
#define PROC_VACUUM_STATE_MASK
Definition: proc.h:61
bool recoveryConflictPending
Definition: proc.h:123
uint8 nxids
Definition: proc.h:223
VariableCache ShmemVariableCache
Definition: varsup.c:34
#define InvalidTransactionId
Definition: transam.h:31
bool delayChkpt
Definition: proc.h:220
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
bool overflowed
Definition: proc.h:219
#define InvalidLocalTransactionId
Definition: lock.h:70
LocalTransactionId lxid
Definition: proc.h:105
TransactionId latestCompletedXid
Definition: transam.h:135
void ProcArrayGetReplicationSlotXmin ( TransactionId xmin,
TransactionId catalog_xmin 
)

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

2984 {
2985  LWLockAcquire(ProcArrayLock, LW_SHARED);
2986 
2987  if (xmin != NULL)
2989 
2990  if (catalog_xmin != NULL)
2991  *catalog_xmin = procArray->replication_slot_catalog_xmin;
2992 
2993  LWLockRelease(ProcArrayLock);
2994 }
TransactionId replication_slot_catalog_xmin
Definition: procarray.c:92
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
static ProcArrayStruct * procArray
Definition: procarray.c:98
TransactionId replication_slot_xmin
Definition: procarray.c:90
#define NULL
Definition: c.h:229
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
static void ProcArrayGroupClearXid ( PGPROC proc,
TransactionId  latestXid 
)
static

Definition at line 483 of file procarray.c.

References Assert, INVALID_PGPROCNO, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MyProc, pg_atomic_compare_exchange_u32(), pg_atomic_read_u32(), pg_atomic_write_u32(), pg_write_barrier, PGPROC::pgprocno, PGSemaphoreLock(), PGSemaphoreUnlock(), pgstat_report_wait_end(), pgstat_report_wait_start(), ProcArrayEndTransactionInternal(), PROC_HDR::procArrayGroupFirst, PGPROC::procArrayGroupMember, PGPROC::procArrayGroupMemberXid, PGPROC::procArrayGroupNext, ProcGlobal, PGPROC::sem, TransactionIdIsValid, WAIT_EVENT_PROCARRAY_GROUP_UPDATE, and PGXACT::xid.

Referenced by ProcArrayEndTransaction().

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

Definition at line 636 of file procarray.c.

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

Referenced by StartupXLOG().

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

Definition at line 1796 of file procarray.c.

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

Referenced by GetSerializableTransactionSnapshotInt(), and SetTransactionSnapshot().

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

Definition at line 1868 of file procarray.c.

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

Referenced by SetTransactionSnapshot().

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

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

333 {
334  ProcArrayStruct *arrayP = procArray;
335  int index;
336 
337 #ifdef XIDCACHE_DEBUG
338  /* dump stats at backend shutdown, but not prepared-xact end */
339  if (proc->pid != 0)
340  DisplayXidCache();
341 #endif
342 
343  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
344 
345  if (TransactionIdIsValid(latestXid))
346  {
348 
349  /* Advance global latestCompletedXid while holding the lock */
351  latestXid))
353  }
354  else
355  {
356  /* Shouldn't be trying to remove a live transaction here */
358  }
359 
360  for (index = 0; index < arrayP->numProcs; index++)
361  {
362  if (arrayP->pgprocnos[index] == proc->pgprocno)
363  {
364  /* Keep the PGPROC array sorted. See notes above */
365  memmove(&arrayP->pgprocnos[index], &arrayP->pgprocnos[index + 1],
366  (arrayP->numProcs - index - 1) * sizeof(int));
367  arrayP->pgprocnos[arrayP->numProcs - 1] = -1; /* for debugging */
368  arrayP->numProcs--;
369  LWLockRelease(ProcArrayLock);
370  return;
371  }
372  }
373 
374  /* Oops */
375  LWLockRelease(ProcArrayLock);
376 
377  elog(LOG, "failed to find proc %p in ProcArray", proc);
378 }
TransactionId xid
Definition: proc.h:209
#define LOG
Definition: elog.h:26
Definition: type.h:90
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
#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:98
static PGXACT * allPgXact
Definition: procarray.c:101
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:95
#define Assert(condition)
Definition: c.h:675
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
int pgprocno
Definition: proc.h:109
#define elog
Definition: elog.h:219
#define TransactionIdIsValid(xid)
Definition: transam.h:41
int pid
Definition: proc.h:108
TransactionId latestCompletedXid
Definition: transam.h:135
void ProcArraySetReplicationSlotXmin ( TransactionId  xmin,
TransactionId  catalog_xmin,
bool  already_locked 
)

Definition at line 2960 of file procarray.c.

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

Referenced by ReplicationSlotsComputeRequiredXmin().

2962 {
2963  Assert(!already_locked || LWLockHeldByMe(ProcArrayLock));
2964 
2965  if (!already_locked)
2966  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
2967 
2969  procArray->replication_slot_catalog_xmin = catalog_xmin;
2970 
2971  if (!already_locked)
2972  LWLockRelease(ProcArrayLock);
2973 }
bool LWLockHeldByMe(LWLock *l)
Definition: lwlock.c:1831
TransactionId replication_slot_catalog_xmin
Definition: procarray.c:92
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
static ProcArrayStruct * procArray
Definition: procarray.c:98
TransactionId replication_slot_xmin
Definition: procarray.c:90
#define Assert(condition)
Definition: c.h:675
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
Size ProcArrayShmemSize ( void  )

Definition at line 179 of file procarray.c.

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

Referenced by CreateSharedMemoryAndSemaphores().

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

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

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

Definition at line 1215 of file procarray.c.

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

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

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

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

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

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

PGPROC* allProcs
static

Definition at line 100 of file procarray.c.

TransactionId standbySnapshotPendingXmin
static

Definition at line 115 of file procarray.c.

Referenced by ProcArrayApplyRecoveryInfo().