PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
procarray.h File Reference
#include "storage/lock.h"
#include "storage/standby.h"
#include "utils/relcache.h"
#include "utils/snapshot.h"
Include dependency graph for procarray.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

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

Functions

Size ProcArrayShmemSize (void)
 
void CreateSharedProcArray (void)
 
void ProcArrayAdd (PGPROC *proc)
 
void ProcArrayRemove (PGPROC *proc, TransactionId latestXid)
 
void ProcArrayEndTransaction (PGPROC *proc, TransactionId latestXid)
 
void ProcArrayClearTransaction (PGPROC *proc)
 
void ProcArrayInitRecovery (TransactionId initializedUptoXID)
 
void ProcArrayApplyRecoveryInfo (RunningTransactions running)
 
void ProcArrayApplyXidAssignment (TransactionId topxid, int nsubxids, TransactionId *subxids)
 
void RecordKnownAssignedTransactionIds (TransactionId xid)
 
void ExpireTreeKnownAssignedTransactionIds (TransactionId xid, int nsubxids, TransactionId *subxids, TransactionId max_xid)
 
void ExpireAllKnownAssignedTransactionIds (void)
 
void ExpireOldKnownAssignedTransactionIds (TransactionId xid)
 
int GetMaxSnapshotXidCount (void)
 
int GetMaxSnapshotSubxidCount (void)
 
Snapshot GetSnapshotData (Snapshot snapshot)
 
bool ProcArrayInstallImportedXmin (TransactionId xmin, VirtualTransactionId *sourcevxid)
 
bool ProcArrayInstallRestoredXmin (TransactionId xmin, PGPROC *proc)
 
RunningTransactions GetRunningTransactionData (void)
 
bool TransactionIdIsInProgress (TransactionId xid)
 
bool TransactionIdIsActive (TransactionId xid)
 
TransactionId GetOldestXmin (Relation rel, int flags)
 
TransactionId GetOldestActiveTransactionId (void)
 
TransactionId GetOldestSafeDecodingTransactionId (bool catalogOnly)
 
VirtualTransactionIdGetVirtualXIDsDelayingChkpt (int *nvxids)
 
bool HaveVirtualXIDsDelayingChkpt (VirtualTransactionId *vxids, int nvxids)
 
PGPROCBackendPidGetProc (int pid)
 
PGPROCBackendPidGetProcWithLock (int pid)
 
int BackendXidGetPid (TransactionId xid)
 
bool IsBackendPid (int pid)
 
VirtualTransactionIdGetCurrentVirtualXIDs (TransactionId limitXmin, bool excludeXmin0, bool allDbs, int excludeVacuum, int *nvxids)
 
VirtualTransactionIdGetConflictingVirtualXIDs (TransactionId limitXmin, Oid dbOid)
 
pid_t CancelVirtualTransaction (VirtualTransactionId vxid, ProcSignalReason sigmode)
 
bool MinimumActiveBackends (int min)
 
int CountDBBackends (Oid databaseid)
 
int CountDBConnections (Oid databaseid)
 
void CancelDBBackends (Oid databaseid, ProcSignalReason sigmode, bool conflictPending)
 
int CountUserBackends (Oid roleid)
 
bool CountOtherDBBackends (Oid databaseId, int *nbackends, int *nprepared)
 
void XidCacheRemoveRunningXids (TransactionId xid, int nxids, const TransactionId *xids, TransactionId latestXid)
 
void ProcArraySetReplicationSlotXmin (TransactionId xmin, TransactionId catalog_xmin, bool already_locked)
 
void ProcArrayGetReplicationSlotXmin (TransactionId *xmin, TransactionId *catalog_xmin)
 

Macro Definition Documentation

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

Definition at line 32 of file procarray.h.

#define PROCARRAY_FLAGS_ANALYZE   PROCARRAY_FLAGS_DEFAULT | PROCARRAY_ANALYZE_FLAG

Definition at line 54 of file procarray.h.

#define PROCARRAY_FLAGS_DEFAULT   PROCARRAY_LOGICAL_DECODING_FLAG

Definition at line 50 of file procarray.h.

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

#define PROCARRAY_FLAGS_VACUUM_ANALYZE   PROCARRAY_FLAGS_DEFAULT | PROCARRAY_VACUUM_FLAG | PROCARRAY_ANALYZE_FLAG

Definition at line 56 of file procarray.h.

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

Definition at line 34 of file procarray.h.

#define PROCARRAY_PROC_FLAGS_MASK
Value:
#define PROCARRAY_ANALYZE_FLAG
Definition: procarray.h:32
#define PROCARRAY_VACUUM_FLAG
Definition: procarray.h:30
#define PROCARRAY_LOGICAL_DECODING_FLAG
Definition: procarray.h:34

Definition at line 44 of file procarray.h.

Referenced by GetOldestXmin().

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

Definition at line 37 of file procarray.h.

Referenced by GetOldestXmin(), and XLogWalRcvSendHSFeedback().

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

Definition at line 30 of file procarray.h.

Function Documentation

PGPROC* BackendPidGetProc ( int  pid)

Definition at line 2346 of file procarray.c.

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

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

2347 {
2348  PGPROC *result;
2349 
2350  if (pid == 0) /* never match dummy PGPROCs */
2351  return NULL;
2352 
2353  LWLockAcquire(ProcArrayLock, LW_SHARED);
2354 
2355  result = BackendPidGetProcWithLock(pid);
2356 
2357  LWLockRelease(ProcArrayLock);
2358 
2359  return result;
2360 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1721
PGPROC * BackendPidGetProcWithLock(int pid)
Definition: procarray.c:2369
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1117
Definition: proc.h:95
PGPROC* BackendPidGetProcWithLock ( int  pid)

Definition at line 2369 of file procarray.c.

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

Referenced by BackendPidGetProc(), and GetBlockerStatusData().

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

Definition at line 2406 of file procarray.c.

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

Referenced by pgrowlocks().

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

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

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

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

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

Definition at line 2739 of file procarray.c.

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

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

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

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

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

Definition at line 2890 of file procarray.c.

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

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

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

Definition at line 2840 of file procarray.c.

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

Referenced by InitializeSessionUserId().

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

Definition at line 221 of file procarray.c.

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

Referenced by CreateSharedMemoryAndSemaphores().

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

Definition at line 3271 of file procarray.c.

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

Referenced by ShutdownRecoveryTransactionEnvironment().

3272 {
3273  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3275  LWLockRelease(ProcArrayLock);
3276 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1721
static void KnownAssignedXidsRemovePreceding(TransactionId xid)
Definition: procarray.c:3723
#define InvalidTransactionId
Definition: transam.h:31
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1117
void ExpireOldKnownAssignedTransactionIds ( TransactionId  xid)

Definition at line 3283 of file procarray.c.

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

Referenced by ProcArrayApplyRecoveryInfo().

3284 {
3285  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3287  LWLockRelease(ProcArrayLock);
3288 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1721
static void KnownAssignedXidsRemovePreceding(TransactionId xid)
Definition: procarray.c:3723
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1117
void ExpireTreeKnownAssignedTransactionIds ( TransactionId  xid,
int  nsubxids,
TransactionId subxids,
TransactionId  max_xid 
)

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

3248 {
3250 
3251  /*
3252  * Uses same locking as transaction commit
3253  */
3254  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3255 
3256  KnownAssignedXidsRemoveTree(xid, nsubxids, subxids);
3257 
3258  /* As in ProcArrayEndTransaction, advance latestCompletedXid */
3260  max_xid))
3262 
3263  LWLockRelease(ProcArrayLock);
3264 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1721
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:3701
#define Assert(condition)
Definition: c.h:664
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1117
HotStandbyState standbyState
Definition: xlog.c:197
TransactionId latestCompletedXid
Definition: transam.h:135
VirtualTransactionId* GetConflictingVirtualXIDs ( TransactionId  limitXmin,
Oid  dbOid 
)

Definition at line 2562 of file procarray.c.

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

Referenced by ResolveRecoveryConflictWithSnapshot(), and ResolveRecoveryConflictWithTablespace().

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

Definition at line 2474 of file procarray.c.

References PGPROC::databaseId, GET_VXID_FROM_PGPROC, LW_SHARED, LWLockAcquire(), LWLockRelease(), ProcArrayStruct::maxProcs, MyDatabaseId, MyProc, ProcArrayStruct::numProcs, palloc(), ProcArrayStruct::pgprocnos, procArray, TransactionIdIsValid, TransactionIdPrecedesOrEquals(), PGXACT::vacuumFlags, VirtualTransactionIdIsValid, and PGXACT::xmin.

Referenced by DefineIndex().

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

Definition at line 1467 of file procarray.c.

References TOTAL_MAX_CACHED_SUBXIDS.

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

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

Definition at line 1456 of file procarray.c.

References ProcArrayStruct::maxProcs.

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

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

Definition at line 2092 of file procarray.c.

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

Referenced by CreateCheckPoint().

2093 {
2094  ProcArrayStruct *arrayP = procArray;
2095  TransactionId oldestRunningXid;
2096  int index;
2097 
2099 
2100  /*
2101  * Read nextXid, as the upper bound of what's still active.
2102  *
2103  * Reading a TransactionId is atomic, but we must grab the lock to make
2104  * sure that all XIDs < nextXid are already present in the proc array (or
2105  * have already completed), when we spin over it.
2106  */
2107  LWLockAcquire(XidGenLock, LW_SHARED);
2108  oldestRunningXid = ShmemVariableCache->nextXid;
2109  LWLockRelease(XidGenLock);
2110 
2111  /*
2112  * Spin over procArray collecting all xids and subxids.
2113  */
2114  LWLockAcquire(ProcArrayLock, LW_SHARED);
2115  for (index = 0; index < arrayP->numProcs; index++)
2116  {
2117  int pgprocno = arrayP->pgprocnos[index];
2118  volatile PGXACT *pgxact = &allPgXact[pgprocno];
2119  TransactionId xid;
2120 
2121  /* Fetch xid just once - see GetNewTransactionId */
2122  xid = pgxact->xid;
2123 
2124  if (!TransactionIdIsNormal(xid))
2125  continue;
2126 
2127  if (TransactionIdPrecedes(xid, oldestRunningXid))
2128  oldestRunningXid = xid;
2129 
2130  /*
2131  * Top-level XID of a transaction is always less than any of its
2132  * subxids, so we don't need to check if any of the subxids are
2133  * smaller than oldestRunningXid
2134  */
2135  }
2136  LWLockRelease(ProcArrayLock);
2137 
2138  return oldestRunningXid;
2139 }
uint32 TransactionId
Definition: c.h:391
Definition: proc.h:219
TransactionId xid
Definition: proc.h:221
bool RecoveryInProgress(void)
Definition: xlog.c:7954
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1721
TransactionId nextXid
Definition: transam.h:117
VariableCache ShmemVariableCache
Definition: varsup.c:34
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
static ProcArrayStruct * procArray
Definition: procarray.c:98
static PGXACT * allPgXact
Definition: procarray.c:101
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:95
#define Assert(condition)
Definition: c.h:664
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1117
#define TransactionIdIsNormal(xid)
Definition: transam.h:42
TransactionId GetOldestSafeDecodingTransactionId ( bool  catalogOnly)

Definition at line 2158 of file procarray.c.

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

Referenced by CreateInitDecodingContext(), and SnapBuildInitialSnapshot().

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

Definition at line 1315 of file procarray.c.

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

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

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

Definition at line 1934 of file procarray.c.

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

Referenced by LogStandbySnapshot().

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

Definition at line 1509 of file procarray.c.

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

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

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

Definition at line 2254 of file procarray.c.

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

Referenced by CreateCheckPoint().

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

Definition at line 2299 of file procarray.c.

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

Referenced by CreateCheckPoint().

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

Definition at line 2441 of file procarray.c.

References BackendPidGetProc().

Referenced by pg_stat_get_subscription().

2442 {
2443  return (BackendPidGetProc(pid) != NULL);
2444 }
PGPROC * BackendPidGetProc(int pid)
Definition: procarray.c:2346
bool MinimumActiveBackends ( int  min)

Definition at line 2685 of file procarray.c.

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

Referenced by XLogFlush().

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

Definition at line 275 of file procarray.c.

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

Referenced by InitProcessPhase2(), and MarkAsPrepared().

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

Definition at line 668 of file procarray.c.

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

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

669 {
670  TransactionId *xids;
671  int nxids;
672  TransactionId nextXid;
673  int i;
674 
679 
680  /*
681  * Remove stale transactions, if any.
682  */
684 
685  /*
686  * Remove stale locks, if any.
687  *
688  * Locks are always assigned to the toplevel xid so we don't need to care
689  * about subxcnt/subxids (and by extension not about ->suboverflowed).
690  */
691  StandbyReleaseOldLocks(running->xcnt, running->xids);
692 
693  /*
694  * If our snapshot is already valid, nothing else to do...
695  */
697  return;
698 
699  /*
700  * If our initial RunningTransactionsData had an overflowed snapshot then
701  * we knew we were missing some subxids from our snapshot. If we continue
702  * to see overflowed snapshots then we might never be able to start up, so
703  * we make another test to see if our snapshot is now valid. We know that
704  * the missing subxids are equal to or earlier than nextXid. After we
705  * initialise we continue to apply changes during recovery, so once the
706  * oldestRunningXid is later than the nextXid from the initial snapshot we
707  * know that we no longer have missing information and can mark the
708  * snapshot as valid.
709  */
711  {
712  /*
713  * If the snapshot isn't overflowed or if its empty we can reset our
714  * pending state and use this snapshot instead.
715  */
716  if (!running->subxid_overflow || running->xcnt == 0)
717  {
718  /*
719  * If we have already collected known assigned xids, we need to
720  * throw them away before we apply the recovery snapshot.
721  */
724  }
725  else
726  {
728  running->oldestRunningXid))
729  {
732  "recovery snapshots are now enabled");
733  }
734  else
736  "recovery snapshot waiting for non-overflowed snapshot or "
737  "until oldest active xid on standby is at least %u (now %u)",
739  running->oldestRunningXid);
740  return;
741  }
742  }
743 
745 
746  /*
747  * OK, we need to initialise from the RunningTransactionsData record.
748  *
749  * NB: this can be reached at least twice, so make sure new code can deal
750  * with that.
751  */
752 
753  /*
754  * Nobody else is running yet, but take locks anyhow
755  */
756  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
757 
758  /*
759  * KnownAssignedXids is sorted so we cannot just add the xids, we have to
760  * sort them first.
761  *
762  * Some of the new xids are top-level xids and some are subtransactions.
763  * We don't call SubtransSetParent because it doesn't matter yet. If we
764  * aren't overflowed then all xids will fit in snapshot and so we don't
765  * need subtrans. If we later overflow, an xid assignment record will add
766  * xids to subtrans. If RunningXacts is overflowed then we don't have
767  * enough information to correctly update subtrans anyway.
768  */
769 
770  /*
771  * Allocate a temporary array to avoid modifying the array passed as
772  * argument.
773  */
774  xids = palloc(sizeof(TransactionId) * (running->xcnt + running->subxcnt));
775 
776  /*
777  * Add to the temp array any xids which have not already completed.
778  */
779  nxids = 0;
780  for (i = 0; i < running->xcnt + running->subxcnt; i++)
781  {
782  TransactionId xid = running->xids[i];
783 
784  /*
785  * The running-xacts snapshot can contain xids that were still visible
786  * in the procarray when the snapshot was taken, but were already
787  * WAL-logged as completed. They're not running anymore, so ignore
788  * them.
789  */
791  continue;
792 
793  xids[nxids++] = xid;
794  }
795 
796  if (nxids > 0)
797  {
799  {
800  LWLockRelease(ProcArrayLock);
801  elog(ERROR, "KnownAssignedXids is not empty");
802  }
803 
804  /*
805  * Sort the array so that we can add them safely into
806  * KnownAssignedXids.
807  */
808  qsort(xids, nxids, sizeof(TransactionId), xidComparator);
809 
810  /*
811  * Add the sorted snapshot into KnownAssignedXids
812  */
813  for (i = 0; i < nxids; i++)
814  KnownAssignedXidsAdd(xids[i], xids[i], true);
815 
817  }
818 
819  pfree(xids);
820 
821  /*
822  * latestObservedXid is at least set to the point where SUBTRANS was
823  * started up to (c.f. 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  /*
882  * ShmemVariableCache->nextXid must be beyond any observed xid.
883  *
884  * We don't expect anyone else to modify nextXid, hence we don't need to
885  * hold a lock while examining it. We still acquire the lock to modify
886  * it, though.
887  */
888  nextXid = latestObservedXid;
889  TransactionIdAdvance(nextXid);
891  {
892  LWLockAcquire(XidGenLock, LW_EXCLUSIVE);
893  ShmemVariableCache->nextXid = nextXid;
894  LWLockRelease(XidGenLock);
895  }
896 
898 
901  elog(trace_recovery(DEBUG1), "recovery snapshots are now enabled");
902  else
904  "recovery snapshot waiting for non-overflowed snapshot or "
905  "until oldest active xid on standby is at least %u (now %u)",
907  running->oldestRunningXid);
908 }
#define TransactionIdAdvance(dest)
Definition: transam.h:48
static TransactionId latestObservedXid
Definition: procarray.c:108
TransactionId oldestRunningXid
Definition: standby.h:76
#define DEBUG1
Definition: elog.h:25
static void KnownAssignedXidsDisplay(int trace_level)
Definition: procarray.c:3909
bool TransactionIdFollows(TransactionId id1, TransactionId id2)
Definition: transam.c:334
uint32 TransactionId
Definition: c.h:391
#define DEBUG3
Definition: elog.h:23
TransactionId * xids
Definition: standby.h:79
bool TransactionIdDidCommit(TransactionId transactionId)
Definition: transam.c:125
#define TransactionIdRetreat(dest)
Definition: transam.h:56
int trace_recovery(int trace_level)
Definition: elog.c:3753
TransactionId latestCompletedXid
Definition: standby.h:77
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1721
void pfree(void *pointer)
Definition: mcxt.c:949
#define ERROR
Definition: elog.h:43
void ExtendSUBTRANS(TransactionId newestXact)
Definition: subtrans.c:324
TransactionId nextXid
Definition: transam.h:117
VariableCache ShmemVariableCache
Definition: varsup.c:34
#define InvalidTransactionId
Definition: transam.h:31
static void KnownAssignedXidsReset(void)
Definition: procarray.c:3948
int numKnownAssignedXids
Definition: procarray.c:75
TransactionId lastOverflowedXid
Definition: procarray.c:87
bool TransactionIdDidAbort(TransactionId transactionId)
Definition: transam.c:181
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
static ProcArrayStruct * procArray
Definition: procarray.c:98
void StandbyReleaseOldLocks(int nxids, TransactionId *xids)
Definition: standby.c:725
#define Assert(condition)
Definition: c.h:664
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1117
static void KnownAssignedXidsAdd(TransactionId from_xid, TransactionId to_xid, bool exclusive_lock)
Definition: procarray.c:3449
TransactionId nextXid
Definition: standby.h:75
void * palloc(Size size)
Definition: mcxt.c:848
int i
void ExpireOldKnownAssignedTransactionIds(TransactionId xid)
Definition: procarray.c:3283
#define elog
Definition: elog.h:219
#define qsort(a, b, c, d)
Definition: port.h:443
#define TransactionIdIsValid(xid)
Definition: transam.h:41
#define TransactionIdIsNormal(xid)
Definition: transam.h:42
static TransactionId standbySnapshotPendingXmin
Definition: procarray.c:115
HotStandbyState standbyState
Definition: xlog.c:197
int xidComparator(const void *arg1, const void *arg2)
Definition: xid.c:138
TransactionId latestCompletedXid
Definition: transam.h:135
void ProcArrayApplyXidAssignment ( TransactionId  topxid,
int  nsubxids,
TransactionId subxids 
)

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

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

Definition at line 605 of file procarray.c.

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

Referenced by PrepareTransaction().

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

Definition at line 396 of file procarray.c.

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

Referenced by AbortTransaction(), and CommitTransaction().

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

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

2988 {
2989  LWLockAcquire(ProcArrayLock, LW_SHARED);
2990 
2991  if (xmin != NULL)
2993 
2994  if (catalog_xmin != NULL)
2995  *catalog_xmin = procArray->replication_slot_catalog_xmin;
2996 
2997  LWLockRelease(ProcArrayLock);
2998 }
TransactionId replication_slot_catalog_xmin
Definition: procarray.c:92
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1721
static ProcArrayStruct * procArray
Definition: procarray.c:98
TransactionId replication_slot_xmin
Definition: procarray.c:90
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1117
void ProcArrayInitRecovery ( TransactionId  initializedUptoXID)

Definition at line 637 of file procarray.c.

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

Referenced by StartupXLOG().

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

Definition at line 1797 of file procarray.c.

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

Referenced by GetSerializableTransactionSnapshotInt(), and SetTransactionSnapshot().

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

Definition at line 1872 of file procarray.c.

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

Referenced by SetTransactionSnapshot().

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

Definition at line 333 of file procarray.c.

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

Referenced by FinishPreparedTransaction(), and RemoveProcFromArray().

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

Definition at line 2964 of file procarray.c.

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

Referenced by ReplicationSlotsComputeRequiredXmin().

2966 {
2967  Assert(!already_locked || LWLockHeldByMe(ProcArrayLock));
2968 
2969  if (!already_locked)
2970  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
2971 
2973  procArray->replication_slot_catalog_xmin = catalog_xmin;
2974 
2975  if (!already_locked)
2976  LWLockRelease(ProcArrayLock);
2977 }
bool LWLockHeldByMe(LWLock *l)
Definition: lwlock.c:1837
TransactionId replication_slot_catalog_xmin
Definition: procarray.c:92
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1721
static ProcArrayStruct * procArray
Definition: procarray.c:98
TransactionId replication_slot_xmin
Definition: procarray.c:90
#define Assert(condition)
Definition: c.h:664
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1117
Size ProcArrayShmemSize ( void  )

Definition at line 179 of file procarray.c.

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

Referenced by CreateSharedMemoryAndSemaphores().

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

Definition at line 3173 of file procarray.c.

References Assert, DEBUG4, elog, ExtendSUBTRANS(), KnownAssignedXidsAdd(), latestObservedXid, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), VariableCacheData::nextXid, ShmemVariableCache, STANDBY_INITIALIZED, standbyState, trace_recovery(), TransactionIdAdvance, TransactionIdFollows(), TransactionIdIsValid, and TransactionIdPrecedes().

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

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

Definition at line 1216 of file procarray.c.

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

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

Definition at line 999 of file procarray.c.

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

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

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

Definition at line 3016 of file procarray.c.

References Assert, elog, i, VariableCacheData::latestCompletedXid, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MyPgXact, MyProc, PGXACT::nxids, ShmemVariableCache, PGPROC::subxids, TransactionIdEquals, TransactionIdIsValid, TransactionIdPrecedes(), WARNING, XidCacheRemove, and XidCache::xids.

Referenced by RecordTransactionAbort().

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