PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
procarray.c File Reference
#include "postgres.h"
#include <signal.h>
#include "access/clog.h"
#include "access/subtrans.h"
#include "access/transam.h"
#include "access/twophase.h"
#include "access/xact.h"
#include "access/xlog.h"
#include "catalog/catalog.h"
#include "miscadmin.h"
#include "storage/proc.h"
#include "storage/procarray.h"
#include "storage/spin.h"
#include "utils/builtins.h"
#include "utils/rel.h"
#include "utils/snapmgr.h"
Include dependency graph for procarray.c:

Go to the source code of this file.

Data Structures

struct  ProcArrayStruct
 

Macros

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

Typedefs

typedef struct ProcArrayStruct ProcArrayStruct
 

Functions

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

Variables

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

Macro Definition Documentation

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

Referenced by CountOtherDBBackends().

#define xc_by_child_xid_inc ( )    ((void) 0)

Definition at line 147 of file procarray.c.

Referenced by TransactionIdIsInProgress().

#define xc_by_known_assigned_inc ( )    ((void) 0)

Definition at line 148 of file procarray.c.

Referenced by TransactionIdIsInProgress().

#define xc_by_known_xact_inc ( )    ((void) 0)

Definition at line 143 of file procarray.c.

Referenced by TransactionIdIsInProgress().

#define xc_by_latest_xid_inc ( )    ((void) 0)

Definition at line 145 of file procarray.c.

Referenced by TransactionIdIsInProgress().

#define xc_by_main_xid_inc ( )    ((void) 0)

Definition at line 146 of file procarray.c.

Referenced by TransactionIdIsInProgress().

#define xc_by_my_xact_inc ( )    ((void) 0)

Definition at line 144 of file procarray.c.

Referenced by TransactionIdIsInProgress().

#define xc_by_recent_xmin_inc ( )    ((void) 0)

Definition at line 142 of file procarray.c.

Referenced by TransactionIdIsInProgress().

#define xc_no_overflow_inc ( )    ((void) 0)

Definition at line 149 of file procarray.c.

Referenced by TransactionIdIsInProgress().

#define xc_slow_answer_inc ( )    ((void) 0)

Definition at line 150 of file procarray.c.

Referenced by TransactionIdIsInProgress().

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

Definition at line 2985 of file procarray.c.

Referenced by XidCacheRemoveRunningXids().

Typedef Documentation

Function Documentation

PGPROC* BackendPidGetProc ( int  pid)

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

2331 {
2332  PGPROC *result;
2333 
2334  if (pid == 0) /* never match dummy PGPROCs */
2335  return NULL;
2336 
2337  LWLockAcquire(ProcArrayLock, LW_SHARED);
2338 
2339  result = BackendPidGetProcWithLock(pid);
2340 
2341  LWLockRelease(ProcArrayLock);
2342 
2343  return result;
2344 }
return result
Definition: formatting.c:1618
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
PGPROC * BackendPidGetProcWithLock(int pid)
Definition: procarray.c:2353
#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 2353 of file procarray.c.

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

Referenced by BackendPidGetProc(), and GetBlockerStatusData().

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

Definition at line 2390 of file procarray.c.

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

Referenced by pgrowlocks().

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

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

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

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

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

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

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

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

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

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

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

Definition at line 2824 of file procarray.c.

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

Referenced by InitializeSessionUserId().

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

Definition at line 220 of file procarray.c.

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

Referenced by CreateSharedMemoryAndSemaphores().

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

Definition at line 3255 of file procarray.c.

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

Referenced by ShutdownRecoveryTransactionEnvironment().

3256 {
3257  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3259  LWLockRelease(ProcArrayLock);
3260 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
static void KnownAssignedXidsRemovePreceding(TransactionId xid)
Definition: procarray.c:3707
#define InvalidTransactionId
Definition: transam.h:31
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
void ExpireOldKnownAssignedTransactionIds ( TransactionId  xid)

Definition at line 3267 of file procarray.c.

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

Referenced by ProcArrayApplyRecoveryInfo().

3268 {
3269  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3271  LWLockRelease(ProcArrayLock);
3272 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
static void KnownAssignedXidsRemovePreceding(TransactionId xid)
Definition: procarray.c:3707
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
void ExpireTreeKnownAssignedTransactionIds ( TransactionId  xid,
int  nsubxids,
TransactionId subxids,
TransactionId  max_xid 
)

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

3232 {
3234 
3235  /*
3236  * Uses same locking as transaction commit
3237  */
3238  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3239 
3240  KnownAssignedXidsRemoveTree(xid, nsubxids, subxids);
3241 
3242  /* As in ProcArrayEndTransaction, advance latestCompletedXid */
3244  max_xid))
3246 
3247  LWLockRelease(ProcArrayLock);
3248 }
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:3685
#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 2546 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().

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

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

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

References TOTAL_MAX_CACHED_SUBXIDS.

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

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

Definition at line 1452 of file procarray.c.

References ProcArrayStruct::maxProcs.

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

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

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

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

Definition at line 2150 of file procarray.c.

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

Referenced by CreateInitDecodingContext().

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

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

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

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

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

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

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

Definition at line 2425 of file procarray.c.

References BackendPidGetProc(), and NULL.

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

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

Definition at line 3646 of file procarray.c.

References Assert, KnownAssignedXidsSearch(), and TransactionIdIsValid.

Referenced by TransactionIdIsInProgress().

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

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

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

Definition at line 3370 of file procarray.c.

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

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

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

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

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

Definition at line 3786 of file procarray.c.

References InvalidTransactionId, and KnownAssignedXidsGetAndSetXmin().

Referenced by TransactionIdIsInProgress().

3787 {
3789 
3790  return KnownAssignedXidsGetAndSetXmin(xarray, &xtmp, xmax);
3791 }
uint32 TransactionId
Definition: c.h:397
#define InvalidTransactionId
Definition: transam.h:31
static int KnownAssignedXidsGetAndSetXmin(TransactionId *xarray, TransactionId *xmin, TransactionId xmax)
Definition: procarray.c:3800
static int KnownAssignedXidsGetAndSetXmin ( TransactionId xarray,
TransactionId xmin,
TransactionId  xmax 
)
static

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

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

Definition at line 3858 of file procarray.c.

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

Referenced by GetOldestXmin().

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

Definition at line 3659 of file procarray.c.

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

Referenced by KnownAssignedXidsRemoveTree().

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

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

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

Definition at line 3685 of file procarray.c.

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

Referenced by ExpireTreeKnownAssignedTransactionIds(), and ProcArrayApplyXidAssignment().

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

Definition at line 3932 of file procarray.c.

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

Referenced by ProcArrayApplyRecoveryInfo().

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

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

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

Definition at line 2669 of file procarray.c.

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

Referenced by XLogFlush().

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

Definition at line 273 of file procarray.c.

References ereport, errcode(), errmsg(), FATAL, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), ProcArrayStruct::maxProcs, memmove, ProcArrayStruct::numProcs, PGPROC::pgprocno, ProcArrayStruct::pgprocnos, and procArray.

Referenced by InitProcessPhase2(), and MarkAsPrepared().

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

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

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

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

References Assert, i, InvalidTransactionId, KnownAssignedXidsRemoveTree(), ProcArrayStruct::lastOverflowedXid, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), RecordKnownAssignedTransactionIds(), STANDBY_INITIALIZED, standbyState, SubTransSetParent(), TransactionIdLatest(), and TransactionIdPrecedes().

Referenced by xact_redo().

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

Definition at line 601 of file procarray.c.

References PGXACT::delayChkpt, InvalidLocalTransactionId, InvalidTransactionId, PGPROC::lxid, PGXACT::nxids, PGXACT::overflowed, PGPROC::pgprocno, PROC_VACUUM_STATE_MASK, PGPROC::recoveryConflictPending, PGXACT::vacuumFlags, PGXACT::xid, and PGXACT::xmin.

Referenced by PrepareTransaction().

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

Definition at line 394 of file procarray.c.

References Assert, PGXACT::delayChkpt, InvalidLocalTransactionId, InvalidTransactionId, LW_EXCLUSIVE, LWLockConditionalAcquire(), LWLockRelease(), PGPROC::lxid, PGXACT::nxids, PGXACT::overflowed, PGPROC::pgprocno, PROC_VACUUM_STATE_MASK, ProcArrayEndTransactionInternal(), ProcArrayGroupClearXid(), PGPROC::recoveryConflictPending, TransactionIdIsValid, PGXACT::vacuumFlags, PGXACT::xid, and PGXACT::xmin.

Referenced by AbortTransaction(), and CommitTransaction().

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

Definition at line 448 of file procarray.c.

References PGXACT::delayChkpt, InvalidLocalTransactionId, InvalidTransactionId, VariableCacheData::latestCompletedXid, PGPROC::lxid, PGXACT::nxids, PGXACT::overflowed, PROC_VACUUM_STATE_MASK, PGPROC::recoveryConflictPending, ShmemVariableCache, TransactionIdPrecedes(), PGXACT::vacuumFlags, PGXACT::xid, and PGXACT::xmin.

Referenced by ProcArrayEndTransaction(), and ProcArrayGroupClearXid().

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

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

2972 {
2973  LWLockAcquire(ProcArrayLock, LW_SHARED);
2974 
2975  if (xmin != NULL)
2977 
2978  if (catalog_xmin != NULL)
2979  *catalog_xmin = procArray->replication_slot_catalog_xmin;
2980 
2981  LWLockRelease(ProcArrayLock);
2982 }
TransactionId replication_slot_catalog_xmin
Definition: procarray.c:91
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
static ProcArrayStruct * procArray
Definition: procarray.c:97
TransactionId replication_slot_xmin
Definition: procarray.c:89
#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 482 of file procarray.c.

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

Referenced by ProcArrayEndTransaction().

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

Definition at line 633 of file procarray.c.

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

Referenced by StartupXLOG().

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

Definition at line 1792 of file procarray.c.

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

Referenced by GetSerializableTransactionSnapshotInt(), and SetTransactionSnapshot().

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

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

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

Definition at line 331 of file procarray.c.

References Assert, elog, VariableCacheData::latestCompletedXid, LOG, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), memmove, ProcArrayStruct::numProcs, PGPROC::pgprocno, ProcArrayStruct::pgprocnos, PGPROC::pid, procArray, ShmemVariableCache, TransactionIdIsValid, TransactionIdPrecedes(), and PGXACT::xid.

Referenced by FinishPreparedTransaction(), and RemoveProcFromArray().

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

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

Referenced by ReplicationSlotsComputeRequiredXmin().

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

Definition at line 178 of file procarray.c.

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

Referenced by CreateSharedMemoryAndSemaphores().

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

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

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

References Assert, ereport, errcode(), errmsg(), ERROR, i, KnownAssignedXidExists(), KnownAssignedXidsGet(), ProcArrayStruct::lastOverflowedXid, VariableCacheData::latestCompletedXid, LW_SHARED, LWLockAcquire(), LWLockRelease(), malloc, ProcArrayStruct::maxProcs, MyProc, NULL, ProcArrayStruct::numProcs, PGXACT::nxids, PGXACT::overflowed, ProcArrayStruct::pgprocnos, procArray, RecentXmin, RecoveryInProgress(), ShmemVariableCache, SubTransGetTopmostTransaction(), PGPROC::subxids, TOTAL_MAX_CACHED_SUBXIDS, TransactionIdDidAbort(), TransactionIdEquals, TransactionIdIsCurrentTransactionId(), TransactionIdIsKnownCompleted(), TransactionIdIsValid, TransactionIdPrecedes(), TransactionIdPrecedesOrEquals(), xc_by_child_xid_inc, xc_by_known_assigned_inc, xc_by_known_xact_inc, xc_by_latest_xid_inc, xc_by_main_xid_inc, xc_by_my_xact_inc, xc_by_recent_xmin_inc, xc_no_overflow_inc, xc_slow_answer_inc, PGXACT::xid, and XidCache::xids.

Referenced by asyncQueueProcessPageEntries(), check_safe_enum_use(), compute_new_xmax_infomask(), ConditionalXactLockTableWait(), Do_MultiXactIdWait(), DoesMultiXactIdConflict(), FreezeMultiXactId(), HeapTupleHeaderIsOnlyLocked(), HeapTupleSatisfiesDirty(), HeapTupleSatisfiesSelf(), HeapTupleSatisfiesToast(), HeapTupleSatisfiesUpdate(), HeapTupleSatisfiesVacuum(), MultiXactIdExpand(), MultiXactIdIsRunning(), test_lockmode_for_conflict(), and XactLockTableWait().

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

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

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

PGPROC* allProcs
static

Definition at line 99 of file procarray.c.

TransactionId standbySnapshotPendingXmin
static

Definition at line 114 of file procarray.c.

Referenced by ProcArrayApplyRecoveryInfo().