PostgreSQL Source Code  git master
procarray.h File Reference
#include "storage/lock.h"
#include "storage/standby.h"
#include "utils/relcache.h"
#include "utils/snapshot.h"
Include dependency graph for procarray.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define PROCARRAY_VACUUM_FLAG
 
#define PROCARRAY_ANALYZE_FLAG
 
#define PROCARRAY_LOGICAL_DECODING_FLAG
 
#define PROCARRAY_SLOTS_XMIN
 
#define PROCARRAY_PROC_FLAGS_MASK
 
#define PROCARRAY_FLAGS_DEFAULT   PROCARRAY_LOGICAL_DECODING_FLAG
 
#define PROCARRAY_FLAGS_VACUUM   PROCARRAY_FLAGS_DEFAULT | PROCARRAY_VACUUM_FLAG
 
#define PROCARRAY_FLAGS_ANALYZE   PROCARRAY_FLAGS_DEFAULT | PROCARRAY_ANALYZE_FLAG
 
#define PROCARRAY_FLAGS_VACUUM_ANALYZE   PROCARRAY_FLAGS_DEFAULT | PROCARRAY_VACUUM_FLAG | PROCARRAY_ANALYZE_FLAG
 

Functions

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

Macro Definition Documentation

◆ PROCARRAY_ANALYZE_FLAG

#define PROCARRAY_ANALYZE_FLAG
Value:
0x04 /* currently running
* analyze */

Definition at line 32 of file procarray.h.

◆ PROCARRAY_FLAGS_ANALYZE

#define PROCARRAY_FLAGS_ANALYZE   PROCARRAY_FLAGS_DEFAULT | PROCARRAY_ANALYZE_FLAG

Definition at line 54 of file procarray.h.

◆ PROCARRAY_FLAGS_DEFAULT

#define PROCARRAY_FLAGS_DEFAULT   PROCARRAY_LOGICAL_DECODING_FLAG

Definition at line 50 of file procarray.h.

Referenced by CreateCheckPoint(), CreateRestartPoint(), and XLogWalRcvSendHSFeedback().

◆ PROCARRAY_FLAGS_VACUUM

◆ PROCARRAY_FLAGS_VACUUM_ANALYZE

#define PROCARRAY_FLAGS_VACUUM_ANALYZE   PROCARRAY_FLAGS_DEFAULT | PROCARRAY_VACUUM_FLAG | PROCARRAY_ANALYZE_FLAG

Definition at line 56 of file procarray.h.

◆ PROCARRAY_LOGICAL_DECODING_FLAG

#define PROCARRAY_LOGICAL_DECODING_FLAG
Value:
0x10 /* currently doing logical
* decoding outside xact */

Definition at line 34 of file procarray.h.

◆ PROCARRAY_PROC_FLAGS_MASK

#define PROCARRAY_PROC_FLAGS_MASK
Value:
PROCARRAY_ANALYZE_FLAG | \
PROCARRAY_LOGICAL_DECODING_FLAG)
#define PROCARRAY_VACUUM_FLAG
Definition: procarray.h:30

Definition at line 44 of file procarray.h.

Referenced by GetOldestXmin().

◆ PROCARRAY_SLOTS_XMIN

#define PROCARRAY_SLOTS_XMIN
Value:
0x20 /* replication slot xmin,
* catalog_xmin */

Definition at line 37 of file procarray.h.

Referenced by GetOldestXmin(), and XLogWalRcvSendHSFeedback().

◆ PROCARRAY_VACUUM_FLAG

#define PROCARRAY_VACUUM_FLAG
Value:
0x02 /* currently running lazy
* vacuum */

Definition at line 30 of file procarray.h.

Function Documentation

◆ BackendPidGetProc()

PGPROC* BackendPidGetProc ( int  pid)

Definition at line 2365 of file procarray.c.

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

Referenced by IsBackendPid(), pg_signal_backend(), pg_stat_get_activity(), pg_stat_get_backend_wait_event(), pg_stat_get_backend_wait_event_type(), ProcSendSignal(), and test_shm_mq_main().

2366 {
2367  PGPROC *result;
2368 
2369  if (pid == 0) /* never match dummy PGPROCs */
2370  return NULL;
2371 
2372  LWLockAcquire(ProcArrayLock, LW_SHARED);
2373 
2374  result = BackendPidGetProcWithLock(pid);
2375 
2376  LWLockRelease(ProcArrayLock);
2377 
2378  return result;
2379 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
PGPROC * BackendPidGetProcWithLock(int pid)
Definition: procarray.c:2388
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121
Definition: proc.h:95

◆ BackendPidGetProcWithLock()

PGPROC* BackendPidGetProcWithLock ( int  pid)

Definition at line 2388 of file procarray.c.

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

Referenced by BackendPidGetProc(), and GetBlockerStatusData().

2389 {
2390  PGPROC *result = NULL;
2391  ProcArrayStruct *arrayP = procArray;
2392  int index;
2393 
2394  if (pid == 0) /* never match dummy PGPROCs */
2395  return NULL;
2396 
2397  for (index = 0; index < arrayP->numProcs; index++)
2398  {
2399  PGPROC *proc = &allProcs[arrayP->pgprocnos[index]];
2400 
2401  if (proc->pid == pid)
2402  {
2403  result = proc;
2404  break;
2405  }
2406  }
2407 
2408  return result;
2409 }
Definition: type.h:89
static PGPROC * allProcs
Definition: procarray.c:100
static ProcArrayStruct * procArray
Definition: procarray.c:98
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:95
Definition: proc.h:95
int pid
Definition: proc.h:109

◆ BackendXidGetPid()

int BackendXidGetPid ( TransactionId  xid)

Definition at line 2425 of file procarray.c.

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

Referenced by pgrowlocks().

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

◆ CancelDBBackends()

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

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

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

◆ CancelVirtualTransaction()

pid_t CancelVirtualTransaction ( VirtualTransactionId  vxid,
ProcSignalReason  sigmode 
)

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

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

◆ CountDBBackends()

int CountDBBackends ( Oid  databaseid)

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

2759 {
2760  ProcArrayStruct *arrayP = procArray;
2761  int count = 0;
2762  int index;
2763 
2764  LWLockAcquire(ProcArrayLock, LW_SHARED);
2765 
2766  for (index = 0; index < arrayP->numProcs; index++)
2767  {
2768  int pgprocno = arrayP->pgprocnos[index];
2769  volatile PGPROC *proc = &allProcs[pgprocno];
2770 
2771  if (proc->pid == 0)
2772  continue; /* do not count prepared xacts */
2773  if (!OidIsValid(databaseid) ||
2774  proc->databaseId == databaseid)
2775  count++;
2776  }
2777 
2778  LWLockRelease(ProcArrayLock);
2779 
2780  return count;
2781 }
#define OidIsValid(objectId)
Definition: c.h:638
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
static PGPROC * allProcs
Definition: procarray.c:100
Oid databaseId
Definition: proc.h:114
static ProcArrayStruct * procArray
Definition: procarray.c:98
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:95
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121
Definition: proc.h:95
int pid
Definition: proc.h:109

◆ CountDBConnections()

int CountDBConnections ( Oid  databaseid)

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

2789 {
2790  ProcArrayStruct *arrayP = procArray;
2791  int count = 0;
2792  int index;
2793 
2794  LWLockAcquire(ProcArrayLock, LW_SHARED);
2795 
2796  for (index = 0; index < arrayP->numProcs; index++)
2797  {
2798  int pgprocno = arrayP->pgprocnos[index];
2799  volatile PGPROC *proc = &allProcs[pgprocno];
2800 
2801  if (proc->pid == 0)
2802  continue; /* do not count prepared xacts */
2803  if (proc->isBackgroundWorker)
2804  continue; /* do not count background workers */
2805  if (!OidIsValid(databaseid) ||
2806  proc->databaseId == databaseid)
2807  count++;
2808  }
2809 
2810  LWLockRelease(ProcArrayLock);
2811 
2812  return count;
2813 }
#define OidIsValid(objectId)
Definition: c.h:638
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
bool isBackgroundWorker
Definition: proc.h:120
static PGPROC * allProcs
Definition: procarray.c:100
Oid databaseId
Definition: proc.h:114
static ProcArrayStruct * procArray
Definition: procarray.c:98
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:95
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121
Definition: proc.h:95
int pid
Definition: proc.h:109

◆ CountOtherDBBackends()

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

Definition at line 2909 of file procarray.c.

References CHECK_FOR_INTERRUPTS, PGPROC::databaseId, kill, LW_SHARED, LWLockAcquire(), LWLockRelease(), MAXAUTOVACPIDS, MyProc, ProcArrayStruct::numProcs, pg_usleep(), ProcArrayStruct::pgprocnos, PGPROC::pid, PROC_IS_AUTOVACUUM, procArray, and PGXACT::vacuumFlags.

Referenced by createdb(), dropdb(), movedb(), and RenameDatabase().

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

◆ CountUserBackends()

int CountUserBackends ( Oid  roleid)

Definition at line 2859 of file procarray.c.

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

Referenced by InitializeSessionUserId().

2860 {
2861  ProcArrayStruct *arrayP = procArray;
2862  int count = 0;
2863  int index;
2864 
2865  LWLockAcquire(ProcArrayLock, LW_SHARED);
2866 
2867  for (index = 0; index < arrayP->numProcs; index++)
2868  {
2869  int pgprocno = arrayP->pgprocnos[index];
2870  volatile PGPROC *proc = &allProcs[pgprocno];
2871 
2872  if (proc->pid == 0)
2873  continue; /* do not count prepared xacts */
2874  if (proc->isBackgroundWorker)
2875  continue; /* do not count background workers */
2876  if (proc->roleId == roleid)
2877  count++;
2878  }
2879 
2880  LWLockRelease(ProcArrayLock);
2881 
2882  return count;
2883 }
Oid roleId
Definition: proc.h:115
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
bool isBackgroundWorker
Definition: proc.h:120
static PGPROC * allProcs
Definition: procarray.c:100
static ProcArrayStruct * procArray
Definition: procarray.c:98
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:95
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121
Definition: proc.h:95
int pid
Definition: proc.h:109

◆ CreateSharedProcArray()

void CreateSharedProcArray ( void  )

Definition at line 221 of file procarray.c.

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

Referenced by CreateSharedMemoryAndSemaphores().

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

◆ ExpireAllKnownAssignedTransactionIds()

void ExpireAllKnownAssignedTransactionIds ( void  )

Definition at line 3290 of file procarray.c.

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

Referenced by ShutdownRecoveryTransactionEnvironment().

3291 {
3292  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3294  LWLockRelease(ProcArrayLock);
3295 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
static void KnownAssignedXidsRemovePreceding(TransactionId xid)
Definition: procarray.c:3742
#define InvalidTransactionId
Definition: transam.h:31
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121

◆ ExpireOldKnownAssignedTransactionIds()

void ExpireOldKnownAssignedTransactionIds ( TransactionId  xid)

Definition at line 3302 of file procarray.c.

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

Referenced by ProcArrayApplyRecoveryInfo().

3303 {
3304  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3306  LWLockRelease(ProcArrayLock);
3307 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
static void KnownAssignedXidsRemovePreceding(TransactionId xid)
Definition: procarray.c:3742
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121

◆ ExpireTreeKnownAssignedTransactionIds()

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

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

3267 {
3269 
3270  /*
3271  * Uses same locking as transaction commit
3272  */
3273  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3274 
3275  KnownAssignedXidsRemoveTree(xid, nsubxids, subxids);
3276 
3277  /* As in ProcArrayEndTransaction, advance latestCompletedXid */
3279  max_xid))
3281 
3282  LWLockRelease(ProcArrayLock);
3283 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
VariableCache ShmemVariableCache
Definition: varsup.c:34
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
static void KnownAssignedXidsRemoveTree(TransactionId xid, int nsubxids, TransactionId *subxids)
Definition: procarray.c:3720
#define Assert(condition)
Definition: c.h:732
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121
HotStandbyState standbyState
Definition: xlog.c:197
TransactionId latestCompletedXid
Definition: transam.h:135

◆ GetConflictingVirtualXIDs()

VirtualTransactionId* GetConflictingVirtualXIDs ( TransactionId  limitXmin,
Oid  dbOid 
)

Definition at line 2581 of file procarray.c.

References VirtualTransactionId::backendId, PGPROC::databaseId, ereport, errcode(), errmsg(), ERROR, GET_VXID_FROM_PGPROC, InvalidBackendId, InvalidLocalTransactionId, VirtualTransactionId::localTransactionId, LW_SHARED, LWLockAcquire(), LWLockRelease(), malloc, ProcArrayStruct::maxProcs, ProcArrayStruct::numProcs, OidIsValid, ProcArrayStruct::pgprocnos, PGPROC::pid, procArray, TransactionIdFollows(), TransactionIdIsValid, VirtualTransactionIdIsValid, and PGXACT::xmin.

Referenced by ResolveRecoveryConflictWithSnapshot(), and ResolveRecoveryConflictWithTablespace().

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

◆ GetCurrentVirtualXIDs()

VirtualTransactionId* GetCurrentVirtualXIDs ( TransactionId  limitXmin,
bool  excludeXmin0,
bool  allDbs,
int  excludeVacuum,
int *  nvxids 
)

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

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

◆ GetMaxSnapshotSubxidCount()

int GetMaxSnapshotSubxidCount ( void  )

Definition at line 1469 of file procarray.c.

References TOTAL_MAX_CACHED_SUBXIDS.

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

1470 {
1471  return TOTAL_MAX_CACHED_SUBXIDS;
1472 }
#define TOTAL_MAX_CACHED_SUBXIDS

◆ GetMaxSnapshotXidCount()

int GetMaxSnapshotXidCount ( void  )

Definition at line 1458 of file procarray.c.

References ProcArrayStruct::maxProcs.

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

1459 {
1460  return procArray->maxProcs;
1461 }
static ProcArrayStruct * procArray
Definition: procarray.c:98

◆ GetOldestActiveTransactionId()

TransactionId GetOldestActiveTransactionId ( void  )

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

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

◆ GetOldestSafeDecodingTransactionId()

TransactionId GetOldestSafeDecodingTransactionId ( bool  catalogOnly)

Definition at line 2177 of file procarray.c.

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

Referenced by CreateInitDecodingContext(), and SnapBuildInitialSnapshot().

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

◆ GetOldestXmin()

TransactionId GetOldestXmin ( Relation  rel,
int  flags 
)

Definition at line 1317 of file procarray.c.

References Assert, PGPROC::databaseId, FirstNormalTransactionId, InvalidTransactionId, KnownAssignedXidsGetOldestXmin(), VariableCacheData::latestCompletedXid, LW_SHARED, LWLockAcquire(), LWLockRelease(), MyDatabaseId, NormalTransactionIdPrecedes, ProcArrayStruct::numProcs, ProcArrayStruct::pgprocnos, procArray, PROCARRAY_PROC_FLAGS_MASK, PROCARRAY_SLOTS_XMIN, RelationData::rd_rel, RecoveryInProgress(), RelationIsAccessibleInLogicalDecoding, ProcArrayStruct::replication_slot_catalog_xmin, ProcArrayStruct::replication_slot_xmin, ShmemVariableCache, TransactionIdAdvance, TransactionIdIsNormal, TransactionIdIsValid, TransactionIdPrecedes(), vacuum_defer_cleanup_age, PGXACT::vacuumFlags, PGXACT::xid, and PGXACT::xmin.

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

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

◆ GetRunningTransactionData()

RunningTransactions GetRunningTransactionData ( void  )

Definition at line 1940 of file procarray.c.

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

Referenced by LogStandbySnapshot().

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

◆ GetSnapshotData()

Snapshot GetSnapshotData ( Snapshot  snapshot)

Definition at line 1511 of file procarray.c.

References SnapshotData::active_count, Assert, SnapshotData::copied, SnapshotData::curcid, ereport, errcode(), errmsg(), ERROR, FirstNormalTransactionId, GetCurrentCommandId(), GetMaxSnapshotSubxidCount(), GetMaxSnapshotXidCount(), GetSnapshotCurrentTimestamp(), GetXLogInsertRecPtr(), InvalidTransactionId, InvalidXLogRecPtr, KnownAssignedXidsGetAndSetXmin(), ProcArrayStruct::lastOverflowedXid, VariableCacheData::latestCompletedXid, SnapshotData::lsn, LW_SHARED, LWLockAcquire(), LWLockRelease(), MaintainOldSnapshotTimeMapping(), malloc, MyPgXact, NormalTransactionIdPrecedes, ProcArrayStruct::numProcs, PGXACT::nxids, old_snapshot_threshold, PGXACT::overflowed, ProcArrayStruct::pgprocnos, PROC_IN_LOGICAL_DECODING, PROC_IN_VACUUM, procArray, RecentGlobalDataXmin, RecentGlobalXmin, RecentXmin, RecoveryInProgress(), SnapshotData::regd_count, ProcArrayStruct::replication_slot_catalog_xmin, ProcArrayStruct::replication_slot_xmin, ShmemVariableCache, SnapshotData::suboverflowed, SnapshotData::subxcnt, PGPROC::subxids, SnapshotData::subxip, SnapshotData::takenDuringRecovery, TransactionIdAdvance, TransactionIdIsNormal, TransactionIdIsValid, TransactionIdPrecedes(), TransactionIdPrecedesOrEquals(), TransactionXmin, vacuum_defer_cleanup_age, PGXACT::vacuumFlags, SnapshotData::whenTaken, SnapshotData::xcnt, PGXACT::xid, XidCache::xids, SnapshotData::xip, SnapshotData::xmax, SnapshotData::xmin, and PGXACT::xmin.

Referenced by GetLatestSnapshot(), GetNonHistoricCatalogSnapshot(), GetSerializableTransactionSnapshotInt(), GetTransactionSnapshot(), and SetTransactionSnapshot().

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

◆ GetVirtualXIDsDelayingChkpt()

VirtualTransactionId* GetVirtualXIDsDelayingChkpt ( int *  nvxids)

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

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

◆ HaveVirtualXIDsDelayingChkpt()

bool HaveVirtualXIDsDelayingChkpt ( VirtualTransactionId vxids,
int  nvxids 
)

Definition at line 2318 of file procarray.c.

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

Referenced by CreateCheckPoint().

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

◆ IsBackendPid()

bool IsBackendPid ( int  pid)

Definition at line 2460 of file procarray.c.

References BackendPidGetProc().

Referenced by pg_stat_get_subscription().

2461 {
2462  return (BackendPidGetProc(pid) != NULL);
2463 }
PGPROC * BackendPidGetProc(int pid)
Definition: procarray.c:2365

◆ MinimumActiveBackends()

bool MinimumActiveBackends ( int  min)

Definition at line 2704 of file procarray.c.

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

Referenced by XLogFlush().

2705 {
2706  ProcArrayStruct *arrayP = procArray;
2707  int count = 0;
2708  int index;
2709 
2710  /* Quick short-circuit if no minimum is specified */
2711  if (min == 0)
2712  return true;
2713 
2714  /*
2715  * Note: for speed, we don't acquire ProcArrayLock. This is a little bit
2716  * bogus, but since we are only testing fields for zero or nonzero, it
2717  * should be OK. The result is only used for heuristic purposes anyway...
2718  */
2719  for (index = 0; index < arrayP->numProcs; index++)
2720  {
2721  int pgprocno = arrayP->pgprocnos[index];
2722  volatile PGPROC *proc = &allProcs[pgprocno];
2723  volatile PGXACT *pgxact = &allPgXact[pgprocno];
2724 
2725  /*
2726  * Since we're not holding a lock, need to be prepared to deal with
2727  * garbage, as someone could have incremented numProcs but not yet
2728  * filled the structure.
2729  *
2730  * If someone just decremented numProcs, 'proc' could also point to a
2731  * PGPROC entry that's no longer in the array. It still points to a
2732  * PGPROC struct, though, because freed PGPROC entries just go to the
2733  * free list and are recycled. Its contents are nonsense in that case,
2734  * but that's acceptable for this function.
2735  */
2736  if (pgprocno == -1)
2737  continue; /* do not count deleted entries */
2738  if (proc == MyProc)
2739  continue; /* do not count myself */
2740  if (pgxact->xid == InvalidTransactionId)
2741  continue; /* do not count if no XID assigned */
2742  if (proc->pid == 0)
2743  continue; /* do not count prepared xacts */
2744  if (proc->waitLock != NULL)
2745  continue; /* do not count if blocked on a lock */
2746  count++;
2747  if (count >= min)
2748  break;
2749  }
2750 
2751  return count >= min;
2752 }
Definition: proc.h:222
PGPROC * MyProc
Definition: proc.c:67
TransactionId xid
Definition: proc.h:224
Definition: type.h:89
#define InvalidTransactionId
Definition: transam.h:31
static PGPROC * allProcs
Definition: procarray.c:100
LOCK * waitLock
Definition: proc.h:139
static ProcArrayStruct * procArray
Definition: procarray.c:98
static PGXACT * allPgXact
Definition: procarray.c:101
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:95
Definition: proc.h:95
int pid
Definition: proc.h:109

◆ ProcArrayAdd()

void ProcArrayAdd ( PGPROC proc)

Definition at line 275 of file procarray.c.

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

Referenced by InitProcessPhase2(), and MarkAsPrepared().

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

◆ ProcArrayApplyRecoveryInfo()

void ProcArrayApplyRecoveryInfo ( RunningTransactions  running)

Definition at line 662 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(), TransactionIdEquals, TransactionIdFollows(), TransactionIdIsNormal, TransactionIdIsValid, TransactionIdPrecedes(), TransactionIdRetreat, RunningTransactionsData::xcnt, xidComparator(), and RunningTransactionsData::xids.

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

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

◆ ProcArrayApplyXidAssignment()

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

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

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

◆ ProcArrayClearTransaction()

void ProcArrayClearTransaction ( PGPROC proc)

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

600 {
601  PGXACT *pgxact = &allPgXact[proc->pgprocno];
602 
603  /*
604  * We can skip locking ProcArrayLock here, because this action does not
605  * actually change anyone's view of the set of running XIDs: our entry is
606  * duplicate with the gxact that has already been inserted into the
607  * ProcArray.
608  */
609  pgxact->xid = InvalidTransactionId;
611  pgxact->xmin = InvalidTransactionId;
612  proc->recoveryConflictPending = false;
613 
614  /* redundant, but just in case */
616  pgxact->delayChkpt = false;
617 
618  /* Clear the subtransaction-XID cache too */
619  pgxact->nxids = 0;
620  pgxact->overflowed = false;
621 }
Definition: proc.h:222
TransactionId xmin
Definition: proc.h:228
TransactionId xid
Definition: proc.h:224
uint8 vacuumFlags
Definition: proc.h:233
#define PROC_VACUUM_STATE_MASK
Definition: proc.h:62
bool recoveryConflictPending
Definition: proc.h:127
uint8 nxids
Definition: proc.h:238
#define InvalidTransactionId
Definition: transam.h:31
bool delayChkpt
Definition: proc.h:235
static PGXACT * allPgXact
Definition: procarray.c:101
bool overflowed
Definition: proc.h:234
int pgprocno
Definition: proc.h:110
#define InvalidLocalTransactionId
Definition: lock.h:69
LocalTransactionId lxid
Definition: proc.h:106

◆ ProcArrayEndTransaction()

void ProcArrayEndTransaction ( PGPROC proc,
TransactionId  latestXid 
)

Definition at line 396 of file procarray.c.

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

Referenced by AbortTransaction(), and CommitTransaction().

397 {
398  PGXACT *pgxact = &allPgXact[proc->pgprocno];
399 
400  if (TransactionIdIsValid(latestXid))
401  {
402  /*
403  * We must lock ProcArrayLock while clearing our advertised XID, so
404  * that we do not exit the set of "running" transactions while someone
405  * else is taking a snapshot. See discussion in
406  * src/backend/access/transam/README.
407  */
409 
410  /*
411  * If we can immediately acquire ProcArrayLock, we clear our own XID
412  * and release the lock. If not, use group XID clearing to improve
413  * efficiency.
414  */
415  if (LWLockConditionalAcquire(ProcArrayLock, LW_EXCLUSIVE))
416  {
417  ProcArrayEndTransactionInternal(proc, pgxact, latestXid);
418  LWLockRelease(ProcArrayLock);
419  }
420  else
421  ProcArrayGroupClearXid(proc, latestXid);
422  }
423  else
424  {
425  /*
426  * If we have no XID, we don't need to lock, since we won't affect
427  * anyone else's calculation of a snapshot. We might change their
428  * estimate of global xmin, but that's OK.
429  */
431 
433  pgxact->xmin = InvalidTransactionId;
434  /* must be cleared with xid/xmin: */
436  pgxact->delayChkpt = false; /* be sure this is cleared in abort */
437  proc->recoveryConflictPending = false;
438 
439  Assert(pgxact->nxids == 0);
440  Assert(pgxact->overflowed == false);
441  }
442 }
Definition: proc.h:222
TransactionId xmin
Definition: proc.h:228
TransactionId xid
Definition: proc.h:224
static void ProcArrayGroupClearXid(PGPROC *proc, TransactionId latestXid)
Definition: procarray.c:484
uint8 vacuumFlags
Definition: proc.h:233
#define PROC_VACUUM_STATE_MASK
Definition: proc.h:62
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
bool LWLockConditionalAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1293
bool recoveryConflictPending
Definition: proc.h:127
uint8 nxids
Definition: proc.h:238
#define InvalidTransactionId
Definition: transam.h:31
bool delayChkpt
Definition: proc.h:235
static PGXACT * allPgXact
Definition: procarray.c:101
bool overflowed
Definition: proc.h:234
static void ProcArrayEndTransactionInternal(PGPROC *proc, PGXACT *pgxact, TransactionId latestXid)
Definition: procarray.c:450
#define Assert(condition)
Definition: c.h:732
int pgprocno
Definition: proc.h:110
#define InvalidLocalTransactionId
Definition: lock.h:69
#define TransactionIdIsValid(xid)
Definition: transam.h:41
LocalTransactionId lxid
Definition: proc.h:106

◆ ProcArrayGetReplicationSlotXmin()

void ProcArrayGetReplicationSlotXmin ( TransactionId xmin,
TransactionId catalog_xmin 
)

Definition at line 3005 of file procarray.c.

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

Referenced by logical_begin_heap_rewrite(), and XLogWalRcvSendHSFeedback().

3007 {
3008  LWLockAcquire(ProcArrayLock, LW_SHARED);
3009 
3010  if (xmin != NULL)
3012 
3013  if (catalog_xmin != NULL)
3014  *catalog_xmin = procArray->replication_slot_catalog_xmin;
3015 
3016  LWLockRelease(ProcArrayLock);
3017 }
TransactionId replication_slot_catalog_xmin
Definition: procarray.c:92
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
static ProcArrayStruct * procArray
Definition: procarray.c:98
TransactionId replication_slot_xmin
Definition: procarray.c:90
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121

◆ ProcArrayInitRecovery()

void ProcArrayInitRecovery ( TransactionId  initializedUptoXID)

Definition at line 631 of file procarray.c.

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

Referenced by StartupXLOG().

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

◆ ProcArrayInstallImportedXmin()

bool ProcArrayInstallImportedXmin ( TransactionId  xmin,
VirtualTransactionId sourcevxid 
)

Definition at line 1799 of file procarray.c.

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

Referenced by GetSerializableTransactionSnapshotInt(), and SetTransactionSnapshot().

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

◆ ProcArrayInstallRestoredXmin()

bool ProcArrayInstallRestoredXmin ( TransactionId  xmin,
PGPROC proc 
)

Definition at line 1874 of file procarray.c.

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

Referenced by SetTransactionSnapshot().

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

◆ ProcArrayRemove()

void ProcArrayRemove ( PGPROC proc,
TransactionId  latestXid 
)

Definition at line 333 of file procarray.c.

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

Referenced by FinishPreparedTransaction(), and RemoveProcFromArray().

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

◆ ProcArraySetReplicationSlotXmin()

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

Definition at line 2983 of file procarray.c.

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

Referenced by ReplicationSlotsComputeRequiredXmin().

2985 {
2986  Assert(!already_locked || LWLockHeldByMe(ProcArrayLock));
2987 
2988  if (!already_locked)
2989  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
2990 
2992  procArray->replication_slot_catalog_xmin = catalog_xmin;
2993 
2994  if (!already_locked)
2995  LWLockRelease(ProcArrayLock);
2996 }
bool LWLockHeldByMe(LWLock *l)
Definition: lwlock.c:1841
TransactionId replication_slot_catalog_xmin
Definition: procarray.c:92
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
static ProcArrayStruct * procArray
Definition: procarray.c:98
TransactionId replication_slot_xmin
Definition: procarray.c:90
#define Assert(condition)
Definition: c.h:732
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121

◆ ProcArrayShmemSize()

Size ProcArrayShmemSize ( void  )

Definition at line 179 of file procarray.c.

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

Referenced by CreateSharedMemoryAndSemaphores().

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

◆ RecordKnownAssignedTransactionIds()

void RecordKnownAssignedTransactionIds ( TransactionId  xid)

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

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

◆ TransactionIdIsActive()

bool TransactionIdIsActive ( TransactionId  xid)

Definition at line 1218 of file procarray.c.

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

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

◆ TransactionIdIsInProgress()

bool TransactionIdIsInProgress ( TransactionId  xid)

Definition at line 1001 of file procarray.c.

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

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

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

◆ XidCacheRemoveRunningXids()

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

Definition at line 3035 of file procarray.c.

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

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