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, VirtualTransactionId *sourcevxid)
 
bool ProcArrayInstallRestoredXmin (TransactionId xmin, PGPROC *proc)
 
RunningTransactions GetRunningTransactionData (void)
 
TransactionId GetOldestActiveTransactionId (void)
 
TransactionId GetOldestSafeDecodingTransactionId (bool catalogOnly)
 
VirtualTransactionIdGetVirtualXIDsDelayingChkpt (int *nvxids)
 
bool HaveVirtualXIDsDelayingChkpt (VirtualTransactionId *vxids, int nvxids)
 
PGPROCBackendPidGetProc (int pid)
 
PGPROCBackendPidGetProcWithLock (int pid)
 
int BackendXidGetPid (TransactionId xid)
 
bool IsBackendPid (int pid)
 
VirtualTransactionIdGetCurrentVirtualXIDs (TransactionId limitXmin, bool excludeXmin0, bool allDbs, int excludeVacuum, int *nvxids)
 
VirtualTransactionIdGetConflictingVirtualXIDs (TransactionId limitXmin, Oid dbOid)
 
pid_t CancelVirtualTransaction (VirtualTransactionId vxid, ProcSignalReason sigmode)
 
bool MinimumActiveBackends (int min)
 
int CountDBBackends (Oid databaseid)
 
int CountDBConnections (Oid databaseid)
 
void CancelDBBackends (Oid databaseid, ProcSignalReason sigmode, bool conflictPending)
 
int CountUserBackends (Oid roleid)
 
bool CountOtherDBBackends (Oid databaseId, int *nbackends, int *nprepared)
 
void ProcArraySetReplicationSlotXmin (TransactionId xmin, TransactionId catalog_xmin, bool already_locked)
 
void ProcArrayGetReplicationSlotXmin (TransactionId *xmin, TransactionId *catalog_xmin)
 
void XidCacheRemoveRunningXids (TransactionId xid, int nxids, const TransactionId *xids, TransactionId latestXid)
 
void RecordKnownAssignedTransactionIds (TransactionId xid)
 
void ExpireTreeKnownAssignedTransactionIds (TransactionId xid, int nsubxids, TransactionId *subxids, TransactionId max_xid)
 
void ExpireAllKnownAssignedTransactionIds (void)
 
void ExpireOldKnownAssignedTransactionIds (TransactionId xid)
 

Variables

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

Macro Definition Documentation

#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 3000 of file procarray.c.

Referenced by XidCacheRemoveRunningXids().

Typedef Documentation

Function Documentation

PGPROC* BackendPidGetProc ( int  pid)

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

2346 {
2347  PGPROC *result;
2348 
2349  if (pid == 0) /* never match dummy PGPROCs */
2350  return NULL;
2351 
2352  LWLockAcquire(ProcArrayLock, LW_SHARED);
2353 
2354  result = BackendPidGetProcWithLock(pid);
2355 
2356  LWLockRelease(ProcArrayLock);
2357 
2358  return result;
2359 }
return result
Definition: formatting.c:1633
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
PGPROC * BackendPidGetProcWithLock(int pid)
Definition: procarray.c:2368
#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 2368 of file procarray.c.

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

Referenced by BackendPidGetProc(), and GetBlockerStatusData().

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

Definition at line 2405 of file procarray.c.

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

Referenced by pgrowlocks().

2406 {
2407  int result = 0;
2408  ProcArrayStruct *arrayP = procArray;
2409  int index;
2410 
2411  if (xid == InvalidTransactionId) /* never match invalid xid */
2412  return 0;
2413 
2414  LWLockAcquire(ProcArrayLock, LW_SHARED);
2415 
2416  for (index = 0; index < arrayP->numProcs; index++)
2417  {
2418  int pgprocno = arrayP->pgprocnos[index];
2419  volatile PGPROC *proc = &allProcs[pgprocno];
2420  volatile PGXACT *pgxact = &allPgXact[pgprocno];
2421 
2422  if (pgxact->xid == xid)
2423  {
2424  result = proc->pid;
2425  break;
2426  }
2427  }
2428 
2429  LWLockRelease(ProcArrayLock);
2430 
2431  return result;
2432 }
Definition: proc.h:207
TransactionId xid
Definition: proc.h:209
return result
Definition: formatting.c:1633
Definition: type.h:89
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 2799 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().

2800 {
2801  ProcArrayStruct *arrayP = procArray;
2802  int index;
2803  pid_t pid = 0;
2804 
2805  /* tell all backends to die */
2806  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
2807 
2808  for (index = 0; index < arrayP->numProcs; index++)
2809  {
2810  int pgprocno = arrayP->pgprocnos[index];
2811  volatile PGPROC *proc = &allProcs[pgprocno];
2812 
2813  if (databaseid == InvalidOid || proc->databaseId == databaseid)
2814  {
2815  VirtualTransactionId procvxid;
2816 
2817  GET_VXID_FROM_PGPROC(procvxid, *proc);
2818 
2819  proc->recoveryConflictPending = conflictPending;
2820  pid = proc->pid;
2821  if (pid != 0)
2822  {
2823  /*
2824  * Kill the pid if it's still here. If not, that's what we
2825  * wanted so ignore any errors.
2826  */
2827  (void) SendProcSignal(pid, sigmode, procvxid.backendId);
2828  }
2829  }
2830  }
2831 
2832  LWLockRelease(ProcArrayLock);
2833 }
#define GET_VXID_FROM_PGPROC(vxid, proc)
Definition: lock.h:80
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
int SendProcSignal(pid_t pid, ProcSignalReason reason, BackendId backendId)
Definition: procsignal.c:180
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 2636 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().

2637 {
2638  ProcArrayStruct *arrayP = procArray;
2639  int index;
2640  pid_t pid = 0;
2641 
2642  LWLockAcquire(ProcArrayLock, LW_SHARED);
2643 
2644  for (index = 0; index < arrayP->numProcs; index++)
2645  {
2646  int pgprocno = arrayP->pgprocnos[index];
2647  volatile PGPROC *proc = &allProcs[pgprocno];
2648  VirtualTransactionId procvxid;
2649 
2650  GET_VXID_FROM_PGPROC(procvxid, *proc);
2651 
2652  if (procvxid.backendId == vxid.backendId &&
2653  procvxid.localTransactionId == vxid.localTransactionId)
2654  {
2655  proc->recoveryConflictPending = true;
2656  pid = proc->pid;
2657  if (pid != 0)
2658  {
2659  /*
2660  * Kill the pid if it's still here. If not, that's what we
2661  * wanted so ignore any errors.
2662  */
2663  (void) SendProcSignal(pid, sigmode, vxid.backendId);
2664  }
2665  break;
2666  }
2667  }
2668 
2669  LWLockRelease(ProcArrayLock);
2670 
2671  return pid;
2672 }
#define GET_VXID_FROM_PGPROC(vxid, proc)
Definition: lock.h:80
LocalTransactionId localTransactionId
Definition: lock.h:66
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
int SendProcSignal(pid_t pid, ProcSignalReason reason, BackendId backendId)
Definition: procsignal.c:180
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 2738 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().

2739 {
2740  ProcArrayStruct *arrayP = procArray;
2741  int count = 0;
2742  int index;
2743 
2744  LWLockAcquire(ProcArrayLock, LW_SHARED);
2745 
2746  for (index = 0; index < arrayP->numProcs; index++)
2747  {
2748  int pgprocno = arrayP->pgprocnos[index];
2749  volatile PGPROC *proc = &allProcs[pgprocno];
2750 
2751  if (proc->pid == 0)
2752  continue; /* do not count prepared xacts */
2753  if (!OidIsValid(databaseid) ||
2754  proc->databaseId == databaseid)
2755  count++;
2756  }
2757 
2758  LWLockRelease(ProcArrayLock);
2759 
2760  return count;
2761 }
#define OidIsValid(objectId)
Definition: c.h:538
Definition: type.h:89
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 2768 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().

2769 {
2770  ProcArrayStruct *arrayP = procArray;
2771  int count = 0;
2772  int index;
2773 
2774  LWLockAcquire(ProcArrayLock, LW_SHARED);
2775 
2776  for (index = 0; index < arrayP->numProcs; index++)
2777  {
2778  int pgprocno = arrayP->pgprocnos[index];
2779  volatile PGPROC *proc = &allProcs[pgprocno];
2780 
2781  if (proc->pid == 0)
2782  continue; /* do not count prepared xacts */
2783  if (proc->isBackgroundWorker)
2784  continue; /* do not count background workers */
2785  if (!OidIsValid(databaseid) ||
2786  proc->databaseId == databaseid)
2787  count++;
2788  }
2789 
2790  LWLockRelease(ProcArrayLock);
2791 
2792  return count;
2793 }
#define OidIsValid(objectId)
Definition: c.h:538
Definition: type.h:89
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 2889 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().

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

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

Referenced by InitializeSessionUserId().

2840 {
2841  ProcArrayStruct *arrayP = procArray;
2842  int count = 0;
2843  int index;
2844 
2845  LWLockAcquire(ProcArrayLock, LW_SHARED);
2846 
2847  for (index = 0; index < arrayP->numProcs; index++)
2848  {
2849  int pgprocno = arrayP->pgprocnos[index];
2850  volatile PGPROC *proc = &allProcs[pgprocno];
2851 
2852  if (proc->pid == 0)
2853  continue; /* do not count prepared xacts */
2854  if (proc->isBackgroundWorker)
2855  continue; /* do not count background workers */
2856  if (proc->roleId == roleid)
2857  count++;
2858  }
2859 
2860  LWLockRelease(ProcArrayLock);
2861 
2862  return count;
2863 }
Oid roleId
Definition: proc.h:114
Definition: type.h:89
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 3270 of file procarray.c.

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

Referenced by ShutdownRecoveryTransactionEnvironment().

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

Definition at line 3282 of file procarray.c.

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

Referenced by ProcArrayApplyRecoveryInfo().

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

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

3247 {
3249 
3250  /*
3251  * Uses same locking as transaction commit
3252  */
3253  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3254 
3255  KnownAssignedXidsRemoveTree(xid, nsubxids, subxids);
3256 
3257  /* As in ProcArrayEndTransaction, advance latestCompletedXid */
3259  max_xid))
3261 
3262  LWLockRelease(ProcArrayLock);
3263 }
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:3700
#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 2561 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().

2562 {
2563  static VirtualTransactionId *vxids;
2564  ProcArrayStruct *arrayP = procArray;
2565  int count = 0;
2566  int index;
2567 
2568  /*
2569  * If first time through, get workspace to remember main XIDs in. We
2570  * malloc it permanently to avoid repeated palloc/pfree overhead. Allow
2571  * result space, remembering room for a terminator.
2572  */
2573  if (vxids == NULL)
2574  {
2575  vxids = (VirtualTransactionId *)
2576  malloc(sizeof(VirtualTransactionId) * (arrayP->maxProcs + 1));
2577  if (vxids == NULL)
2578  ereport(ERROR,
2579  (errcode(ERRCODE_OUT_OF_MEMORY),
2580  errmsg("out of memory")));
2581  }
2582 
2583  LWLockAcquire(ProcArrayLock, LW_SHARED);
2584 
2585  for (index = 0; index < arrayP->numProcs; index++)
2586  {
2587  int pgprocno = arrayP->pgprocnos[index];
2588  volatile PGPROC *proc = &allProcs[pgprocno];
2589  volatile PGXACT *pgxact = &allPgXact[pgprocno];
2590 
2591  /* Exclude prepared transactions */
2592  if (proc->pid == 0)
2593  continue;
2594 
2595  if (!OidIsValid(dbOid) ||
2596  proc->databaseId == dbOid)
2597  {
2598  /* Fetch xmin just once - can't change on us, but good coding */
2599  TransactionId pxmin = pgxact->xmin;
2600 
2601  /*
2602  * We ignore an invalid pxmin because this means that backend has
2603  * no snapshot currently. We hold a Share lock to avoid contention
2604  * with users taking snapshots. That is not a problem because the
2605  * current xmin is always at least one higher than the latest
2606  * removed xid, so any new snapshot would never conflict with the
2607  * test here.
2608  */
2609  if (!TransactionIdIsValid(limitXmin) ||
2610  (TransactionIdIsValid(pxmin) && !TransactionIdFollows(pxmin, limitXmin)))
2611  {
2612  VirtualTransactionId vxid;
2613 
2614  GET_VXID_FROM_PGPROC(vxid, *proc);
2615  if (VirtualTransactionIdIsValid(vxid))
2616  vxids[count++] = vxid;
2617  }
2618  }
2619  }
2620 
2621  LWLockRelease(ProcArrayLock);
2622 
2623  /* add the terminator */
2624  vxids[count].backendId = InvalidBackendId;
2626 
2627  return vxids;
2628 }
#define GET_VXID_FROM_PGPROC(vxid, proc)
Definition: lock.h:80
bool TransactionIdFollows(TransactionId id1, TransactionId id2)
Definition: transam.c:334
uint32 TransactionId
Definition: c.h: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:89
#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:71
#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:69
#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 2473 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().

2476 {
2477  VirtualTransactionId *vxids;
2478  ProcArrayStruct *arrayP = procArray;
2479  int count = 0;
2480  int index;
2481 
2482  /* allocate what's certainly enough result space */
2483  vxids = (VirtualTransactionId *)
2484  palloc(sizeof(VirtualTransactionId) * arrayP->maxProcs);
2485 
2486  LWLockAcquire(ProcArrayLock, LW_SHARED);
2487 
2488  for (index = 0; index < arrayP->numProcs; index++)
2489  {
2490  int pgprocno = arrayP->pgprocnos[index];
2491  volatile PGPROC *proc = &allProcs[pgprocno];
2492  volatile PGXACT *pgxact = &allPgXact[pgprocno];
2493 
2494  if (proc == MyProc)
2495  continue;
2496 
2497  if (excludeVacuum & pgxact->vacuumFlags)
2498  continue;
2499 
2500  if (allDbs || proc->databaseId == MyDatabaseId)
2501  {
2502  /* Fetch xmin just once - might change on us */
2503  TransactionId pxmin = pgxact->xmin;
2504 
2505  if (excludeXmin0 && !TransactionIdIsValid(pxmin))
2506  continue;
2507 
2508  /*
2509  * InvalidTransactionId precedes all other XIDs, so a proc that
2510  * hasn't set xmin yet will not be rejected by this test.
2511  */
2512  if (!TransactionIdIsValid(limitXmin) ||
2513  TransactionIdPrecedesOrEquals(pxmin, limitXmin))
2514  {
2515  VirtualTransactionId vxid;
2516 
2517  GET_VXID_FROM_PGPROC(vxid, *proc);
2518  if (VirtualTransactionIdIsValid(vxid))
2519  vxids[count++] = vxid;
2520  }
2521  }
2522  }
2523 
2524  LWLockRelease(ProcArrayLock);
2525 
2526  *nvxids = count;
2527  return vxids;
2528 }
#define GET_VXID_FROM_PGPROC(vxid, proc)
Definition: lock.h:80
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:89
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:71
static PGXACT * allPgXact
Definition: procarray.c:101
Oid MyDatabaseId
Definition: globals.c:77
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 2091 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().

2092 {
2093  ProcArrayStruct *arrayP = procArray;
2094  TransactionId oldestRunningXid;
2095  int index;
2096 
2098 
2099  LWLockAcquire(ProcArrayLock, LW_SHARED);
2100 
2101  /*
2102  * It's okay to read nextXid without acquiring XidGenLock because (1) we
2103  * assume TransactionIds can be read atomically and (2) we don't care if
2104  * we get a slightly stale value. It can't be very stale anyway, because
2105  * the LWLockAcquire above will have done any necessary memory
2106  * interlocking.
2107  */
2108  oldestRunningXid = ShmemVariableCache->nextXid;
2109 
2110  /*
2111  * Spin over procArray collecting all xids and subxids.
2112  */
2113  for (index = 0; index < arrayP->numProcs; index++)
2114  {
2115  int pgprocno = arrayP->pgprocnos[index];
2116  volatile PGXACT *pgxact = &allPgXact[pgprocno];
2117  TransactionId xid;
2118 
2119  /* Fetch xid just once - see GetNewTransactionId */
2120  xid = pgxact->xid;
2121 
2122  if (!TransactionIdIsNormal(xid))
2123  continue;
2124 
2125  if (TransactionIdPrecedes(xid, oldestRunningXid))
2126  oldestRunningXid = xid;
2127 
2128  /*
2129  * Top-level XID of a transaction is always less than any of its
2130  * subxids, so we don't need to check if any of the subxids are
2131  * smaller than oldestRunningXid
2132  */
2133  }
2134 
2135  LWLockRelease(ProcArrayLock);
2136 
2137  return oldestRunningXid;
2138 }
uint32 TransactionId
Definition: c.h:397
Definition: proc.h:207
TransactionId xid
Definition: proc.h:209
bool RecoveryInProgress(void)
Definition: xlog.c:7872
Definition: type.h:89
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 2157 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().

2158 {
2159  ProcArrayStruct *arrayP = procArray;
2160  TransactionId oldestSafeXid;
2161  int index;
2162  bool recovery_in_progress = RecoveryInProgress();
2163 
2164  Assert(LWLockHeldByMe(ProcArrayLock));
2165 
2166  /*
2167  * Acquire XidGenLock, so no transactions can acquire an xid while we're
2168  * running. If no transaction with xid were running concurrently a new xid
2169  * could influence the RecentXmin et al.
2170  *
2171  * We initialize the computation to nextXid since that's guaranteed to be
2172  * a safe, albeit pessimal, value.
2173  */
2174  LWLockAcquire(XidGenLock, LW_SHARED);
2175  oldestSafeXid = ShmemVariableCache->nextXid;
2176 
2177  /*
2178  * If there's already a slot pegging the xmin horizon, we can start with
2179  * that value, it's guaranteed to be safe since it's computed by this
2180  * routine initially and has been enforced since. We can always use the
2181  * slot's general xmin horizon, but the catalog horizon is only usable
2182  * when we only catalog data is going to be looked at.
2183  */
2186  oldestSafeXid))
2187  oldestSafeXid = procArray->replication_slot_xmin;
2188 
2189  if (catalogOnly &&
2192  oldestSafeXid))
2193  oldestSafeXid = procArray->replication_slot_catalog_xmin;
2194 
2195  /*
2196  * If we're not in recovery, we walk over the procarray and collect the
2197  * lowest xid. Since we're called with ProcArrayLock held and have
2198  * acquired XidGenLock, no entries can vanish concurrently, since
2199  * PGXACT->xid is only set with XidGenLock held and only cleared with
2200  * ProcArrayLock held.
2201  *
2202  * In recovery we can't lower the safe value besides what we've computed
2203  * above, so we'll have to wait a bit longer there. We unfortunately can
2204  * *not* use KnownAssignedXidsGetOldestXmin() since the KnownAssignedXids
2205  * machinery can miss values and return an older value than is safe.
2206  */
2207  if (!recovery_in_progress)
2208  {
2209  /*
2210  * Spin over procArray collecting all min(PGXACT->xid)
2211  */
2212  for (index = 0; index < arrayP->numProcs; index++)
2213  {
2214  int pgprocno = arrayP->pgprocnos[index];
2215  volatile PGXACT *pgxact = &allPgXact[pgprocno];
2216  TransactionId xid;
2217 
2218  /* Fetch xid just once - see GetNewTransactionId */
2219  xid = pgxact->xid;
2220 
2221  if (!TransactionIdIsNormal(xid))
2222  continue;
2223 
2224  if (TransactionIdPrecedes(xid, oldestSafeXid))
2225  oldestSafeXid = xid;
2226  }
2227  }
2228 
2229  LWLockRelease(XidGenLock);
2230 
2231  return oldestSafeXid;
2232 }
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:7872
Definition: type.h:89
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:1633
Form_pg_class rd_rel
Definition: rel.h:114
bool RecoveryInProgress(void)
Definition: xlog.c:7872
uint8 vacuumFlags
Definition: proc.h:218
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
#define FirstNormalTransactionId
Definition: transam.h:34
#define PROCARRAY_SLOTS_XMIN
Definition: procarray.h:37
#define PROCARRAY_PROC_FLAGS_MASK
Definition: procarray.h:44
VariableCache ShmemVariableCache
Definition: varsup.c:34
#define InvalidTransactionId
Definition: transam.h:31
static PGPROC * allProcs
Definition: procarray.c:100
Oid databaseId
Definition: proc.h: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:559
Oid MyDatabaseId
Definition: globals.c:77
static TransactionId KnownAssignedXidsGetOldestXmin(void)
Definition: procarray.c:3873
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 1933 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().

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

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

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

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

Definition at line 2440 of file procarray.c.

References BackendPidGetProc(), and NULL.

Referenced by pg_stat_get_subscription().

2441 {
2442  return (BackendPidGetProc(pid) != NULL);
2443 }
PGPROC * BackendPidGetProc(int pid)
Definition: procarray.c:2345
#define NULL
Definition: c.h:229
static bool KnownAssignedXidExists ( TransactionId  xid)
static

Definition at line 3661 of file procarray.c.

References Assert, KnownAssignedXidsSearch(), and TransactionIdIsValid.

Referenced by TransactionIdIsInProgress().

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

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

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

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

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

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

3909 {
3910  /* use volatile pointer to prevent code rearrangement */
3911  volatile ProcArrayStruct *pArray = procArray;
3913  int head,
3914  tail,
3915  i;
3916  int nxids = 0;
3917 
3918  tail = pArray->tailKnownAssignedXids;
3919  head = pArray->headKnownAssignedXids;
3920 
3921  initStringInfo(&buf);
3922 
3923  for (i = tail; i < head; i++)
3924  {
3925  if (KnownAssignedXidsValid[i])
3926  {
3927  nxids++;
3928  appendStringInfo(&buf, "[%d]=%u ", i, KnownAssignedXids[i]);
3929  }
3930  }
3931 
3932  elog(trace_level, "%d KnownAssignedXids (num=%d tail=%d head=%d) %s",
3933  nxids,
3934  pArray->numKnownAssignedXids,
3935  pArray->tailKnownAssignedXids,
3936  pArray->headKnownAssignedXids,
3937  buf.data);
3938 
3939  pfree(buf.data);
3940 }
void pfree(void *pointer)
Definition: mcxt.c:950
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
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:46
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 3801 of file procarray.c.

References InvalidTransactionId, and KnownAssignedXidsGetAndSetXmin().

Referenced by TransactionIdIsInProgress().

3802 {
3804 
3805  return KnownAssignedXidsGetAndSetXmin(xarray, &xtmp, xmax);
3806 }
uint32 TransactionId
Definition: c.h:397
#define InvalidTransactionId
Definition: transam.h:31
static int KnownAssignedXidsGetAndSetXmin(TransactionId *xarray, TransactionId *xmin, TransactionId xmax)
Definition: procarray.c:3815
static int KnownAssignedXidsGetAndSetXmin ( TransactionId xarray,
TransactionId xmin,
TransactionId  xmax 
)
static

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

3817 {
3818  int count = 0;
3819  int head,
3820  tail;
3821  int i;
3822 
3823  /*
3824  * Fetch head just once, since it may change while we loop. We can stop
3825  * once we reach the initially seen head, since we are certain that an xid
3826  * cannot enter and then leave the array while we hold ProcArrayLock. We
3827  * might miss newly-added xids, but they should be >= xmax so irrelevant
3828  * anyway.
3829  *
3830  * Must take spinlock to ensure we see up-to-date array contents.
3831  */
3836 
3837  for (i = tail; i < head; i++)
3838  {
3839  /* Skip any gaps in the array */
3840  if (KnownAssignedXidsValid[i])
3841  {
3842  TransactionId knownXid = KnownAssignedXids[i];
3843 
3844  /*
3845  * Update xmin if required. Only the first XID need be checked,
3846  * since the array is sorted.
3847  */
3848  if (count == 0 &&
3849  TransactionIdPrecedes(knownXid, *xmin))
3850  *xmin = knownXid;
3851 
3852  /*
3853  * Filter out anything >= xmax, again relying on sorted property
3854  * of array.
3855  */
3856  if (TransactionIdIsValid(xmax) &&
3857  TransactionIdFollowsOrEquals(knownXid, xmax))
3858  break;
3859 
3860  /* Add knownXid into output array */
3861  xarray[count++] = knownXid;
3862  }
3863  }
3864 
3865  return count;
3866 }
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 3873 of file procarray.c.

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

Referenced by GetOldestXmin().

3874 {
3875  int head,
3876  tail;
3877  int i;
3878 
3879  /*
3880  * Fetch head just once, since it may change while we loop.
3881  */
3886 
3887  for (i = tail; i < head; i++)
3888  {
3889  /* Skip any gaps in the array */
3890  if (KnownAssignedXidsValid[i])
3891  return KnownAssignedXids[i];
3892  }
3893 
3894  return InvalidTransactionId;
3895 }
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 3674 of file procarray.c.

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

Referenced by KnownAssignedXidsRemoveTree().

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

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

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

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

Referenced by ExpireTreeKnownAssignedTransactionIds(), and ProcArrayApplyXidAssignment().

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

Definition at line 3947 of file procarray.c.

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

Referenced by ProcArrayApplyRecoveryInfo().

3948 {
3949  /* use volatile pointer to prevent code rearrangement */
3950  volatile ProcArrayStruct *pArray = procArray;
3951 
3952  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3953 
3954  pArray->numKnownAssignedXids = 0;
3955  pArray->tailKnownAssignedXids = 0;
3956  pArray->headKnownAssignedXids = 0;
3957 
3958  LWLockRelease(ProcArrayLock);
3959 }
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 3567 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().

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

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

Referenced by XLogFlush().

2685 {
2686  ProcArrayStruct *arrayP = procArray;
2687  int count = 0;
2688  int index;
2689 
2690  /* Quick short-circuit if no minimum is specified */
2691  if (min == 0)
2692  return true;
2693 
2694  /*
2695  * Note: for speed, we don't acquire ProcArrayLock. This is a little bit
2696  * bogus, but since we are only testing fields for zero or nonzero, it
2697  * should be OK. The result is only used for heuristic purposes anyway...
2698  */
2699  for (index = 0; index < arrayP->numProcs; index++)
2700  {
2701  int pgprocno = arrayP->pgprocnos[index];
2702  volatile PGPROC *proc = &allProcs[pgprocno];
2703  volatile PGXACT *pgxact = &allPgXact[pgprocno];
2704 
2705  /*
2706  * Since we're not holding a lock, need to be prepared to deal with
2707  * garbage, as someone could have incremented numProcs but not yet
2708  * filled the structure.
2709  *
2710  * If someone just decremented numProcs, 'proc' could also point to a
2711  * PGPROC entry that's no longer in the array. It still points to a
2712  * PGPROC struct, though, because freed PGPROC entries just go to the
2713  * free list and are recycled. Its contents are nonsense in that case,
2714  * but that's acceptable for this function.
2715  */
2716  if (pgprocno == -1)
2717  continue; /* do not count deleted entries */
2718  if (proc == MyProc)
2719  continue; /* do not count myself */
2720  if (pgxact->xid == InvalidTransactionId)
2721  continue; /* do not count if no XID assigned */
2722  if (proc->pid == 0)
2723  continue; /* do not count prepared xacts */
2724  if (proc->waitLock != NULL)
2725  continue; /* do not count if blocked on a lock */
2726  count++;
2727  if (count >= min)
2728  break;
2729  }
2730 
2731  return count >= min;
2732 }
Definition: proc.h:207
PGPROC * MyProc
Definition: proc.c:67
TransactionId xid
Definition: proc.h:209
Definition: type.h:89
#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:89
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:3908
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:324
TransactionId nextXid
Definition: transam.h:117
VariableCache ShmemVariableCache
Definition: varsup.c:34
#define InvalidTransactionId
Definition: transam.h:31
static void KnownAssignedXidsReset(void)
Definition: procarray.c:3947
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:3448
TransactionId nextXid
Definition: standby.h:75
void * palloc(Size size)
Definition: mcxt.c:849
int i
void ExpireOldKnownAssignedTransactionIds(TransactionId xid)
Definition: procarray.c:3282
#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:3700
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:3172
void SubTransSetParent(TransactionId xid, TransactionId parent)
Definition: subtrans.c:74
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:69
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:69
#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:69
LocalTransactionId lxid
Definition: proc.h:105
TransactionId latestCompletedXid
Definition: transam.h:135
void ProcArrayGetReplicationSlotXmin ( TransactionId xmin,
TransactionId catalog_xmin 
)

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

2987 {
2988  LWLockAcquire(ProcArrayLock, LW_SHARED);
2989 
2990  if (xmin != NULL)
2992 
2993  if (catalog_xmin != NULL)
2994  *catalog_xmin = procArray->replication_slot_catalog_xmin;
2995 
2996  LWLockRelease(ProcArrayLock);
2997 }
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,
VirtualTransactionId sourcevxid 
)

Definition at line 1796 of file procarray.c.

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

Referenced by GetSerializableTransactionSnapshotInt(), and SetTransactionSnapshot().

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

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

1872 {
1873  bool result = false;
1874  TransactionId xid;
1875  volatile PGXACT *pgxact;
1876 
1878  Assert(proc != NULL);
1879 
1880  /* Get lock so source xact can't end while we're doing this */
1881  LWLockAcquire(ProcArrayLock, LW_SHARED);
1882 
1883  pgxact = &allPgXact[proc->pgprocno];
1884 
1885  /*
1886  * Be certain that the referenced PGPROC has an advertised xmin which is
1887  * no later than the one we're installing, so that the system-wide xmin
1888  * can't go backwards. Also, make sure it's running in the same database,
1889  * so that the per-database xmin cannot go backwards.
1890  */
1891  xid = pgxact->xmin; /* fetch just once */
1892  if (proc->databaseId == MyDatabaseId &&
1893  TransactionIdIsNormal(xid) &&
1894  TransactionIdPrecedesOrEquals(xid, xmin))
1895  {
1896  MyPgXact->xmin = TransactionXmin = xmin;
1897  result = true;
1898  }
1899 
1900  LWLockRelease(ProcArrayLock);
1901 
1902  return result;
1903 }
uint32 TransactionId
Definition: c.h:397
Definition: proc.h:207
TransactionId xmin
Definition: proc.h:213
return result
Definition: formatting.c:1633
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:77
#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:89
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 2963 of file procarray.c.

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

Referenced by ReplicationSlotsComputeRequiredXmin().

2965 {
2966  Assert(!already_locked || LWLockHeldByMe(ProcArrayLock));
2967 
2968  if (!already_locked)
2969  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
2970 
2972  procArray->replication_slot_catalog_xmin = catalog_xmin;
2973 
2974  if (!already_locked)
2975  LWLockRelease(ProcArrayLock);
2976 }
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 3172 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().

3173 {
3177 
3178  elog(trace_recovery(DEBUG4), "record known xact %u latestObservedXid %u",
3179  xid, latestObservedXid);
3180 
3181  /*
3182  * When a newly observed xid arrives, it is frequently the case that it is
3183  * *not* the next xid in sequence. When this occurs, we must treat the
3184  * intervening xids as running also.
3185  */
3187  {
3188  TransactionId next_expected_xid;
3189 
3190  /*
3191  * Extend subtrans like we do in GetNewTransactionId() during normal
3192  * operation using individual extend steps. Note that we do not need
3193  * to extend clog since its extensions are WAL logged.
3194  *
3195  * This part has to be done regardless of standbyState since we
3196  * immediately start assigning subtransactions to their toplevel
3197  * transactions.
3198  */
3199  next_expected_xid = latestObservedXid;
3200  while (TransactionIdPrecedes(next_expected_xid, xid))
3201  {
3202  TransactionIdAdvance(next_expected_xid);
3203  ExtendSUBTRANS(next_expected_xid);
3204  }
3205  Assert(next_expected_xid == xid);
3206 
3207  /*
3208  * If the KnownAssignedXids machinery isn't up yet, there's nothing
3209  * more to do since we don't track assigned xids yet.
3210  */
3212  {
3213  latestObservedXid = xid;
3214  return;
3215  }
3216 
3217  /*
3218  * Add (latestObservedXid, xid] onto the KnownAssignedXids array.
3219  */
3220  next_expected_xid = latestObservedXid;
3221  TransactionIdAdvance(next_expected_xid);
3222  KnownAssignedXidsAdd(next_expected_xid, xid, false);
3223 
3224  /*
3225  * Now we can advance latestObservedXid
3226  */
3227  latestObservedXid = xid;
3228 
3229  /* ShmemVariableCache->nextXid must be beyond any observed xid */
3230  next_expected_xid = latestObservedXid;
3231  TransactionIdAdvance(next_expected_xid);
3232  LWLockAcquire(XidGenLock, LW_EXCLUSIVE);
3233  ShmemVariableCache->nextXid = next_expected_xid;
3234  LWLockRelease(XidGenLock);
3235  }
3236 }
#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:324
TransactionId nextXid
Definition: transam.h:117
VariableCache ShmemVariableCache
Definition: varsup.c:34
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
#define Assert(condition)
Definition: c.h: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:3448
#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:1633
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:150
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:7872
#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:3801
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:3661
#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 3015 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().

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