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 TerminateOtherDBBackends (Oid databaseId)
 
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 2362 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(), TerminateOtherDBBackends(), and test_shm_mq_main().

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

◆ BackendPidGetProcWithLock()

PGPROC* BackendPidGetProcWithLock ( int  pid)

Definition at line 2385 of file procarray.c.

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

Referenced by BackendPidGetProc(), and GetBlockerStatusData().

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

◆ BackendXidGetPid()

int BackendXidGetPid ( TransactionId  xid)

Definition at line 2422 of file procarray.c.

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

Referenced by pgrowlocks().

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

◆ CancelDBBackends()

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

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

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

◆ CancelVirtualTransaction()

pid_t CancelVirtualTransaction ( VirtualTransactionId  vxid,
ProcSignalReason  sigmode 
)

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

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

◆ CountDBBackends()

int CountDBBackends ( Oid  databaseid)

Definition at line 2755 of file procarray.c.

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

Referenced by ResolveRecoveryConflictWithDatabase().

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

◆ CountDBConnections()

int CountDBConnections ( Oid  databaseid)

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

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

◆ CountOtherDBBackends()

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

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

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

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

Referenced by InitializeSessionUserId().

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

◆ CreateSharedProcArray()

void CreateSharedProcArray ( void  )

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

226 {
227  bool found;
228 
229  /* Create or attach to the ProcArray shared structure */
231  ShmemInitStruct("Proc Array",
232  add_size(offsetof(ProcArrayStruct, pgprocnos),
233  mul_size(sizeof(int),
235  &found);
236 
237  if (!found)
238  {
239  /*
240  * We're the first - initialize.
241  */
242  procArray->numProcs = 0;
252  }
253 
256 
257  /* Create or attach to the KnownAssignedXids arrays too, if needed */
258  if (EnableHotStandby)
259  {
261  ShmemInitStruct("KnownAssignedXids",
262  mul_size(sizeof(TransactionId),
264  &found);
265  KnownAssignedXidsValid = (bool *)
266  ShmemInitStruct("KnownAssignedXidsValid",
267  mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS),
268  &found);
269  }
270 }
#define PROCARRAY_MAXPROCS
uint32 TransactionId
Definition: c.h:513
PGXACT * allPgXact
Definition: proc.h:247
#define SpinLockInit(lock)
Definition: spin.h:60
TransactionId replication_slot_catalog_xmin
Definition: procarray.c:96
slock_t known_assigned_xids_lck
Definition: procarray.c:82
PROC_HDR * ProcGlobal
Definition: proc.c:80
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition: shmem.c:392
int maxKnownAssignedXids
Definition: procarray.c:78
#define InvalidTransactionId
Definition: transam.h:31
static PGPROC * allProcs
Definition: procarray.c:104
int numKnownAssignedXids
Definition: procarray.c:79
static bool * KnownAssignedXidsValid
Definition: procarray.c:111
TransactionId lastOverflowedXid
Definition: procarray.c:91
static ProcArrayStruct * procArray
Definition: procarray.c:102
TransactionId replication_slot_xmin
Definition: procarray.c:94
Size mul_size(Size s1, Size s2)
Definition: shmem.c:515
static PGXACT * allPgXact
Definition: procarray.c:105
Size add_size(Size s1, Size s2)
Definition: shmem.c:498
#define TOTAL_MAX_CACHED_SUBXIDS
static TransactionId * KnownAssignedXids
Definition: procarray.c:110
bool EnableHotStandby
Definition: xlog.c:96
PGPROC * allProcs
Definition: proc.h:245
int tailKnownAssignedXids
Definition: procarray.c:80
#define offsetof(type, field)
Definition: c.h:661
int headKnownAssignedXids
Definition: procarray.c:81

◆ ExpireAllKnownAssignedTransactionIds()

void ExpireAllKnownAssignedTransactionIds ( void  )

Definition at line 3403 of file procarray.c.

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

Referenced by ShutdownRecoveryTransactionEnvironment().

3404 {
3405  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3407  LWLockRelease(ProcArrayLock);
3408 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
static void KnownAssignedXidsRemovePreceding(TransactionId xid)
Definition: procarray.c:3852
#define InvalidTransactionId
Definition: transam.h:31
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208

◆ ExpireOldKnownAssignedTransactionIds()

void ExpireOldKnownAssignedTransactionIds ( TransactionId  xid)

Definition at line 3415 of file procarray.c.

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

Referenced by ProcArrayApplyRecoveryInfo().

3416 {
3417  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3419  LWLockRelease(ProcArrayLock);
3420 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
static void KnownAssignedXidsRemovePreceding(TransactionId xid)
Definition: procarray.c:3852
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208

◆ ExpireTreeKnownAssignedTransactionIds()

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

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

3380 {
3382 
3383  /*
3384  * Uses same locking as transaction commit
3385  */
3386  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3387 
3388  KnownAssignedXidsRemoveTree(xid, nsubxids, subxids);
3389 
3390  /* As in ProcArrayEndTransaction, advance latestCompletedXid */
3392  max_xid))
3394 
3395  LWLockRelease(ProcArrayLock);
3396 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
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:3830
#define Assert(condition)
Definition: c.h:738
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
HotStandbyState standbyState
Definition: xlog.c:207
TransactionId latestCompletedXid
Definition: transam.h:196

◆ GetConflictingVirtualXIDs()

VirtualTransactionId* GetConflictingVirtualXIDs ( TransactionId  limitXmin,
Oid  dbOid 
)

Definition at line 2578 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, UINT32_ACCESS_ONCE, VirtualTransactionIdIsValid, and PGXACT::xmin.

Referenced by ResolveRecoveryConflictWithSnapshot(), and ResolveRecoveryConflictWithTablespace().

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

Referenced by WaitForOlderSnapshots().

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

◆ GetMaxSnapshotSubxidCount()

int GetMaxSnapshotSubxidCount ( void  )

Definition at line 1462 of file procarray.c.

References TOTAL_MAX_CACHED_SUBXIDS.

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

1463 {
1464  return TOTAL_MAX_CACHED_SUBXIDS;
1465 }
#define TOTAL_MAX_CACHED_SUBXIDS

◆ GetMaxSnapshotXidCount()

int GetMaxSnapshotXidCount ( void  )

Definition at line 1451 of file procarray.c.

References ProcArrayStruct::maxProcs.

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

1452 {
1453  return procArray->maxProcs;
1454 }
static ProcArrayStruct * procArray
Definition: procarray.c:102

◆ GetOldestActiveTransactionId()

TransactionId GetOldestActiveTransactionId ( void  )

Definition at line 2110 of file procarray.c.

References Assert, LW_SHARED, LWLockAcquire(), LWLockRelease(), VariableCacheData::nextFullXid, ProcArrayStruct::numProcs, ProcArrayStruct::pgprocnos, procArray, RecoveryInProgress(), ShmemVariableCache, TransactionIdIsNormal, TransactionIdPrecedes(), UINT32_ACCESS_ONCE, PGXACT::xid, and XidFromFullTransactionId.

Referenced by CreateCheckPoint().

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

◆ GetOldestSafeDecodingTransactionId()

TransactionId GetOldestSafeDecodingTransactionId ( bool  catalogOnly)

Definition at line 2176 of file procarray.c.

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

Referenced by CreateInitDecodingContext(), and SnapBuildInitialSnapshot().

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

◆ GetOldestXmin()

TransactionId GetOldestXmin ( Relation  rel,
int  flags 
)

Definition at line 1305 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(), UINT32_ACCESS_ONCE, vacuum_defer_cleanup_age, PGXACT::vacuumFlags, PGXACT::xid, and PGXACT::xmin.

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

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

◆ GetRunningTransactionData()

RunningTransactions GetRunningTransactionData ( void  )

Definition at line 1936 of file procarray.c.

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

Referenced by LogStandbySnapshot().

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

◆ GetSnapshotData()

Snapshot GetSnapshotData ( Snapshot  snapshot)

Definition at line 1504 of file procarray.c.

References SnapshotData::active_count, Assert, SnapshotData::copied, SnapshotData::curcid, ereport, errcode(), errmsg(), ERROR, FirstNormalTransactionId, GetCurrentCommandId(), GetMaxSnapshotSubxidCount(), GetMaxSnapshotXidCount(), GetSnapshotCurrentTimestamp(), GetXLogInsertRecPtr(), InvalidTransactionId, InvalidXLogRecPtr, KnownAssignedXidsGetAndSetXmin(), ProcArrayStruct::lastOverflowedXid, VariableCacheData::latestCompletedXid, SnapshotData::lsn, LW_SHARED, LWLockAcquire(), LWLockRelease(), MaintainOldSnapshotTimeMapping(), malloc, MyPgXact, NormalTransactionIdPrecedes, ProcArrayStruct::numProcs, PGXACT::nxids, old_snapshot_threshold, PGXACT::overflowed, pg_read_barrier, 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, UINT32_ACCESS_ONCE, vacuum_defer_cleanup_age, PGXACT::vacuumFlags, SnapshotData::whenTaken, SnapshotData::xcnt, PGXACT::xid, XidCache::xids, SnapshotData::xip, SnapshotData::xmax, SnapshotData::xmin, and PGXACT::xmin.

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

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

◆ GetVirtualXIDsDelayingChkpt()

VirtualTransactionId* GetVirtualXIDsDelayingChkpt ( int *  nvxids)

Definition at line 2272 of file procarray.c.

References PGPROC::delayChkpt, GET_VXID_FROM_PGPROC, LW_SHARED, LWLockAcquire(), LWLockRelease(), ProcArrayStruct::maxProcs, ProcArrayStruct::numProcs, palloc(), ProcArrayStruct::pgprocnos, procArray, and VirtualTransactionIdIsValid.

Referenced by CreateCheckPoint().

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

◆ HaveVirtualXIDsDelayingChkpt()

bool HaveVirtualXIDsDelayingChkpt ( VirtualTransactionId vxids,
int  nvxids 
)

Definition at line 2316 of file procarray.c.

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

Referenced by CreateCheckPoint().

2317 {
2318  bool result = false;
2319  ProcArrayStruct *arrayP = procArray;
2320  int index;
2321 
2322  LWLockAcquire(ProcArrayLock, LW_SHARED);
2323 
2324  for (index = 0; index < arrayP->numProcs; index++)
2325  {
2326  int pgprocno = arrayP->pgprocnos[index];
2327  PGPROC *proc = &allProcs[pgprocno];
2328  VirtualTransactionId vxid;
2329 
2330  GET_VXID_FROM_PGPROC(vxid, *proc);
2331 
2332  if (proc->delayChkpt && VirtualTransactionIdIsValid(vxid))
2333  {
2334  int i;
2335 
2336  for (i = 0; i < nvxids; i++)
2337  {
2338  if (VirtualTransactionIdEquals(vxid, vxids[i]))
2339  {
2340  result = true;
2341  break;
2342  }
2343  }
2344  if (result)
2345  break;
2346  }
2347  }
2348 
2349  LWLockRelease(ProcArrayLock);
2350 
2351  return result;
2352 }
#define GET_VXID_FROM_PGPROC(vxid, proc)
Definition: lock.h:79
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
#define VirtualTransactionIdEquals(vxid1, vxid2)
Definition: lock.h:73
bool delayChkpt
Definition: proc.h:145
static PGPROC * allProcs
Definition: procarray.c:104
static ProcArrayStruct * procArray
Definition: procarray.c:102
#define VirtualTransactionIdIsValid(vxid)
Definition: lock.h:70
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:99
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
int i
Definition: proc.h:95

◆ IsBackendPid()

bool IsBackendPid ( int  pid)

Definition at line 2457 of file procarray.c.

References BackendPidGetProc().

Referenced by pg_stat_get_subscription().

2458 {
2459  return (BackendPidGetProc(pid) != NULL);
2460 }
PGPROC * BackendPidGetProc(int pid)
Definition: procarray.c:2362

◆ MinimumActiveBackends()

bool MinimumActiveBackends ( int  min)

Definition at line 2701 of file procarray.c.

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

Referenced by XLogFlush().

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

◆ ProcArrayAdd()

void ProcArrayAdd ( PGPROC proc)

Definition at line 276 of file procarray.c.

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

Referenced by InitProcessPhase2(), and MarkAsPrepared().

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

◆ ProcArrayApplyRecoveryInfo()

void ProcArrayApplyRecoveryInfo ( RunningTransactions  running)

Definition at line 663 of file procarray.c.

References AdvanceNextFullTransactionIdPastXid(), Assert, DEBUG1, DEBUG3, elog, ERROR, ExpireOldKnownAssignedTransactionIds(), ExtendSUBTRANS(), FullTransactionIdIsValid, i, InvalidTransactionId, KnownAssignedXidsAdd(), KnownAssignedXidsDisplay(), KnownAssignedXidsReset(), ProcArrayStruct::lastOverflowedXid, RunningTransactionsData::latestCompletedXid, VariableCacheData::latestCompletedXid, latestObservedXid, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), VariableCacheData::nextFullXid, RunningTransactionsData::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, TransactionIdIsNormal, TransactionIdIsValid, TransactionIdPrecedes(), TransactionIdRetreat, RunningTransactionsData::xcnt, xidComparator(), and RunningTransactionsData::xids.

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

664 {
665  TransactionId *xids;
666  int nxids;
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  * NB: this can be reached at least twice, so make sure new code can deal
739  * with that.
740  */
741 
742  /*
743  * Nobody else is running yet, but take locks anyhow
744  */
745  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
746 
747  /*
748  * KnownAssignedXids is sorted so we cannot just add the xids, we have to
749  * sort them first.
750  *
751  * Some of the new xids are top-level xids and some are subtransactions.
752  * We don't call SubTransSetParent because it doesn't matter yet. If we
753  * aren't overflowed then all xids will fit in snapshot and so we don't
754  * need subtrans. If we later overflow, an xid assignment record will add
755  * xids to subtrans. If RunningTransactionsData is overflowed then we
756  * don't have enough information to correctly update subtrans anyway.
757  */
758 
759  /*
760  * Allocate a temporary array to avoid modifying the array passed as
761  * argument.
762  */
763  xids = palloc(sizeof(TransactionId) * (running->xcnt + running->subxcnt));
764 
765  /*
766  * Add to the temp array any xids which have not already completed.
767  */
768  nxids = 0;
769  for (i = 0; i < running->xcnt + running->subxcnt; i++)
770  {
771  TransactionId xid = running->xids[i];
772 
773  /*
774  * The running-xacts snapshot can contain xids that were still visible
775  * in the procarray when the snapshot was taken, but were already
776  * WAL-logged as completed. They're not running anymore, so ignore
777  * them.
778  */
780  continue;
781 
782  xids[nxids++] = xid;
783  }
784 
785  if (nxids > 0)
786  {
788  {
789  LWLockRelease(ProcArrayLock);
790  elog(ERROR, "KnownAssignedXids is not empty");
791  }
792 
793  /*
794  * Sort the array so that we can add them safely into
795  * KnownAssignedXids.
796  */
797  qsort(xids, nxids, sizeof(TransactionId), xidComparator);
798 
799  /*
800  * Add the sorted snapshot into KnownAssignedXids. The running-xacts
801  * snapshot may include duplicated xids because of prepared
802  * transactions, so ignore them.
803  */
804  for (i = 0; i < nxids; i++)
805  {
806  if (i > 0 && TransactionIdEquals(xids[i - 1], xids[i]))
807  {
808  elog(DEBUG1,
809  "found duplicated transaction %u for KnownAssignedXids insertion",
810  xids[i]);
811  continue;
812  }
813  KnownAssignedXidsAdd(xids[i], xids[i], true);
814  }
815 
817  }
818 
819  pfree(xids);
820 
821  /*
822  * latestObservedXid is at least set to the point where SUBTRANS was
823  * started up to (cf. ProcArrayInitRecovery()) or to the biggest xid
824  * RecordKnownAssignedTransactionIds() was called for. Initialize
825  * subtrans from thereon, up to nextXid - 1.
826  *
827  * We need to duplicate parts of RecordKnownAssignedTransactionId() here,
828  * because we've just added xids to the known assigned xids machinery that
829  * haven't gone through RecordKnownAssignedTransactionId().
830  */
834  {
837  }
838  TransactionIdRetreat(latestObservedXid); /* = running->nextXid - 1 */
839 
840  /* ----------
841  * Now we've got the running xids we need to set the global values that
842  * are used to track snapshots as they evolve further.
843  *
844  * - latestCompletedXid which will be the xmax for snapshots
845  * - lastOverflowedXid which shows whether snapshots overflow
846  * - nextXid
847  *
848  * If the snapshot overflowed, then we still initialise with what we know,
849  * but the recovery snapshot isn't fully valid yet because we know there
850  * are some subxids missing. We don't know the specific subxids that are
851  * missing, so conservatively assume the last one is latestObservedXid.
852  * ----------
853  */
854  if (running->subxid_overflow)
855  {
857 
860  }
861  else
862  {
864 
866  }
867 
868  /*
869  * If a transaction wrote a commit record in the gap between taking and
870  * logging the snapshot then latestCompletedXid may already be higher than
871  * the value from the snapshot, so check before we use the incoming value.
872  */
874  running->latestCompletedXid))
876 
878 
879  LWLockRelease(ProcArrayLock);
880 
881  /* ShmemVariableCache->nextFullXid must be beyond any observed xid. */
883 
885 
888  elog(trace_recovery(DEBUG1), "recovery snapshots are now enabled");
889  else
891  "recovery snapshot waiting for non-overflowed snapshot or "
892  "until oldest active xid on standby is at least %u (now %u)",
894  running->oldestRunningXid);
895 }
#define TransactionIdAdvance(dest)
Definition: transam.h:89
static TransactionId latestObservedXid
Definition: procarray.c:112
TransactionId oldestRunningXid
Definition: standby.h:76
#define DEBUG1
Definition: elog.h:25
static void KnownAssignedXidsDisplay(int trace_level)
Definition: procarray.c:4037
#define TransactionIdEquals(id1, id2)
Definition: transam.h:43
uint32 TransactionId
Definition: c.h:513
void AdvanceNextFullTransactionIdPastXid(TransactionId xid)
Definition: varsup.c:262
#define DEBUG3
Definition: elog.h:23
#define FullTransactionIdIsValid(x)
Definition: transam.h:55
TransactionId * xids
Definition: standby.h:79
FullTransactionId nextFullXid
Definition: transam.h:178
bool TransactionIdDidCommit(TransactionId transactionId)
Definition: transam.c:125
#define TransactionIdRetreat(dest)
Definition: transam.h:106
int trace_recovery(int trace_level)
Definition: elog.c:3505
TransactionId latestCompletedXid
Definition: standby.h:77
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
void pfree(void *pointer)
Definition: mcxt.c:1056
#define ERROR
Definition: elog.h:43
void ExtendSUBTRANS(TransactionId newestXact)
Definition: subtrans.c:326
VariableCache ShmemVariableCache
Definition: varsup.c:34
#define InvalidTransactionId
Definition: transam.h:31
static void KnownAssignedXidsReset(void)
Definition: procarray.c:4075
int numKnownAssignedXids
Definition: procarray.c:79
TransactionId lastOverflowedXid
Definition: procarray.c:91
bool TransactionIdDidAbort(TransactionId transactionId)
Definition: transam.c:181
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
static ProcArrayStruct * procArray
Definition: procarray.c:102
#define Assert(condition)
Definition: c.h:738
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
static void KnownAssignedXidsAdd(TransactionId from_xid, TransactionId to_xid, bool exclusive_lock)
Definition: procarray.c:3580
TransactionId nextXid
Definition: standby.h:75
void * palloc(Size size)
Definition: mcxt.c:949
#define elog(elevel,...)
Definition: elog.h:214
int i
void ExpireOldKnownAssignedTransactionIds(TransactionId xid)
Definition: procarray.c:3415
#define qsort(a, b, c, d)
Definition: port.h:479
#define TransactionIdIsValid(xid)
Definition: transam.h:41
#define TransactionIdIsNormal(xid)
Definition: transam.h:42
static TransactionId standbySnapshotPendingXmin
Definition: procarray.c:119
HotStandbyState standbyState
Definition: xlog.c:207
void StandbyReleaseOldLocks(TransactionId oldxid)
Definition: standby.c:773
int xidComparator(const void *arg1, const void *arg2)
Definition: xid.c:139
TransactionId latestCompletedXid
Definition: transam.h:196

◆ ProcArrayApplyXidAssignment()

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

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

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

◆ ProcArrayClearTransaction()

void ProcArrayClearTransaction ( PGPROC proc)

Definition at line 600 of file procarray.c.

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

601 {
602  PGXACT *pgxact = &allPgXact[proc->pgprocno];
603 
604  /*
605  * We can skip locking ProcArrayLock here, because this action does not
606  * actually change anyone's view of the set of running XIDs: our entry is
607  * duplicate with the gxact that has already been inserted into the
608  * ProcArray.
609  */
610  pgxact->xid = InvalidTransactionId;
612  pgxact->xmin = InvalidTransactionId;
613  proc->recoveryConflictPending = false;
614 
615  /* redundant, but just in case */
617  proc->delayChkpt = false;
618 
619  /* Clear the subtransaction-XID cache too */
620  pgxact->nxids = 0;
621  pgxact->overflowed = false;
622 }
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 delayChkpt
Definition: proc.h:145
bool recoveryConflictPending
Definition: proc.h:127
uint8 nxids
Definition: proc.h:236
#define InvalidTransactionId
Definition: transam.h:31
static PGXACT * allPgXact
Definition: procarray.c:105
bool overflowed
Definition: proc.h:234
int pgprocno
Definition: proc.h:110
#define InvalidLocalTransactionId
Definition: lock.h:68
LocalTransactionId lxid
Definition: proc.h:106

◆ ProcArrayEndTransaction()

void ProcArrayEndTransaction ( PGPROC proc,
TransactionId  latestXid 
)

Definition at line 397 of file procarray.c.

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

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

◆ ProcArrayGetReplicationSlotXmin()

void ProcArrayGetReplicationSlotXmin ( TransactionId xmin,
TransactionId catalog_xmin 
)

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

3116 {
3117  LWLockAcquire(ProcArrayLock, LW_SHARED);
3118 
3119  if (xmin != NULL)
3121 
3122  if (catalog_xmin != NULL)
3123  *catalog_xmin = procArray->replication_slot_catalog_xmin;
3124 
3125  LWLockRelease(ProcArrayLock);
3126 }
TransactionId replication_slot_catalog_xmin
Definition: procarray.c:96
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
static ProcArrayStruct * procArray
Definition: procarray.c:102
TransactionId replication_slot_xmin
Definition: procarray.c:94
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208

◆ ProcArrayInitRecovery()

void ProcArrayInitRecovery ( TransactionId  initializedUptoXID)

Definition at line 632 of file procarray.c.

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

Referenced by StartupXLOG().

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

◆ ProcArrayInstallImportedXmin()

bool ProcArrayInstallImportedXmin ( TransactionId  xmin,
VirtualTransactionId sourcevxid 
)

Definition at line 1795 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, UINT32_ACCESS_ONCE, PGXACT::vacuumFlags, and PGXACT::xmin.

Referenced by GetSerializableTransactionSnapshotInt(), and SetTransactionSnapshot().

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

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

Referenced by SetTransactionSnapshot().

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

◆ ProcArrayRemove()

void ProcArrayRemove ( PGPROC proc,
TransactionId  latestXid 
)

Definition at line 334 of file procarray.c.

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

Referenced by FinishPreparedTransaction(), and RemoveProcFromArray().

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

◆ ProcArraySetReplicationSlotXmin()

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

Definition at line 3092 of file procarray.c.

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

Referenced by ReplicationSlotsComputeRequiredXmin().

3094 {
3095  Assert(!already_locked || LWLockHeldByMe(ProcArrayLock));
3096 
3097  if (!already_locked)
3098  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3099 
3101  procArray->replication_slot_catalog_xmin = catalog_xmin;
3102 
3103  if (!already_locked)
3104  LWLockRelease(ProcArrayLock);
3105 }
bool LWLockHeldByMe(LWLock *l)
Definition: lwlock.c:1928
TransactionId replication_slot_catalog_xmin
Definition: procarray.c:96
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
static ProcArrayStruct * procArray
Definition: procarray.c:102
TransactionId replication_slot_xmin
Definition: procarray.c:94
#define Assert(condition)
Definition: c.h:738
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208

◆ ProcArrayShmemSize()

Size ProcArrayShmemSize ( void  )

Definition at line 183 of file procarray.c.

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

Referenced by CreateSharedMemoryAndSemaphores().

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

◆ RecordKnownAssignedTransactionIds()

void RecordKnownAssignedTransactionIds ( TransactionId  xid)

Definition at line 3307 of file procarray.c.

References AdvanceNextFullTransactionIdPastXid(), Assert, DEBUG4, elog, ExtendSUBTRANS(), KnownAssignedXidsAdd(), latestObservedXid, STANDBY_INITIALIZED, standbyState, trace_recovery(), TransactionIdAdvance, TransactionIdFollows(), TransactionIdIsValid, and TransactionIdPrecedes().

Referenced by ProcArrayApplyXidAssignment(), StartupXLOG(), xact_redo_abort(), and xact_redo_commit().

3308 {
3312 
3313  elog(trace_recovery(DEBUG4), "record known xact %u latestObservedXid %u",
3314  xid, latestObservedXid);
3315 
3316  /*
3317  * When a newly observed xid arrives, it is frequently the case that it is
3318  * *not* the next xid in sequence. When this occurs, we must treat the
3319  * intervening xids as running also.
3320  */
3322  {
3323  TransactionId next_expected_xid;
3324 
3325  /*
3326  * Extend subtrans like we do in GetNewTransactionId() during normal
3327  * operation using individual extend steps. Note that we do not need
3328  * to extend clog since its extensions are WAL logged.
3329  *
3330  * This part has to be done regardless of standbyState since we
3331  * immediately start assigning subtransactions to their toplevel
3332  * transactions.
3333  */
3334  next_expected_xid = latestObservedXid;
3335  while (TransactionIdPrecedes(next_expected_xid, xid))
3336  {
3337  TransactionIdAdvance(next_expected_xid);
3338  ExtendSUBTRANS(next_expected_xid);
3339  }
3340  Assert(next_expected_xid == xid);
3341 
3342  /*
3343  * If the KnownAssignedXids machinery isn't up yet, there's nothing
3344  * more to do since we don't track assigned xids yet.
3345  */
3347  {
3348  latestObservedXid = xid;
3349  return;
3350  }
3351 
3352  /*
3353  * Add (latestObservedXid, xid] onto the KnownAssignedXids array.
3354  */
3355  next_expected_xid = latestObservedXid;
3356  TransactionIdAdvance(next_expected_xid);
3357  KnownAssignedXidsAdd(next_expected_xid, xid, false);
3358 
3359  /*
3360  * Now we can advance latestObservedXid
3361  */
3362  latestObservedXid = xid;
3363 
3364  /* ShmemVariableCache->nextFullXid must be beyond any observed xid */
3366  next_expected_xid = latestObservedXid;
3367  TransactionIdAdvance(next_expected_xid);
3368  }
3369 }
#define TransactionIdAdvance(dest)
Definition: transam.h:89
static TransactionId latestObservedXid
Definition: procarray.c:112
bool TransactionIdFollows(TransactionId id1, TransactionId id2)
Definition: transam.c:334
uint32 TransactionId
Definition: c.h:513
void AdvanceNextFullTransactionIdPastXid(TransactionId xid)
Definition: varsup.c:262
#define DEBUG4
Definition: elog.h:22
int trace_recovery(int trace_level)
Definition: elog.c:3505
void ExtendSUBTRANS(TransactionId newestXact)
Definition: subtrans.c:326
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
#define Assert(condition)
Definition: c.h:738
static void KnownAssignedXidsAdd(TransactionId from_xid, TransactionId to_xid, bool exclusive_lock)
Definition: procarray.c:3580
#define elog(elevel,...)
Definition: elog.h:214
#define TransactionIdIsValid(xid)
Definition: transam.h:41
HotStandbyState standbyState
Definition: xlog.c:207

◆ TerminateOtherDBBackends()

void TerminateOtherDBBackends ( Oid  databaseId)

Definition at line 2984 of file procarray.c.

References BackendPidGetProc(), PGPROC::databaseId, ereport, errcode(), errdetail_plural(), errmsg(), ERROR, get_database_name(), GetUserId(), has_privs_of_role(), i, kill, lappend_int(), lfirst_int, LW_SHARED, LWLockAcquire(), LWLockRelease(), MyProc, NIL, ProcArrayStruct::numProcs, ProcArrayStruct::pgprocnos, PGPROC::pid, procArray, PGPROC::roleId, superuser(), and superuser_arg().

Referenced by dropdb().

2985 {
2986  ProcArrayStruct *arrayP = procArray;
2987  List *pids = NIL;
2988  int nprepared = 0;
2989  int i;
2990 
2991  LWLockAcquire(ProcArrayLock, LW_SHARED);
2992 
2993  for (i = 0; i < procArray->numProcs; i++)
2994  {
2995  int pgprocno = arrayP->pgprocnos[i];
2996  PGPROC *proc = &allProcs[pgprocno];
2997 
2998  if (proc->databaseId != databaseId)
2999  continue;
3000  if (proc == MyProc)
3001  continue;
3002 
3003  if (proc->pid != 0)
3004  pids = lappend_int(pids, proc->pid);
3005  else
3006  nprepared++;
3007  }
3008 
3009  LWLockRelease(ProcArrayLock);
3010 
3011  if (nprepared > 0)
3012  ereport(ERROR,
3013  (errcode(ERRCODE_OBJECT_IN_USE),
3014  errmsg("database \"%s\" is being used by prepared transaction",
3015  get_database_name(databaseId)),
3016  errdetail_plural("There is %d prepared transaction using the database.",
3017  "There are %d prepared transactions using the database.",
3018  nprepared,
3019  nprepared)));
3020 
3021  if (pids)
3022  {
3023  ListCell *lc;
3024 
3025  /*
3026  * Check whether we have the necessary rights to terminate other
3027  * sessions. We don't terminate any session until we ensure that we
3028  * have rights on all the sessions to be terminated. These checks are
3029  * the same as we do in pg_terminate_backend.
3030  *
3031  * In this case we don't raise some warnings - like "PID %d is not a
3032  * PostgreSQL server process", because for us already finished session
3033  * is not a problem.
3034  */
3035  foreach(lc, pids)
3036  {
3037  int pid = lfirst_int(lc);
3038  PGPROC *proc = BackendPidGetProc(pid);
3039 
3040  if (proc != NULL)
3041  {
3042  /* Only allow superusers to signal superuser-owned backends. */
3043  if (superuser_arg(proc->roleId) && !superuser())
3044  ereport(ERROR,
3045  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
3046  errmsg("must be a superuser to terminate superuser process")));
3047 
3048  /* Users can signal backends they have role membership in. */
3049  if (!has_privs_of_role(GetUserId(), proc->roleId) &&
3050  !has_privs_of_role(GetUserId(), DEFAULT_ROLE_SIGNAL_BACKENDID))
3051  ereport(ERROR,
3052  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
3053  errmsg("must be a member of the role whose process is being terminated or member of pg_signal_backend")));
3054  }
3055  }
3056 
3057  /*
3058  * There's a race condition here: once we release the ProcArrayLock,
3059  * it's possible for the session to exit before we issue kill. That
3060  * race condition possibility seems too unlikely to worry about. See
3061  * pg_signal_backend.
3062  */
3063  foreach(lc, pids)
3064  {
3065  int pid = lfirst_int(lc);
3066  PGPROC *proc = BackendPidGetProc(pid);
3067 
3068  if (proc != NULL)
3069  {
3070  /*
3071  * If we have setsid(), signal the backend's whole process
3072  * group
3073  */
3074 #ifdef HAVE_SETSID
3075  (void) kill(-pid, SIGTERM);
3076 #else
3077  (void) kill(pid, SIGTERM);
3078 #endif
3079  }
3080  }
3081  }
3082 }
#define NIL
Definition: pg_list.h:65
Oid GetUserId(void)
Definition: miscinit.c:448
PGPROC * BackendPidGetProc(int pid)
Definition: procarray.c:2362
PGPROC * MyProc
Definition: proc.c:67
bool has_privs_of_role(Oid member, Oid role)
Definition: acl.c:4892
Oid roleId
Definition: proc.h:115
int errcode(int sqlerrcode)
Definition: elog.c:610
bool superuser(void)
Definition: superuser.c:46
#define kill(pid, sig)
Definition: win32_port.h:426
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
#define ERROR
Definition: elog.h:43
#define lfirst_int(lc)
Definition: pg_list.h:191
char * get_database_name(Oid dbid)
Definition: dbcommands.c:2155
static PGPROC * allProcs
Definition: procarray.c:104
Oid databaseId
Definition: proc.h:114
bool superuser_arg(Oid roleid)
Definition: superuser.c:56
List * lappend_int(List *list, int datum)
Definition: list.c:339
static ProcArrayStruct * procArray
Definition: procarray.c:102
#define ereport(elevel,...)
Definition: elog.h:144
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:99
int errdetail_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n,...)
Definition: elog.c:1049
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
int errmsg(const char *fmt,...)
Definition: elog.c:824
int i
Definition: proc.h:95
Definition: pg_list.h:50
int pid
Definition: proc.h:109

◆ TransactionIdIsActive()

bool TransactionIdIsActive ( TransactionId  xid)

Definition at line 1206 of file procarray.c.

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

1207 {
1208  bool result = false;
1209  ProcArrayStruct *arrayP = procArray;
1210  int i;
1211 
1212  /*
1213  * Don't bother checking a transaction older than RecentXmin; it could not
1214  * possibly still be running.
1215  */
1217  return false;
1218 
1219  LWLockAcquire(ProcArrayLock, LW_SHARED);
1220 
1221  for (i = 0; i < arrayP->numProcs; i++)
1222  {
1223  int pgprocno = arrayP->pgprocnos[i];
1224  PGPROC *proc = &allProcs[pgprocno];
1225  PGXACT *pgxact = &allPgXact[pgprocno];
1226  TransactionId pxid;
1227 
1228  /* Fetch xid just once - see GetNewTransactionId */
1229  pxid = UINT32_ACCESS_ONCE(pgxact->xid);
1230 
1231  if (!TransactionIdIsValid(pxid))
1232  continue;
1233 
1234  if (proc->pid == 0)
1235  continue; /* ignore prepared transactions */
1236 
1237  if (TransactionIdEquals(pxid, xid))
1238  {
1239  result = true;
1240  break;
1241  }
1242  }
1243 
1244  LWLockRelease(ProcArrayLock);
1245 
1246  return result;
1247 }
#define TransactionIdEquals(id1, id2)
Definition: transam.h:43
uint32 TransactionId
Definition: c.h:513
Definition: proc.h:222
TransactionId xid
Definition: proc.h:224
#define UINT32_ACCESS_ONCE(var)
Definition: procarray.c:67
TransactionId RecentXmin
Definition: snapmgr.c:167
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
static PGPROC * allProcs
Definition: procarray.c:104
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
static ProcArrayStruct * procArray
Definition: procarray.c:102
static PGXACT * allPgXact
Definition: procarray.c:105
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:99
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
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 986 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, pg_read_barrier, ProcArrayStruct::pgprocnos, procArray, RecentXmin, RecoveryInProgress(), ShmemVariableCache, SubTransGetTopmostTransaction(), PGPROC::subxids, TOTAL_MAX_CACHED_SUBXIDS, TransactionIdDidAbort(), TransactionIdEquals, TransactionIdIsCurrentTransactionId(), TransactionIdIsKnownCompleted(), TransactionIdIsValid, TransactionIdPrecedes(), TransactionIdPrecedesOrEquals(), UINT32_ACCESS_ONCE, 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().

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

◆ XidCacheRemoveRunningXids()

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

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

3148 {
3149  int i,
3150  j;
3151 
3153 
3154  /*
3155  * We must hold ProcArrayLock exclusively in order to remove transactions
3156  * from the PGPROC array. (See src/backend/access/transam/README.) It's
3157  * possible this could be relaxed since we know this routine is only used
3158  * to abort subtransactions, but pending closer analysis we'd best be
3159  * conservative.
3160  *
3161  * Note that we do not have to be careful about memory ordering of our own
3162  * reads wrt. GetNewTransactionId() here - only this process can modify
3163  * relevant fields of MyProc/MyPgXact. But we do have to be careful about
3164  * our own writes being well ordered.
3165  */
3166  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3167 
3168  /*
3169  * Under normal circumstances xid and xids[] will be in increasing order,
3170  * as will be the entries in subxids. Scan backwards to avoid O(N^2)
3171  * behavior when removing a lot of xids.
3172  */
3173  for (i = nxids - 1; i >= 0; i--)
3174  {
3175  TransactionId anxid = xids[i];
3176 
3177  for (j = MyPgXact->nxids - 1; j >= 0; j--)
3178  {
3179  if (TransactionIdEquals(MyProc->subxids.xids[j], anxid))
3180  {
3181  XidCacheRemove(j);
3182  break;
3183  }
3184  }
3185 
3186  /*
3187  * Ordinarily we should have found it, unless the cache has
3188  * overflowed. However it's also possible for this routine to be
3189  * invoked multiple times for the same subtransaction, in case of an
3190  * error during AbortSubTransaction. So instead of Assert, emit a
3191  * debug warning.
3192  */
3193  if (j < 0 && !MyPgXact->overflowed)
3194  elog(WARNING, "did not find subXID %u in MyProc", anxid);
3195  }
3196 
3197  for (j = MyPgXact->nxids - 1; j >= 0; j--)
3198  {
3199  if (TransactionIdEquals(MyProc->subxids.xids[j], xid))
3200  {
3201  XidCacheRemove(j);
3202  break;
3203  }
3204  }
3205  /* Ordinarily we should have found it, unless the cache has overflowed */
3206  if (j < 0 && !MyPgXact->overflowed)
3207  elog(WARNING, "did not find subXID %u in MyProc", xid);
3208 
3209  /* Also advance global latestCompletedXid while holding the lock */
3211  latestXid))
3213 
3214  LWLockRelease(ProcArrayLock);
3215 }
#define XidCacheRemove(i)
Definition: procarray.c:3129
#define TransactionIdEquals(id1, id2)
Definition: transam.h:43
uint32 TransactionId
Definition: c.h:513
PGPROC * MyProc
Definition: proc.c:67
PGXACT * MyPgXact
Definition: proc.c:68
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
uint8 nxids
Definition: proc.h:236
VariableCache ShmemVariableCache
Definition: varsup.c:34
struct XidCache subxids
Definition: proc.h:164
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:738
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
#define elog(elevel,...)
Definition: elog.h:214
int i
#define TransactionIdIsValid(xid)
Definition: transam.h:41
TransactionId latestCompletedXid
Definition: transam.h:196